VYPR
Moderate severityNVD Advisory· Published Dec 14, 2022· Updated Apr 21, 2025

CVE-2022-47407

CVE-2022-47407

Description

CVE-2022-47407 allows an attacker to continue another user's quiz in TYPO3 Master-Quiz, viewing and modifying their answers due to missing session validation.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

CVE-2022-47407 allows an attacker to continue another user's quiz in TYPO3 Master-Quiz, viewing and modifying their answers due to missing session validation.

Vulnerability

Overview

CVE-2022-47407 affects the TYPO3 extension fp_masterquiz (Master-Quiz) in versions before 2.2.1 and 3.x before 3.5.1. The vulnerability arises from insufficient validation of session identifiers during quiz participation. An attacker can continue a quiz initiated by a different user, gaining unauthorized access to that user's quiz state [1][2].

Attack

Vector and Exploitation

The issue is rooted in the extension's failure to properly associate and verify a session key with a specific participant. In affected versions, the session key was not always required or checked against the participant record. This allows an attacker, by manipulating request parameters or the session identifier, to hijack an active quiz session of another user [3][4]. The attack likely requires some knowledge of the target user's quiz identifier or the ability to craft a request without proper authentication checks.

Impact

A successful exploit enables the attacker to view the victim's submitted answers and modify them. This could result in data tampering, privacy violations, and the potential to distort quiz results or learning records. The impact is primarily on the integrity and confidentiality of quiz data for affected installations.

Mitigation

The vulnerability is fixed in version 2.2.1 (for the 2.x branch) and version 3.5.1 (for the 3.x branch). In the fix (e.g., commit fce4ec6), a session-key is always required and validated against the participant record [1][3]. Users who use custom templates with Ajax functionality must add a hidden session field to their forms. Administrators are advised to update the extension immediately to the patched versions [2][4].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
fixpunkt/fp-masterquizPackagist
>= 3.0.0, < 3.5.23.5.2
fixpunkt/fp-masterquizPackagist
< 2.2.12.2.1

Affected products

2

Patches

2
f6f1baa59433

Security fix

https://github.com/bihor/fp_masterquizKurt GusbethDec 13, 2022via ghsa
13 files changed · +223 56
  • Classes/Controller/QuizController.php+151 41 modified
    @@ -191,6 +191,29 @@ public function initializeShowByTagAction()
             $this->forward('list');
         }
     
    +    /**
    +     * Prüft, ob eine Session gültig ist: check the session against the request-parameter
    +     *
    +     * @param string $c_debug
    +     * @return boolean
    +     */
    +    public function isSessionOK(string &$c_debug): bool
    +    {
    +        if ($this->request->hasArgument('session')) {
    +            $tmp_session = $this->request->getArgument('session');
    +        } else {
    +            $tmp_session = '';
    +        }
    +        if ($this->participant->getSession() != $tmp_session) {
    +            $this->participant = null;
    +            if ($this->settings['debug']) {
    +                $c_debug .= "\nParticipant not accepted, because the session from argument is wrong: " . $tmp_session;
    +            }
    +            return false;
    +        }
    +        return true;
    +    }
    +
         /**
          * Sucht einen Teilnehmer und erzeugt ggf. einen
          *
    @@ -205,11 +228,16 @@ public function findParticipant(int $quizUid, int $quizPid)
             $newUser = false;
             $context = GeneralUtility::makeInstance(Context::class);
             $fe_user_uid = intval($context->getPropertyFromAspect('frontend.user', 'id'));
    -        if (!$this->settings['ajax']) {
    +        $isAjax = $this->settings['ajax'];
    +        if ($this->settings['debug'] && $isAjax) {
    +            $debug .= "\nAjax mode is enabled.";
    +        }
    +//        if (!$isAjax) {
                 if ($this->request->hasArgument('session')) {
    +                // wir dürften nicht auf der Startseite sein, außer beim 1. Ajax-call
                     $session = $this->request->getArgument('session');
    -            } else if (!$this->request->hasArgument('participant')) {
    -                // keine Session gefunden... und jetzt Cookie checken?
    +            } else if (!$this->request->hasArgument('participant') && !$isAjax) {
    +                // keine Session gefunden... und jetzt Cookie checken? Hier dürften wir auf der Startseite sein
                     if (intval($this->settings['user']['useCookie']) == -1) {
                         $session = $GLOBALS["TSFE"]->fe_user->getKey('ses', 'qsession' . $quizUid);
                     } else if ((intval($this->settings['user']['useCookie']) > 0) && isset($_COOKIE['qsession' . $quizUid])) {
    @@ -235,23 +263,14 @@ public function findParticipant(int $quizUid, int $quizPid)
                             }
                         }
                         if (!$session) {
    -                        $session = uniqid(random_int(1000, 9999));
    -                        $newUser = true;
                             $this->participant = null;
                             if ($this->settings['debug']) {
    -                            $debug .= "\ncreating new session: " . $session;
    +                            $debug .= "\nNo session found, will creating a new participant...";
                             }
                         }
                     }
                 }
    -            if (intval($this->settings['user']['useCookie']) == -1) {
    -                // Store the session in a cookie
    -                $GLOBALS['TSFE']->fe_user->setKey('ses', 'qsession' . $quizUid, $session);
    -                $GLOBALS["TSFE"]->fe_user->storeSessionData();
    -            } else if (intval($this->settings['user']['useCookie']) > 0) {
    -                setcookie('qsession' . $quizUid, $session, time() + (3600 * 24 * intval($this->settings['user']['useCookie'])));  /* verfällt in x Tagen */
    -            }
    -        }
    +//        }
     
             if ($this->request->hasArgument('participant') && $this->request->getArgument('participant')) {
                 // wir sind nicht auf Seite 1
    @@ -262,9 +281,13 @@ public function findParticipant(int $quizUid, int $quizPid)
                     $this->participant = $this->participantRepository->findOneByUid($participantUid);
                 }
                 if ($this->participant) {
    +                // ein abgelegter session-key hat Vorrang
                     $session = $this->participant->getSession();
    -                if ($this->settings['debug']) {
    -                    $debug .= "\nparticipant from request: " . $participantUid;
    +                if ($session && !$this->isSessionOK($debug)) {
    +                    $participantUid = 0;
    +                }
    +                if ($this->settings['debug'] && $participantUid) {
    +                    $debug .= "\nParticipant from request: " . $participantUid . ' with session: ' . $session;
                     }
                 }
             }
    @@ -287,13 +310,28 @@ public function findParticipant(int $quizUid, int $quizPid)
                     }
                 }
                 if (!$session) {
    +                // ggf. wird die Session von der Startseite beibehalten
                     $session = uniqid(random_int(1000, 9999));
    +                $this->participant->setSession($session);
                     $newUser = true;
                     if ($this->settings['debug']) {
                         $debug .= "\ncreating new session: " . $session;
                     }
                 }
             }
    +        if (!$isAjax && !$newUser && !$this->participant->getUid()) {
    +            // Cookie nicht schon auf der Startseite setzen, sondern erst und nur auf der Folgeseite
    +            if ($this->settings['debug']) {
    +                $debug .= "\nSetting a cookie with this session: " . $session;
    +            }
    +            if (intval($this->settings['user']['useCookie']) == -1) {
    +                // Store the session in a cookie
    +                $GLOBALS['TSFE']->fe_user->setKey('ses', 'qsession' . $quizUid, $session);
    +                $GLOBALS["TSFE"]->fe_user->storeSessionData();
    +            } else if (intval($this->settings['user']['useCookie']) > 0) {
    +                setcookie('qsession' . $quizUid, $session, time() + (3600 * 24 * intval($this->settings['user']['useCookie'])));  /* verfällt in x Tagen */
    +            }
    +        }
             $result = [];
             $result['session'] = $session;
             $result['newUser'] = $newUser;
    @@ -341,6 +379,14 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
             if (!$questionsPerPage) {
                 $questionsPerPage = 1;
             }
    +       /* if ($this->settings['ajax'] && $session && !$this->participant->getUid() && ($showAnswers || $page>1)) {
    +            $page = 1;
    +            $showAnswers = false;
    +            $reload = true;
    +            if ($this->settings['debug']) {
    +                $debug .= "\nReload auf Ajax-Startseite detektiert.";
    +            }
    +        } */
             if ($this->settings['allowEdit']) {
                 if ($this->participant->isCompleted()) {
                     $showAnswers = true;
    @@ -411,7 +457,8 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
     	    			$this->participant->setHomepage($defaultHomepage);
     	    			$this->participant->setUser(isset($GLOBALS['TSFE']->fe_user->user['uid']) ? intval($GLOBALS['TSFE']->fe_user->user['uid']) : 0);
     	    			$this->participant->setIp($this->getRealIpAddr());
    -	    			$this->participant->setSession($session);
    +                    // Die Session wurde bisher nur auf der Startseite gesetzt, deshalb wird sie hier nochmal gesetzt
    +                    $this->participant->setSession($session);
                         if ($startTime) {
                             $this->participant->setSessionstart(time() - $startTime);
                         }
    @@ -424,7 +471,7 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
     	    			$persistenceManager->persistAll();
     	    			$newUser = true;
     	    			if ($this->settings['debug']) {
    -	    				$debug .= "\nNew participant created: " . $this->participant->getUid();
    +	    				$debug .= "\nNew participant created: " . $this->participant->getUid() . '; with session: ' . $session;
         				}
         			}
         		}
    @@ -905,27 +952,29 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
          */
         protected function checkForClosure() : bool
         {
    +        $debug = '';
             $page = $this->request->hasArgument('currentPage') ? intval($this->request->getArgument('currentPage')) : 1;
             if (($page == 999) && ($this->settings['user']['askForData'] == 3) && $this->settings['closurePageUid'] &&
                 $this->request->hasArgument('participant') && $this->request->getArgument('participant')) {
                 $participantUid = intval($this->request->getArgument('participant'));
                 $this->participant = $this->participantRepository->findOneByUid($participantUid);
    -            if ($this->request->hasArgument('name') && $this->request->getArgument('name')) {
    -                $this->participant->setName($this->request->getArgument('name'));
    -            }
    -            if ($this->request->hasArgument('email') && $this->request->getArgument('email')) {
    -                $this->participant->setEmail($this->request->getArgument('email'));
    -            }
    -            if ($this->request->hasArgument('homepage') && $this->request->getArgument('homepage')) {
    -                $this->participant->setHomepage($this->request->getArgument('homepage'));
    +            if ($this->isSessionOK($debug)) {
    +                if ($this->request->hasArgument('name') && $this->request->getArgument('name')) {
    +                    $this->participant->setName($this->request->getArgument('name'));
    +                }
    +                if ($this->request->hasArgument('email') && $this->request->getArgument('email')) {
    +                    $this->participant->setEmail($this->request->getArgument('email'));
    +                }
    +                if ($this->request->hasArgument('homepage') && $this->request->getArgument('homepage')) {
    +                    $this->participant->setHomepage($this->request->getArgument('homepage'));
    +                }
    +                $this->participantRepository->update($this->participant);
    +                $persistenceManager = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\PersistenceManager');
    +                $persistenceManager->persistAll();
    +                return true;
                 }
    -            $this->participantRepository->update($this->participant);
    -            $persistenceManager = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\PersistenceManager');
    -            $persistenceManager->persistAll();
    -            return true;
    -        } else {
    -            return false;
             }
    +        return false;
         }
     
         /**
    @@ -1134,7 +1183,7 @@ protected function setAllUserAnswersForOneQuestion(\Fixpunkt\FpMasterquiz\Domain
                 if ($votesTotal) {
                     $percentage = 100 * ($thisVotes / $votesTotal);
                 }
    -            if ($this->settings['debug']) {
    +            if ($this->settings['debug'] && $votes) {
                     $debug .= "\n percent: 100*" . $thisVotes . '/' . $votes . ' = ' . 100 * ($thisVotes / $votes);
                     $debug .= "\n total percent: 100*" . $thisVotes . '/' . $votesTotal . ' = ' . $percentage;
                 }
    @@ -1182,7 +1231,41 @@ protected function setMetatags(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz &$c_quiz
             $meta = $metaTagManager->getManagerForProperty('og:title');
             $meta->addProperty('og:title', $title);
         }
    -    
    +
    +    /**
    +     * Checks if a quiz is allowed
    +     *
    +     * @param integer $pid
    +     * @param integer $uid
    +     * @return boolean
    +     */
    +    public function checkQuizAccess(int $pid, int $uid): bool
    +    {
    +        $storagePidsArray = $this->quizRepository->getStoragePids();
    +        if (is_array($storagePidsArray) && !$storagePidsArray[0] == 0) {
    +            if (!in_array($pid, $storagePidsArray)) {
    +                $this->addFlashMessage(
    +                    LocalizationUtility::translate('error.quizNotFound', 'fp_masterquiz') . ' ' . intval($pid),
    +                    LocalizationUtility::translate('error.error', 'fp_masterquiz'),
    +                    \TYPO3\CMS\Core\Messaging\AbstractMessage::WARNING,
    +                    false
    +                );
    +                return false;
    +            }
    +        }
    +        if ($this->settings['defaultQuizUid'] && $uid!=$this->settings['defaultQuizUid']) {
    +            $this->addFlashMessage(
    +                LocalizationUtility::translate('error.quizNotAllowed', 'fp_masterquiz') . ' ' . intval($uid),
    +                LocalizationUtility::translate('error.error', 'fp_masterquiz'),
    +                \TYPO3\CMS\Core\Messaging\AbstractMessage::WARNING,
    +                false
    +            );
    +            return false;
    +        }
    +        return true;
    +    }
    +
    +
         /**
          * action list
          *
    @@ -1294,10 +1377,15 @@ public function introAction()
          */
         public function showAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
         {
    +        if (!$this->checkQuizAccess($quiz->getPid(), $quiz->getUid())) {
    +            return;
    +        }
             if ($this->checkForClosure()) {
    -            $this->redirect('closure', 'Quiz', NULL, ['participant' => $this->participant], $this->settings['closurePageUid']);
    +            $this->redirect('closure', 'Quiz', NULL, ['participant' => $this->participant,'session'=>$this->participant->getSession()], $this->settings['closurePageUid']);
             }
    +        // participant wird zuerst hier definiert ...
             $userData = $this->findParticipant($quiz->getUid(), $quiz->getPid());
    +        /// ... und dann hier in der DB abgespeichert
             $data = $this->doAll($quiz, $userData,0, []);
             $page = $data['page'];
             $pages = $data['pages'];
    @@ -1359,8 +1447,11 @@ public function showAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
          */
         public function showByTagAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
         {
    +        if (!$this->checkQuizAccess($quiz->getPid(), $quiz->getUid())) {
    +            return;
    +        }
             if ($this->checkForClosure()) {
    -            $this->redirect('closure', 'Quiz', NULL, ['participant' => $this->participant], $this->settings['closurePageUid']);
    +            $this->redirect('closure', 'Quiz', NULL, ['participant' => $this->participant,'session'=>$this->participant->getSession()], $this->settings['closurePageUid']);
             }
             $userData = $this->findParticipant($quiz->getUid(), $quiz->getPid());
             $page = $this->request->hasArgument('currentPage') ? intval($this->request->getArgument('currentPage')) : 1;
    @@ -1456,8 +1547,11 @@ public function showByTagAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
          */
         public function showAjaxAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
         {
    +        if (!$this->checkQuizAccess($quiz->getPid(), $quiz->getUid())) {
    +            return;
    +        }
             if ($this->checkForClosure()) {
    -            $this->redirect('closure', 'Quiz', NULL, ['participant' => $this->participant], $this->settings['closurePageUid']);
    +            $this->redirect('closure', 'Quiz', NULL, ['participant' => $this->participant,'session'=>$this->participant->getSession()], $this->settings['closurePageUid']);
             }
         	// siehe: https://www.sebkln.de/tutorials/erstellung-einer-typo3-extension-mit-ajax-aufruf/
             //	$quizUid = $this->request->hasArgument('quiz') ? intval($this->request->getArgument('quiz')) : 0;
    @@ -1568,10 +1662,13 @@ public function showAjaxAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
          */
         public function resultAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
         {
    +        if (!$this->checkQuizAccess($quiz->getPid(), $quiz->getUid())) {
    +            return;
    +        }
         	$languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language');
         	$sys_language_uid = $languageAspect->getId();
         	$pid = (int)$GLOBALS['TSFE']->id;
    -	    $debug = $this->setAllUserAnswers($quiz, $pid, false);
    +        $debug = $this->setAllUserAnswers($quiz, $pid, false);
         	$this->view->assign('quiz', $quiz);
         	$this->view->assign('debug', $debug);
         	$this->view->assign("sysLanguageUid", $sys_language_uid);
    @@ -1587,6 +1684,9 @@ public function resultAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
          */
         public function highscoreAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
         {
    +        if (!$this->checkQuizAccess($quiz->getPid(), $quiz->getUid())) {
    +            return;
    +        }
             $languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language');
             $sys_language_uid = $languageAspect->getId();
             $pid = (int)$GLOBALS['TSFE']->id;
    @@ -1604,12 +1704,22 @@ public function highscoreAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
          * action show
          *
          * @param \Fixpunkt\FpMasterquiz\Domain\Model\Participant $participant
    +     * @param string $session
          * @return void
          */
    -    public function closureAction(\Fixpunkt\FpMasterquiz\Domain\Model\Participant $participant)
    +    public function closureAction(\Fixpunkt\FpMasterquiz\Domain\Model\Participant $participant, string $session = '')
         {
    -        $this->view->assign('participant', $participant);
    -        $this->view->assign('quiz', $participant->getQuiz());
    +        if ($participant->getSession() == $session) {
    +            $this->view->assign('participant', $participant);
    +            $this->view->assign('quiz', $participant->getQuiz());
    +        } else {
    +            $this->addFlashMessage(
    +                LocalizationUtility::translate('error.invalidParameters', 'fp_masterquiz'),
    +                LocalizationUtility::translate('error.error', 'fp_masterquiz'),
    +                \TYPO3\CMS\Core\Messaging\AbstractMessage::WARNING,
    +                false
    +            );
    +        }
         }
     
         /**
    
  • Classes/Domain/Repository/QuizRepository.php+11 1 modified
    @@ -40,5 +40,15 @@ public function findFromPid($pageId)
         	$query->matching($query->equals('pid', $pageId));
         	return $query->execute();
         }
    -    
    +
    +    /**
    +     * Get the PIDs
    +     *
    +     * @return array
    +     */
    +    public function getStoragePids()
    +    {
    +        $query = $this->createQuery();
    +        return $query->getQuerySettings()->getStoragePageIds();
    +    }
     }
    
  • Configuration/TypoScript/setup.ts+1 3 modified
    @@ -15,8 +15,6 @@ plugin.tx_fpmasterquiz {
             skipDefaultArguments = 1
             # if set to 1, the enable fields are ignored in BE context
             ignoreAllEnableFieldsInBe = 0
    -        # Should be on by default, but can be disabled if all action in the plugin are uncached
    -        requireCHashArgumentForActionArguments = 0
         }
         mvc {
             callDefaultActionIfActionCantBeResolved = 1
    @@ -27,7 +25,7 @@ plugin.tx_fpmasterquiz {
     		closurePageUid =
     		resultPageUid =
     		highscorePageUid =
    -		defaultQuizUid = 1
    +		defaultQuizUid =
     		introContentUid =
     		introNextAction = show
     		showAnswerPage = 1
    
  • Documentation/Administrator/Index.rst+26 0 modified
    @@ -126,6 +126,32 @@ Exporting participant entries
     * There is a scheduler task which whom you can export participants from a single folder (pid). The csv-file will be written to fileadmin.
     
     
    +.. _security-fix:
    +
    +Security fix in version 3.5.2
    +-----------------------------
    +
    +Since version 3.5.2 a session-key is always required and this session-key will be checked against a participant.
    +If you use the Ajax-version AND if you use an own HTML-template, then you must add some code to your templates!
    +In the Show.html template you need to add this line to the hidden-fields of the first form::
    +
    +  <f:form.hidden name="session" value="" id="quiz-form-session" />
    +
    +In the ShowAjax.html template you need to add 2 lines.
    +This one after "$('#quiz-form'+ceuid+' #quiz-form-parti').val('{participant.uid}');"::
    +
    +  $('#quiz-form'+ceuid+' #quiz-form-session').val('{session}');
    +
    +and this one after "$('#quiz-form-parti').val('0');"::
    +
    +  $('#quiz-form-session').val('');
    +
    +That will set a session-key for every participant.
    +
    +Another change was made in the settings. The default quiz-UID 1 was removed. If you use that default setting,
    +you must set settings.defaultQuizUid again to 1.
    +
    +
     .. _admin-faq:
     
     FAQ
    
  • Documentation/ChangeLog/Index.rst+8 4 modified
    @@ -104,7 +104,7 @@ ChangeLog
       TCA-Bugfix for TYPO3 10.
       Refactoring.
     
    -3.0.2:
    +3.0.0/2:
       Version for TYPO3 10 and 11.
       closure action and setting closurePageUid added.
       Default-value for setting ajaxType changed from POST to GET.
    @@ -127,7 +127,7 @@ ChangeLog
       Div with class card-body added to all cards.
       Variable participant.username added.
     
    -3.3.1:
    +3.3.0/1:
       Backend-Layout adapted for TYPO3 11.5.
       Evaluation of the most used category is now possible too. Setting showDetailedCategoryEvaluation added.
       TYPO3 categories are now available at a quiz, question, answer, selected and evaluation.
    @@ -148,6 +148,10 @@ ChangeLog
       Bugfix: category evaluation.
       Bugfix: wrong Namespace in TemplateLayout corrected.
     
    -3.5.0:
    +3.5.0/1:
       Mandatory check with PHP too, if setting phpFormCheck=1.
    -  New question mode: matrix with categories of a question.
    \ No newline at end of file
    +  New question mode: matrix with categories of a question.
    +
    +3.5.2:
    +  Security fix: checking participant against a session-key. Please read the section Administrator / Security fix in version 3.5.2.
    +  Security fix: check if a quiz/poll is allowed on a page. Therefore, the defaultQuizUid was removed in the settings!
    \ No newline at end of file
    
  • Documentation/Configuration/Index.rst+1 1 modified
    @@ -39,7 +39,7 @@ showPageUid                  integer     UID of the single-page of a quiz (detai
     closurePageUid               integer     UID of a closure-page of a quiz.                -
     resultPageUid                integer     UID of the page where to show quiz results.     -
     highscorePageUid             integer     UID of the page where to show a highscore.      -
    -defaultQuizUid               integer     UID of the quiz to show.                        1
    +defaultQuizUid               integer     UID of the quiz to show.                        -
     introContentUid              integer     Content element for the intro page.             -
     introNextAction              string      Action after the intro page: show or showByTag. show
     showAnswerPage               boolean     Show an answer page after every submit?         1
    
  • Documentation/KnownProblems/Index.rst+1 3 modified
    @@ -14,10 +14,8 @@ Known Problems
     The bug tracker is here:
     `bug tracker <https://github.com/bihor/fp_masterquiz/issues>`_?
     
    -jQuery needed to be loaded in the head.
    -
     There might be some problems, if you enable Ajax!
    -Sessions and Cookies are currently not supported if you enable Ajax.
    +User-data and cookies are currently not supported if you enable Ajax.
     
     Note for versions < 3: it might be necessary to change the Quiz/Show.html template, if you will see the startpage
     instead of a question as a ajax result page. You could try to change the type from POST to GET in the $.ajax call.
    
  • ext_emconf.php+1 1 modified
    @@ -18,7 +18,7 @@
         'state' => 'stable',
         'createDirs' => '',
         'clearCacheOnLoad' => 0,
    -    'version' => '3.5.1',
    +    'version' => '3.5.2',
         'constraints' => [
             'depends' => [
                 'typo3' => '10.4.6-11.5.99',
    
  • README.md+6 2 modified
    @@ -1,6 +1,6 @@
     # fp_masterquiz
     
    -version 3.5.1
    +version 3.5.2
     
     TYPO3 extension to create a quiz, poll or test. The participant result will be saved in the DB too and can be deleted automatically via Scheduler.
     
    @@ -34,6 +34,10 @@ Changes in version 3.4.4:
     - Bugfix: category evaluation.
     - Bugfix: wrong Namespace in TemplateLayout corrected.
     
    -Changes in version 3.5.0:
    +Changes in version 3.5.1:
     - Mandatory check with PHP too, if setting phpFormCheck=1.
     - New question mode: matrix with categories of a question.
    +
    +Changes in version 3.5.2:
    +- Security fix: checking participant against a session-key. Please read the section Administrator / Security fix in version 3.5.2.
    +- Bugfix: check if a quiz/poll is allowed on a page. Therefore, the defaultQuizUid was removed in the settings!
    \ No newline at end of file
    
  • Resources/Private/Language/de.locallang.xlf+8 0 modified
    @@ -351,6 +351,10 @@
     				<source>The quiz with this uid was not found (Record Storage Place set?):</source>
     				<target>Das Quiz mit dieser Uid wurde nicht gefunden (Datensatzsammlung gesetzt?):</target>
     			</trans-unit>
    +			<trans-unit id="error.quizNotAllowed" resname="error.quizNotAllowed">
    +				<source>The quiz was not allowed, because another default quiz is set in the Backend:</source>
    +				<target>Das Quiz ist nicht erlaubt, da ein anderes Quiz im Backend ausgewählt wurde:</target>
    +			</trans-unit>
     			<trans-unit id="error.quizDetailNotFound" resname="error.quizDetailNotFound">
     				<source>No quiz and no detail page was not found!</source>
     				<target>Es wurde kein Quiz und keine Startseite gesetzt! (Datensatzsammlung gesetzt?)</target>
    @@ -359,6 +363,10 @@
     				<source>Error: mandatory questions not answered!</source>
     				<target>Fehler: bitte die markierten Fragen beantworten!</target>
     			</trans-unit>
    +			<trans-unit id="error.invalidParameters" resname="error.invalidParameters">
    +				<source>Error: the parameters could not be validated!</source>
    +				<target>Fehler: die Parameter konnten nicht validiert werden!</target>
    +			</trans-unit>
     			<trans-unit id="text.answer.input" resname="text.answer.input">
     				<source>Answer:</source>
     				<target>Antwort:</target>
    
  • Resources/Private/Language/locallang.xlf+6 0 modified
    @@ -264,12 +264,18 @@
     			<trans-unit id="error.quizNotFound" resname="error.quizNotFound">
     				<source>The quiz with this uid was not found (Record Storage Place set?):</source>
     			</trans-unit>
    +			<trans-unit id="error.quizNotAllowed" resname="error.quizNotAllowed">
    +				<source>The quiz was not allowed, because another default quiz is set in the Backend:</source>
    +			</trans-unit>
     			<trans-unit id="error.quizDetailNotFound" resname="error.quizDetailNotFound">
     				<source>No quiz and no detail page was not found!</source>
     			</trans-unit>
     			<trans-unit id="error.notAnswered" resname="error.notAnswered">
     				<source>Error: mandatory questions not answered!</source>
     			</trans-unit>
    +			<trans-unit id="error.invalidParameters" resname="error.invalidParameters">
    +				<source>Error: the parameters could not be validated!</source>
    +			</trans-unit>
     			<trans-unit id="text.answer.input" resname="text.answer.input">
     				<source>Answer:</source>
     			</trans-unit>
    
  • Resources/Private/Templates/Quiz/ShowAjax.html+2 0 modified
    @@ -48,6 +48,7 @@
     			<script>
     			quizfinal = 0;
     			thisPage = {page};
    +			$('#quiz-form'+ceuid+' #quiz-form-session').val('{session}');
     			$('#quiz-form'+ceuid+' #quiz-form-parti').val('{participant.uid}');
     			$('#quiz-form'+ceuid+' #quiz-form-page').val('{nextPage}');
     			$('#quiz-form'+ceuid+' #quiz-form-answers').val('{showAnswersNext}');
    @@ -79,6 +80,7 @@
     					$('#quiz-form-parti').val('0');
     					$('#quiz-form-page').val('1');
     					$('#quiz-form-answers').val('0');
    +					$('#quiz-form-session').val('');
     					quizfinal = 0;
     					$('#quiz-GoOn').val(text_goon);
     					$('#quiz-button-wrap').show();
    
  • Resources/Private/Templates/Quiz/Show.html+1 0 modified
    @@ -74,6 +74,7 @@
     				<f:form.hidden name="action" value="showAjax" />
     				<f:form.hidden name="quiz" value="{quiz.uid}" />
     				<f:form.hidden name="uidOfCE" value="{uidOfCE}" />
    +				<f:form.hidden name="session" value="" id="quiz-form-session" />
     				<f:form.hidden name="startTime" value="{startTime}" id="quiz-form-time" />
     				<f:form.hidden name="participant" value="0" id="quiz-form-parti" />
     				<f:form.hidden name="currentPage" value="1" id="quiz-form-page" />
    
fce4ec64600d

Security fix. Please update as soon as possible.

https://github.com/bihor/fp_masterquizKurt GusbethDec 13, 2022via ghsa
104 files changed · +2175 3568
  • Classes/Controller/AnswerController.php+1 10 modified
    @@ -21,19 +21,10 @@ class AnswerController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControlle
          * answerRepository
          *
          * @var \Fixpunkt\FpMasterquiz\Domain\Repository\AnswerRepository
    +     * @TYPO3\CMS\Extbase\Annotation\Inject
          */
         protected $answerRepository = null;
     
    -    /**
    -     * Injects the answer-Repository
    -     *
    -     * @param \Fixpunkt\FpMasterquiz\Domain\Repository\AnswerRepository $answerRepository
    -     */
    -    public function injectAnswerRepository(\Fixpunkt\FpMasterquiz\Domain\Repository\AnswerRepository $answerRepository)
    -    {
    -        $this->answerRepository = $answerRepository;
    -    }
    -
         /**
          * action list
          *
    
  • Classes/Controller/ParticipantController.php+2 41 modified
    @@ -2,8 +2,6 @@
     namespace Fixpunkt\FpMasterquiz\Controller;
     
     use TYPO3\CMS\Core\Utility\GeneralUtility;
    -use TYPO3\CMS\Core\Pagination\ArrayPaginator;
    -use TYPO3\CMS\Core\Pagination\SimplePagination;
     
     /***
      *
    @@ -25,26 +23,16 @@ class ParticipantController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionCont
          * participantRepository
          *
          * @var \Fixpunkt\FpMasterquiz\Domain\Repository\ParticipantRepository
    +     * @TYPO3\CMS\Extbase\Annotation\Inject
          */
         protected $participantRepository = null;
     
    -    /**
    -     * Injects the participant-Repository
    -     *
    -     * @param \Fixpunkt\FpMasterquiz\Domain\Repository\ParticipantRepository $participantRepository
    -     */
    -    public function injectParticipantRepository(\Fixpunkt\FpMasterquiz\Domain\Repository\ParticipantRepository $participantRepository)
    -    {
    -        $this->participantRepository = $participantRepository;
    -    }
    -
         /**
          * action list
          *
    -     * @param int $currentPage
          * @return void
          */
    -    public function listAction(int $currentPage = 1)
    +    public function listAction()
         {
             $pid = (int)GeneralUtility::_GP('id');
             $qid = $this->request->hasArgument('quiz') ? intval($this->request->getArgument('quiz')) : 0;
    @@ -53,20 +41,9 @@ public function listAction(int $currentPage = 1)
             } else {
             	$participants = $this->participantRepository->findFromPid($pid);
             }
    -        if ($participants) {
    -            $participantArray = $participants->toArray();
    -        } else {
    -            $participantArray = [];
    -        }
    -        $participantPaginator = new ArrayPaginator($participantArray, $currentPage, $this->settings['pagebrowser']['itemsPerPage']);
    -        $participantPagination = new SimplePagination($participantPaginator);
    -
             $this->view->assign('pid', $pid);
             $this->view->assign('qid', $qid);
             $this->view->assign('participants', $participants);
    -        $this->view->assign('paginator', $participantPaginator);
    -        $this->view->assign('pagination', $participantPagination);
    -        $this->view->assign('pages', range(1, $participantPagination->getLastPageNumber()));
         }
         
         /**
    @@ -77,22 +54,6 @@ public function listAction(int $currentPage = 1)
          */
         public function detailAction(\Fixpunkt\FpMasterquiz\Domain\Model\Participant $participant)
         {
    -        foreach ($participant->getSelections() as $selection) {
    -            if ($selection->getQuestion()->getQmode() == 8) {
    -                $categoriesArray = [];
    -                foreach ($selection->getQuestion()->getCategories() as $category) {
    -                    $categoriesArray[$category->getUid()] = $category->getTitle();
    -                }
    -                $ownCategoryAnswers = unserialize($selection->getEntered());
    -                foreach ($selection->getAnswers() as $answer) {
    -                    foreach ($ownCategoryAnswers as $key => $ownCategoryAnswer) {
    -                        if ($key == $answer->getUid()) {
    -                            $answer->setOwnCategoryAnswer([$ownCategoryAnswer, $categoriesArray[$ownCategoryAnswer]]);
    -                        }
    -                    }
    -                }
    -            }
    -        }
             $this->view->assign('participant', $participant);
         }
         
    
  • Classes/Controller/QuestionController.php+1 30 modified
    @@ -21,19 +21,10 @@ class QuestionController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
          * questionRepository
          *
          * @var \Fixpunkt\FpMasterquiz\Domain\Repository\QuestionRepository
    +     * @TYPO3\CMS\Extbase\Annotation\Inject
          */
         protected $questionRepository = null;
     
    -    /**
    -     * Injects the question-Repository
    -     *
    -     * @param \Fixpunkt\FpMasterquiz\Domain\Repository\QuestionRepository $questionRepository
    -     */
    -    public function injectQuestionRepository(\Fixpunkt\FpMasterquiz\Domain\Repository\QuestionRepository $questionRepository)
    -    {
    -        $this->questionRepository = $questionRepository;
    -    }
    -
         /**
          * action list
          *
    @@ -55,24 +46,4 @@ public function showAction(\Fixpunkt\FpMasterquiz\Domain\Model\Question $questio
         {
             $this->view->assign('question', $question);
         }
    -
    -    /**
    -     * action move
    -     *
    -     * @param \Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz
    -     * @param \Fixpunkt\FpMasterquiz\Domain\Model\Question $question
    -     * @return void
    -     */
    -    public function moveAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, \Fixpunkt\FpMasterquiz\Domain\Model\Question $question = NULL)
    -    {
    -        $pid = (int)\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('id');
    -        if ($question) {
    -            $this->questionRepository->moveToQuiz($question->getUid(), $quiz->getUid());
    -        }
    -        $questions = $this->questionRepository->findOtherThan($pid, $quiz->getUid());
    -        $this->view->assign('question', $question);
    -        $this->view->assign('questions', $questions);
    -        $this->view->assign('quiz', $quiz);
    -    }
    -
     }
    
  • Classes/Controller/QuizController.php+385 631 modified
    @@ -4,7 +4,6 @@
     use TYPO3\CMS\Core\Utility\GeneralUtility;
     use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
     use TYPO3\CMS\Core\Context\Context;
    -use TYPO3\CMS\Core\Pagination\ArrayPaginator;
     
     /***
      *
    @@ -26,30 +25,34 @@ class QuizController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
          * quizRepository
          *
          * @var \Fixpunkt\FpMasterquiz\Domain\Repository\QuizRepository
    +     * @TYPO3\CMS\Extbase\Annotation\Inject
          */
         protected $quizRepository = null;
     
         /**
          * answerRepository
          *
          * @var \Fixpunkt\FpMasterquiz\Domain\Repository\AnswerRepository
    +     * @TYPO3\CMS\Extbase\Annotation\Inject
          */
         protected $answerRepository = null;
     
         /**
          * participantRepository
          *
          * @var \Fixpunkt\FpMasterquiz\Domain\Repository\ParticipantRepository
    +     * @TYPO3\CMS\Extbase\Annotation\Inject
          */
         protected $participantRepository = null;
         
         /**
          * selectedRepository
          *
          * @var \Fixpunkt\FpMasterquiz\Domain\Repository\SelectedRepository
    +     * @TYPO3\CMS\Extbase\Annotation\Inject
          */
         protected $selectedRepository = null;
    -
    +    
         /**
          * participant
          *
    @@ -61,47 +64,7 @@ class QuizController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
          * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
          */
         protected $configurationManager;
    -
    -    /**
    -     * Injects the quiz-Repository
    -     *
    -     * @param \Fixpunkt\FpMasterquiz\Domain\Repository\QuizRepository $quizRepository
    -     */
    -    public function injectQuizRepository(\Fixpunkt\FpMasterquiz\Domain\Repository\QuizRepository $quizRepository)
    -    {
    -        $this->quizRepository = $quizRepository;
    -    }
    -
    -    /**
    -     * Injects the answer-Repository
    -     *
    -     * @param \Fixpunkt\FpMasterquiz\Domain\Repository\AnswerRepository $answerRepository
    -     */
    -    public function injectAnswerRepository(\Fixpunkt\FpMasterquiz\Domain\Repository\AnswerRepository $answerRepository)
    -    {
    -        $this->answerRepository = $answerRepository;
    -    }
    -
    -    /**
    -     * Injects the selected-Repository
    -     *
    -     * @param \Fixpunkt\FpMasterquiz\Domain\Repository\SelectedRepository $selectedRepository
    -     */
    -    public function injectSelectedRepository(\Fixpunkt\FpMasterquiz\Domain\Repository\SelectedRepository $selectedRepository)
    -    {
    -        $this->selectedRepository = $selectedRepository;
    -    }
    -
    -    /**
    -     * Injects the participant-Repository
    -     *
    -     * @param \Fixpunkt\FpMasterquiz\Domain\Repository\ParticipantRepository $participantRepository
    -     */
    -    public function injectParticipantRepository(\Fixpunkt\FpMasterquiz\Domain\Repository\ParticipantRepository $participantRepository)
    -    {
    -        $this->participantRepository = $participantRepository;
    -    }
    -
    +    
         /**
          * Injects the Configuration Manager and is initializing the framework settings: wird doppelt aufgerufen!
          *
    @@ -126,14 +89,12 @@ public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\Conf
                     if (strpos($fieldName, '.') !== false) {
                         // Multilevel
                         $keyAsArray = explode('.', $fieldName);
    -                    if ((!isset($originalSettings[$keyAsArray[0]][$keyAsArray[1]]) || !($originalSettings[$keyAsArray[0]][$keyAsArray[1]]))
    -                        && isset($tsSettings[$keyAsArray[0] . '.'][$keyAsArray[1]])) {
    +                    if (!($originalSettings[$keyAsArray[0]][$keyAsArray[1]]) && isset($tsSettings[$keyAsArray[0] . '.'][$keyAsArray[1]])) {
                             $originalSettings[$keyAsArray[0]][$keyAsArray[1]] = $tsSettings[$keyAsArray[0] . '.'][$keyAsArray[1]];
                         }
                     } else {
                         // Simple
    -                    if ((!isset($originalSettings[$fieldName]) || !($originalSettings[$fieldName]))
    -                        && isset($tsSettings[$fieldName])) {
    +                    if (!($originalSettings[$fieldName]) && isset($tsSettings[$fieldName])) {
                             $originalSettings[$fieldName] = $tsSettings[$fieldName];
                         }
                     }
    @@ -192,24 +153,73 @@ public function initializeShowByTagAction()
         }
     
         /**
    -     * Sucht einen Teilnehmer und erzeugt ggf. einen
    +     * Prüft, ob eine Session gültig ist: check the session against the request-parameter
    +     *
    +     * @param string $c_debug
    +     * @return boolean
    +     */
    +    public function isSessionOK(string &$c_debug)
    +    {
    +        if ($this->request->hasArgument('session')) {
    +            $tmp_session = $this->request->getArgument('session');
    +        } else {
    +            $tmp_session = '';
    +        }
    +        if ($this->participant->getSession() != $tmp_session) {
    +            $this->participant = null;
    +            if ($this->settings['debug']) {
    +                $c_debug .= "\nParticipant not accepted, because the session from argument is wrong: " . $tmp_session;
    +            }
    +            return false;
    +        }
    +        return true;
    +    }
    +
    +    /**
    +     * action doAll
          *
    -     * @param int $quizUid
    -     * @param int $quizPid
    +     * @param \Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz
    +     * @param int $pages No. of pages if tags are used
          * @return array
          */
    -    public function findParticipant(int $quizUid, int $quizPid)
    +    public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, $pages): array
         {
    -        $session = '';          // session key
    -        $debug = '';
    -        $newUser = false;
    -        $context = GeneralUtility::makeInstance(Context::class);
    -        $fe_user_uid = intval($context->getPropertyFromAspect('frontend.user', 'id'));
    -        if (!$this->settings['ajax']) {
    +    	/* @var \Fixpunkt\FpMasterquiz\Domain\Model\Answer $answer */
    +        $answer = null;
    +        $saveIt = false;
    +    	$newUser = false;
    +    	$reload = false;
    +    	$completed = false;
    +    	$doPersist = false;
    +    	$partBySes = null;
    +    	$questions = 0;
    +    	$maximum1 = 0;
    +    	$session = '';          // session key
    +    	$finalBodytext = '';	// bodytext and image for the final page
    +    	$finalImageuid = 0;     // image for the final page
    +    	$finalContent = '';		// special content for the final page
    +    	$emailAnswers = [];		// special admin email to answer relations
    +    	$specialRecievers = [];	// special admin email recievers
    +    	$debug = '';			// debug output
    +    	$quizUid = $quiz->getUid();
    +    	$questionsPerPage = intval($this->settings['pagebrowser']['itemsPerPage']);
    +    	$showAnswers = $this->request->hasArgument('showAnswers') ? intval($this->request->getArgument('showAnswers')) : 0;
    +    	$useJoker = $this->request->hasArgument('useJoker') ? intval($this->request->getArgument('useJoker')) : 0;
    +        $startTime = $this->request->hasArgument('startTime') ? intval($this->request->getArgument('startTime')) : 0;
    +    	$context = GeneralUtility::makeInstance(Context::class);
    +    	$fe_user_uid = intval($context->getPropertyFromAspect('frontend.user', 'id'));
    +   		$persistenceManager = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\PersistenceManager');
    +        $isAjax = $this->settings['ajax'];
    +        if ($this->settings['debug'] && $isAjax) {
    +            $debug .= "\nAjax mode is enabled.";
    +        }
    +
    +//        if (!$this->settings['ajax']) {
                 if ($this->request->hasArgument('session')) {
    +                // wir dürften nicht auf der Startseite sein, außer beim 1. Ajax-call
                     $session = $this->request->getArgument('session');
    -            } else if (!$this->request->hasArgument('participant')) {
    -                // keine Session gefunden... und jetzt Cookie checken?
    +            } else if (!$this->request->hasArgument('participant') && !$isAjax) {
    +                // keine Session gefunden... und jetzt Cookie checken? Hier dürften wir auf der Startseite sein
                     if (intval($this->settings['user']['useCookie']) == -1) {
                         $session = $GLOBALS["TSFE"]->fe_user->getKey('ses', 'qsession' . $quizUid);
                     } else if ((intval($this->settings['user']['useCookie']) > 0) && isset($_COOKIE['qsession' . $quizUid])) {
    @@ -235,128 +245,73 @@ public function findParticipant(int $quizUid, int $quizPid)
                             }
                         }
                         if (!$session) {
    -                        $session = uniqid(random_int(1000, 9999));
    -                        $newUser = true;
                             $this->participant = null;
                             if ($this->settings['debug']) {
    -                            $debug .= "\ncreating new session: " . $session;
    +                            $debug .= "\nNo session found, will creating a new participant...";
                             }
                         }
                     }
                 }
    -            if (intval($this->settings['user']['useCookie']) == -1) {
    -                // Store the session in a cookie
    -                $GLOBALS['TSFE']->fe_user->setKey('ses', 'qsession' . $quizUid, $session);
    -                $GLOBALS["TSFE"]->fe_user->storeSessionData();
    -            } else if (intval($this->settings['user']['useCookie']) > 0) {
    -                setcookie('qsession' . $quizUid, $session, time() + (3600 * 24 * intval($this->settings['user']['useCookie'])));  /* verfällt in x Tagen */
    -            }
    -        }
    +//        }
     
    -        if ($this->request->hasArgument('participant') && $this->request->getArgument('participant')) {
    -            // wir sind nicht auf Seite 1
    -            $participantUid = intval($this->request->getArgument('participant'));
    -            if ($this->settings['user']['useQuizPid']) {
    -                $this->participant = $this->participantRepository->findOneByUidAndPid($participantUid, $quizPid);
    -            } else {
    -                $this->participant = $this->participantRepository->findOneByUid($participantUid);
    +    	if ($this->request->hasArgument('participant') && $this->request->getArgument('participant')) {
    +    		// wir sind nicht auf Seite 1
    +    		$participantUid = intval($this->request->getArgument('participant'));
    +    		$this->participant = $this->participantRepository->findOneByUid($participantUid);
    +    		$session = $this->participant->getSession();
    +            if ($session && !$this->isSessionOK($debug)) {
    +                $participantUid = 0;
                 }
    -            if ($this->participant) {
    -                $session = $this->participant->getSession();
    -                if ($this->settings['debug']) {
    -                    $debug .= "\nparticipant from request: " . $participantUid;
    -                }
    +            if ($this->settings['debug'] && $participantUid) {
    +                $debug .= "\nParticipant from request: " . $participantUid . ' with session: ' . $session;
                 }
    -        }
    +    	}
             if (!$this->participant) {
                 $this->participant = GeneralUtility::makeInstance('Fixpunkt\\FpMasterquiz\\Domain\\Model\\Participant');
    -            $this->participant->_setProperty('_languageUid', -1);
                 if ($this->settings['debug']) {
    -                $debug .= "\nMaking new participant.";
    -            }
    -            if ($this->settings['user']['useQuizPid']) {
    -                $this->participant->setPid($quizPid);
    -                if ($this->settings['debug']) {
    -                    $debug .= ' Set pid to ' . $quizPid;
    -                }
    -            }
    -            if ($this->settings['random'] && $this->request->hasArgument('randomPages') && $this->request->getArgument('randomPages')) {
    -                $this->participant->setRandompages(explode(',', $this->request->getArgument('randomPages')));
    -                if ($this->settings['debug']) {
    -                    $debug .= " Set random pages: " . $this->request->getArgument('randomPages');
    -                }
    +                $debug .= "\nmaking new participant.";
                 }
                 if (!$session) {
    +                // ggf. wird die Session von der Startseite beibehalten
                     $session = uniqid(random_int(1000, 9999));
    +                $this->participant->setSession($session);
                     $newUser = true;
                     if ($this->settings['debug']) {
                         $debug .= "\ncreating new session: " . $session;
                     }
                 }
             }
    -        $result = [];
    -        $result['session'] = $session;
    -        $result['newUser'] = $newUser;
    -        $result['fe_user_uid'] = $fe_user_uid;
    -        $result['debug'] = $debug;
    -        return $result;
    -    }
    -
    -    /**
    -     * action doAll
    -     *
    -     * @param \Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz
    -     * @param array $userData Some user data in an array
    -     * @param int $pages No. of pages if tags are used
    -     * @param array $randomNumbers Random page numbers
    -     * @return array
    -     */
    -    public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $userData, int $pages, array $randomNumbers): array
    -    {
    -    	$saveIt = false;
    -    	$reload = false;
    -        $mandatoryNotAnswered = false;
    -    	$doPersist = false;
    -    	$partBySes = null;
    -    	$maximum1 = 0;              // maximum points
    -    	$finalBodytext = '';	    // bodytext and image for the final page
    -    	$finalImageuid = 0;         // image for the final page
    -    	$finalContent = '';		    // special content for the final page
    -        $finalCategoryArray = [];   // Auswertung der angeklickten Kategorien
    -    	$emailAnswers = [];		    // special admin email to answer relations
    -    	$specialRecievers = [];	    // special admin email recievers
    -    	$debug = $userData['debug'];	    // debug output
    -        $session = $userData['session'];    // session key
    -        $newUser = $userData['newUser'];	// is a new user?
    -        $fe_user_uid = $userData['fe_user_uid'];	// FE user uid
    -    	$quizPid = $quiz->getPid();
    -        $phpFormCheck = $this->settings['phpFormCheck'];
    -    	$questionsPerPage = intval($this->settings['pagebrowser']['itemsPerPage']);
    -    	$showAnswers = $this->request->hasArgument('showAnswers') ? intval($this->request->getArgument('showAnswers')) : 0;
    -    	$useJoker = $this->request->hasArgument('useJoker') ? intval($this->request->getArgument('useJoker')) : 0;
    -        $startTime = $this->request->hasArgument('startTime') ? intval($this->request->getArgument('startTime')) : 0;
    -        $page = $this->request->hasArgument('currentPage') ? intval($this->request->getArgument('currentPage')) : 1;
    -        $persistenceManager = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\PersistenceManager');
    -    	$reachedPage = $this->participant->getPage();
    -        if (!$questionsPerPage) {
    -            $questionsPerPage = 1;
    -        }
    -        if ($this->settings['allowEdit']) {
    -            if ($this->participant->isCompleted()) {
    -                $showAnswers = true;
    -            } else {
    -                $showAnswers = false;
    +        if (!$isAjax && !$newUser && !$this->participant->getUid()) {
    +            // Cookie nicht schon auf der Startseite setzen, sondern erst und nur auf der Folgeseite
    +            if ($this->settings['debug']) {
    +                $debug .= "\nSetting a cookie with this session: " . $session;
                 }
    -            $showAnswerPage = false;
    -        } else {
    -            if ($reachedPage >= $page) {
    -                // beantwortete Seiten soll man nicht nochmal beantworten können
    -                $showAnswers = true;
    +            if (intval($this->settings['user']['useCookie']) == -1) {
    +                // Store the session in a cookie
    +                $GLOBALS['TSFE']->fe_user->setKey('ses', 'qsession' . $quizUid, $session);
    +                $GLOBALS["TSFE"]->fe_user->storeSessionData();
    +            } else if (intval($this->settings['user']['useCookie']) > 0) {
    +                setcookie('qsession' . $quizUid, $session, time() + (3600 * 24 * intval($this->settings['user']['useCookie'])));  /* verfällt in x Tagen */
                 }
    -            $showAnswerPage = intval($this->settings['showAnswerPage']);
             }
    +
    +    	$page = $this->request->hasArgument('@widget_0') ? $this->request->getArgument('@widget_0') : 1;
    +    	if (is_array($page)) {
    +    		$page = intval($page['currentPage']);
    +    	} else {
    +    		$page = $this->request->hasArgument('currentPage') ? intval($this->request->getArgument('currentPage')) : 1;
    +    	}
    +    	$reachedPage = $this->participant->getPage();
    +    	if ($reachedPage >= $page) {
    +    		// beantwortete Seiten soll man nicht nochmal beantworten können
    +    		$showAnswers = true;
    +    	}
    +    	if (!$questionsPerPage) {
    +    		$questionsPerPage = 1;
    +    	}
    +    	$showAnswerPage = intval($this->settings['showAnswerPage']);
         	if ($showAnswerPage && !$showAnswers) {
    -    		// als Nächstes erstmal die Antworten dieser Seite zeigen
    +    		// als nächstes erstmal die Antworten dieser Seite zeigen
         		$nextPage = $page;
         	} else {
         		$nextPage = $page + 1;
    @@ -369,8 +324,8 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
         	$questions = count($quiz->getQuestions());
         	if ($showAnswers || (!$showAnswerPage && $page > 1)) {
         		// Antworten sollen ausgewertet und gespeichert werden
    -    		if (($reachedPage < $page) || $this->settings['allowEdit']) {
    -    			// nur nicht beantwortete Seiten speichern, es sei denn allowEdit=1
    +    		if ($reachedPage < $page) {
    +    			// nur nicht beantwortete Seiten speichern
         			$saveIt = true;
         		}
         		if (!$this->participant->getUid()) {
    @@ -409,22 +364,19 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
     	    			$this->participant->setName($defaultName);
     	    			$this->participant->setEmail($defaultEmail);
     	    			$this->participant->setHomepage($defaultHomepage);
    -	    			$this->participant->setUser(isset($GLOBALS['TSFE']->fe_user->user['uid']) ? intval($GLOBALS['TSFE']->fe_user->user['uid']) : 0);
    +	    			$this->participant->setUser(intval($GLOBALS['TSFE']->fe_user->user['uid']));
     	    			$this->participant->setIp($this->getRealIpAddr());
     	    			$this->participant->setSession($session);
                         if ($startTime) {
                             $this->participant->setSessionstart(time() - $startTime);
    -                    }
    -                    if ($this->settings['random'] && count($randomNumbers)>1) {
    -                        $this->participant->setRandompages($randomNumbers);
                         }
     	    			$this->participant->setQuiz($quiz);
     	    			$this->participant->setMaximum2($quiz->getMaximum2());
     	    			$this->participantRepository->add($this->participant);
     	    			$persistenceManager->persistAll();
     	    			$newUser = true;
     	    			if ($this->settings['debug']) {
    -	    				$debug .= "\nNew participant created: " . $this->participant->getUid();
    +	    				$debug .= "\nNew participant created: " . $this->participant->getUid(). ', with session: ' . $session;
         				}
         			}
         		}
    @@ -439,69 +391,47 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
        				//var_dump($emailAnswers);
         		}
         		$i = 0;
    -    		// cycle through all questions after a form-submit
    +    		// cycle through all questions after a submit
         		foreach ($quiz->getQuestions() as $question) {
         			$quid = $question->getUid();
         			$debug .= "\n#" . $quid . '#: ';
         			if ($this->request->hasArgument('quest_' . $quid) && $this->request->getArgument('quest_' . $quid)) {
         				$isActive = true;
    -    			} else if (isset($_POST['quest_' . $quid]) || isset($_GET['quest_' . $quid])) {
    -    				// Ajax-call is without extension-name :-(
    +    			} else if ($_POST['quest_' . $quid] || $_GET['quest_' . $quid]) {
    +    				// Ajax-call is without extensionname :-(
         				$isActive = true;
         			} else {
         				$isActive = false;
         			}
    -    			if ($isActive) {
    +    			if ($isActive) {	
         				// Auswertung der abgesendeten Fragen
    -                    $vorhanden = 0;
         				if (!$newUser) {
         					// zuerst prüfen, ob dieser Eintrag schon existiert (z.B. durch Reload)
         					$vorhanden = $this->selectedRepository->countByParticipantAndQuestion($this->participant->getUid(), $quid);
         				}
    -    				if (($vorhanden > 0) && !$this->settings['allowEdit']) {
    -    					$debug .= ' reload!? ';
    +    				if ($vorhanden > 0) {
    +    					$debug .= ' reload! ';
         				} else {
    -                        $qmode = $question->getQmode();
    -                        $isOptional = ($this->settings['noFormCheck'] || $question->isOptional() || $qmode==4 || $qmode==7) ? true : false;
    -                        if ($this->settings['debug']) {
    -                            $debug .= ' OK ' . (($isOptional) ? 'optional: ' : 'mandatory: ');
    -                        }
    +	    				$debug .= ' OK ';
     	    				// selected/answered question
    -                        if ($vorhanden) {
    -                            // alten Eintrag erst löschen
    -                            //$this->selectedRepository->deleteByParticipantAndQuestion($this->participant->getUid(), $quid);
    -                            $oldSelection = $this->selectedRepository->findByParticipantAndQuestion($this->participant->getUid(), $quid);
    -                            if ($oldSelection) {
    -                                $oldPoints = $oldSelection->getPoints();
    -                                $this->participant->subtractPoints($oldPoints);
    -                                $this->participant->removeSelection($oldSelection);
    -                            }
    -                        }
    -                        $selected = GeneralUtility::makeInstance('Fixpunkt\\FpMasterquiz\\Domain\\Model\\Selected');
    -                        $selected->_setProperty('_languageUid', -1);
    -                        if ($this->settings['user']['useQuizPid']) {
    -                            $selected->setPid($quizPid);
    -                        }
    -                        $selected->setQuestion($question);
    -                        if ($pages) {
    -                            // bei Verwendung von Tags kann die Reihenfolge nicht mit der Reihenfolge der Fragen übereinstimmen
    -                            $sorting = $page * 100 + $i;
    +	    				$selected = GeneralUtility::makeInstance('Fixpunkt\\FpMasterquiz\\Domain\\Model\\Selected');
    +	    				$selected->setQuestion($question);
    +	    				if ($pages) {
    +	    				    // bei Verwendung von Tags kann die Reihenfolge nicht mit der Reihenfolge der Fragen übereinstimmen
    +	    				    $sorting = $page*100 + $i;
                             } else {
    -                            // Reihenfolge der Fragen übernehmen
    -                            $sorting = $question->getSorting();
    +	    				    // Reihenfolge der Fragen übernehmen
    +	    				    $sorting = $question->getSorting();
                             }
    -                        $selected->setSorting($sorting);
    -                        $selectedWithAnswer = false;
    -                        $qmode8Answers = [];
    +	    				$selected->setSorting($sorting);
    +	    				$qmode = $question->getQmode();
     	    				$newPoints = 0;
     	    				switch ($qmode) {
     	    					case 0:
     	    					case 4:
    -                            case 8:
    -	    					    // Checkbox, ja/nein und Kategorie-Matrix
    +	    					    // Checkbox und ja/nein
     	    						foreach ($question->getAnswers() as $answer) {
     	    							$auid = $answer->getUid();
    -                                    $selectedCategoryUid = 0;
     	    							if ($this->request->hasArgument('answer_' . $quid . '_' . $auid) && $this->request->getArgument('answer_' . $quid . '_' . $auid)) {
     	    								$selectedAnswerUid = intval($this->request->getArgument('answer_' . $quid . '_' . $auid));
     	    							} else if ($_POST['answer_' . $quid . '_' . $auid]) {
    @@ -511,33 +441,12 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
     	    							} else {
     	    								$selectedAnswerUid = -1;
     	    							}
    -                                    if ($selectedAnswerUid > 0) {
    -                                        if ($qmode == 8) {
    -                                            // im Matrix-Modus wird eine Kategorie-UID übermittelt!
    -                                            $selectedCategoryUid = $selectedAnswerUid;
    -                                            $selectedAnswerUid = $auid;
    -                                            $qmode8Answers[$auid] = $selectedCategoryUid;
    -                                            // für propertiesSent wird die eigene Antwort benötigt
    -                                            foreach ($question->getCategories() as $oneCategory) {
    -                                                if ($oneCategory->getUid() == $selectedCategoryUid) {
    -                                                    $answer->setOwnCategoryAnswer([$selectedCategoryUid,$oneCategory->getTitle()]);
    -                                                    break;
    -                                                }
    -                                            }
    -                                        } elseif ($selectedAnswerUid != $auid) {
    -                                            // dies sollte nie der Fall sein, deshalb erlauben wir das nicht
    -                                            $selectedAnswerUid = -1;
    -                                        }
    -                                    }
     	    							if ($this->settings['debug']) {
     	    								$debug .= $quid . '_' . $auid . '-' . $selectedAnswerUid . ' ';
     	    							}
     	    							if ($selectedAnswerUid > 0) {
    -                                        // für PHP-check; im FE müssen Eingaben im Fehlerfall übernommen werden
    -                                        $answer->setOwnAnswer(1);
    -                                        // wir brauchen theoretisch kein select mehr, denn die aktuelle Antwort ist die ausgewählte!
    -	    								//$selectedAnswer = $this->answerRepository->findByUid($selectedAnswerUid);
    -	    								$newPoints = $answer->getPoints();
    +	    								$selectedAnswer = $this->answerRepository->findByUid($selectedAnswerUid);
    +	    								$newPoints = $selectedAnswer->getPoints();
     		    							// halbierte Punkte setzen? Ändert aber die echte Antwort!
     	    								// so nicht: $selectedAnswer->setPoints($newPoints);
     	    								if ($newPoints != 0) {
    @@ -551,16 +460,14 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
     	    										$debug .= $newPoints . 'P ';
     	    									}
     	    								}
    -		    							$selected->addAnswer($answer);
    -                                        $selectedWithAnswer = true;
    +		    							$selected->addAnswer($selectedAnswer);
     		    							if ($emailAnswers[$quid][$auid]) {
     		    								$specialRecievers[$emailAnswers[$quid][$auid]['email']] = $emailAnswers[$quid][$auid];
     		    							}
     	    							}
    +	    							// statt hier nun nach der Schleife: $maximum1 += $answer->getPoints();
     	    						}
    -	    						if (!$vorhanden) {
    -                                    $maximum1 += $question->getMaximum1();
    -                                }
    +	    						$maximum1 += $question->getMaximum1();
     	    						break;
     	    					case 1:
     	    					case 2:
    @@ -578,10 +485,9 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
     	    						if ($this->settings['debug']) {
     	    							$debug .= $quid . '-' . $selectedAnswerUid . ' ';
     	    						}
    -	    						if ($selectedAnswerUid) {
    -                                    $selectedAnswer = $this->answerRepository->findByUid($selectedAnswerUid);
    -                                    $selectedAnswer->setOwnAnswer(1);       // für PHP-check
    -                                    if ($qmode == 7) {
    +	    						if ($selectedAnswerUid) { // Alternative: && $qmode != 4) {
    +	    							$selectedAnswer = $this->answerRepository->findByUid($selectedAnswerUid);
    +	    							if ($qmode == 7) {
     	    								$cycle = count($question->getAnswers());
     	    								foreach ($question->getAnswers() as $answer) {
     	    									if ($answer->getUid() == $selectedAnswerUid) {
    @@ -606,83 +512,48 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
     	    								}
     	    							}
     	    							$selected->addAnswer($selectedAnswer);
    -                                    $selectedWithAnswer = true;
    -	    							if (isset($emailAnswers[$quid][$selectedAnswerUid])) {
    +	    							if ($emailAnswers[$quid][$selectedAnswerUid]) {
     	    								$specialRecievers[$emailAnswers[$quid][$selectedAnswerUid]['email']] = $emailAnswers[$quid][$selectedAnswerUid];
     	    							}
     	    						}
    -                                if (!$vorhanden) {
    -                                    $maximum1 += $question->getMaximum1();
    -                                }
    +	    						$maximum1 += $question->getMaximum1();
     	    						break;
                                 case 3:
                                 case 5:
                                     // When enter an answer in a textbox: try to evaluate the answer of the textbox
    -	    					    $tmpMaximum1 = $this->evaluateInputTextAnswerResult($quid, $question, $selected, $debug);
    -                                if ($phpFormCheck && $selected->getEntered()) {
    -                                    $selectedWithAnswer = true;
    -                                    // für PHP-check: im FE werden die Eingaben im Fehlerfall benötigt
    -                                    $ownAnswer = [];
    -                                    $ownAnswer[] = $selected->getEntered();
    -                                    $question->setTextAnswers($ownAnswer);
    -                                }
    -                                if (!$vorhanden) {
    -                                    $maximum1 += $tmpMaximum1;
    -                                }
    +	    					    $this->evaluateInputTextAnswerResult($quid, $question, $selected, $debug, $maximum1);
     	    					    break;
                                 default:
                                     // hier passiert nichts
     	    				}
    -                        if ($phpFormCheck && !$isOptional && !$selectedWithAnswer) {
    -                            if ($this->settings['debug']) {
    -                                $debug .= "\n!!! Mandatory question not answered !!!";
    -                            }
    -                            $mandatoryNotAnswered = true;
    -                        } else {
    -                            if ($qmode == 8) {
    -                                // Die Kategorieauswahl wird als Text gespeichert :-(
    -                                $selected->setEntered(serialize($qmode8Answers));
    -                            }
    -                            // assign the selected dataset to the participant
    -                            $this->participant->addSelection($selected);
    -                        }
    +	    				// assign the selected dataset to the participant
    +	    				$this->participant->addSelection($selected);
         				}
         			}
         			$i++;
         		}
    -            if (!$mandatoryNotAnswered) {
    -                // Update the participant result
    -                if ($maximum1 > 0) {
    -                    $this->participant->addMaximum1($maximum1);
    -                }
    -                $this->participant->setPage($lastPage);
    -                $this->participantRepository->update($this->participant);
    -                //$doPersist = true;
    -                // better persist data before evaluation!
    -                $persistenceManager->persistAll();
    -            }
    +    		// Update the participant result
    +    		if ($maximum1 > 0) {
    +    			$this->participant->addMaximum1($maximum1);
    +    		}
    +    		$this->participant->setPage($lastPage);
    +    		$this->participantRepository->update($this->participant);
    +    		$doPersist = true;
         	}
         	if (!$pages) {
                 $pages = intval(ceil($questions / $questionsPerPage));
             }
    +    	if ($this->settings['debug']) {
    +    		$debug .= "\nlast page: ".$lastPage.'; page: '.$page.'; reached page before: '.$reachedPage.'; next page: '.$nextPage.'; showAnswers: '.$showAnswers;
    +    		$debug .= "\nqs/qpp=pages#" . $questions . '/' . $questionsPerPage . '=' . $pages;
    +            $debug .= "\ntime period=" . $quiz->getTimeperiod() . '; time passed: ' . $this->participant->getTimePassed();
    +    	}
     
    -        if (!$mandatoryNotAnswered) {
    -            // toggle mode for show answers after submit questions
    -            if ($showAnswerPage) {
    -                $showAnswersNext = $showAnswers == 1 ? 0 : 1;
    -            } else {
    -                $showAnswersNext = 0;
    -            }
    +        // toggle mode for show answers after submit questions
    +        if ($showAnswerPage) {
    +            $showAnswersNext = $showAnswers == 1 ? 0 : 1;
             } else {
    -            // benötigte Felder wurden nicht ausgefüllt
    -            $showAnswers = 0;
    -            $nextPage = $this->request->hasArgument('currentPage') ? intval($this->request->getArgument('currentPage')) : 1;
    -            if ($showAnswerPage) {
    -                $showAnswersNext = 1;
    -            } else {
    -                $showAnswersNext = 0;
    -                $nextPage++;
    -            }
    +            $showAnswersNext = 0;
             }
     
             if (!$showAnswers && $quiz->getTimeperiod() && ($this->participant->getTimePassed() >= $quiz->getTimeperiod())) {
    @@ -691,44 +562,19 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
                 $nextPage = $page;
             }
     
    -        if ($this->settings['debug']) {
    -            $debug .= "\nlast page: ".$lastPage.'; page: '.$page.'; reached page before: '.$reachedPage.'; next page: '.$nextPage.'; showAnswers: '.$showAnswers.'; showAnswersNext: '.$showAnswersNext;
    -            $debug .= "\nqs/qpp=pages#" . $questions . '/' . $questionsPerPage . '=' . $pages;
    -            $debug .= "\ntime period=" . $quiz->getTimeperiod() . '; time passed: ' . $this->participant->getTimePassed();
    -        }
    -
         	if ($page > $pages) {
         		// finale Auswertung ...
         		$final = 1;
                 $showAnswersNext = 0;
         		foreach ($quiz->getEvaluations() as $evaluation) {
    -                $categories = $evaluation->getCategories();
    -                $categoryUid = 0;
    -                $finalCategory = 0;
    -                $finalPoints = 0;
    -                if ($categories->count()) {
    -                    foreach ($categories as $category) {
    -                        $categoryUid = $category->getUid();
    -                        break;
    -                    }
    -                    if ($categoryUid) {
    -                        if (!isset($finalCategoryArray['uid'])) {
    -                            // hole die am meisten angeklickte Kategorie + andere Daten nur einmal
    -                            $finalCategoryArray = $this->participant->getCategoryMost();
    -                        }
    -                        $finalCategory = $finalCategoryArray['uid'];
    -                    }
    -                } else {
    -                    if (!$evaluation->isEvaluate()) {
    -                        // Punkte auswerten
    -                        $finalPoints = $this->participant->getPoints();
    -                    } else {
    -                        // Prozente auswerten
    -                        $finalPoints = $this->participant->getPercent2();
    -                    }
    -                }
    -    			if (($categoryUid && $finalCategory==$categoryUid) ||
    -                    (!$categoryUid && ($finalPoints >= $evaluation->getMinimum()) && ($finalPoints <= $evaluation->getMaximum()))) {
    +    			if (!$evaluation->isEvaluate()) {
    +    				// Punkte auswerten
    +    				$final_points = $this->participant->getPoints();
    +    			} else {
    +    				// Prozente auswerten
    +    				$final_points = $this->participant->getPercent2();
    +    			}
    +    			if (($final_points >= $evaluation->getMinimum()) && ($final_points <= $evaluation->getMaximum())) {
         				// Punkte-Match
         				if ($evaluation->getPage() > 0) {
         					// Weiterleitung zu diese Seite
    @@ -740,11 +586,10 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
         				} else if ($evaluation->getCe() > 0) {
         					// Content-Element ausgeben
         					// oder so: https://www.andrerinas.de/tutorials/typo3-viewhelper-zum-rendern-von-tt-content-anhand-der-uid.html
    -    					$ttContentConfig = [
    +    					$ttContentConfig = array(
         							'tables'       => 'tt_content',
         							'source'       => $evaluation->getCe(),
    -    							'dontCheckPid' => 1
    -                        ];
    +    							'dontCheckPid' => 1);
         					$finalContent = $this->objectManager->get('TYPO3\CMS\Frontend\ContentObject\RecordsContentObject')->render($ttContentConfig);
         					$finalBodytext = $evaluation->getBodytext();
         					$finalImageuid = $evaluation->getImage();
    @@ -762,54 +607,17 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
         		    // alle Fragen durchgehen, die der User beantwortet hat:
         		    foreach ($this->participant->getSortedSelections() as $selection) {
         		        $oneQuestion = $selection->getQuestion();
    -                    if ($oneQuestion->getQmode() == 8) {
    -                        $oneQuestionCategories = $oneQuestion->getCategoriesArray();
    -                    } else {
    -                        $oneQuestionCategories = [];
    -                    }
                         $debug .= $this->setAllUserAnswersForOneQuestion($oneQuestion, 0,false);
                         // eigene Ergebnisse durchgehen
                         $ownResults = [];
                         foreach ($selection->getAnswers() as $oneAnswer) {
                             if ($this->settings['debug']) {
                                 $debug .= "\n own:" . $oneAnswer->getTitle() . ': ' . $oneAnswer->getPoints() . "P";
                             }
    -                        if (isset($ownResults[$oneAnswer->getUid()])) {
    -                            $ownResults[$oneAnswer->getUid()]++;
    -                        } else {
    -                            $ownResults[$oneAnswer->getUid()] = 1;
    -                        }
    +                        $ownResults[$oneAnswer->getUid()]++;
                         }
                         foreach ($oneQuestion->getAnswers() as $oneAnswer) {
    -                        $own = 0;
    -                        if (isset($ownResults[$oneAnswer->getUid()])) {
    -                            $own = intval($ownResults[$oneAnswer->getUid()]);
    -                        }
    -                        $oneAnswer->setOwnAnswer ($own);
    -                        if ($oneQuestion->getQmode() == 8) {
    -                            $ownCategoryAnswers = unserialize($selection->getEntered());
    -                            foreach ($ownCategoryAnswers as $key => $ownCategoryAnswer) {
    -                                if ($key == $oneAnswer->getUid()) {
    -                                    $oneAnswer->setOwnCategoryAnswer([$ownCategoryAnswer, $oneQuestionCategories[$ownCategoryAnswer]]);
    -                                }
    -                            }
    -                        }
    -                    }
    -    		    }
    -    		} elseif ($this->settings['showOwnAnswers']) {
    -                // alle Fragen durchgehen, die der User beantwortet hat:
    -    		    foreach ($this->participant->getSortedSelections() as $selection) {
    -                    $oneQuestion = $selection->getQuestion();
    -                    if ($oneQuestion->getQmode() == 8) {
    -                        $oneQuestionCategories = $oneQuestion->getCategoriesArray();
    -                        $ownCategoryAnswers = unserialize($selection->getEntered());
    -                        foreach ($oneQuestion->getAnswers() as $oneAnswer) {
    -                            foreach ($ownCategoryAnswers as $key => $ownCategoryAnswer) {
    -                                if ($key == $oneAnswer->getUid()) {
    -                                    $oneAnswer->setOwnCategoryAnswer([$ownCategoryAnswer, $oneQuestionCategories[$ownCategoryAnswer]]);
    -                                }
    -                            }
    -                        }
    +                        $oneAnswer->setOwnAnswer (intval($ownResults[$oneAnswer->getUid()]));
                         }
         		    }
         		}
    @@ -880,7 +688,7 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
         	if ($doPersist) {
         		$persistenceManager->persistAll();
             }
    -    	return [
    +    	$data = [
        			'page' => $page,
        			'pages' => $pages,
                 'lastPage' => $lastPage,
    @@ -890,59 +698,30 @@ public function doAll(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz, array $use
        			'finalContent' => $finalContent,
         		'finalBodytext' => $finalBodytext,
         		'finalImageuid' => $finalImageuid,
    -            'finalCategories' => $finalCategoryArray,
        			'showAnswers' => $showAnswers,
         	    'showAnswersNext' => $showAnswersNext,
         	    'useJoker' => $useJoker,
    -            'mandatoryNotAnswered' => $mandatoryNotAnswered,
         		'session' => $session,
        			'debug' => $debug
         	];
    +    	return $data;
         }
    -
    -    /**
    -     * Update user data after the final page
    -     */
    -    protected function checkForClosure() : bool
    -    {
    -        $page = $this->request->hasArgument('currentPage') ? intval($this->request->getArgument('currentPage')) : 1;
    -        if (($page == 999) && ($this->settings['user']['askForData'] == 3) && $this->settings['closurePageUid'] &&
    -            $this->request->hasArgument('participant') && $this->request->getArgument('participant')) {
    -            $participantUid = intval($this->request->getArgument('participant'));
    -            $this->participant = $this->participantRepository->findOneByUid($participantUid);
    -            if ($this->request->hasArgument('name') && $this->request->getArgument('name')) {
    -                $this->participant->setName($this->request->getArgument('name'));
    -            }
    -            if ($this->request->hasArgument('email') && $this->request->getArgument('email')) {
    -                $this->participant->setEmail($this->request->getArgument('email'));
    -            }
    -            if ($this->request->hasArgument('homepage') && $this->request->getArgument('homepage')) {
    -                $this->participant->setHomepage($this->request->getArgument('homepage'));
    -            }
    -            $this->participantRepository->update($this->participant);
    -            $persistenceManager = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\PersistenceManager');
    -            $persistenceManager->persistAll();
    -            return true;
    -        } else {
    -            return false;
    -        }
    -    }
    -
    +    
         /**
          * Try to evaluate the answer of an Input Textbox 
          * 
          * @param int $i_quid The Question ID
          * @param \Fixpunkt\FpMasterquiz\Domain\Model\Question $i_question The Question dataset
          * @param \Fixpunkt\FpMasterquiz\Domain\Model\Selected $c_selected The Selected dataset
          * @param string $c_debug Debug
    -     * @return int The max. possible points until the current question
    +     * @param int $c_maximum1 The max. possible points until the current question
          */
         protected function evaluateInputTextAnswerResult(int $i_quid, 
                                                        \Fixpunkt\FpMasterquiz\Domain\Model\Question $i_question, 
                                                        \Fixpunkt\FpMasterquiz\Domain\Model\Selected &$c_selected,
    -                                                   string &$c_debug)
    +                                                   string &$c_debug,
    +                                                   int &$c_maximum1)
         {
    -        $maximum1 = 0;
             // retreive answer over the GET arguments
             if ($this->request->hasArgument('answer_text_' . $i_quid) && $this->request->getArgument('answer_text_' . $i_quid)) {
                 $answerText = $this->request->getArgument('answer_text_' . $i_quid);
    @@ -976,7 +755,7 @@ protected function evaluateInputTextAnswerResult(int $i_quid,
                 
                 if ($i_question->getQmode() == 3) {
     	            // sum the the points of the current answer to the max. possible point until the current question
    -                $maximum1 += $answer->getPoints();
    +	            $c_maximum1 += $answer->getPoints();
     	            
     	            // if the answer is right
     	            if (strtoupper(trim($answer->getTitle())) == strtoupper(trim($answerText))) {
    @@ -989,7 +768,6 @@ protected function evaluateInputTextAnswerResult(int $i_quid,
     	            }
     	        }
             }
    -        return $maximum1;
         }
         
         /**
    @@ -1051,7 +829,6 @@ protected function setAllUserAnswersForOneQuestion(\Fixpunkt\FpMasterquiz\Domain
             $votesTotal = 0;
             $debug = '';
             $allResults = [];
    -        //$allCategoryResults = [];
             $questionID = $oneQuestion->getUid();
             $isEnterQuestion = (($oneQuestion->getQmode() == 3) || ($oneQuestion->getQmode() == 5));
             if ($this->settings['debug']) {
    @@ -1071,27 +848,7 @@ protected function setAllUserAnswersForOneQuestion(\Fixpunkt\FpMasterquiz\Domain
                         $debug .= "\n all: " . $oneAnswer->getTitle() . ': ' . $oneAnswer->getPoints() . "P";
                     }
                     if (($isEnterQuestion && ($aSelectedQuestion->getEntered() == $oneAnswer->getTitle())) || !$isEnterQuestion) {
    -                    if (isset($allResults[$oneAnswer->getUid()])) {
    -                        $allResults[$oneAnswer->getUid()]++;
    -                    } else {
    -                        $allResults[$oneAnswer->getUid()] = 1;
    -                    }
    -                    /* TODO:
    -                    if ($oneQuestion->getQmode() == 8) {
    -                        // ausgewählte Kategorien einer Antwort
    -                        $catAnswers = unserialize($aSelectedQuestion->getEntered());
    -                        foreach ($catAnswers as $key => $value) {
    -                            if (!is_array($allCategoryResults[$key])) {
    -                                $allCategoryResults[$key] = [];
    -                            }
    -                            if (isset($allCategoryResults[$key][$value])) {
    -                                $allCategoryResults[$key][$value]++;
    -                            } else {
    -                                $allCategoryResults[$key][$value] = 1;
    -                            }
    -                        }
    -                    }
    -                    */
    +                    $allResults[$oneAnswer->getUid()]++;
                     } else if ($be) {
                         // Text-Antworten anderer interessieren uns nur im Backend
                         if (!is_array($allResults['text'])) {
    @@ -1100,17 +857,13 @@ protected function setAllUserAnswersForOneQuestion(\Fixpunkt\FpMasterquiz\Domain
                         if (!is_array($allResults['text'][$aSelectedQuestion->getEntered()])) {
                             $allResults['text'][$aSelectedQuestion->getEntered()] = [];
                         }
    -                    if (isset($allResults['text'][$aSelectedQuestion->getEntered()]['sum'])) {
    -                        $allResults['text'][$aSelectedQuestion->getEntered()]['sum']++;
    -                    } else {
    -                        $allResults['text'][$aSelectedQuestion->getEntered()]['sum'] = 1;
    -                    }
    +                    $allResults['text'][$aSelectedQuestion->getEntered()]['sum']++;
                     }
                 }
             }
    -        // gesammeltes speichern bei: alle möglichen Antworten einer Frage...
    +        // gesammeltes speichern bei: alle möglichen Antworten einer Frage und Prozentwerte setzen
             foreach ($oneQuestion->getAnswers() as $oneAnswer) {
    -            $thisVotes = isset($allResults[$oneAnswer->getUid()]) ? intval($allResults[$oneAnswer->getUid()]) : 0;
    +            $thisVotes = intval($allResults[$oneAnswer->getUid()]);
                 $votesTotal += $thisVotes;
                 if ($be && $isEnterQuestion && is_array($allResults) && is_array($allResults['text'])) {
                     // bei Text-Antworten alle Textantworten berücksichtigen
    @@ -1122,9 +875,8 @@ protected function setAllUserAnswersForOneQuestion(\Fixpunkt\FpMasterquiz\Domain
                 }
                 $oneAnswer->setAllAnswers($thisVotes);
             }
    -        // ... und Prozentwerte speichern
             foreach ($oneQuestion->getAnswers() as $oneAnswer) {
    -            $thisVotes = isset($allResults[$oneAnswer->getUid()]) ? intval($allResults[$oneAnswer->getUid()]) : 0;
    +            $thisVotes = intval($allResults[$oneAnswer->getUid()]);
                 $percentage = 0;
                 if ($votes) {
                     $percentage = 100 * ($thisVotes / $votes);
    @@ -1134,7 +886,7 @@ protected function setAllUserAnswersForOneQuestion(\Fixpunkt\FpMasterquiz\Domain
                 if ($votesTotal) {
                     $percentage = 100 * ($thisVotes / $votesTotal);
                 }
    -            if ($this->settings['debug']) {
    +            if ($this->settings['debug'] && $votes) {
                     $debug .= "\n percent: 100*" . $thisVotes . '/' . $votes . ' = ' . 100 * ($thisVotes / $votes);
                     $debug .= "\n total percent: 100*" . $thisVotes . '/' . $votesTotal . ' = ' . $percentage;
                 }
    @@ -1182,7 +934,40 @@ protected function setMetatags(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz &$c_quiz
             $meta = $metaTagManager->getManagerForProperty('og:title');
             $meta->addProperty('og:title', $title);
         }
    -    
    +
    +    /**
    +     * Checks if a quiz is allowed
    +     *
    +     * @param integer $pid
    +     * @param integer $uid
    +     * @return boolean
    +     */
    +    public function checkQuizAccess(int $pid, int $uid): bool
    +    {
    +        $storagePidsArray = $this->quizRepository->getStoragePids();
    +        if (is_array($storagePidsArray) && !$storagePidsArray[0] == 0) {
    +            if (!in_array($pid, $storagePidsArray)) {
    +                $this->addFlashMessage(
    +                    LocalizationUtility::translate('error.quizNotFound', 'fp_masterquiz') . ' ' . intval($pid),
    +                    LocalizationUtility::translate('error.error', 'fp_masterquiz'),
    +                    \TYPO3\CMS\Core\Messaging\AbstractMessage::WARNING,
    +                    false
    +                );
    +                return false;
    +            }
    +        }
    +        if ($this->settings['defaultQuizUid'] && $uid!=$this->settings['defaultQuizUid']) {
    +            $this->addFlashMessage(
    +                LocalizationUtility::translate('error.quizNotAllowed', 'fp_masterquiz') . ' ' . intval($uid),
    +                LocalizationUtility::translate('error.error', 'fp_masterquiz'),
    +                \TYPO3\CMS\Core\Messaging\AbstractMessage::WARNING,
    +                false
    +            );
    +            return false;
    +        }
    +        return true;
    +    }
    +
         /**
          * action list
          *
    @@ -1294,45 +1079,38 @@ public function introAction()
          */
         public function showAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
         {
    -        if ($this->checkForClosure()) {
    -            $this->redirect('closure', 'Quiz', NULL, ['participant' => $this->participant], $this->settings['closurePageUid']);
    +        if (!$this->checkQuizAccess($quiz->getPid(), $quiz->getUid())) {
    +            return;
             }
    -        $userData = $this->findParticipant($quiz->getUid(), $quiz->getPid());
    -        $data = $this->doAll($quiz, $userData,0, []);
    +        $data = $this->doAll($quiz,0);
             $page = $data['page'];
             $pages = $data['pages'];
             $languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language');
             $sys_language_uid = $languageAspect->getId();
             if ($this->settings['setMetatags']) {
                 $this->setMetatags($quiz);
             }
    -
    -        if ($quiz->getQuestions()) {
    -            $questionsArray = $quiz->getQuestions()->toArray();
    -        } else {
    -            $questionsArray = [];
    -        }
    -        if ($this->participant && $this->participant->getSelections()) {
    -            $participantArray = $this->participant->getSelections()->toArray();
    -        } else {
    -            $participantArray = [];
    -        }
    -        $quizPaginator = new ArrayPaginator($questionsArray, $page, intval($this->settings['pagebrowser']['itemsPerPage']));
    -        $participantPaginator = new ArrayPaginator($participantArray, $page, intval($this->settings['pagebrowser']['itemsPerPage']));
    -
    +        
    +        $this->view->assign('debug', $data['debug']);
             $this->view->assign('quiz', $quiz);
    -        $this->view->assign('quizPaginator', $quizPaginator);
             $this->view->assign('participant', $this->participant);
    -        $this->view->assign('participantPaginator', $participantPaginator);
    +        $this->view->assign('page', $page);
             if ($pages > 0) {
             	$this->view->assign('pagePercent', intval(round(100*($page/$pages))));
             	$this->view->assign('pagePercentInclFinalPage', intval(round(100*($page/($pages+1)))));
    -        }
    -        foreach ($data as $key => $value) {
    -            $this->view->assign($key, $value);
    -        }
    +        }        
    +        $this->view->assign('nextPage', $data['nextPage']);
    +        $this->view->assign('pages', $pages);
             $this->view->assign('pagesInclFinalPage', ($pages+1));
    +        $this->view->assign('questions', $data['questions']);
             $this->view->assign('pageBasis', ($page-1) * $this->settings['pagebrowser']['itemsPerPage']);
    +        $this->view->assign('final', $data['final']);
    +        $this->view->assign('finalContent', $data['finalContent']);
    +        $this->view->assign('finalBodytext', $data['finalBodytext']);
    +        $this->view->assign('finalImageuid', $data['finalImageuid']);
    +        $this->view->assign('session', $data['session']);
    +        $this->view->assign('showAnswers', $data['showAnswers']);
    +        $this->view->assign('showAnswersNext', $data['showAnswersNext']);
             $this->view->assign("sysLanguageUid", $sys_language_uid);
             $this->view->assign('uidOfPage', $GLOBALS['TSFE']->id);
             $this->view->assign('uidOfCE', $this->configurationManager->getContentObject()->data['uid']);
    @@ -1359,78 +1137,50 @@ public function showAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
          */
         public function showByTagAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
         {
    -        if ($this->checkForClosure()) {
    -            $this->redirect('closure', 'Quiz', NULL, ['participant' => $this->participant], $this->settings['closurePageUid']);
    +        if (!$this->checkQuizAccess($quiz->getPid(), $quiz->getUid())) {
    +            return;
             }
    -        $userData = $this->findParticipant($quiz->getUid(), $quiz->getPid());
             $page = $this->request->hasArgument('currentPage') ? intval($this->request->getArgument('currentPage')) : 1;
             // Suche Fragen passend zu einer Seite (jeweils nur 1 Tag verwendet)
    -        $tagArray = $quiz->getQuestionsSortByTag($page, $this->settings['random'], $this->participant->getRandompages());
    +        $tagArray = $quiz->getQuestionsSortByTag($page);
             $tag = $tagArray['pagetags'][$page];
             $pages = $tagArray['pages'];
    -        $data = $this->doAll($quiz, $userData, $pages, $tagArray['randomNumbers']);
    +        $data = $this->doAll($quiz, $pages);
             $lastPage = $data['lastPage'];
    -        if ($this->settings['allowEdit']) {
    -            $lastPage = $page;
    -        }
             $languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language');
             $sys_language_uid = $languageAspect->getId();
             if ($this->settings['setMetatags']) {
                 $this->setMetatags($quiz);
             }
             if ($lastPage < 1) {
                 $tagSelections = [];
    -        } else if ($data['showAnswers'] || $this->settings['allowEdit']) {
    -            // Antworten vom user suchen
    +        } else {
                 $tagSelections = $this->participant->getSelectionsByTag($tagArray['pagetags'][$lastPage]);
             }
    -        if ($this->settings['debug']) {
    -            $data['debug'] .= "\nTag=$tag; page=$page; pages=$pages; random page order: " . implode(',', $tagArray['randomNumbers']);
    -        }
    -        if ($this->settings['allowEdit']) {
    -            $answeredQuestions = [];
    -            // eigene Antworten holen
    -            foreach ($tagSelections as $selection) {
    -                $quid = $selection->getQuestion()->getUid();
    -                $answeredQuestions[$quid] = [];
    -                $answeredQuestions[$quid]['text'] = [];
    -                $answeredQuestions[$quid]['check'] = [];
    -                $answeredQuestions[$quid]['text'][0] = $selection->getEntered();
    -                foreach ($selection->getAnswers() as $answer) {
    -                    $answeredQuestions[$quid]['check'][$answer->getTitle()] = 1;
    -                }
    -            }
    -            // eigene Antworten setzen
    -            foreach ($tagArray['questions'] as $question) {
    -                $quid = $question->getUid();
    -                if ($answeredQuestions[$quid]) {
    -                    if (is_array($answeredQuestions[$quid]['text'])) {
    -                        $question->setTextAnswers($answeredQuestions[$quid]['text']);
    -                    }
    -                    foreach ($question->getAnswers() as $answer) {
    -                        $checked = ($answeredQuestions[$quid]['check'][$answer->getTitle()]) ? 1 : 0;
    -                        $answer->setOwnAnswer($checked);
    -                    }
    -                }
    -            }
    -        }
     
    +        $this->view->assign('debug', $data['debug']);
             $this->view->assign('quiz', $quiz);
             $this->view->assign('tag', $tag);
    -        $this->view->assign('tags', $tagArray['pagetags']);
             $this->view->assign('tagQuestions', $tagArray['questions']);
             $this->view->assign('tagSelections', $tagSelections);
    -        $this->view->assign('randomPages', implode(',', $tagArray['randomNumbers']));
             $this->view->assign('participant', $this->participant);
    +        $this->view->assign('page', $page);
             if ($pages > 0) {
                 $this->view->assign('pagePercent', intval(round(100*($page/$pages))));
                 $this->view->assign('pagePercentInclFinalPage', intval(round(100*($page/($pages+1)))));
             }
    -        foreach ($data as $key => $value) {
    -            $this->view->assign($key, $value);
    -        }
    +        $this->view->assign('nextPage', $data['nextPage']);
    +        $this->view->assign('pages', $pages);
             $this->view->assign('pagesInclFinalPage', ($pages+1));
    +        $this->view->assign('questions', $data['questions']);
             $this->view->assign('pageBasis', 0);
    +        $this->view->assign('final', $data['final']);
    +        $this->view->assign('finalContent', $data['finalContent']);
    +        $this->view->assign('finalBodytext', $data['finalBodytext']);
    +        $this->view->assign('finalImageuid', $data['finalImageuid']);
    +        $this->view->assign('session', $data['session']);
    +        $this->view->assign('showAnswers', $data['showAnswers']);
    +        $this->view->assign('showAnswersNext', $data['showAnswersNext']);
             $this->view->assign("sysLanguageUid", $sys_language_uid);
             $this->view->assign('uidOfPage', $GLOBALS['TSFE']->id);
             $this->view->assign('uidOfCE', $this->configurationManager->getContentObject()->data['uid']);
    @@ -1456,108 +1206,110 @@ public function showByTagAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
          */
         public function showAjaxAction(\Fixpunkt\FpMasterquiz\Domain\Model\Quiz $quiz)
         {
    -        if ($this->checkForClosure()) {
    -            $this->redirect('closure', 'Quiz', NULL, ['participant' => $this->participant], $this->settings['closurePageUid']);
    +        if (!$this->checkQuizAccess($quiz->getPid(), $quiz->getUid())) {
    +            return;
             }
         	// siehe: https://www.sebkln.de/tutorials/erstellung-einer-typo3-extension-mit-ajax-aufruf/
    -        //	$quizUid = $this->request->hasArgument('quiz') ? intval($this->request->getArgument('quiz')) : 0;
    -        //		$quiz = $this->quizRepository->findOneByUid($quizUid);
    -        // vorerst mal
    -        $this->settings['user']['useCookie'] = 0;
    -        $userData = $this->findParticipant($quiz->getUid(), $quiz->getPid());
    -        $data = $this->doAll($quiz, $userData,0, []);
    -        $page = $data['page'];
    -        $pages = $data['pages'];
    -        $from = 1 + (($page-1) * intval($this->settings['pagebrowser']['itemsPerPage']));
    -        $to = ($page * intval($this->settings['pagebrowser']['itemsPerPage']));
    -        $languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language');
    -        $sys_language_uid = $languageAspect->getId();
    -
    -        if ($data['useJoker'] == 1) {
    -            // Joker-Antworten hier automatisch setzen
    -            if ($this->settings['debug']) {
    -                $data['debug'] .= "\nJoker was used. Setting automatic joker answers: ";
    -            }
    -            $i=0;
    -            $jokerSet = 0;
    -            $jokerMax = 0;
    -            foreach ($quiz->getQuestions() as $question) {
    -                $i++;
    -                // uns interessiert nur die aktuelle Seite
    -                if ($i == $page) {
    -                    // Schritt 1: richtige Antworten auf 0 setzen, falsche auf 1
    -                    if ($this->settings['debug']) {
    -                        $data['debug'] .= $question->getTitle() . "/";
    -                    }
    -                    foreach ($question->getAnswers() as $answer) {
    -                        $jokerMax++;
    -                        $points = $answer->getPoints();
    -                        if ($points > 0) {
    -                            $answer->setJokerAnswer(0);
    -                            $jokerSet++;
    -                        } else {
    -                            $answer->setJokerAnswer(1);
    -                        }
    -                    }
    -                    $jokerHalf = intval(ceil($jokerMax/2));   // aus 5 wird 3, aus 4 wird 2
    -                    $jokerFehlend = $jokerHalf - $jokerSet;   // 3-1=2; 2-1=1 bei 1 richtigen Antwort
    -                    // Schritt 2: # fehlende Joker auf 0 (richtig) setzen
    -                    foreach ($question->getAnswers() as $answer) {
    -                        if ($jokerFehlend && ($answer->getJokerAnswer() == 1)) {
    -                            $random = random_int($jokerSet+1, $jokerMax);     // 2 bis 5 (1/4) bzw. 2 bis 4 (1/3)
    -                            if ($random == $jokerMax) {       // Wahrscheinlichkeit 1/4 bzw. 1/3
    -                                $jokerFehlend--;
    -                                $answer->setJokerAnswer(0);
    -                                if ($this->settings['debug']) {
    -                                    $data['debug'] .= $answer->getTitle() . "#";
    -                                }
    -                            }
    -                        }
    -                    }
    -                    // Schritt 3: falls nicht genug Antworten als pseudo-richtig ausgewählt wurden...
    -                    if ($jokerFehlend) {
    -                        // ...einfach die ersten Antworten auswählen
    -                        foreach ($question->getAnswers() as $answer) {
    -                            if ($jokerFehlend && ($answer->getJokerAnswer() == 1)) {
    -                                $jokerFehlend--;
    -                                $answer->setJokerAnswer(0);
    -                                if ($this->settings['debug']) {
    -                                    $data['debug'] .= $answer->getTitle() . "##";
    -                                }
    -                            }
    -                        }
    -                    }
    -                }
    -            }
    -        }
    +    //	$quizUid = $this->request->hasArgument('quiz') ? intval($this->request->getArgument('quiz')) : 0;
    +    //	if ($quizUid) {
    +    		// vorerst mal
    +    		$this->settings['user']['useCookie'] = 0;
    +    //		$quiz = $this->quizRepository->findOneByUid($quizUid);
    +    		$data = $this->doAll($quiz,0);
    +    		$page = $data['page'];
    +    		$pages = $data['pages'];
    +    		$from = 1 + (($page-1) * intval($this->settings['pagebrowser']['itemsPerPage']));
    +    		$to = ($page * intval($this->settings['pagebrowser']['itemsPerPage']));
    +    		$languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language');
    +    		$sys_language_uid = $languageAspect->getId();
     
    -        $this->view->assign('debug', $data['debug']);
    -        $this->view->assign('quiz', $quiz);
    -        $this->view->assign('participant', $this->participant);
    -        $this->view->assign('page', $page);
    -        if ($pages > 0) {
    -            $this->view->assign('pagePercent', intval(round(100*($page/$pages))));
    -            $this->view->assign('pagePercentInclFinalPage', intval(round(100*($page/($pages+1)))));
    -        }
    -        $this->view->assign('nextPage', $data['nextPage']);
    -        $this->view->assign('pages', $pages);
    -        $this->view->assign('pagesInclFinalPage', ($pages+1));
    -        $this->view->assign('questions', $data['questions']);
    -        $this->view->assign('pageBasis', ($page-1) * $this->settings['pagebrowser']['itemsPerPage']);
    -        $this->view->assign('final', $data['final']);
    -        $this->view->assign('finalContent', $data['finalContent']);
    -        $this->view->assign('finalCategories', $data['finalCategories']);
    -        $this->view->assign('session', $data['session']);
    -        $this->vi
    ... [truncated]
    
  • Classes/Controller/SelectedController.php+1 10 modified
    @@ -21,19 +21,10 @@ class SelectedController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
          * selectedRepository
          *
          * @var \Fixpunkt\FpMasterquiz\Domain\Repository\SelectedRepository
    +     * @TYPO3\CMS\Extbase\Annotation\Inject
          */
         protected $selectedRepository = null;
     
    -    /**
    -     * Injects the selected-Repository
    -     *
    -     * @param \Fixpunkt\FpMasterquiz\Domain\Repository\SelectedRepository $selectedRepository
    -     */
    -    public function injectSelectedRepository(\Fixpunkt\FpMasterquiz\Domain\Repository\SelectedRepository $selectedRepository)
    -    {
    -        $this->selectedRepository = $selectedRepository;
    -    }
    -
         /**
          * action list
          *
    
  • Classes/Domain/Model/Answer.php+2 70 modified
    @@ -45,14 +45,7 @@ class Answer extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
          * @var int
          */
         protected $ownAnswer = 0;
    -
    -    /**
    -     * own category answer (for question mode 8): uid and title
    -     *
    -     * @var array
    -     */
    -    protected $ownCategoryAnswer = [];
    -
    +    
         /**
          * total answers of all users
          *
    @@ -74,26 +67,6 @@ class Answer extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
          */
         protected $totalPercent = 0.0;
     
    -    /**
    -     * category
    -     *
    -     * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>
    -     */
    -    protected $categories = null;
    -
    -    /**
    -     * Initializes all ObjectStorage properties
    -     * Do not modify this method!
    -     * It will be rewritten on each save in the extension builder
    -     * You may modify the constructor of this class instead
    -     *
    -     * @return void
    -     */
    -    protected function initStorageObjects()
    -    {
    -        $this->categories = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
    -    }
    -
         /**
          * Returns the title
          *
    @@ -188,28 +161,7 @@ public function setOwnAnswer($nr)
         {
             $this->ownAnswer = $nr;
         }
    -
    -    /**
    -     * Returns the own Category Answer
    -     *
    -     * @return array $ownCategoryAnswer
    -     */
    -    public function getOwnCategoryAnswer()
    -    {
    -        return $this->ownCategoryAnswer;
    -    }
    -
    -    /**
    -     * Sets the own category answer
    -     *
    -     * @param array $array uid and title of a category
    -     * @return void
    -     */
    -    public function setOwnCategoryAnswer($array)
    -    {
    -        $this->ownCategoryAnswer = $array;
    -    }
    -
    +    
         /**
          * Returns no. of all answers
          *
    @@ -272,24 +224,4 @@ public function setTotalPercent($percent)
         {
             $this->totalPercent = $percent;
         }
    -
    -    /**
    -     * Adds a Category
    -     *
    -     * @param \TYPO3\CMS\Extbase\Domain\Model\Category $category
    -     * @return void
    -     */
    -    public function addCategory(\TYPO3\CMS\Extbase\Domain\Model\Category $category) {
    -        $this->categories->attach($category);
    -    }
    -
    -    /**
    -     * Returns the categories
    -     *
    -     * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>
    -     */
    -    public function getCategories()
    -    {
    -        return $this->categories;
    -    }
     }
    
  • Classes/Domain/Model/Evaluation.php+0 30 modified
    @@ -67,26 +67,6 @@ class Evaluation extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
          */
         protected $page = 0;
     
    -    /**
    -     * category
    -     *
    -     * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>
    -     */
    -    protected $categories = null;
    -
    -    /**
    -     * Initializes all ObjectStorage properties
    -     * Do not modify this method!
    -     * It will be rewritten on each save in the extension builder
    -     * You may modify the constructor of this class instead
    -     *
    -     * @return void
    -     */
    -    protected function initStorageObjects()
    -    {
    -        $this->categories = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
    -    }
    -
         /**
          * Returns the evaluate
          *
    @@ -243,14 +223,4 @@ public function setPage($page)
         {
             $this->page = $page;
         }
    -
    -    /**
    -     * Returns the categories
    -     *
    -     * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>
    -     */
    -    public function getCategories()
    -    {
    -        return $this->categories;
    -    }
     }
    
  • Classes/Domain/Model/Participant.php+4 110 modified
    @@ -76,13 +76,6 @@ class Participant extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
          */
         protected $sessionstart = 0;
     
    -    /**
    -     * List of random pages for this user
    -     *
    -     * @var string
    -     */
    -    protected $randompages = '';
    -
         /**
          * Reached points for this quiz
          *
    @@ -132,7 +125,7 @@ class Participant extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
          * @TYPO3\CMS\Extbase\Annotation\ORM\Cascade("remove")
          */
         protected $selections = null;
    -
    +    
         /**
          * __construct
          */
    @@ -292,32 +285,6 @@ public function getUser()
             return $this->user;
         }
     
    -    /**
    -     * Returns the username
    -     *
    -     * @return string $username
    -     */
    -    public function getUsername()
    -    {
    -        if (!$this->user) {
    -            return '';
    -        } else {
    -            $queryBuilder = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class)->getQueryBuilderForTable('fe_users');
    -            $statement = $queryBuilder
    -                ->select('username')
    -                ->from('fe_users')
    -                ->where(
    -                    $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($this->user, \PDO::PARAM_INT))
    -                )
    -                ->setMaxResults(1)
    -                ->execute();
    -            while ($row = $statement->fetch()) {
    -                return $row['username'];
    -            }
    -            return '';
    -        }
    -    }
    -
         /**
          * Sets the user
          *
    @@ -371,27 +338,6 @@ public function setSessionstart($sessionstart)
             $this->sessionstart = $sessionstart;
         }
     
    -    /**
    -     * Returns the randompages
    -     *
    -     * @return array $randompages
    -     */
    -    public function getRandompages()
    -    {
    -        return explode(',', $this->randompages);
    -    }
    -
    -    /**
    -     * Sets the randompages
    -     *
    -     * @param array $randompages
    -     * @return void
    -     */
    -    public function setRandompages($randompages)
    -    {
    -        $this->randompages = implode(',', $randompages);
    -    }
    -
         /**
          * Returns the quiz
          *
    @@ -466,17 +412,6 @@ public function addPoints($points)
             $this->points += $points;
         }
     
    -    /**
    -     * Sets the minus points
    -     *
    -     * @param int $points
    -     * @return void
    -     */
    -    public function subtractPoints($points)
    -    {
    -        $this->points -= $points;
    -    }
    -
         /**
          * Returns the maximum1
          *
    @@ -498,7 +433,7 @@ public function getPercent1()
         }
     
         /**
    -     * Sets the maximum1 (maximum bisher)
    +     * Sets the maximum1
          *
          * @param int $maximum1
          * @return void
    @@ -540,7 +475,7 @@ public function getPercent2()
         }
     
         /**
    -     * Sets the maximum2 (maximum gesamt)
    +     * Sets the maximum2
          *
          * @param int $maximum2
          * @return void
    @@ -601,48 +536,7 @@ public function isCompleted()
         {
             return $this->completed;
         }
    -
    -    /**
    -     * Returns the most selected category
    -     *
    -     * @return array
    -     */
    -    public function getCategoryMost()
    -    {
    -        $mostValue = 0;
    -        $mostUid = 0;
    -        $mostArray = [];
    -        $mostEntry = [];
    -        $generalArray = [];
    -        foreach ($this->selections as $selection) {
    -            foreach ($selection->getAnswers() as $answer) {
    -                $cats = $answer->getCategories();
    -                foreach ($cats as $cat) {
    -                    $uid = $cat->getUid();
    -                    if (isset($mostArray[$uid])) {
    -                        $mostArray[$uid]++;
    -                    } else {
    -                        $mostArray[$uid] = 1;
    -                        $generalArray[$uid] = [];
    -                        $generalArray[$uid]['title'] = $cat->getTitle();
    -                    }
    -                }
    -            }
    -        }
    -        foreach ($mostArray as $key => $value) {
    -            $generalArray[$key]['count'] = $value;
    -            if ($value > $mostValue) {
    -                $mostUid = $key;
    -                $mostValue = $value;
    -            }
    -        }
    -        $mostEntry['uid'] = $mostUid;
    -        $mostEntry['count'] = $mostValue;
    -        $mostEntry['title'] = $generalArray[$mostUid]['title'];
    -        $mostEntry['all'] = $generalArray;
    -        return $mostEntry;
    -    }
    -
    +    
         /**
          * Adds a Selected
          *
    
  • Classes/Domain/Model/Question.php+2 97 modified
    @@ -61,13 +61,6 @@ class Question extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
          */
         protected $tag = null;
     
    -    /**
    -     * Beantwortung optional?
    -     *
    -     * @var bool
    -     */
    -    protected $optional = false;
    -
         /**
          * Answers of this question
          *
    @@ -103,14 +96,7 @@ class Question extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
          * @var int
          */
         protected $sorting = 0;
    -
    -    /**
    -     * category
    -     *
    -     * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>
    -     */
    -    protected $categories = null;
    -
    +    
         /**
          * __construct
          */
    @@ -131,7 +117,6 @@ public function __construct()
         protected function initStorageObjects()
         {
         	$this->answers = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
    -        $this->categories = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
         }
         
         /**
    @@ -260,37 +245,6 @@ public function setTag(\Fixpunkt\FpMasterquiz\Domain\Model\Tag $tag)
             $this->tag = $tag;
         }
     
    -    /**
    -     * Returns the Optional
    -     *
    -     * @return bool
    -     */
    -    public function getOptional()
    -    {
    -        return $this->optional;
    -    }
    -
    -    /**
    -     * Sets the Optional
    -     *
    -     * @param bool $optional
    -     * @return void
    -     */
    -    public function setOptional($optional)
    -    {
    -        $this->optional = $optional;
    -    }
    -
    -    /**
    -     * Returns the boolean state of Optional
    -     *
    -     * @return bool
    -     */
    -    public function isOptional()
    -    {
    -        return $this->optional;
    -    }
    -
         /**
          * Adds a Answer
          *
    @@ -468,7 +422,7 @@ public function getNumberOfAnswers()
         }
         
         /**
    -     * Returns an array with no. of answers for this question
    +     * Returns the an array with no. of answers for this question
          *
          * @return array
          */
    @@ -480,53 +434,4 @@ public function getArrayOfAnswers()
         	}
         	return $array;
         }
    -
    -    /**
    -     * Returns the categories
    -     *
    -     * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>
    -     */
    -    public function getCategories()
    -    {
    -        return $this->categories;
    -    }
    -
    -    /**
    -     * Returns the categories as array
    -     *
    -     * @return array
    -     */
    -    public function getCategoriesArray()
    -    {
    -        $catArray = [];
    -        foreach ($this->categories as $category) {
    -            $catArray[$category->getUid()] = $category->getTitle();
    -        }
    -        return $catArray;
    -    }
    -
    -    /**
    -     * Returns the categories as array in sorting order
    -     *
    -     * @return array
    -     */
    -    public function getSortedCategoriesArray() {
    -        $table = 'sys_category';
    -        $queryBuilder = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class)->getQueryBuilderForTable($table);
    -        return $queryBuilder
    -            ->select('uid','title')
    -            ->from($table)
    -            ->join(
    -                $table,
    -                'sys_category_record_mm',
    -                'mm',
    -                $queryBuilder->expr()->eq('mm.uid_local', $queryBuilder->quoteIdentifier('sys_category.uid'))
    -            )
    -            ->where(
    -                $queryBuilder->expr()->eq('mm.uid_foreign', $queryBuilder->createNamedParameter($this->uid, \PDO::PARAM_INT)),
    -                $queryBuilder->expr()->eq('mm.tablenames', $queryBuilder->createNamedParameter('tx_fpmasterquiz_domain_model_question'))
    -            )
    -            ->orderBy('sys_category.sorting')
    -            ->execute();
    -    }
     }
    
  • Classes/Domain/Model/Quiz.php+2 32 modified
    @@ -220,35 +220,16 @@ public function setQuestions(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $quest
          * Returns the questions
          *
          * @param integer $page Seite 1..n
    -     * @param bool $random Zufällig ordnen?
    -     * @param array $randomNumbers andere Seitenreihenfolge?
          * @return array
          */
    -    public function getQuestionsSortByTag(int $page, bool $random, array $randomNumbers)
    +    public function getQuestionsSortByTag($page)
         {
             // wir brauchen last-page und current-page
             $pages = 0;
             $tags = [];
             $pagetags = [];
             $questions = [];
             $result = [];
    -        if ($random && !(count($randomNumbers)>1)) {
    -            // Seitenanzahl bestimmen
    -            foreach ($this->questions as $question) {
    -                $tag = $question->getTag();
    -                if ($tag) {
    -                    if (!$tags[$tag->getName()]) {
    -                        $pages++;
    -                        $tags[$tag->getName()] = 1;
    -                    }
    -                }
    -            }
    -            // jeder Seite eine zufällige Reihenfolge zuordnen
    -            $randomNumbers = range(1, $pages);
    -            shuffle($randomNumbers);
    -            $tags = [];
    -            $pages = 0;
    -        }
             foreach ($this->questions as $question) {
                 $tag = $question->getTag();
                 if ($tag) {
    @@ -257,14 +238,7 @@ public function getQuestionsSortByTag(int $page, bool $random, array $randomNumb
                         $forpage = $tags[$tag->getName()];
                     } else {
                         $pages++;
    -                    if ($random) {
    -                        // Die Seitennummer kommt aus einem random Array 0 .. $pages-1
    -                        $forpage = $randomNumbers[$pages - 1];
    -                        //echo "### Seite: " . $pages . ' wird zu ' . $forpage . '/' . $tag->getName();
    -                    } else {
    -                        // Die Seitennummer erhöht sich kontinuierlich
    -                        $forpage = $pages;
    -                    }
    +                    $forpage = $pages;
                         $pagetags[$forpage] = $tag->getName();
                         $tags[$tag->getName()] = $forpage;
                     }
    @@ -273,14 +247,10 @@ public function getQuestionsSortByTag(int $page, bool $random, array $randomNumb
                     }
                 }
             }
    -        if ($random && (count($randomNumbers)>1)) {
    -            ksort($pagetags);
    -        }
             $result['page'] = $page;
             $result['pages'] = $pages;
             $result['pagetags'] = $pagetags;
             $result['tags'] = $tags;
    -        $result['randomNumbers'] = $randomNumbers;
             $result['questions'] = $questions;
             return $result;
         }
    
  • Classes/Domain/Model/Selected.php+3 21 modified
    @@ -51,14 +51,7 @@ class Selected extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
          * @var int
          */
         protected $sorting = 0;
    -
    -    /**
    -     * category
    -     *
    -     * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>
    -     */
    -    protected $categories = null;
    -
    +    
         /**
          * __construct
          */
    @@ -79,7 +72,6 @@ public function __construct()
         protected function initStorageObjects()
         {
             $this->answers = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
    -        $this->categories = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
         }
         
         /**
    @@ -178,7 +170,7 @@ public function setQuestion(\Fixpunkt\FpMasterquiz\Domain\Model\Question $questi
         }
     
         /**
    -     * Adds an Answer
    +     * Adds a Answer
          *
          * @param \Fixpunkt\FpMasterquiz\Domain\Model\Answer $answer
          * @return void
    @@ -189,7 +181,7 @@ public function addAnswer(\Fixpunkt\FpMasterquiz\Domain\Model\Answer $answer)
         }
     
         /**
    -     * Removes an Answer
    +     * Removes a Answer
          *
          * @param \Fixpunkt\FpMasterquiz\Domain\Model\Answer $answerToRemove The Answer to be removed
          * @return void
    @@ -229,14 +221,4 @@ public function getMaximumPoints()
         {
             return $this->question->getMaximum1();
         }
    -
    -    /**
    -     * Returns the categories
    -     *
    -     * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>
    -     */
    -    public function getCategories()
    -    {
    -        return $this->categories;
    -    }
     }
    
  • Classes/Domain/Repository/ParticipantRepository.php+0 20 modified
    @@ -95,24 +95,4 @@ public function findOneByUserAndQuiz($userId, $quizId)
         	);
         	return $query->execute()->getFirst();
         }
    -
    -    /**
    -     * Fetches a entry for a pid and user.
    -     *
    -     * @param	integer	$userId	FEuser-UID
    -     * @param	integer	$quizId	Quiz-PID
    -     * @return	array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
    -     */
    -    public function findOneByUidAndPid($userId, $quizPid)
    -    {
    -        $query = $this->createQuery();
    -        $query->getQuerySettings()->setRespectStoragePage(false);
    -        $query->matching(
    -            $query->logicalAnd(
    -                $query->equals('uid', $userId),
    -                $query->equals('pid', $quizPid)
    -            )
    -        );
    -        return $query->execute()->getFirst();
    -    }
     }
    
  • Classes/Domain/Repository/QuestionRepository.php+1 38 modified
    @@ -41,44 +41,7 @@ public function findLostQuestions($pageId)
         	);
         	return $query->execute();
         }
    -
    -    /**
    -     * Find questions from other quizzes
    -     *
    -     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
    -     */
    -    public function findOtherThan($pageId, $quizID)
    -    {
    -        $query = $this->createQuery();
    -        $query->getQuerySettings()->setRespectStoragePage(false);
    -        $query->matching(
    -            $query->logicalAnd(
    -                $query->equals('pid', $pageId),
    -                $query->logicalNot($query->equals('quiz', $quizID))
    -            )
    -        );
    -        return $query->execute();
    -    }
    -
    -    /**
    -     * Move a question
    -     *
    -     * @param	integer	$questionID	Question
    -     * @param	integer	$quizID 	Quiz
    -     */
    -    public function moveToQuiz($questionID, $quizID)
    -    {
    -        $table = 'tx_fpmasterquiz_domain_model_question';
    -        $queryBuilder = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class)->getQueryBuilderForTable($table);
    -        $queryBuilder
    -            ->update($table)
    -            ->where(
    -                $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($questionID, \PDO::PARAM_INT))
    -            )
    -            ->set('quiz', intval($quizID))
    -            ->execute();
    -    }
    -
    +    
         /**
          * Get the PIDs
          *
    
  • Classes/Domain/Repository/QuizRepository.php+11 1 modified
    @@ -40,5 +40,15 @@ public function findFromPid($pageId)
         	$query->matching($query->equals('pid', $pageId));
         	return $query->execute();
         }
    -    
    +
    +    /**
    +     * Get the PIDs
    +     *
    +     * @return array
    +     */
    +    public function getStoragePids()
    +    {
    +        $query = $this->createQuery();
    +        return $query->getQuerySettings()->getStoragePageIds();
    +    }
     }
    
  • Classes/Domain/Repository/SelectedRepository.php+3 55 modified
    @@ -76,6 +76,9 @@ public function countByParticipantAndQuestion($participantId, $questionId)
     	{
     		$query = $this->createQuery();
     		$query->getQuerySettings()->setRespectStoragePage(false);
    +		$query->setOrderings([
    +			'tstamp' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
    +		]);
     		$query->matching(
     			$query->logicalAnd(
     				$query->equals('participant', $participantId),
    @@ -84,59 +87,4 @@ public function countByParticipantAndQuestion($participantId, $questionId)
     		);
     		return $query->execute()->count();
     	}
    -
    -    /**
    -     * Fetches no. of a participant and question.
    -     *
    -     * @param	integer	$participantId	Participant-UID
    -     * @param	integer	$questionId		Question-UID
    -     * @return	array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
    -     */
    -    public function findByParticipantAndQuestion($participantId, $questionId)
    -    {
    -        $query = $this->createQuery();
    -        $query->getQuerySettings()->setRespectStoragePage(false);
    -        $query->matching(
    -            $query->logicalAnd(
    -                $query->equals('participant', $participantId),
    -                $query->equals('question', $questionId)
    -            )
    -        );
    -        return $query->execute()->getFirst();
    -    }
    -
    -    /**
    -     * Delete entry for participant and question. Wird doch nicht gebraucht!
    -     *
    -     * @param	integer	$participantId	Participant-UID
    -     * @param	integer	$questionId		Question-UID
    -     */
    -    public function deleteByParticipantAndQuestion($participantId, $questionId)
    -    {
    -        $table = 'tx_fpmasterquiz_domain_model_selected';
    -        $queryBuilder = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class)->getQueryBuilderForTable($table);
    -        $rows = $queryBuilder
    -            ->select('uid')
    -            ->from($table)
    -            ->where(
    -                $queryBuilder->expr()->andX(
    -                    $queryBuilder->expr()->eq('participant', $queryBuilder->createNamedParameter($participantId, \PDO::PARAM_INT)),
    -                    $queryBuilder->expr()->eq('question', $queryBuilder->createNamedParameter($questionId, \PDO::PARAM_INT))
    -                )
    -            )
    -            ->execute()
    -            ->fetchAll();
    -        foreach ($rows as $row) {
    -            \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class)->getConnectionForTable($table)
    -                ->delete(
    -                    $table,
    -                    ['uid' => (int)$row['uid']]
    -                );
    -            \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class)->getConnectionForTable('tx_fpmasterquiz_selected_answer_mm')
    -                ->delete(
    -                    'tx_fpmasterquiz_selected_answer_mm',
    -                    ['uid_local' => (int)$row['uid']]
    -                );
    -        }
    -    }
     }
    
  • Classes/Hooks/PageLayoutView.php+3 12 modified
    @@ -137,14 +137,6 @@ public function getExtensionSummary($params, &$pObj)
                    		$content
                    	];
                    }
    -                $closurePageUid = (int)$this->getFieldFromFlexform('settings.closurePageUid');
    -                if ($closurePageUid > 0) {
    -                    $content = $this->getRecordData($closurePageUid);
    -                    $this->tableData[] = [
    -                        $this->getLanguageService()->sL(self::LLPATH . 'settings.closurePageUid'),
    -                        $content
    -                    ];
    -                }
                    $defaultQuizUid = (int)$this->getFieldFromFlexform('settings.defaultQuizUid');
                    if ($defaultQuizUid > 0) {
                        $content = $this->getRecordData($defaultQuizUid, 'tx_fpmasterquiz_domain_model_quiz');
    @@ -165,8 +157,7 @@ public function getExtensionSummary($params, &$pObj)
                        $this->getLanguageService()->sL(self::LLPATH . 'settings.ajax'),
                        (($ajax) ? $this->getLanguageService()->sL(self::LLPATH . 'settings.yes') : $this->getLanguageService()->sL(self::LLPATH . 'settings.no'))
                    ];
    -               if (isset($GLOBALS['TYPO3_CONF_VARS']['EXT']['fp_masterquiz']['Quizpalme\\fp_masterquiz\\Hooks\\PageLayoutView']['extensionSummary'])
    -                   && is_array($GLOBALS['TYPO3_CONF_VARS']['EXT']['fp_masterquiz']['Quizpalme\\fp_masterquiz\\Hooks\\PageLayoutView']['extensionSummary'])) {
    +               if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXT']['fp_masterquiz']['Quizpalme\\fp_masterquiz\\Hooks\\PageLayoutView']['extensionSummary'])) {
                         $params = [
                             'action' => $actionTranslationKey
                         ];
    @@ -303,8 +294,8 @@ public function getFieldFromFlexform($key, $sheet = 'sDEF')
             $flexform = $this->flexformData;
             if (isset($flexform['data'])) {
                 $flexform = $flexform['data'];
    -            if (isset($flexform) && isset($flexform[$sheet]) && isset($flexform[$sheet]['lDEF']) 
    -                && isset($flexform[$sheet]['lDEF'][$key]) && isset($flexform[$sheet]['lDEF'][$key]['vDEF'])
    +            if (is_array($flexform) && is_array($flexform[$sheet]) && is_array($flexform[$sheet]['lDEF'])
    +                && is_array($flexform[$sheet]['lDEF'][$key]) && isset($flexform[$sheet]['lDEF'][$key]['vDEF'])
                 ) {
                     return $flexform[$sheet]['lDEF'][$key]['vDEF'];
                 }
    
  • Classes/Task/CsvExportAdditionalFieldProvider.php+0 194 removed
    @@ -1,194 +0,0 @@
    -<?php
    -namespace Fixpunkt\FpMasterquiz\Task;
    -
    -use TYPO3\CMS\Backend\Utility\BackendUtility;
    -use TYPO3\CMS\Core\Utility\GeneralUtility;
    -use TYPO3\CMS\Core\Database\ConnectionPool;
    -use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
    -use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
    -use TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider;
    -use TYPO3\CMS\Scheduler\Controller\SchedulerModuleController;
    -use TYPO3\CMS\Scheduler\Task\AbstractTask;
    -use TYPO3\CMS\Scheduler\Task\Enumeration\Action;
    -use TYPO3\CMS\Core\Messaging\FlashMessage;
    -
    -class CsvExportAdditionalFieldProvider extends AbstractAdditionalFieldProvider
    -{
    -    /**
    -     * Render additional information fields within the scheduler backend.
    -     *
    -     * @param array $taskInfo Array information of task to return
    -     * @param ValidatorTask|null $task The task object being edited. Null when adding a task!
    -     * @param SchedulerModuleController $schedulerModule Reference to the BE module of the Scheduler
    -     * @return array Additional fields
    -     * @see AdditionalFieldProviderInterface->getAdditionalFields($taskInfo, $task, $schedulerModule)
    -     */
    -    public function getAdditionalFields(array &$taskInfo, $task, SchedulerModuleController $schedulerModule)
    -    {
    -        $additionalFields = array();
    -        $currentSchedulerModuleAction = $schedulerModule->getCurrentAction();
    -        if (empty($taskInfo['csvfile'])) {
    -            if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    -                $taskInfo['csvfile'] = 'fileadmin/';
    -            } else {
    -                $taskInfo['csvfile'] = $task->getCsvfile();
    -            }
    -        }
    -        if (empty($taskInfo['page'])) {
    -            if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    -                $taskInfo['page'] = '';
    -            } else {
    -                $taskInfo['page'] = $task->getPage();
    -            }
    -        }
    -        if (empty($taskInfo['separator'])) {
    -            if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    -                $taskInfo['separator'] = '"';
    -            } else {
    -                $taskInfo['separator'] = $task->getSeparator();
    -            }
    -        }
    -        if (empty($taskInfo['delimiter'])) {
    -            if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    -                $taskInfo['delimiter'] = ';';
    -            } else {
    -                $taskInfo['delimiter'] = $task->getDelimiter();
    -            }
    -        }
    -        if (empty($taskInfo['ansdelimiter'])) {
    -            if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    -                $taskInfo['ansdelimiter'] = ', ';
    -            } else {
    -                $taskInfo['ansdelimiter'] = $task->getAnswersDelimiter();
    -            }
    -        }
    -        if (empty($taskInfo['convert'])) {
    -            if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    -                $taskInfo['convert'] = 0;
    -            } else {
    -                $taskInfo['convert'] = $task->getConvert();
    -            }
    -        }
    -
    -        // Ordner
    -        $fieldId = 'task_page';
    -        $fieldCode = '<input type="text" name="tx_scheduler[fpmasterquiz][page]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['page']) . '"/>';
    -        $label = $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.page');
    -        $label = BackendUtility::wrapInHelp('fpmasterquiz', $fieldId, $label);
    -        $additionalFields[$fieldId] = array(
    -            'code' => $fieldCode,
    -            'label' => $label
    -        );
    -        // path to csv file
    -        $fieldId = 'task_csvfile';
    -        $fieldCode = '<input type="text" name="tx_scheduler[fpmasterquiz][csvfile]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['csvfile']) . '" size="50" />';
    -        $label = $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.csvfile');
    -        $label = BackendUtility::wrapInHelp('fpmasterquiz', $fieldId, $label);
    -        $additionalFields[$fieldId] = array(
    -            'code' => $fieldCode,
    -            'label' => $label
    -        );
    -        // separator
    -        $fieldId = 'task_separator';
    -        $fieldCode = '<input type="text" name="tx_scheduler[fpmasterquiz][separator]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['separator']) . '" size="5" />';
    -        $label = $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.separator');
    -        $label = BackendUtility::wrapInHelp('fpmasterquiz', $fieldId, $label);
    -        $additionalFields[$fieldId] = array(
    -            'code' => $fieldCode,
    -            'label' => $label
    -        );
    -        // delimiter
    -        $fieldId = 'task_delimiter';
    -        $fieldCode = '<input type="text" name="tx_scheduler[fpmasterquiz][delimiter]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['delimiter']) . '" size="5" />';
    -        $label = $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.delimiter');
    -        $label = BackendUtility::wrapInHelp('fpmasterquiz', $fieldId, $label);
    -        $additionalFields[$fieldId] = array(
    -            'code' => $fieldCode,
    -            'label' => $label
    -        );
    -        // ansdelimiter
    -        $fieldId = 'task_ansdelimiter';
    -        $fieldCode = '<input type="text" name="tx_scheduler[fpmasterquiz][ansdelimiter]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['ansdelimiter']) . '" size="5" />';
    -        $label = $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.ansdelimiter');
    -        $label = BackendUtility::wrapInHelp('fpmasterquiz', $fieldId, $label);
    -        $additionalFields[$fieldId] = array(
    -            'code' => $fieldCode,
    -            'label' => $label
    -        );
    -        // convert
    -        $fieldId = 'task_convert';
    -        $checked = ($taskInfo['convert']) ? ' checked="checked"' : '';
    -        $fieldCode = '<input type="checkbox" name="tx_scheduler[fpmasterquiz][convert]" id="' . $fieldId . '" value="1"' . $checked . ' />';
    -        $label = $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.convert');
    -        $label = BackendUtility::wrapInHelp('fpmasterquiz', $fieldId, $label);
    -        $additionalFields[$fieldId] = array(
    -            'code' => $fieldCode,
    -            'label' => $label
    -        );
    -        return $additionalFields;
    -    }
    -
    -
    -    /**
    -     * This method checks any additional data that is relevant to the specific task.
    -     * If the task class is not relevant, the method is expected to return TRUE.
    -     *
    -     * @param array $submittedData Reference to the array containing the data submitted by the user
    -     * @param SchedulerModuleController $schedulerModule Reference to the BE module of the Scheduler
    -     * @return bool TRUE if validation was ok (or selected class is not relevant), FALSE otherwise
    -     */
    -    public function validateAdditionalFields(array &$submittedData, SchedulerModuleController $schedulerModule)
    -    {
    -        $isValid = TRUE;
    -        if ($submittedData['fpmasterquiz']['page'] > 0) {
    -            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
    -            $count = $queryBuilder
    -                ->count('uid')
    -                ->from('pages')
    -                ->where(
    -                    $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter((int)$submittedData['fpmasterquiz']['page'], \PDO::PARAM_INT))
    -                )
    -                ->execute()
    -                ->fetchColumn(0);
    -            if ($count == 0) {
    -                $isValid = FALSE;
    -                $this->addMessage(
    -                    $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.invalidPage'),
    -                    FlashMessage::ERROR
    -                );
    -            }
    -        } else {
    -            $isValid = FALSE;
    -            $this->addMessage(
    -                $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.invalidPage'),
    -                FlashMessage::ERROR
    -            );
    -        }
    -        if (substr($submittedData['fpmasterquiz']['csvfile'],0,10) != 'fileadmin/') {
    -            $isValid = FALSE;
    -            $this->addMessage(
    -                $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.invalidCsvfile'),
    -                FlashMessage::ERROR
    -            );
    -        }
    -        return $isValid;
    -    }
    -
    -    /**
    -     * This method is used to save any additional input into the current task object
    -     * if the task class matches.
    -     *
    -     * @param array $submittedData Array containing the data submitted by the user
    -     * @param AbstractTask $task Reference to the current task object
    -     */
    -    public function saveAdditionalFields(array $submittedData, AbstractTask $task)
    -    {
    -        /** @var $task ValidatorTask */
    -        $task->setCsvfile($submittedData['fpmasterquiz']['csvfile']);
    -        $task->setPage($submittedData['fpmasterquiz']['page']);
    -        $task->setSeparator($submittedData['fpmasterquiz']['separator']);
    -        $task->setDelimiter($submittedData['fpmasterquiz']['delimiter']);
    -        $task->setAnswersDelimiter($submittedData['fpmasterquiz']['ansdelimiter']);
    -        $task->setConvert($submittedData['fpmasterquiz']['convert']);
    -    }
    -}
    \ No newline at end of file
    
  • Classes/Task/CsvExportTask.php+0 297 removed
    @@ -1,297 +0,0 @@
    -<?php
    -namespace Fixpunkt\FpMasterquiz\Task;
    -
    -use TYPO3\CMS\Core\Utility\GeneralUtility;
    -use TYPO3\CMS\Core\Database\ConnectionPool;
    -use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
    -use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
    -use TYPO3\CMS\Scheduler\Task\AbstractTask;
    -
    -class CsvExportTask extends AbstractTask
    -{
    -
    -    /**
    -     * CSV file
    -     *
    -     * @var string
    -     */
    -    protected $csvfile;
    -
    -    /**
    -     * Uid of the folder
    -     *
    -     * @var integer
    -     */
    -    protected $page = 0;
    -
    -    /**
    -     * Separator
    -     *
    -     * @var string
    -     */
    -    protected $separator;
    -
    -    /**
    -     * Delimiter
    -     *
    -     * @var string
    -     */
    -    protected $delimiter;
    -
    -    /**
    -     * Answers-Delimiter
    -     *
    -     * @var string
    -     */
    -    protected $ansdelimiter;
    -
    -    /**
    -     * Convert from UTF-8 to ISO?
    -     *
    -     * @var integer
    -     */
    -    protected $convert = 0;
    -
    -    /**
    -     * @var TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
    -     */
    -    protected $configurationManager;
    -
    -    /**
    -     * Get the value of the csv file
    -     *
    -     * @return string
    -     */
    -    public function getCsvfile() {
    -        return $this->csvfile;
    -    }
    -
    -    /**
    -     * Set the value of the private property csvfile.
    -     *
    -     * @param string $csvfile Path to the csv file
    -     * @return void
    -     */
    -    public function setCsvfile($csvfile) {
    -        $this->csvfile = $csvfile;
    -    }
    -
    -    /**
    -     * Get the value of the protected property page
    -     *
    -     * @return integer UID of the start page for this task
    -     */
    -    public function getPage() {
    -        return $this->page;
    -    }
    -
    -    /**
    -     * Set the value of the private property page
    -     *
    -     * @param integer $page UID of the start page for this task.
    -     * @return void
    -     */
    -    public function setPage($page) {
    -        $this->page = $page;
    -    }
    -
    -    /**
    -     * Get the separator
    -     *
    -     * @return string
    -     */
    -    public function getSeparator() {
    -        return $this->separator;
    -    }
    -
    -    /**
    -     * Set the value of the separator
    -     *
    -     * @param string $separator
    -     * @return void
    -     */
    -    public function setSeparator($separator) {
    -        $this->separator = $separator;
    -    }
    -
    -    /**
    -     * Get the delimiter
    -     *
    -     * @return string
    -     */
    -    public function getDelimiter() {
    -        return $this->delimiter;
    -    }
    -
    -    /**
    -     * Set the value of the delimiter
    -     *
    -     * @param string $delimiter
    -     * @return void
    -     */
    -    public function setDelimiter($delimiter) {
    -        $this->delimiter = $delimiter;
    -    }
    -
    -    /**
    -     * Get the ansdelimiter
    -     *
    -     * @return string
    -     */
    -    public function getAnswersDelimiter() {
    -        return $this->ansdelimiter;
    -    }
    -
    -    /**
    -     * Set the value of the ansdelimiter
    -     *
    -     * @param string $ansdelimiter
    -     * @return void
    -     */
    -    public function setAnswersDelimiter($ansdelimiter) {
    -        $this->ansdelimiter = $ansdelimiter;
    -    }
    -
    -    /**
    -     * Get the value of the protected property convert
    -     *
    -     * @return integer
    -     */
    -    public function getConvert() {
    -        return $this->convert;
    -    }
    -
    -    /**
    -     * Set the value of the private property convert
    -     *
    -     * @param integer $convert
    -     * @return void
    -     */
    -    public function setConvert($convert) {
    -        $this->convert = ($convert) ? 1 : 0;
    -    }
    -
    -
    -    public function execute() {
    -        $successfullyExecuted = true;
    -        $ln = "\r\n";							// line break
    -        $uid = (int) $this->getPage();			// folder with quiz elements
    -        $fieldArray = ['uid', 'sys_language_uid', 'crdate', 'name', 'email', 'homepage', 'qname', 'qtitle', 'atitle', 'entered', 'spoints', 'ppoints', 'maximum1', 'maximum2'];
    -        $separator = $this->getSeparator();		// Texttrenner
    -        $delimiter = $this->getDelimiter();		// Feldtrenner
    -        $answersDelimiter = $this->getAnswersDelimiter();	// Feldtrenner bei Kategorien
    -        $convert = ($this->getConvert()) ? true : false;	// convert from UTF-8 to ASCII?
    -        $text = $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_participant').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_participant.sys_language_uid').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_participant.crdate').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_participant.name').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_participant.email').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_participant.homepage').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_quiz').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_question').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_answer').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_selected.entered').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_selected.points').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_participant.points').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_participant.maximum1').$separator.$delimiter.
    -            $separator.$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_participant.maximum2').$separator.$delimiter;
    -        if ($convert) $text = iconv('utf-8', 'iso-8859-1', $text);
    -        $content = $text . $ln;					// header of the csv file
    -        $i = 0;									// Counter
    -        $mmArray = [];
    -
    -        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_fpmasterquiz_domain_model_answer');
    -        $statement = $queryBuilder
    -            ->select('title', 'points', 'uid_local', 'uid_foreign')
    -            ->from('tx_fpmasterquiz_domain_model_answer')
    -            ->join(
    -                'tx_fpmasterquiz_domain_model_answer',
    -                'tx_fpmasterquiz_selected_answer_mm',
    -                'mm',
    -                $queryBuilder->expr()->eq('mm.uid_foreign', $queryBuilder->quoteIdentifier('tx_fpmasterquiz_domain_model_answer.uid'))
    -            )
    -            ->where(
    -                $queryBuilder->expr()->eq('tx_fpmasterquiz_domain_model_answer.pid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))
    -            )
    -            ->orderBy('mm.sorting', 'ASC')
    -            ->execute();
    -        while ($row = $statement->fetch()) {
    -            if (isset($mmArray[$row['uid_local']])) {
    -                $mmArray[$row['uid_local']] .= $answersDelimiter . $row['title'];
    -            } else {
    -                $mmArray[$row['uid_local']] = $row['title'];
    -            }
    -        }
    -
    -        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_fpmasterquiz_domain_model_participant');
    -        $statement = $queryBuilder
    -            ->select('tx_fpmasterquiz_domain_model_selected.uid AS suid', 'quiz.name AS qname', 'question.title AS qtitle',
    -                'question.qmode', 'tx_fpmasterquiz_domain_model_selected.points AS spoints', 'tx_fpmasterquiz_domain_model_selected.entered',
    -                'part.uid', 'part.name', 'email', 'homepage', 'part.points AS ppoints', 'part.maximum1', 'part.maximum2',
    -                'part.sys_language_uid', 'part.crdate')
    -            ->from('tx_fpmasterquiz_domain_model_selected')
    -            ->join(
    -                'tx_fpmasterquiz_domain_model_selected',
    -                'tx_fpmasterquiz_domain_model_participant',
    -                'part',
    -                $queryBuilder->expr()->eq('part.uid', $queryBuilder->quoteIdentifier('tx_fpmasterquiz_domain_model_selected.participant'))
    -            )
    -            ->join(
    -                'part',
    -                'tx_fpmasterquiz_domain_model_quiz',
    -                'quiz',
    -                $queryBuilder->expr()->eq('quiz.uid', $queryBuilder->quoteIdentifier('part.quiz'))
    -            )
    -            ->join(
    -                'tx_fpmasterquiz_domain_model_selected',
    -                'tx_fpmasterquiz_domain_model_question',
    -                'question',
    -                $queryBuilder->expr()->eq('question.uid', $queryBuilder->quoteIdentifier('tx_fpmasterquiz_domain_model_selected.question'))
    -            )
    -            ->where(
    -                $queryBuilder->expr()->eq('tx_fpmasterquiz_domain_model_selected.pid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))
    -            )
    -            ->orderBy('part.uid', 'DESC')
    -            ->addOrderBy('suid', 'ASC')
    -            ->execute();
    -        while ($row = $statement->fetch()) {
    -
    -            if ($i > 0)
    -                $content .= $ln;
    -            $j = 0;
    -            foreach ($fieldArray as $field) {
    -                if ($j>0)
    -                    $content .= $delimiter;
    -                if ($field == 'atitle') {
    -                    if ($row['qmode'] == 3 || $row['qmode'] == 5 || $row['qmode'] == 6) {
    -                        $text = '';
    -                    } else {
    -                        $text = $mmArray[$row['suid']];
    -                    }
    -                } else {
    -                    $text = $row[trim($field)];
    -                }
    -                $text = preg_replace( "/\r|\n/", " ", $text);
    -                if ($convert)
    -                    $text = iconv('utf-8', 'iso-8859-1', $text);
    -                if ($field == 'crdate')
    -                    $text = date("d.m.Y H:i", $text);
    -                elseif ($separator)
    -                    $text = str_replace($separator, '', $text);
    -                $content .= $separator . $text . $separator;
    -                $j++;
    -            }
    -            $i++;
    -
    -        }
    -
    -        $fp = fopen(\TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/' . $this->getCsvfile(), 'w');
    -        $ergebnis = fwrite($fp, $content);
    -        fclose($fp);
    -        if (!$ergebnis)
    -            $successfullyExecuted = FALSE;
    -
    -        //echo "Anzahl exportiert: " . $i;
    -        return $successfullyExecuted;
    -    }
    -}
    
  • Classes/Task/CsvImportAdditionalFieldProvider.php+265 0 added
    @@ -0,0 +1,265 @@
    +<?php
    +namespace Fixpunkt\FpMasterquiz\Task;
    +
    +use TYPO3\CMS\Backend\Utility\BackendUtility;
    +use TYPO3\CMS\Core\Utility\GeneralUtility;
    +use TYPO3\CMS\Core\Database\ConnectionPool;
    +use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
    +use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
    +use TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider;
    +use TYPO3\CMS\Scheduler\Controller\SchedulerModuleController;
    +use TYPO3\CMS\Scheduler\Task\AbstractTask;
    +use TYPO3\CMS\Scheduler\Task\Enumeration\Action;
    +use TYPO3\CMS\Core\Messaging\FlashMessage;
    +
    +class CsvImportAdditionalFieldProvider extends AbstractAdditionalFieldProvider
    +{
    +	/**
    +	 * Render additional information fields within the scheduler backend.
    +	 *
    +	 * @param array $taskInfo Array information of task to return
    +	 * @param ValidatorTask|null $task The task object being edited. Null when adding a task!
    +	 * @param SchedulerModuleController $schedulerModule Reference to the BE module of the Scheduler
    +	 * @return array Additional fields
    +	 * @see AdditionalFieldProviderInterface->getAdditionalFields($taskInfo, $task, $schedulerModule)
    +	 */
    +	public function getAdditionalFields(array &$taskInfo, $task, SchedulerModuleController $schedulerModule)
    +	{
    +		$additionalFields = array();
    +		$currentSchedulerModuleAction = $schedulerModule->getCurrentAction();
    +		if (empty($taskInfo['page'])) {
    +			if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    +				$taskInfo['page'] = '';
    +			} else {
    +				$taskInfo['page'] = $task->getPage();
    +			}
    +		}
    +		if (empty($taskInfo['language'])) {
    +			if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    +				$taskInfo['language'] = '0';
    +			} else {
    +				$taskInfo['language'] = $task->getLanguage();
    +			}
    +		}
    +		if (empty($taskInfo['csvfile'])) {
    +			if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    +				$taskInfo['csvfile'] = 'fileadmin/';
    +			} else {
    +				$taskInfo['csvfile'] = $task->getCsvfile();
    +			}
    +		}
    +		if (empty($taskInfo['fields'])) {
    +			if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    +				$taskInfo['fields'] = '';
    +			} else {
    +				$taskInfo['fields'] = $task->getFields();
    +			}
    +		}
    +		if (empty($taskInfo['separator'])) {
    +			if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    +				$taskInfo['separator'] = '"';
    +			} else {
    +				$taskInfo['separator'] = $task->getSeparator();
    +			}
    +		}
    +		if (empty($taskInfo['delimiter'])) {
    +			if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    +				$taskInfo['delimiter'] = ';';
    +			} else {
    +				$taskInfo['delimiter'] = $task->getDelimiter();
    +			}
    +		}
    +		if (empty($taskInfo['convert'])) {
    +			if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    +				$taskInfo['convert'] = 0;
    +			} else {
    +				$taskInfo['convert'] = $task->getConvert();
    +			}
    +		}
    +		if (empty($taskInfo['delete'])) {
    +			if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    +				$taskInfo['delete'] = 0;
    +			} else {
    +				$taskInfo['delete'] = $task->getDelete();
    +			}
    +		}
    +		if (empty($taskInfo['simulate'])) {
    +			if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    +				$taskInfo['simulate'] = 0;
    +			} else {
    +				$taskInfo['simulate'] = $task->getSimulate();
    +			}
    +		}
    +		
    +		// Ordner
    +		$fieldId = 'task_page';
    +		$fieldCode = '<input type="text" name="tx_scheduler[fp_masterquiz][page]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['page']) . '"/>';
    +		$label = $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.page');
    +		$label = BackendUtility::wrapInHelp('fp_masterquiz', $fieldId, $label);
    +		$additionalFields[$fieldId] = array(
    +				'code' => $fieldCode,
    +				'label' => $label
    +		);
    +		// Sprache
    +		$fieldId = 'task_language';
    +		$fieldCode = '<input type="text" name="tx_scheduler[fp_masterquiz][language]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['language']) . '"/>';
    +		$label = $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.language');
    +		$label = BackendUtility::wrapInHelp('fp_masterquiz', $fieldId, $label);
    +		$additionalFields[$fieldId] = array(
    +				'code' => $fieldCode,
    +				'label' => $label
    +		);
    +		// path to csv file
    +		$fieldId = 'task_csvfile';
    +		$fieldCode = '<input type="text" name="tx_scheduler[fp_masterquiz][csvfile]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['csvfile']) . '" size="50" />';
    +		$label = 'CSV-Datei';
    +		$label = BackendUtility::wrapInHelp('fp_masterquiz', $fieldId, $label);
    +		$additionalFields[$fieldId] = array(
    +				'code' => $fieldCode,
    +				'label' => $label
    +		);
    +		// fields in the DB
    +		$fieldId = 'task_fields';
    +		$fieldCode = '<input type="text" name="tx_scheduler[fp_masterquiz][fields]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['fields']) . '" size="50" />';
    +		$label = 'Felder';
    +		$label = BackendUtility::wrapInHelp('fp_masterquiz', $fieldId, $label);
    +		$additionalFields[$fieldId] = array(
    +				'code' => $fieldCode,
    +				'label' => $label
    +		);
    +		// separator
    +		$fieldId = 'task_separator';
    +		$fieldCode = '<input type="text" name="tx_scheduler[fp_masterquiz][separator]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['separator']) . '" size="5" />';
    +		$label = 'Separator';
    +		$label = BackendUtility::wrapInHelp('fp_masterquiz', $fieldId, $label);
    +		$additionalFields[$fieldId] = array(
    +				'code' => $fieldCode,
    +				'label' => $label
    +		);
    +		// delimiter
    +		$fieldId = 'task_delimiter';
    +		$fieldCode = '<input type="text" name="tx_scheduler[fp_masterquiz][delimiter]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['delimiter']) . '" size="5" />';
    +		$label = 'Delimiter';
    +		$label = BackendUtility::wrapInHelp('fp_masterquiz', $fieldId, $label);
    +		$additionalFields[$fieldId] = array(
    +				'code' => $fieldCode,
    +				'label' => $label
    +		);
    +		// convert
    +		$fieldId = 'task_convert';
    +		$checked = ($taskInfo['convert']) ? ' checked="checked"' : '';
    +		$fieldCode = '<input type="checkbox" name="tx_scheduler[fp_masterquiz][convert]" id="' . $fieldId . '" value="1"' . $checked . ' />';
    +		$label = 'Nach UTF-8 konvertieren?';
    +		$label = BackendUtility::wrapInHelp('fp_masterquiz', $fieldId, $label);
    +		$additionalFields[$fieldId] = array(
    +				'code' => $fieldCode,
    +				'label' => $label
    +		);
    +		// delete
    +		$fieldId = 'task_delete';
    +		$checked = ($taskInfo['delete']) ? ' checked="checked"' : '';
    +		$fieldCode = '<input type="checkbox" name="tx_scheduler[fp_masterquiz][delete]" id="' . $fieldId . '" value="1"' . $checked . ' />';
    +		$label = 'CDs vorher löschen?';
    +		$label = BackendUtility::wrapInHelp('fp_masterquiz', $fieldId, $label);
    +		$additionalFields[$fieldId] = array(
    +				'code' => $fieldCode,
    +				'label' => $label
    +		);
    +		// simulate
    +		$fieldId = 'task_simulate';
    +		$checked = ($taskInfo['simulate']) ? ' checked="checked"' : '';
    +		$fieldCode = '<input type="checkbox" name="tx_scheduler[fp_masterquiz][simulate]" id="' . $fieldId . '" value="1"' . $checked . ' />';
    +		$label = $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.simulate');
    +		$label = BackendUtility::wrapInHelp('fp_masterquiz', $fieldId, $label);
    +		$additionalFields[$fieldId] = array(
    +				'code' => $fieldCode,
    +				'label' => $label
    +		);
    +		return $additionalFields;
    +	}
    +	
    +	/**
    +	 * This method checks any additional data that is relevant to the specific task.
    +	 * If the task class is not relevant, the method is expected to return TRUE.
    +	 *
    +	 * @param array $submittedData Reference to the array containing the data submitted by the user
    +	 * @param SchedulerModuleController $schedulerModule Reference to the BE module of the Scheduler
    +	 * @return bool TRUE if validation was ok (or selected class is not relevant), FALSE otherwise
    +	 */
    +	public function validateAdditionalFields(array &$submittedData, SchedulerModuleController $schedulerModule)
    +	{
    +		$isValid = TRUE;
    +		if ($submittedData['fp_masterquiz']['page'] > 0) {
    +			$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
    +			$count = $queryBuilder
    +				->count('uid')
    +				->from('pages')
    +				->where(
    +					$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter((int)$submittedData['fp_masterquiz']['page'], \PDO::PARAM_INT))
    +				)
    +				->execute()
    +				->fetchColumn(0);
    +			if ($count == 0) {
    +				$isValid = FALSE;
    +				$this->addMessage(
    +					$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.invalidPage'),
    +					FlashMessage::ERROR
    +				);
    +			}
    +		} else {
    +			$isValid = FALSE;
    +			$this->addMessage(
    +				$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.invalidPage'),
    +				FlashMessage::ERROR
    +			);
    +		}
    +		$lang = (int)$submittedData['fp_masterquiz']['language'];
    +		if ($lang > 0) {
    +			$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_language');
    +			$count = $queryBuilder
    +				->count('uid')
    +				->from('sys_language')
    +				->where(
    +					$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($lang, \PDO::PARAM_INT))
    +				)
    +				->execute()
    +				->fetchColumn(0);
    +			if ($count == 0) {
    +				$isValid = FALSE;
    +				$this->addMessage(
    +					$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.invalidLanguage'),
    +					FlashMessage::ERROR
    +				);
    +			}
    +		}
    +		if (substr($submittedData['fp_masterquiz']['csvfile'],0,10) != 'fileadmin/') {
    +			$isValid = FALSE;
    +			$this->addMessage(
    +				$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.invalidFile'),
    +				FlashMessage::ERROR
    +			);
    +		}
    +		return $isValid;
    +	}
    +	
    +	/**
    +	 * This method is used to save any additional input into the current task object
    +	 * if the task class matches.
    +	 *
    +	 * @param array $submittedData Array containing the data submitted by the user
    +	 * @param AbstractTask $task Reference to the current task object
    +	 */
    +	public function saveAdditionalFields(array $submittedData, AbstractTask $task)
    +	{
    +		/** @var $task ValidatorTask */
    +		$task->setCsvfile($submittedData['fp_masterquiz']['csvfile']);
    +		$task->setFields($submittedData['fp_masterquiz']['fields']);
    +		$task->setPage($submittedData['fp_masterquiz']['page']);
    +		$task->setLanguage($submittedData['fp_masterquiz']['language']);
    +		$task->setSeparator($submittedData['fp_masterquiz']['separator']);
    +		$task->setDelimiter($submittedData['fp_masterquiz']['delimiter']);
    +		$task->setConvert($submittedData['fp_masterquiz']['convert']);
    +		$task->setDelete($submittedData['fp_masterquiz']['delete']);
    +		$task->setSimulate($submittedData['fp_masterquiz']['simulate']);
    +	}
    +}
    \ No newline at end of file
    
  • Classes/Task/CsvImportTask.php+412 0 added
    @@ -0,0 +1,412 @@
    +<?php
    +namespace Fixpunkt\FpMasterquiz\Task;
    +
    +class CsvImportTask extends \TYPO3\CMS\Scheduler\Task\AbstractTask {
    +
    +	/**
    +	 * CSV file
    +	 *
    +	 * @var string
    +	 */
    +	protected $csvfile;
    +
    +	/**
    +	 * Fields to export
    +	 *
    +	 * @var string
    +	 */
    +	protected $fields;
    +	
    +	/**
    +	 * Uid of the folder
    +	 *
    +	 * @var integer
    +	 */
    +	protected $page = 0;
    +
    +	/**
    +	 * Uid of the language
    +	 *
    +	 * @var integer
    +	 */
    +	protected $language = 0;
    +	
    +	/**
    +	 * Separator
    +	 *
    +	 * @var string
    +	 */
    +	protected $separator;
    +
    +	/**
    +	 * Delimiter
    +	 *
    +	 * @var string
    +	 */
    +	protected $delimiter;
    +
    +	/**
    +	 * Convert from UTF-8 to ISO?
    +	 *
    +	 * @var integer
    +	 */
    +	protected $convert = 0;
    +
    +	/**
    +	 * Delete entries first?
    +	 *
    +	 * @var integer
    +	 */
    +	protected $delete = 0;
    +
    +	/**
    +	 * Simulate only?
    +	 *
    +	 * @var integer
    +	 */
    +	protected $simulate = 0;
    +	
    +	
    +	/**
    +	 * Get the value of the csv file
    +	 *
    +	 * @return string
    +	 */
    +	public function getCsvfile() {
    +		return $this->csvfile;
    +	}
    +
    +	/**
    +	 * Set the value of the private property csvfile.
    +	 *
    +	 * @param string $csvfile Path to the csv file
    +	 * @return void
    +	 */
    +	public function setCsvfile($csvfile) {
    +		$this->csvfile = $csvfile;
    +	}
    +	
    +	/**
    +	 * Get the value of fields
    +	 *
    +	 * @return string
    +	 */
    +	public function getFields() {
    +		return $this->fields;
    +	}
    +	
    +	/**
    +	 * Set the value of the private property fields.
    +	 *
    +	 * @param string $fields Fields to export
    +	 * @return void
    +	 */
    +	public function setFields($fields) {
    +		$this->fields = $fields;
    +	}
    +	
    +	/**
    +	 * Get the value of the protected property page
    +	 *
    +	 * @return integer UID of the start page for this task
    +	 */
    +	public function getPage() {
    +		return $this->page;
    +	}
    +
    +	/**
    +	 * Set the value of the private property page
    +	 *
    +	 * @param integer $page UID of the start page for this task.
    +	 * @return void
    +	 */
    +	public function setPage($page) {
    +		$this->page = $page;
    +	}
    +
    +	/**
    +	 * Get the value of the protected property language
    +	 *
    +	 * @return integer UID of the language for this task
    +	 */
    +	public function getLanguage() {
    +		return $this->language;
    +	}
    +	
    +	/**
    +	 * Set the value of the private property language
    +	 *
    +	 * @param integer $page UID of the language for this task.
    +	 * @return void
    +	 */
    +	public function setLanguage($language) {
    +		$this->language = $language;
    +	}
    +	
    +	/**
    +	 * Get the separator
    +	 *
    +	 * @return string
    +	 */
    +	public function getSeparator() {
    +		return $this->separator;
    +	}
    +	
    +	/**
    +	 * Set the value of the separator
    +	 *
    +	 * @param string $separator
    +	 * @return void
    +	 */
    +	public function setSeparator($separator) {
    +		$this->separator = $separator;
    +	}
    +
    +	/**
    +	 * Get the delimiter
    +	 *
    +	 * @return string
    +	 */
    +	public function getDelimiter() {
    +		return $this->delimiter;
    +	}
    +	
    +	/**
    +	 * Set the value of the delimiter
    +	 *
    +	 * @param string $delimiter
    +	 * @return void
    +	 */
    +	public function setDelimiter($delimiter) {
    +		$this->delimiter = $delimiter;
    +	}
    +	
    +	/**
    +	 * Get the value of the protected property convert
    +	 *
    +	 * @return integer
    +	 */
    +	public function getConvert() {
    +		return $this->convert;
    +	}
    +	
    +	/**
    +	 * Set the value of the private property convert
    +	 *
    +	 * @param integer $convert
    +	 * @return void
    +	 */
    +	public function setConvert($convert) {
    +		$this->convert = ($convert) ? 1 : 0;
    +	}
    +
    +	/**
    +	 * Get the value of the protected property delete
    +	 *
    +	 * @return integer
    +	 */
    +	public function getDelete() {
    +		return $this->delete;
    +	}
    +	
    +	/**
    +	 * Set the value of the private property delete
    +	 *
    +	 * @param integer $delete
    +	 * @return void
    +	 */
    +	public function setDelete($delete) {
    +		$this->delete = ($delete) ? 1 : 0;
    +	}
    +
    +	/**
    +	 * Get the value of the protected property simulate
    +	 *
    +	 * @return integer
    +	 */
    +	public function getSimulate() {
    +		return $this->simulate;
    +	}
    +	
    +	/**
    +	 * Set the value of the private property simulate
    +	 *
    +	 * @param integer $simulate
    +	 * @return void
    +	 */
    +	public function setSimulate($simulate) {
    +		$this->simulate = ($simulate) ? 1 : 0;
    +	}
    +	
    +	
    +	public function execute()
    +	{
    +		$successfullyExecuted = TRUE;
    +		$insert = array();
    +		$ln = "\r\n";							// line break
    +		$pid = (int) $this->getPage();			// folder with CD elements
    +		$syslanguid = (int) $this->getLanguage();	// sys_language_uid ID
    +		$separator = $this->getSeparator();		// Texttrenner
    +		$delimiter = $this->getDelimiter();		// Feldtrenner
    +		$convert = ($this->getConvert()) ? TRUE : FALSE;	// convert from ASCII to UTF-8?
    +		$delete = ($this->getDelete()) ? TRUE : FALSE;		// delete entries first?
    +		$simulate = ($this->getSimulate()) ? TRUE : FALSE;	// simulate import?
    +		$fields = $this->getFields();			// fields for import
    +		$fields_names = explode(',', $fields);	// field-array
    +		
    +		// files sortiert nach Name, dann umkehren
    +		$path = \TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/' . $this->getCsvfile();
    +		$files = array_filter(glob($path), 'is_file');
    +		$total = count($files);
    +		if ($total > 1) $files = array_reverse($files);
    +		$newestFile = '';
    +		foreach ($files as $file) {
    +			$newestFile = $file;				// take only the first found file
    +			break;
    +		}
    +		if (!$newestFile) {
    +			return FALSE;	// keine Datei gefunden
    +		}
    +		
    +		if ($delete && !$simulate) {
    +			// erst löschen
    +			/*
    +			$res = $GLOBALS['TYPO3_DB']->exec_DELETEquery( 'tx_fpmasterquiz_domain_model_quiz', 'pid=' . $pid . ' AND sys_language_uid=' . $syslanguid );
    +			$res = $GLOBALS['TYPO3_DB']->exec_DELETEquery( 'tx_fpmasterquiz_domain_model_question', 'pid=' . $pid . ' AND sys_language_uid=' . $syslanguid );
    +			$res = $GLOBALS['TYPO3_DB']->exec_DELETEquery( 'tx_fpmasterquiz_domain_model_answer', 'pid=' . $pid . ' AND sys_language_uid=' . $syslanguid );
    +			$res = $GLOBALS['TYPO3_DB']->exec_DELETEquery( 'tx_fpmasterquiz_domain_model_evaluation', 'pid=' . $pid . ' AND sys_language_uid=' . $syslanguid );
    +			*/
    +		}
    +		
    +		// Import
    +		$lines = array();
    +		if ($newestFile)
    +			$lines = file($newestFile);
    +		if ( count($lines) > 1 ) {
    +			$nr=0;
    +			$fields_values = array();
    +			$fields_values['pid'] = $pid;
    +			$fields_values['tstamp'] = time();
    +			$fields_values['crdate'] = time();
    +			$fields_values['sys_language_uid'] = $syslanguid;
    +			$fields_values['cruser_id'] = $GLOBALS['BE_USER']->user["uid"];
    +			$handle = fopen ($newestFile, "r");              // Datei zum Lesen oeffnen
    +
    +			if ($separator) {
    +				while ( ($fields_read = fgetcsv ($handle, 2000, $delimiter, $separator)) !== FALSE ) {
    +					if ($nr==0) {
    +						//$fields_names = $Felder;
    +					} else if ($fields_read[0]) {
    +						$result = $this->insertLine($fields_names, $fields_values, $fields_read, $simulate, $convert);
    +						if ($simulate) {
    +							$insert[] = $result;
    +						} else if (!$result) {
    +							$successfullyExecuted = FALSE;
    +						}
    +					}
    +					$nr++;
    +				}
    +			} else {
    +				while ( ($fields_read = fgetcsv ($handle, 2000, $delimiter)) !== FALSE ) {
    +					if ($nr==0) {
    +						//$fields_names = $Felder;
    +					} else if ($fields_read[0]) {
    +						$result = $this->insertLine($fields_names, $fields_values, $fields_read, $simulate, $convert);
    +						if ($simulate) {
    +							$insert[] = $result;
    +						} else if (!$result) {
    +							$successfullyExecuted = FALSE;
    +						}
    +					}
    +					$nr++;
    +				}
    +			}
    +			
    +			fclose ($handle);
    +			if ($simulate) {
    +				$output = $this->build_table($insert);
    +				$message = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
    +						$output,
    +						'Simulation:', // the header is optional
    +						\TYPO3\CMS\Core\Messaging\FlashMessage::INFO,
    +						FALSE
    +				);
    +				$flashMessageService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessageService');
    +				$messageQueue = $flashMessageService->getMessageQueueByIdentifier();
    +				$messageQueue->addMessage($message);
    +			}
    +		} else {
    +			$successfullyExecuted = FALSE;
    +		}
    +		return $successfullyExecuted;
    +	}
    +	
    +	/**
    +	 * Inserts a line to the database
    +	 *
    +	 * @return	mixed
    +	 */
    +	function insertLine($names, $values, $fields, $simulate, $convert)
    +	{
    +		$success_global = TRUE;
    +		for ($i=0; $i<count($names); $i++) {
    +			$feld = trim($names[$i]);
    +			
    +				if ($convert) {
    +					$values[$feld] = trim(iconv('iso-8859-1','utf-8',$fields[$i]));
    +				} else {
    +					$values[$feld] = trim($fields[$i]);
    +				}
    +			
    +		}
    +		if (!$simulate) {
    +			/*
    +			$success_insert = $GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_fpmasterquiz_domain_model_question', $values);
    +			if ($success_insert) {
    +				$values['uid'] = $GLOBALS['TYPO3_DB']->sql_insert_id();
    +			} else {
    +				$values['uid'] = 0;
    +				$success_global = FALSE;
    +			}
    +			*/
    +		} else {
    +			$values['uid'] = 0;
    +		}
    +		
    +		if ($simulate) {
    +			return $values;
    +		} else {
    +			return $success_global;
    +		}
    +	}
    +
    +	/**
    +	 * Aray nach Tabelle
    +	 *
    +	 * @return	string
    +	 */
    +	function build_table($array)
    +	{
    +		// start table
    +		$html = '<style>table tr th, table tr td {padding:3px;border:1px solid #666;}</style><table class="dump">';
    +		// header row
    +		$html .= '<tr>';
    +		foreach($array[0] as $key=>$value){
    +			$html .= '<th>' . $key . '</th>';
    +		}
    +		$html .= '</tr>';
    +	
    +		// data rows
    +		foreach( $array as $key=>$value){
    +			$html .= '<tr>';
    +			foreach($value as $key2=>$value2){
    +				$html .= '<td>' . strip_tags($value2) . '</td>';
    +			}
    +			$html .= '</tr>';
    +		}
    +	
    +		// finish table and return it
    +		$html .= '</table>';
    +		return $html;
    +	}
    +}
    
  • Classes/Task/ImportQuizAdditionalFieldProvider.php+154 0 added
    @@ -0,0 +1,154 @@
    +<?php
    +namespace Fixpunkt\FpMasterquiz\Task;
    +
    +use TYPO3\CMS\Backend\Utility\BackendUtility;
    +use TYPO3\CMS\Core\Utility\GeneralUtility;
    +use TYPO3\CMS\Core\Database\ConnectionPool;
    +use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
    +use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
    +use TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider;
    +use TYPO3\CMS\Scheduler\Controller\SchedulerModuleController;
    +use TYPO3\CMS\Scheduler\Task\AbstractTask;
    +use TYPO3\CMS\Scheduler\Task\Enumeration\Action;
    +use TYPO3\CMS\Core\Messaging\FlashMessage;
    +
    +class ImportQuizAdditionalFieldProvider extends AbstractAdditionalFieldProvider
    +{
    +	/**
    +	 * Render additional information fields within the scheduler backend.
    +	 *
    +	 * @param array $taskInfo Array information of task to return
    +	 * @param ValidatorTask|null $task The task object being edited. Null when adding a task!
    +	 * @param SchedulerModuleController $schedulerModule Reference to the BE module of the Scheduler
    +	 * @return array Additional fields
    +	 * @see AdditionalFieldProviderInterface->getAdditionalFields($taskInfo, $task, $schedulerModule)
    +	 */
    +	public function getAdditionalFields(array &$taskInfo, $task, SchedulerModuleController $schedulerModule)
    +	{
    +		$additionalFields = array();
    +		$currentSchedulerModuleAction = $schedulerModule->getCurrentAction();
    +		if (empty($taskInfo['page'])) {
    +			if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    +				$taskInfo['page'] = '';
    +			} else {
    +				$taskInfo['page'] = $task->getPage();
    +			}
    +		}
    +		if (empty($taskInfo['language'])) {
    +			if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    +				$taskInfo['language'] = '0';
    +			} else {
    +				$taskInfo['language'] = $task->getLanguage();
    +			}
    +		}
    +		if (empty($taskInfo['simulate'])) {
    +			if ($currentSchedulerModuleAction->equals(Action::ADD)) {
    +				$taskInfo['simulate'] = 0;
    +			} else {
    +				$taskInfo['simulate'] = $task->getSimulate();
    +			}
    +		}
    +		
    +		// Ordner
    +		$fieldId = 'task_page';
    +		$fieldCode = '<input type="text" name="tx_scheduler[fp_masterquiz][page]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['page']) . '"/>';
    +		$label = $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.page');
    +		$label = BackendUtility::wrapInHelp('fp_masterquiz', $fieldId, $label);
    +		$additionalFields[$fieldId] = array(
    +				'code' => $fieldCode,
    +				'label' => $label
    +		);
    +		// Sprache
    +		$fieldId = 'task_language';
    +		$fieldCode = '<input type="text" name="tx_scheduler[fp_masterquiz][language]" id="' . $fieldId . '" value="' . htmlspecialchars($taskInfo['language']) . '"/>';
    +		$label = $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.language');
    +		$label = BackendUtility::wrapInHelp('fp_masterquiz', $fieldId, $label);
    +		$additionalFields[$fieldId] = array(
    +				'code' => $fieldCode,
    +				'label' => $label
    +		);
    +		// simulate
    +		$fieldId = 'task_simulate';
    +		$checked = ($taskInfo['simulate']) ? ' checked="checked"' : '';
    +		$fieldCode = '<input type="checkbox" name="tx_scheduler[fp_masterquiz][simulate]" id="' . $fieldId . '" value="1"' . $checked . ' />';
    +		$label = $GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.simulate');
    +		$label = BackendUtility::wrapInHelp('fp_masterquiz', $fieldId, $label);
    +		$additionalFields[$fieldId] = array(
    +				'code' => $fieldCode,
    +				'label' => $label
    +		);
    +		return $additionalFields;
    +	}
    +	
    +	/**
    +	 * This method checks any additional data that is relevant to the specific task.
    +	 * If the task class is not relevant, the method is expected to return TRUE.
    +	 *
    +	 * @param array $submittedData Reference to the array containing the data submitted by the user
    +	 * @param SchedulerModuleController $schedulerModule Reference to the BE module of the Scheduler
    +	 * @return bool TRUE if validation was ok (or selected class is not relevant), FALSE otherwise
    +	 */
    +	public function validateAdditionalFields(array &$submittedData, SchedulerModuleController $schedulerModule)
    +	{
    +		$isValid = TRUE;
    +		if ($submittedData['fp_masterquiz']['page'] > 0) {
    +			$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
    +			$count = $queryBuilder
    +				->count('uid')
    +				->from('pages')
    +				->where(
    +					$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter((int)$submittedData['fp_masterquiz']['page'], \PDO::PARAM_INT))
    +				)
    +				->execute()
    +				->fetchColumn(0);
    +			if ($count == 0) {
    +				$isValid = FALSE;
    +				$this->addMessage(
    +					$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.invalidPage'),
    +					FlashMessage::ERROR
    +				);
    +			}
    +		} else {
    +			$isValid = FALSE;
    +			$this->addMessage(
    +				$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.invalidPage'),
    +				FlashMessage::ERROR
    +			);
    +		}
    +		$lang = (int)$submittedData['fp_masterquiz']['language'];
    +		if ($lang > 0) {
    +			$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_language');
    +			$count = $queryBuilder
    +				->count('uid')
    +				->from('sys_language')
    +				->where(
    +					$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($lang, \PDO::PARAM_INT))
    +				)
    +				->execute()
    +				->fetchColumn(0);
    +			if ($count == 0) {
    +				$isValid = FALSE;
    +				$this->addMessage(
    +					$GLOBALS['LANG']->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.validate.invalidLanguage'),
    +					FlashMessage::ERROR
    +				);
    +			}
    +		}
    +		return $isValid;
    +	}
    +	
    +	/**
    +	 * This method is used to save any additional input into the current task object
    +	 * if the task class matches.
    +	 *
    +	 * @param array $submittedData Array containing the data submitted by the user
    +	 * @param AbstractTask $task Reference to the current task object
    +	 */
    +	public function saveAdditionalFields(array $submittedData, AbstractTask $task)
    +	{
    +		/** @var $task ValidatorTask */
    +		$task->setPage($submittedData['fp_masterquiz']['page']);
    +		$task->setLanguage($submittedData['fp_masterquiz']['language']);
    +		$task->setSimulate($submittedData['fp_masterquiz']['simulate']);
    +	}
    +}
    \ No newline at end of file
    
  • Classes/Task/ImportQuizTask.php+281 0 added
    @@ -0,0 +1,281 @@
    +<?php
    +namespace Fixpunkt\FpMasterquiz\Task;
    +
    +use TYPO3\CMS\Core\Utility\GeneralUtility;
    +use TYPO3\CMS\Core\Database\ConnectionPool;
    +use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
    +use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
    +
    +class ImportQuizTask extends \TYPO3\CMS\Scheduler\Task\AbstractTask {
    +    
    +    /**
    +     * Uid of the folder
    +     *
    +     * @var integer
    +     */
    +    protected $page = 0;
    +    
    +    /**
    +     * Uid of the language
    +     *
    +     * @var integer
    +     */
    +    protected $language = 0;
    +    
    +    /**
    +     * Simulate only?
    +     *
    +     * @var integer
    +     */
    +    protected $simulate = 0;
    +    
    +    
    +    /**
    +     * Get the value of the protected property page
    +     *
    +     * @return integer UID of the start page for this task
    +     */
    +    public function getPage() {
    +        return $this->page;
    +    }
    +    
    +    /**
    +     * Set the value of the private property page
    +     *
    +     * @param integer $page UID of the start page for this task.
    +     * @return void
    +     */
    +    public function setPage($page) {
    +        $this->page = $page;
    +    }
    +    
    +    /**
    +     * Get the value of the protected property language
    +     *
    +     * @return integer UID of the language for this task
    +     */
    +    public function getLanguage() {
    +        return $this->language;
    +    }
    +    
    +    /**
    +     * Set the value of the private property language
    +     *
    +     * @param integer $page UID of the language for this task.
    +     * @return void
    +     */
    +    public function setLanguage($language) {
    +        $this->language = $language;
    +    }
    +    
    +    /**
    +     * Get the value of the protected property simulate
    +     *
    +     * @return integer
    +     */
    +    public function getSimulate() {
    +        return $this->simulate;
    +    }
    +    
    +    /**
    +     * Set the value of the private property simulate
    +     *
    +     * @param integer $simulate
    +     * @return void
    +     */
    +    public function setSimulate($simulate) {
    +        $this->simulate = ($simulate) ? 1 : 0;
    +    }
    +    
    +    
    +    public function execute() {
    +        $successfullyExecuted = TRUE;
    +        $insert = [];
    +        $pid = (int) $this->getPage();			// folder with CD elements
    +        $syslanguid = (int) $this->getLanguage();	// sys_language_uid ID
    +        $simulate = ($this->getSimulate()) ? TRUE : FALSE;	// simulate import?
    +        
    +        $fieldConfig = $GLOBALS['TCA']['tx_fpmasterquiz_domain_model_quiz']['columns']['path_segment']['config'];
    +        $slugHelper = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\SlugHelper::class, 'tx_fpmasterquiz_domain_model_quiz', 'path_segment', $fieldConfig);
    +        
    +        // Import
    +        $slugArray = [];
    +        $selectedArray = [];
    +        // select all participant elements of one folder
    +        /*
    +         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_myquizpoll_question');
    +         $statement = $queryBuilder
    +         ->select('*')
    +         ->from('tx_myquizpoll_question')
    +         ->where(
    +         $queryBuilder->expr()->eq('deleted', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
    +         )
    +         ->andWhere(
    +         $queryBuilder->expr()->eq('hidden', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
    +         )
    +         ->andWhere(
    +         $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT))
    +         )
    +         ->andWhere(
    +         $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($syslanguid, \PDO::PARAM_INT))
    +         )
    +         ->execute();
    +         while ($row = $statement->fetch()) {
    +         $selectedArray[] = $row;
    +         }
    +         */
    +        $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
    +            '*',
    +            'tx_myquizpoll_question',
    +            'deleted=0 AND hidden=0 AND t3ver_oid=0 AND pid=' . $pid . ' AND sys_language_uid IN (' . $syslanguid . ',-1)',
    +            '',
    +            'sorting ASC'
    +            );
    +        if ($GLOBALS['TYPO3_DB']->sql_num_rows($res) > 0) {
    +            while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)){
    +                $selectedArray[] = $row;
    +            }
    +        }
    +        $GLOBALS['TYPO3_DB']->sql_free_result($res);
    +        
    +        if ( count($selectedArray) > 0 ) {
    +            $nr=0;
    +            $fields_values = array();
    +            $fields_values['pid'] = $pid;
    +            $fields_values['tstamp'] = time();
    +            $fields_values['sys_language_uid'] = $syslanguid;
    +            $fields_values['cruser_id'] = $GLOBALS['BE_USER']->user["uid"];
    +            
    +            // Quiz einfügen
    +            $quiz_values = $fields_values;
    +            $answer_values = $fields_values;
    +            $quiz_values['crdate'] = time();
    +            $quiz_values['name'] = 'Import-Quiz ' . time();
    +            $quiz_values['about'] = 'Dummy text';
    +            $quiz_values['questions'] = count($selectedArray);
    +            $quiz_values['sorting'] = 128;
    +            $slug = $slugHelper->generate($quiz_values, $quiz_values['pid']);
    +            if ($slugArray[$slug]) {
    +                // Der Slughelper prüft nicht auf unique, also müssen wir das machen
    +                for ($i = 1; $i < 99; $i++) {
    +                    $tmp = $slug . '-' . $i;
    +                    if (!$slugArray[$tmp]) {
    +                        $slug = $tmp;
    +                        break;
    +                    }
    +                }
    +            }
    +            $slugArray[$slug] = 1;
    +            $quiz_values['path_segment'] = $slug;
    +            if ($simulate) {
    +                $success_insert = TRUE;
    +            } else {
    +                $success_insert = $GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_fpmasterquiz_domain_model_quiz', $quiz_values);
    +            }
    +            if ($success_insert) {
    +                $quiz_uid = ($simulate) ? 1 : $GLOBALS['TYPO3_DB']->sql_insert_id();
    +                if ($quiz_uid) {
    +                    // Fragen einfügen
    +                    foreach ($selectedArray as $entry) {
    +                        $fields_values['crdate'] = $entry['crdate'];
    +                        $fields_values['sorting'] = $entry['sorting'];
    +                        $fields_values['l10n_parent'] = 0;   // kennen wir nicht wirklich
    +                        $fields_values['title'] = $entry['title'];
    +                        $fields_values['bodytext'] = $entry['name'];
    +                        $fields_values['qmode'] = $entry['qtype'];
    +                        $fields_values['explanation'] = $entry['explanation'];
    +                        $fields_values['quiz'] = $quiz_uid;
    +                        $nr=0;
    +                        for ($i=1; $i<=6; $i++) {
    +                            if ($entry['answer' . $i]) {
    +                                $nr++;
    +                            }
    +                        }
    +                        $fields_values['answers'] = $nr;
    +                        $insert[] = $fields_values;
    +                        if (!$simulate) {
    +                            $success_insert = $GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_fpmasterquiz_domain_model_question', $fields_values);
    +                            if ($success_insert) {
    +                                // Antworten einfügen
    +                                $question_uid = $GLOBALS['TYPO3_DB']->sql_insert_id();
    +                                if ($question_uid) {
    +                                    for ($i=1; $i<=6; $i++) {
    +                                        if ($entry['answer' . $i]) {
    +                                            $points = $entry['points' . $i];
    +                                            if (!$points && $entry['correct' . $i]) {
    +                                                $points = $entry['points'];
    +                                            }
    +                                            $answer_values['crdate'] = $entry['crdate'];
    +                                            $answer_values['sorting'] = $i * 128;
    +                                            $answer_values['l10n_parent'] = 0;   // is unknown
    +                                            $answer_values['title'] = $entry['answer' . $i];
    +                                            $answer_values['points'] = $points;
    +                                            $answer_values['question'] = $question_uid;
    +                                            $success_insert = $GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_fpmasterquiz_domain_model_answer', $answer_values);
    +                                            if (!$selectedArray) {
    +                                                $successfullyExecuted = FALSE;
    +                                            }
    +                                        }
    +                                    }
    +                                } else {
    +                                    $successfullyExecuted = FALSE;
    +                                }
    +                            } else {
    +                                $successfullyExecuted = FALSE;
    +                            }
    +                        }
    +                    }
    +                } else {
    +                    $successfullyExecuted = FALSE;
    +                }
    +            } else {
    +                $successfullyExecuted = FALSE;
    +            }
    +            
    +            if ($simulate) {
    +                $output = $this->build_table($insert);
    +                $message = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
    +                    $output,
    +                    'Simulation:', // the header is optional
    +                    \TYPO3\CMS\Core\Messaging\FlashMessage::INFO,
    +                    FALSE
    +                    );
    +                $flashMessageService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessageService');
    +                $messageQueue = $flashMessageService->getMessageQueueByIdentifier();
    +                $messageQueue->addMessage($message);
    +            }
    +        } else {
    +            $successfullyExecuted = FALSE;
    +        }
    +        return $successfullyExecuted;
    +    }
    +    
    +    /**
    +     * Aray nach Tabelle
    +     *
    +     * @return	string
    +     */
    +    function build_table($array){
    +        // start table
    +        $html = '<style>table tr th, table tr td {padding:3px;border:1px solid #666;}</style><table class="dump">';
    +        // header row
    +        $html .= '<tr>';
    +        foreach($array[0] as $key=>$value){
    +            $html .= '<th>' . $key . '</th>';
    +        }
    +        $html .= '</tr>';
    +        
    +        // data rows
    +        foreach( $array as $value){
    +            $html .= '<tr>';
    +            foreach($value as $value2){
    +                $html .= '<td>' . strip_tags($value2) . '</td>';
    +            }
    +            $html .= '</tr>';
    +        }
    +        
    +        // finish table and return it
    +        $html .= '</table>';
    +        return $html;
    +    }
    +}
    
  • Classes/Utility/TemplateLayout.php+1 1 modified
    @@ -24,7 +24,7 @@
     /*
      * modified 2019 by Kurt Gusbeth
     */
    -namespace Fixpunkt\FpMasterquiz\Utility;
    +namespace Fixpunkt\FpMasterQuiz\Utility;
     
     /**
      * TemplateLayout: Template-Layout per TSconfig
    
  • Classes/Widgets/Provider/ParticipantsDataProvider.php+0 171 removed
    @@ -1,171 +0,0 @@
    -<?php
    -
    -declare(strict_types=1);
    -
    -/*
    - * This file is part of the TYPO3 CMS project.
    - *
    - * It is free software; you can redistribute it and/or modify it under
    - * the terms of the GNU General Public License, either version 2
    - * of the License, or any later version.
    - *
    - * For the full copyright and license information, please read the
    - * LICENSE.txt file that was distributed with this source code.
    - *
    - * The TYPO3 project - inspiring people to share!
    - */
    -
    -namespace Fixpunkt\FpMasterquiz\Widgets\Provider;
    -
    -use TYPO3\CMS\Core\Database\Connection;
    -use TYPO3\CMS\Core\Database\ConnectionPool;
    -use TYPO3\CMS\Core\Localization\LanguageService;
    -use TYPO3\CMS\Core\Utility\GeneralUtility;
    -use TYPO3\CMS\Dashboard\WidgetApi;
    -use TYPO3\CMS\Dashboard\Widgets\ChartDataProviderInterface;
    -
    -class ParticipantsDataProvider implements ChartDataProviderInterface
    -{
    -    /**
    -     * Number of days to gather information for.
    -     *
    -     * @var int
    -     */
    -    protected $days = 31;
    -
    -    /**
    -     * @var array
    -     */
    -    protected $labels = [];
    -
    -    /**
    -     * @var array
    -     */
    -    protected $data = [];
    -
    -    public function __construct(int $days = 31)
    -    {
    -        $this->days = $days;
    -    }
    -
    -    /**
    -     * @inheritDoc
    -     */
    -    public function getChartData(): array
    -    {
    -        $this->calculateDataForLastDays();
    -
    -        return [
    -            'labels' => $this->labels,
    -            'datasets' => [
    -                [
    -                    'label' => $this->getLanguageService()->sL('LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:votes'),
    -                    'backgroundColor' => WidgetApi::getDefaultChartColors()[0],
    -                    'border' => 0,
    -                    'data' => $this->data,
    -                ],
    -            ],
    -        ];
    -    }
    -
    -    protected function getNumberOfVotesInPeriod(int $start, int $end): int
    -    {
    -        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_fpmasterquiz_domain_model_participant');
    -        return (int)$queryBuilder
    -            ->count('*')
    -            ->from('tx_fpmasterquiz_domain_model_participant')
    -            ->where(
    -                $queryBuilder->expr()->gte(
    -                    'tstamp',
    -                    $queryBuilder->createNamedParameter($start, Connection::PARAM_INT)
    -                ),
    -                $queryBuilder->expr()->lte(
    -                    'tstamp',
    -                    $queryBuilder->createNamedParameter($end, Connection::PARAM_INT)
    -                )
    -            )
    -            ->execute()
    -            ->fetchColumn();
    -    }
    -
    -    protected function calculateDataForLastDays(): void
    -    {
    -        $format = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] ?: 'Y-m-d';
    -
    -        for ($daysBefore = $this->days; $daysBefore >= 0; $daysBefore--) {
    -            $this->labels[] = date($format, (int)strtotime('-' . $daysBefore . ' day'));
    -            $startPeriod = (int)strtotime('-' . $daysBefore . ' day 0:00:00');
    -            $endPeriod =  (int)strtotime('-' . $daysBefore . ' day 23:59:59');
    -
    -            $this->data[] = $this->getNumberOfVotesInPeriod($startPeriod, $endPeriod);
    -        }
    -    }
    -
    -    public function getRecentParticipants(): array
    -    {
    -        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_fpmasterquiz_domain_model_participant');
    -        $dataArray = $queryBuilder
    -            ->select('tx_fpmasterquiz_domain_model_participant.uid AS partid','tx_fpmasterquiz_domain_model_participant.crdate AS startdate','tx_fpmasterquiz_domain_model_participant.name AS username', 'points', 'maximum2', 'quiztable.name AS quizname')
    -            ->from('tx_fpmasterquiz_domain_model_participant')
    -            ->join(
    -                'tx_fpmasterquiz_domain_model_participant',
    -                'tx_fpmasterquiz_domain_model_quiz',
    -                'quiztable',
    -                $queryBuilder->expr()->eq('quiztable.uid', $queryBuilder->quoteIdentifier('tx_fpmasterquiz_domain_model_participant.quiz'))
    -            )
    -            ->orderBy('startdate', 'DESC')
    -            ->setMaxResults(7)
    -            ->execute()
    -            ->fetchAll();
    -        $i = 0;
    -        foreach ($dataArray as $result) {
    -            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_fpmasterquiz_domain_model_selected');
    -            $answerArray = $queryBuilder
    -                ->select('participant','answertable.title AS answertitle', 'questiontable.title AS questiontitle')
    -                ->from('tx_fpmasterquiz_domain_model_selected')
    -                ->where($queryBuilder->expr()->eq('participant', $queryBuilder->createNamedParameter($result['partid'], \PDO::PARAM_INT)))
    -                ->join(
    -                    'tx_fpmasterquiz_domain_model_selected',
    -                    'tx_fpmasterquiz_selected_answer_mm',
    -                    'mmrel',
    -                    $queryBuilder->expr()->eq(
    -                        'mmrel.uid_local',
    -                        $queryBuilder->quoteIdentifier('tx_fpmasterquiz_domain_model_selected.uid')
    -                    )
    -                )
    -                ->join(
    -                    'mmrel',
    -                    'tx_fpmasterquiz_domain_model_answer',
    -                    'answertable',
    -                    $queryBuilder->expr()->eq(
    -                        'answertable.uid',
    -                        $queryBuilder->quoteIdentifier('mmrel.uid_foreign')
    -                    )
    -                )
    -                ->join(
    -                    'tx_fpmasterquiz_domain_model_selected',
    -                    'tx_fpmasterquiz_domain_model_question',
    -                    'questiontable',
    -                    $queryBuilder->expr()->eq(
    -                        'questiontable.uid',
    -                        $queryBuilder->quoteIdentifier('tx_fpmasterquiz_domain_model_selected.question')
    -                    )
    -                )
    -                ->orderBy('tx_fpmasterquiz_domain_model_selected.sorting', 'ASC')
    -                ->setMaxResults(1)
    -                ->execute()
    -                ->fetchAll();
    -            foreach ($answerArray as $oneAnswer) {
    -                $dataArray[$i]['question1'] = $oneAnswer['questiontitle'];
    -                $dataArray[$i]['answer1'] = $oneAnswer['answertitle'];
    -            }
    -            $i++;
    -        }
    -        return $dataArray;
    -    }
    -
    -    protected function getLanguageService(): LanguageService
    -    {
    -        return $GLOBALS['LANG'];
    -    }
    -}
    \ No newline at end of file
    
  • Classes/Widgets/RecentParticipantsWidget.php+0 61 removed
    @@ -1,61 +0,0 @@
    -<?php
    -
    -declare(strict_types = 1);
    -
    -namespace Fixpunkt\FpMasterquiz\Widgets;
    -
    -use Fixpunkt\FpMasterquiz\Widgets\Provider\ParticipantsDataProvider;
    -use TYPO3\CMS\Dashboard\Widgets\WidgetConfigurationInterface;
    -use TYPO3\CMS\Dashboard\Widgets\WidgetInterface;
    -use TYPO3\CMS\Fluid\View\StandaloneView;
    -
    -class RecentParticipantsWidget implements WidgetInterface
    -{
    -    /**
    -     * @var WidgetConfigurationInterface
    -     */
    -    private $configuration;
    -
    -    /**
    -     * @var StandaloneView
    -     */
    -    private $view;
    -
    -    /**
    -     * @var array
    -     */
    -    private $options;
    -
    -    /**
    -     * @var ParticipantsDataProvider
    -     */
    -    private $dataProvider;
    -
    -    public function __construct(
    -        WidgetConfigurationInterface $configuration,
    -        StandaloneView               $view,
    -        ParticipantsDataProvider     $dataProvider,
    -        array                        $options = []
    -    ) {
    -        $this->configuration = $configuration;
    -        $this->view = $view;
    -        $this->dataProvider = $dataProvider;
    -        $this->options = array_merge(
    -            [
    -                'showErrors' => true,
    -                'showWarnings' => false
    -            ],
    -            $options
    -        );
    -    }
    -
    -    public function renderWidgetContent(): string
    -    {
    -        $this->view->setTemplate('Widget/RecentParticipantsWidget');
    -        $this->view->assignMultiple([
    -            'configuration' => $this->configuration,
    -            'participants' => $this->dataProvider->getRecentParticipants()
    -        ]);
    -        return $this->view->render();
    -    }
    -}
    
  • composer.json+4 1 modified
    @@ -8,7 +8,7 @@
     		}
     	],
     	"require" : {
    -		"typo3/cms-core" : "~10.4.6 || ~11.5.0"
    +		"typo3/cms-core" : "~9.5.20 || ~10.4.6"
     	},
     	"autoload" : {
     		"psr-4" : {
    @@ -24,6 +24,9 @@
     		"typo3-ter/fp-masterquiz" : "self.version"
     	},
     	"homepage" : "https://github.com/bihor/fp_masterquiz",
    +	"support" : {
    +		"email" : "info@quizpalme.de"
    +	},
     	"license" : "GPL-3.0-or-later",
     	"keywords" : [
     		"quiz poll myquizpoll"
    
  • Configuration/Backend/DashboardWidgetGroups.php+0 6 removed
    @@ -1,6 +0,0 @@
    -<?php
    -return [
    -    'fixpunkt' => [
    -        'title' => 'Fixpunkt',
    -    ],
    -];
    \ No newline at end of file
    
  • Configuration/FlexForms/flexform_pi1.xml+11 198 modified
    @@ -32,15 +32,11 @@
     			   <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:template.intro</numIndex>
     			   <numIndex index="1">Quiz->intro;Quiz->show;Quiz->showAjax;Quiz->showByTag</numIndex>
     			 </numIndex>
    -			   <numIndex index="4">
    -				   <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:template.closure</numIndex>
    -				   <numIndex index="1">Quiz->closure</numIndex>
    -			   </numIndex>
    -             <numIndex index="5">
    +             <numIndex index="4">
                     <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:template.result</numIndex>
                     <numIndex index="1">Quiz->defaultres;Quiz->result</numIndex>
                  </numIndex>
    -			 <numIndex index="6">
    +			 <numIndex index="5">
     				<numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:template.highscore</numIndex>
     				<numIndex index="1">Quiz->highscore</numIndex>
     			 </numIndex>
    @@ -92,21 +88,6 @@
     					</config>
     				</TCEforms>
     		  </settings.showPageUid>
    -			<settings.closurePageUid>
    -				<TCEforms>
    -					<label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.closurePageUid</label>
    -					<displayCond>FIELD:sUSER.settings.user.askForData:=:3</displayCond>
    -					<config>
    -						<type>group</type>
    -						<internal_type>db</internal_type>
    -						<allowed>pages</allowed>
    -						<size>1</size>
    -						<maxitems>1</maxitems>
    -						<minitems>0</minitems>
    -						<show_thumbs>0</show_thumbs>
    -					</config>
    -				</TCEforms>
    -			</settings.closurePageUid>
               <settings.resultPageUid>
     				<TCEforms>
     					<label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.resultPageUid</label>
    @@ -138,6 +119,15 @@
               <settings.defaultQuizUid>
     				<TCEforms>
     					<label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.defaultQuizUid</label>
    +					<displayCond>
    +						<OR>
    +							<numIndex index="0"><![CDATA[FIELD:sDEF.switchableControllerActions:=:Quiz->default;Quiz->show;Quiz->showAjax]]></numIndex>
    +							<numIndex index="1"><![CDATA[FIELD:sDEF.switchableControllerActions:=:Quiz->showByTag]]></numIndex>
    +							<numIndex index="2"><![CDATA[FIELD:sDEF.switchableControllerActions:=:Quiz->intro;Quiz->show;Quiz->showAjax;Quiz->showByTag]]></numIndex>
    +							<numIndex index="3"><![CDATA[FIELD:sDEF.switchableControllerActions:=:Quiz->defaultres;Quiz->result]]></numIndex>
    +							<numIndex index="4"><![CDATA[FIELD:sDEF.switchableControllerActions:=:Quiz->highscore]]></numIndex>
    +						</OR>
    +					</displayCond>
     	                <config>
     						<type>group</type>
     						<internal_type>db</internal_type>
    @@ -313,96 +303,6 @@
     					</config>
     				</TCEforms>
     		  </settings.showPoints>
    -			<settings.showDetailedCategoryEval>
    -				<TCEforms>
    -					<label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.showDetailedCategoryEval</label>
    -					<config>
    -						<type>radio</type>
    -						<items type="array">
    -							<numIndex index="0" type="array">
    -								<numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.no</numIndex>
    -								<numIndex index="1">0</numIndex>
    -							</numIndex>
    -							<numIndex index="1" type="array">
    -								<numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.yes</numIndex>
    -								<numIndex index="1">1</numIndex>
    -							</numIndex>
    -						</items>
    -					</config>
    -				</TCEforms>
    -			</settings.showDetailedCategoryEval>
    -			<settings.noFormCheck>
    -				<TCEforms>
    -					<label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.noFormCheck</label>
    -					<config>
    -						<type>radio</type>
    -						<items type="array">
    -							<numIndex index="0" type="array">
    -								<numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.no</numIndex>
    -								<numIndex index="1">0</numIndex>
    -							</numIndex>
    -							<numIndex index="1" type="array">
    -								<numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.yes</numIndex>
    -								<numIndex index="1">1</numIndex>
    -							</numIndex>
    -						</items>
    -					</config>
    -				</TCEforms>
    -			</settings.noFormCheck>
    -			<settings.phpFormCheck>
    -				<TCEforms>
    -					<label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.phpFormCheck</label>
    -					<config>
    -						<type>radio</type>
    -						<items type="array">
    -							<numIndex index="0" type="array">
    -								<numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.no</numIndex>
    -								<numIndex index="1">0</numIndex>
    -							</numIndex>
    -							<numIndex index="1" type="array">
    -								<numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.yes</numIndex>
    -								<numIndex index="1">1</numIndex>
    -							</numIndex>
    -						</items>
    -					</config>
    -				</TCEforms>
    -			</settings.phpFormCheck>
    -          <settings.allowEdit>
    -				<TCEforms>
    -					<label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.allowEdit</label>
    -	                <config>
    -						<type>radio</type>
    -						<items type="array">
    -							<numIndex index="0" type="array">
    -								<numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.no</numIndex>
    -								<numIndex index="1">0</numIndex>
    -							</numIndex>
    -							<numIndex index="1" type="array">
    -								<numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.yes</numIndex>
    -								<numIndex index="1">1</numIndex>
    -							</numIndex>
    -						</items>
    -					</config>
    -				</TCEforms>
    -		  </settings.allowEdit>
    -			<settings.random>
    -				<TCEforms>
    -					<label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.random</label>
    -					<config>
    -						<type>radio</type>
    -						<items type="array">
    -							<numIndex index="0" type="array">
    -								<numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.no</numIndex>
    -								<numIndex index="1">0</numIndex>
    -							</numIndex>
    -							<numIndex index="1" type="array">
    -								<numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.yes</numIndex>
    -								<numIndex index="1">1</numIndex>
    -							</numIndex>
    -						</items>
    -					</config>
    -				</TCEforms>
    -			</settings.random>
               <settings.ajax>
     				<TCEforms>
     					<label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.ajax</label>
    @@ -449,97 +349,10 @@
     								  <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.yesIntroPage</numIndex>
     								  <numIndex index="1">2</numIndex>
     							  </numIndex>
    -							  <numIndex index="3" type="array">
    -								  <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.yesFinalPage</numIndex>
    -								  <numIndex index="1">3</numIndex>
    -							  </numIndex>
     						  </items>
     					  </config>
     				  </TCEforms>
     			  </settings.user.askForData>
    -			  <settings.user.checkFEuser>
    -				  <TCEforms>
    -					  <label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.user.checkFEuser</label>
    -					  <config>
    -						  <type>radio</type>
    -						  <items type="array">
    -							  <numIndex index="0" type="array">
    -								  <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.no</numIndex>
    -								  <numIndex index="1">0</numIndex>
    -							  </numIndex>
    -							  <numIndex index="1" type="array">
    -								  <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.yes</numIndex>
    -								  <numIndex index="1">1</numIndex>
    -							  </numIndex>
    -						  </items>
    -					  </config>
    -				  </TCEforms>
    -			  </settings.user.checkFEuser>
    -			  <settings.user.useQuizPid>
    -				  <TCEforms>
    -					  <label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.user.useQuizPid</label>
    -					  <config>
    -						  <type>radio</type>
    -						  <items type="array">
    -							  <numIndex index="0" type="array">
    -								  <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.no</numIndex>
    -								  <numIndex index="1">0</numIndex>
    -							  </numIndex>
    -							  <numIndex index="1" type="array">
    -								  <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.yes</numIndex>
    -								  <numIndex index="1">1</numIndex>
    -							  </numIndex>
    -						  </items>
    -					  </config>
    -				  </TCEforms>
    -			  </settings.user.useQuizPid>
    -			  <settings.user.ipSave>
    -				  <TCEforms>
    -					  <label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.user.ipSave</label>
    -					  <config>
    -						  <type>radio</type>
    -						  <items type="array">
    -							  <numIndex index="0" type="array">
    -								  <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.no</numIndex>
    -								  <numIndex index="1">0</numIndex>
    -							  </numIndex>
    -							  <numIndex index="1" type="array">
    -								  <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.yes</numIndex>
    -								  <numIndex index="1">1</numIndex>
    -							  </numIndex>
    -						  </items>
    -					  </config>
    -				  </TCEforms>
    -			  </settings.user.ipSave>
    -			  <settings.user.ipAnonymous>
    -				  <TCEforms>
    -					  <label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.user.ipAnonymous</label>
    -					  <config>
    -						  <type>radio</type>
    -						  <items type="array">
    -							  <numIndex index="0" type="array">
    -								  <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.no</numIndex>
    -								  <numIndex index="1">0</numIndex>
    -							  </numIndex>
    -							  <numIndex index="1" type="array">
    -								  <numIndex index="0">LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.yes</numIndex>
    -								  <numIndex index="1">1</numIndex>
    -							  </numIndex>
    -						  </items>
    -					  </config>
    -				  </TCEforms>
    -			  </settings.user.ipAnonymous>
    -			  <settings.user.useCookie>
    -				  <TCEforms>
    -					  <label>LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:settings.user.useCookie</label>
    -					  <config>
    -						  <type>input</type>
    -						  <size>5</size>
    -						  <max>5</max>
    -						  <eval>trim</eval>
    -					  </config>
    -				  </TCEforms>
    -			  </settings.user.useCookie>
     		  </el>
     		  </ROOT>
     	  </sUSER>
    
  • Configuration/Services.php+0 50 removed
    @@ -1,50 +0,0 @@
    -<?php
    -declare(strict_types=1);
    -
    -use Symfony\Component\DependencyInjection\ContainerBuilder;
    -use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
    -use Symfony\Component\DependencyInjection\Reference;
    -use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
    -use TYPO3\CMS\Dashboard\Widgets\BarChartWidget;
    -use Fixpunkt\FpMasterquiz\Widgets\Provider\ParticipantsDataProvider;
    -use Fixpunkt\FpMasterquiz\Widgets\RecentParticipantsWidget;
    -
    -return function (ContainerConfigurator $configurator, ContainerBuilder $containerBuilder) {
    -    if ($containerBuilder->hasDefinition(BarChartWidget::class)) {
    -        $services = $configurator->services();
    -
    -        $services->set('dashboard.widget.fixpunktRecentParticipants')
    -            ->class(RecentParticipantsWidget::class)
    -            ->arg('$view', new Reference('dashboard.views.widget'))
    -            ->arg('$dataProvider', new Reference(ParticipantsDataProvider::class))
    -            ->tag(
    -                'dashboard.widget',
    -                [
    -                    'identifier' => 'fixpunktRecentParticipants',
    -                    'groupNames' => 'fixpunkt',
    -                    'title' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:dashboard.widget.fixpunktRecentParticipants.title',
    -                    'description' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:dashboard.widget.fixpunktRecentParticipants.description',
    -                    'iconIdentifier' => 'content-widget-list',
    -                    'height' => 'medium',
    -                    'width' => 'medium'
    -                ]
    -            );
    -
    -        $services->set('dashboard.widget.fixpunktLastDays')
    -            ->class(BarChartWidget::class)
    -            ->arg('$dataProvider', new Reference(ParticipantsDataProvider::class))
    -            ->arg('$view', new Reference('dashboard.views.widget'))
    -            ->tag(
    -                'dashboard.widget',
    -                [
    -                    'identifier' => 'fixpunktLastDays',
    -                    'groupNames' => 'fixpunkt',
    -                    'title' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:dashboard.widget.fixpunktLastDays.title',
    -                    'description' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:dashboard.widget.fixpunktLastDays.description',
    -                    'iconIdentifier' => 'content-widget-chart-bar',
    -                    'height' => 'medium',
    -                    'width' => 'medium'
    -                ]
    -            );
    -    }
    -};
    \ No newline at end of file
    
  • Configuration/Services.yaml+0 8 removed
    @@ -1,8 +0,0 @@
    -services:
    -  _defaults:
    -    autowire: false
    -    autoconfigure: false
    -    public: false
    -
    -  Fixpunkt\FpMasterquiz\:
    -    resource: '../Classes/*'
    \ No newline at end of file
    
  • Configuration/TCA/Overrides/tt_content.php+1 7 modified
    @@ -3,10 +3,4 @@
     $pluginSignature = 'fpmasterquiz_pi1';
     $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature] = 'pi_flexform';
     \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( $pluginSignature, 'FILE:EXT:fp_masterquiz/Configuration/FlexForms/flexform_pi1.xml' );
    -
    -\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
    -    'FpMasterquiz',
    -    'Pi1',
    -    'Master-Quiz',
    -    'EXT:fp_masterquiz/ext_icon.gif'
    -);
    \ No newline at end of file
    +?>
    \ No newline at end of file
    
  • Configuration/TCA/Overrides/tx_fpmasterquiz_domain_model_evaluation.php+0 7 removed
    @@ -1,7 +0,0 @@
    -<?php
    -defined('TYPO3_MODE') || die();
    -
    -\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable(
    -   'fp_masterquiz',
    -   'tx_fpmasterquiz_domain_model_evaluation'
    -);
    
  • Configuration/TCA/tx_fpmasterquiz_domain_model_answer.php+4 0 modified
    @@ -20,6 +20,9 @@
             'searchFields' => 'title,points',
             'iconfile' => 'EXT:fp_masterquiz/Resources/Public/Icons/tx_fpmasterquiz_domain_model_answer.gif'
         ],
    +    'interface' => [
    +        'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, title, points',
    +    ],
         'types' => [
             '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, title, points, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, starttime, endtime'],
         ],
    @@ -132,6 +135,7 @@
                     'eval' => 'int'
                 ]
             ],
    +    
             'question' => [
                 'config' => [
                     'type' => 'passthrough',
    
  • Configuration/TCA/tx_fpmasterquiz_domain_model_evaluation.php+4 0 modified
    @@ -19,6 +19,9 @@
             'searchFields' => 'evaluate,minimum,maximum,bodytext,ce,page',
             'iconfile' => 'EXT:fp_masterquiz/Resources/Public/Icons/tx_fpmasterquiz_domain_model_evaluation.gif'
         ],
    +    'interface' => [
    +        'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, evaluate, minimum, maximum, image, bodytext, ce, page',
    +    ],
         'types' => [
             '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, evaluate, minimum, maximum, image, bodytext, ce, page, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, starttime, endtime'],
         ],
    @@ -230,6 +233,7 @@
                 	'default' => 0
     			],
             ],
    +    
             'quiz' => [
                 'config' => [
                     'type' => 'passthrough',
    
  • Configuration/TCA/tx_fpmasterquiz_domain_model_participant.php+10 15 modified
    @@ -17,8 +17,11 @@
             'searchFields' => 'name,email,homepage,user,ip,session,points,maximum1,maximum2,quiz,selections',
             'iconfile' => 'EXT:fp_masterquiz/Resources/Public/Icons/tx_fpmasterquiz_domain_model_participant.gif'
         ],
    +    'interface' => [
    +        'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, name, email, homepage, user, ip, session, sessionstart, points, maximum1, maximum2, page, completed, quiz, selections',
    +    ],
         'types' => [
    -        '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, name, email, homepage, user, ip, session, sessionstart, randompages, points, maximum1, maximum2, page, completed, quiz, selections'],
    +        '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, name, email, homepage, user, ip, session, sessionstart, points, maximum1, maximum2, page, completed, quiz, selections'],
         ],
         'columns' => [
             'sys_language_uid' => [
    @@ -127,8 +130,7 @@
     				'allowed' => 'fe_users',	
     				'size' => 1,	
     				'minitems' => 0,
    -				'maxitems' => 1,
    -                'default' => 0
    +				'maxitems' => 1
     			],
             ],
             'ip' => [
    @@ -158,15 +160,6 @@
                     'eval' => 'int'
                 ]
             ],
    -        'randompages' => [
    -            'exclude' => true,
    -            'label' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_participant.randompages',
    -            'config' => [
    -                'type' => 'input',
    -                'size' => 30,
    -                'eval' => 'trim'
    -            ]
    -        ],
             'points' => [
                 'exclude' => true,
                 'label' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_participant.points',
    @@ -213,8 +206,9 @@
                             '0' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.enabled'
                         ]
                     ],
    -                'default' => 0
    +                'default' => 0,
                 ]
    +            
             ],
             'quiz' => [
                 'exclude' => true,
    @@ -225,7 +219,6 @@
                     'foreign_table' => 'tx_fpmasterquiz_domain_model_quiz',
                     'minitems' => 0,
                     'maxitems' => 1,
    -                'default' => 0
                 ],
             ],
             'selections' => [
    @@ -244,6 +237,8 @@
                         'showAllLocalizationLink' => 1
                     ],
                 ],
    +
             ],
    +    
         ],
    -];
    \ No newline at end of file
    +];
    
  • Configuration/TCA/tx_fpmasterquiz_domain_model_question.php+6 17 modified
    @@ -20,8 +20,11 @@
             'searchFields' => 'title,qmode,image,bodytext,explanation,answers',
             'iconfile' => 'EXT:fp_masterquiz/Resources/Public/Icons/tx_fpmasterquiz_domain_model_question.gif'
         ],
    +    'interface' => [
    +        'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, sorting, title, qmode, image, bodytext, explanation, tag, answers',
    +    ],
         'types' => [
    -        '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, title, qmode, image, bodytext, explanation, tag, optional, answers, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, starttime, endtime'],
    +        '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, title, qmode, image, bodytext, explanation, tag, answers, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, starttime, endtime'],
         ],
         'columns' => [
             'sys_language_uid' => [
    @@ -141,8 +144,7 @@
     					['LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.qmode.4', 4],
     					['LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.qmode.5', 5],
     					['LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.qmode.6', 6],
    -					['LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.qmode.7', 7],
    -                    ['LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.qmode.8', 8]
    +					['LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.qmode.7', 7]
                     ],
                     'size' => 1,
                     'maxitems' => 1,
    @@ -239,22 +241,9 @@
                     'foreign_table' => 'tx_fpmasterquiz_domain_model_tag',
                     'default' => 0,
                     'minitems' => 0,
    -                'maxitems' => 1
    +                'maxitems' => 1,
                 ],
             ],
    -        'optional' => [
    -            'exclude' => true,
    -            'label' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.optional',
    -            'config' => [
    -                'type' => 'check',
    -                'items' => [
    -                    '1' => [
    -                        '0' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.enabled'
    -                    ]
    -                ],
    -                'default' => 0
    -            ]
    -        ],
             'answers' => [
                 'exclude' => true,
                 'label' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.answers',
    
  • Configuration/TCA/tx_fpmasterquiz_domain_model_quiz.php+5 0 modified
    @@ -20,6 +20,9 @@
             'searchFields' => 'name,about,questions,evaluations',
             'iconfile' => 'EXT:fp_masterquiz/Resources/Public/Icons/tx_fpmasterquiz_domain_model_quiz.gif'
         ],
    +    'interface' => [
    +        'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, name, path_segment, about, timeperiod, media, questions, evaluations',
    +    ],
         'types' => [
             '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, name, path_segment, about, timeperiod, media, questions, evaluations, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, starttime, endtime'],
         ],
    @@ -235,6 +238,8 @@
                         'showAllLocalizationLink' => 1
                     ],
                 ],
    +
             ],
    +    
         ],
     ];
    
  • Configuration/TCA/tx_fpmasterquiz_domain_model_selected.php+5 1 modified
    @@ -6,6 +6,7 @@
             'tstamp' => 'tstamp',
             'crdate' => 'crdate',
         	'cruser_id' => 'cruser_id',
    +    	'sortby' => 'uid',
             'versioningWS' => true,
             'languageField' => 'sys_language_uid',
             'transOrigPointerField' => 'l10n_parent',
    @@ -17,6 +18,9 @@
             'searchFields' => 'points,entered,question,answers',
             'iconfile' => 'EXT:fp_masterquiz/Resources/Public/Icons/tx_fpmasterquiz_domain_model_selected.gif'
         ],
    +    'interface' => [
    +        'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, sorting, points, entered, question, answers',
    +    ],
         'types' => [
             '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, points, entered, question, answers'],
         ],
    @@ -114,7 +118,6 @@
                     'foreign_table' => 'tx_fpmasterquiz_domain_model_question',
                     'minitems' => 0,
                     'maxitems' => 1,
    -                'default' => 0
                 ],
             ],
             'answers' => [
    @@ -127,6 +130,7 @@
                     'foreign_table_where' => 'AND question = ###REC_FIELD_question###',
                     'MM' => 'tx_fpmasterquiz_selected_answer_mm',
                 ],
    +            
             ],
         
             'participant' => [
    
  • Configuration/TCA/tx_fpmasterquiz_domain_model_tag.php+3 0 modified
    @@ -18,6 +18,9 @@
             'searchFields' => 'name',
             'iconfile' => 'EXT:fp_masterquiz/Resources/Public/Icons/tx_fpmasterquiz_domain_model_tag.gif'
         ],
    +    'interface' => [
    +        'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, name, timeperiod',
    +    ],
         'types' => [
             '1' => ['showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, name, timeperiod'],
         ],
    
  • Configuration/TypoScript/setup.ts+10 26 modified
    @@ -24,10 +24,9 @@ plugin.tx_fpmasterquiz {
     	settings {
     		startPageUid =
     		showPageUid =
    -		closurePageUid =
     		resultPageUid =
     		highscorePageUid =
    -		defaultQuizUid = 1
    +		defaultQuizUid =
     		introContentUid =
     		introNextAction = show
     		showAnswerPage = 1
    @@ -39,24 +38,17 @@ plugin.tx_fpmasterquiz {
     		showPoints = 1
     		showPageNo = 1
     		showQuestionNo = 0
    -		showDetailedCategoryEval = 0
    -		highscoreLimit = 10
     		checkAllStars = 0
    -		noFormCheck = 0
    -		phpFormCheck = 0
    -		allowEdit = 0
     		allowHtml = 0
    -		random = 0
     		joker = 0
     		ajax = 0
    -		ajaxType = GET
    +		ajaxType = POST
     		setMetatags = 0
    -		includeRatingCSS = 1
    +		highscoreLimit = 10
     		user {
     			ipSave = 1
     			ipAnonymous = 1
     			useCookie = 0
    -			useQuizPid = 0
     			checkFEuser = 0
     			askForData = 0
     			defaultName = default {TIME}
    @@ -85,7 +77,6 @@ plugin.tx_fpmasterquiz {
     		template {
     			colText = col-md-8
     			colImage = col-md-4
    -			col12 = col-12
     			wrapQuizTitle1 = <h2>
     			wrapQuizTitle2 = </h2>
     			wrapQuizDesc1 = <h3>
    @@ -98,14 +89,13 @@ plugin.tx_fpmasterquiz {
     			wrapQuestionDesc2 = </div>
     			wrapDone1 = <h4>
     			wrapDone2 = </h4>
    -			optionalMark =
     		}
     		chart {
     			type = pie
     			width = 492
     		}
     		templateLayout =
    -		overrideFlexformSettingsIfEmpty = startPageUid,showPageUid,closurePageUid,resultPageUid,highscorePageUid,defaultQuizUid,introContentUid,templateLayout,pagebrowser.itemsPerPage,user.useCookie
    +		overrideFlexformSettingsIfEmpty = startPageUid,showPageUid,resultPageUid,highscorePageUid,defaultQuizUid,introContentUid,templateLayout,pagebrowser.itemsPerPage
     		debug = 0
     		typeNum = {$plugin.tx_fpmasterquiz.settings.typeNum}
     	}
    @@ -127,24 +117,15 @@ module.tx_fpmasterquiz_web_fpmasterquizmod1 {
         settings {
     		pagebrowser {
                itemsPerPage         = 25
    -           insertAbove          = 1
    +           insertAbove          = 0
                insertBelow          = 1
                maximumNumberOfLinks = 70
     		}
     		debug = 0
         }
     }
     
    -module.tx_dashboard {
    -	view {
    -		layoutRootPaths {
    -			42 = EXT:fp_masterquiz/Resources/Private/Backend/Layouts/
    -		}
    -		templateRootPaths {
    -			42 = EXT:fp_masterquiz/Resources/Private/Backend/Templates/
    -		}
    -	}
    -}
    +## EXTENSION BUILDER DEFAULTS END TOKEN - Everything BEFORE this line is overwritten with the defaults of the extension builder
     
     # PAGE object for Ajax call (you need to add your language settings here too!):
     ajaxfpmasterquiz_page = PAGE
    @@ -159,4 +140,7 @@ ajaxfpmasterquiz_page {
             admPanel = 0
         }
         10 < tt_content.list.20.fpmasterquiz_pi1
    -}
    \ No newline at end of file
    +}
    +
    +# CSS for Star Rating. You can delete it, if you dont need it
    +page.includeCSS.fpMasterQuizRatingStar = EXT:fp_masterquiz/Resources/Public/Css/RatingStar.css
    
  • Documentation/Administrator/Index.rst+35 44 modified
    @@ -12,7 +12,7 @@ Administrator Manual
     ====================
     
     Note: only the templates Quiz/List.html, Quiz/Show.html and Quiz/ShowAjax.html are in use!
    -Don´t remove classes or IDs that begin with quiz, because some of them are used to validate the form!
    +Don´t remove classes or IDs that begin with quiz, because they are used to vaildate the form!
     
     
     .. _admin-installation:
    @@ -44,40 +44,34 @@ name, about, timeperiod (in seconds), media, questions, questionsSortByTag, cate
     maximum2 (maximum points for a quiz).
     
     A question has this variables:
    -title, qmode (question-mode), image, bodytext, explanation, sorting, tag, answers, selectOptions, numberOfAnswers,
    -arrayOfAnswers, categories, categoriesArray, sortedCategoriesArray.
    -And furthermore:
    +title, qmode (question-mode), image, bodytext, explanation, sorting, tag, answers, selectOptions, numberOfAnswers, arrayOfAnswers.
    +Furthermore:
     maximum1 (maximum points for a question),
     allAnswers (no. of all answers/votes - checkboxes counted once),
     totalAnswers (no. of all answers/votes - all checkboxes counted),
     textAnswers (array with entered text answers, only in the BE available).
     
     An answer has this variables:
    -title, titleJS, points, jokerAnswer, onwAnswer (yes/no), ownCategoryAnswer (has 2 keys: 0 the uid and 1 the title),
    -allAnswers (total answers of all users),
    +title, titleJS, points, jokerAnswer, onwAnswer (yes/no), allAnswers (total answers of all users),
     allPercent (total percent of all users - checkbox counted ounce),
    -totalPercent (total percent of all users - all checkboxes counted) and
    -categories.
    +totalPercent (total percent of all users - all checkboxes counted).
     
     An evaluation has this variables:
     evaluate (evaluate points (unchecked) or percentage (checked)), minimum and maximum, image, bodytext,
    -ce (content element ID), page (page ID) and categories.
    -Note: if a category is marked, the evaluation will seek for categories instead. The category of answers will be validated.
    -The category which was used most be the participant will be taken.
    +ce (content element ID), page (page ID).
     
     A tag has this variables:
     name, timeperiod (in seconds).
     
     A participant has this variables:
    -name, email, homepage, user (FE-user UID), username (FE-user username), ip, session, sessionstart, quiz, points,
    +name, email, homepage, user (FE-user-ID), ip, session, sessionstart, quiz, points,
     maximum1 (maximum points for the answered questions), maximum2 (maximum points for a quiz),
     startdate, crdate, tstamp, datesNotEqual, timePassed, page (reached page), completed (quiz completed?),
    -selections (all answered questions), selectionsByTag (answered questions of a tag) and
    +selections (all answered questions), selectionsByTag (answered questions of a tag),
     sortedSelections (answered questions, well sorted).
     
     A selection has this variables:
    -question, answers, sorting, points, maximumPoints (maximum points for this question), entered (entered text to this question)
    -and categories.
    +question, answers, sorting, points, maximumPoints (maximum points for this question), entered (entered text to this question).
     
     
     .. _admin-configuration:
    @@ -95,16 +89,6 @@ User results
        Take a look at the TypoScript configuration. You can change the layout with the settings.template.*
     
     
    -.. _admin-final:
    -
    -Final page
    -----------
    -
    -There are several more variables at the final page available. You find them in the FinalPage.html partial.
    -Furthermore there is an array filled only when you use categories at the evaluation: {finalCategories}.
    -This array contains this variables: uid, title, count and all. all is an array again and contains: title and count.
    -
    -
     .. _admin-import:
     
     Importing myquizpoll entries
    @@ -114,16 +98,34 @@ Importing myquizpoll entries
     
     .. important::
     
    -   You will need TYPO3 8 or 9 if you use this import task. This task was removed in version 3.0.0 of this extension!
    +   You will need TYPO3 8 or 9 if you use this import task.
        If you are using TYPO3 9 and you want to import myquizpoll-questions, then you will need the extension typo3db_legacy too!
     
     
    -.. _admin-export:
    +.. _security-fix:
     
    -Exporting participant entries
    +Security fix in version 2.2.1
     -----------------------------
     
    -* There is a scheduler task which whom you can export participants from a single folder (pid). The csv-file will be written to fileadmin.
    +Since version 2.2.1/3.5.2 a session-key is always required and this session-key will be checked against a participant.
    +If you use the Ajax-version AND if you use an own HTML-template, then you must add some code to your templates!
    +In the Show.html template you need to add this line to the hidden-fields of the first form::
    +
    +  <f:form.hidden name="session" value="" id="quiz-form-session" />
    +
    +In the ShowAjax.html template you need to add 2 lines.
    +This one after "$('#quiz-form'+ceuid+' #quiz-form-parti').val('{participant.uid}');"::
    +
    +  $('#quiz-form'+ceuid+' #quiz-form-session').val('{session}');
    +
    +and this one after "$('#quiz-form-parti').val('0');"::
    +
    +  $('#quiz-form-session').val('');
    +
    +That will set a session-key for every participant.
    +
    +Another change was made in the settings. The default quiz-UID 1 was removed. If you use that default setting,
    +you must set settings.defaultQuizUid again to 1.
     
     
     .. _admin-faq:
    @@ -135,32 +137,21 @@ FAQ
     
       No.
     
    -- Are there any dependencies?
    -
    -  Yes, you will need jQuery.
    -
    -- How can I change the translations text?
    -
    -  Here an TypoScript example:
    +- How can I change the translations text? Here an TypoScript example:
     
       ::
     
          plugin.tx_fpmasterquiz._LOCAL_LANG.de.text.yourAnswers = Deine Abstimmung:
          plugin.tx_fpmasterquiz._LOCAL_LANG.de.text.allAnswers = Bisherige Abstimmung:
    -     plugin.tx_fpmasterquiz._LOCAL_LANG.de.text.done = Danke für deine Teilnahme! Deine Auswertung:
     
     - How can I rename or hide some fields in the Backend?
     
    -  See chapter “Configuration / Page TSConfig”.
    +    See chapter “Configuration / Page TSConfig”.
       
     - How can I use routing / speaking urls?
     
    -  See chapter “Configuration / Routing”.
    +    See chapter “Configuration / Routing”.
     
     - Does the extension uses cookies?
     
    -  Only if you enable them via settings.user.useCookie. See chapter “Configuration”.
    -
    -- Is there a widget for the TYPO3 dashboard?
    -
    -  Yes, of course, there are 2. They were added in version 3.2.4.
    \ No newline at end of file
    +    Only if you enable them via settings.user.useCookie. See chapter “Configuration”.
    \ No newline at end of file
    
  • Documentation/ChangeLog/Index.rst+20 74 modified
    @@ -11,64 +11,55 @@
     ChangeLog
     =========
     
    -0.2.0:
    -  First release for the TER.
    +0.2.0: First release for the TER.
     
    -0.3.0:
    -  Now optimized for Bootstrap 4.
    +0.2.2: Bug with points fixed.
    +  New settings: settings.showCorrectAnswers and settings.showPoints.
    +
    +0.3.0: Now optimized for Bootstrap 4.
       New settings: showAnswersAtFinalPage and template.
     
    -0.4.0:
    -  Now polls possible, because all submited results are avaiable.
    +0.4.0: Now polls possible, because all submited results are avaiable.
       New settings: showOwnAnswers, showAllAnswers, templateLayout...
     
    -0.5.0:
    -  Now for TYPO3 8 and 9. Backend module added. Charts added.
    +0.5.0: Now for TYPO3 8 and 9. Backend module added. Charts added.
       Deletion-task changed: delete-flag and real deletion now possible.
       Lazy loading removed, because delete cascade does not work with lazy loading.
       New settings: showPageNo and showQuestionNo.
     
    -0.6.0:
    -  Donut chart added.
    +0.6.0: Donut chart added.
       Session-token added to prevent reload-manipulations.
       New settings: user.useCookie.
     
    -0.7.0:
    -  Text-answer now possible. Thanks to Gerald Loss.
    +0.7.0: Text-answer now possible. Thanks to Gerald Loss.
       New settings: user.checkFEuser.
       Bug fixed: anonymous IP address.
     
    -1.0.0:
    -  Question mode "Show a comment" and "Star rating" implemented.
    +1.0.0: Question mode "Show a comment" and "Star rating" implemented.
     
    -1.1.0:
    -  Question mode "Enter a comment (textarea)" implemented.
    +1.1.0: Question mode "Enter a comment (textarea)" implemented.
       New settings: checkAllStars.
       Sending of emails now possible.
       Using of FE-user-data, if user.checkFEuser is set.
       Dropped support for TYPO3 8. Now for TYPO3 9 and 10.
     
    -1.2.0:
    -  New feature: 50:50 joker.
    +1.2.0: New feature: 50:50 joker.
       Page layout view / preview in the backend. 
       Bugfix: summation of points works now with negative points too.
       Bugfix: FlexForms in TYPO3 10.
       Bugfix: hidden-fields in the backend.
     
    -1.3.0:
    -  New setting: ajaxType.
    +1.3.0: New setting: ajaxType.
       New setting: email.likeFinalPage.
       New settings: showEveryAnswer and option 2 for showOwnAnswers and showCorrectAnswers.
       Bugfix: sending of emails.
     
    -1.4.0:
    -  New setting: resultPageUid and new action: result for a result page.
    -  Possibility added to add a question to a quiz via backend module.
    +1.4.0: New setting: resultPageUid and new action: result for a result page.
    +  Possiblity added to add a question to a quiz via backend module.
       Question mode "Yes/no-boxes (2 radio-buttons)" implemented.
       Important bugfix for PHP 7.3 and other bugfixes points related.
     
    -1.5.0:
    -  Bodytext and image added to the evaluation.
    +1.5.0: Bodytext and image added to the evaluation.
       Routing/slug/path segment added to a quiz.
       Categories added to a quiz.
       Layout of yes/no-questions changed.
    @@ -77,8 +68,7 @@ ChangeLog
       Another bugfix points related.
       See issues #12 - #18.
     
    -2.0.0:
    -  The ajax-action gets now the quiz-object.
    +2.0.0: The ajax-action gets now the quiz-object.
       Media-field added to a quiz.
       Default value of the setting showAnswersAtFinalPage and showAllAnswers changed from 0 to 1.
       Default value of the setting showOwnAnswers changed from 1 to 2.
    @@ -104,50 +94,6 @@ ChangeLog
       TCA-Bugfix for TYPO3 10.
       Refactoring.
     
    -3.0.2:
    -  Version for TYPO3 10 and 11.
    -  closure action and setting closurePageUid added.
    -  Default-value for setting ajaxType changed from POST to GET.
    -  Language of a participant and his answers changed from 0 to -1.
    -  Breaking: myquizpoll-import-task removed.
    -
    -3.1.1:
    -  Setting user.useQuizPid, noFormCheck, random and allowEdit added.
    -  Possibility added to move questions from one quiz to another quiz.
    -  More Flexforms.
    -
    -3.1.2:
    -  Bugfix for breaking change in TYPO3 11.5.0.
    -
    -3.2.0:
    -  Every question can now be set to be optional. Setting template.optionalMark added.
    -  The answer of text-fields is now checked too (it is no longer optional, but can be set to optional).
    -  The RatingStar.css will now be included by the viewhelper f:asset in the template itself. Use includeRatingCSS=0 to disable it.
    -  Setting template.col12 added for questions without an image.
    -  Div with class card-body added to all cards.
    -  Variable participant.username added.
    -
    -3.3.1:
    -  Backend-Layout adapted for TYPO3 11.5.
    -  Evaluation of the most used category is now possible too. Setting showDetailedCategoryEvaluation added.
    -  TYPO3 categories are now available at a quiz, question, answer, selected and evaluation.
    -  Mandatory questions are now marked when an error appears. The error message is now not a JavaScript-alert-message.
    -  2 widgets for the TYPO3 dashboard added (the extension dashboard is required in TYPO3 11).
    -  Supports now PHP 8; thanks to Gerald Loss.
    -  Bugfix: moving participant data to another folder.
    -  Bugfix: check of checkboxes fixed.
    -
    -3.4.0:
    -  The answer of textarea-fields is now checked too (it is no longer optional, but can be set to optional).
    -  CSV-export added as scheduler task.
    -  Dashboard no longer required in TYPO3 11.
    -  Layout optimizations.
    -
    -3.4.4:
    -  Bugfix: persist data before evaluation.
    -  Bugfix: category evaluation.
    -  Bugfix: wrong Namespace in TemplateLayout corrected.
    -
    -3.5.0:
    -  Mandatory check with PHP too, if setting phpFormCheck=1.
    -  New question mode: matrix with categories of a question.
    \ No newline at end of file
    +2.2.1:
    +  Security fix: checking participant against a session-key. Please read the section Administrator / Security fix in version 3.5.2.
    +  Security fix: check if a quiz/poll is allowed on a page. Therefore, the defaultQuizUid was removed in the settings!
    \ No newline at end of file
    
  • Documentation/Configuration/Index.rst+81 146 modified
    @@ -31,108 +31,98 @@ Properties
     
     .. container:: ts-properties
     
    -============================ =========== =============================================== ===========================
    -Property                     Data type   Description                                     Default
    -============================ =========== =============================================== ===========================
    -startPageUid                 integer     UID of the page where to restart (listPid).     -
    -showPageUid                  integer     UID of the single-page of a quiz (detailPid).   -
    -closurePageUid               integer     UID of a closure-page of a quiz.                -
    -resultPageUid                integer     UID of the page where to show quiz results.     -
    -highscorePageUid             integer     UID of the page where to show a highscore.      -
    -defaultQuizUid               integer     UID of the quiz to show.                        1
    -introContentUid              integer     Content element for the intro page.             -
    -introNextAction              string      Action after the intro page: show or showByTag. show
    -showAnswerPage               boolean     Show an answer page after every submit?         1
    -showOwnAnswers               integer     Show the answers of the quiz taker? 0,1 or 2.   2
    -showCorrectAnswers           integer     Show the correct answers? 0, 1 or 2.            1
    -showEveryAnswer              integer     Show every answer? 0, 1 or 2 (see below).       0
    -showAnswersAtFinalPage       boolean     Show answers with solutions at the final page?  1
    -showAllAnswers               boolean     Show finally all answers (no. of choices)?      1
    -showPoints                   boolean     Show the possible/reached points if maximum>0?  1
    -showPageNo                   boolean     Show the page number / number of pages?         1
    -showQuestionNo               boolean     Show the question no. / no. of questions?       0
    -showDetailedCategoryEval     boolean     Show detailed category evaluation if available? 0
    -checkAllStars                boolean     Check all stars on star rating by default?      0
    -highscoreLimit               integer     Number of entries in the highscore              10
    -noFormCheck                  boolean     Don´t check for answered questions at all?      0
    -phpFormCheck                 boolean     Enable check for answered questions with PHP?   0
    -allowEdit                    boolean     Show links to pages and allow to edit answers?  0
    -allowHtml                    boolean     Allow HTML at question-answers from the BE?     0
    -random                       boolean     Enable a random mode? Works only with tags.     0
    -joker                        boolean     Enable a joker-button? Works only with AJAX.    0
    -ajax                         boolean     Enable the AJAX-version* of the quiz?           0
    -ajaxType                     string      POST or GET                                     GET
    -setMetatags                  boolean     Set some metatags and change the title?         0
    -includeRatingCSS             boolean     Include the RatingStar.css via f:asset?         1
    -user.ipSave                  boolean     Save the IP-address of a user?                  1
    -user.ipAnonymous             boolean     Anonymize the IP-address?                       1
    -user.useCookie               integer     Save the session in a cookie too? See below.    0
    -user.useQuizPid              boolean     Use automatically the pid from the quiz?        0
    -user.checkFEuser             boolean     Check if a FEuser has already participated?     0
    -user.askForData              integer     Ask for user data? 0, 1, 2 or 3 (see below).    0
    -user.defaultName             string      Default user name ({TIME} will be replaced).    default {TIME}
    -user.defaultEmail            string      Default user email.                             -
    -user.defaultHomepage         string      Default user homepage.                          -
    -email.fromEmail              string      Your email-address.                             -
    -email.fromName               string      Your name.                                      -
    -email.adminEmail             string      Admin email-address.                            -
    -email.adminName              string      Admin name.                                     -
    -email.adminSubject           string      Subject of the admin-email.                     New poll/quiz-result
    -email.userSubject            string      Subject of the email to the user.               Your poll/quiz-result
    -email.sendToAdmin            boolean     Send an email to the admin at the final page?   0
    -email.sendToUser             boolean     Send an email to the user at the final page?    0
    -email.specific               string      Send email to specific admins (see below)?      -
    -email.likeFinalPage          boolean     Handle the email like a final page?             0
    -pagebrowser.itemsPerPage     integer     Number of questions on a page.                  1
    -pagebrowser.insertAbove      boolean     You don´t need this.                            0
    -pagebrowser.insertBelow      boolean     You don´t need this.                            0
    -pagebrowser.maximumNum...    integer     You don´t need this.                            50
    -template.colText             string      Class for a question with answers.              col-md-8
    -template.colImage            string      Class for the image of a question.              col-md-4
    -template.col12               string      Class for the text of a question; if no image.  col-12
    -template.wrapQuizTitle1      string      Wrap for the quiz title.                        <h2>
    -template.wrapQuizTitle2      string      Wrap for the quiz title.                        </h2>
    -template.wrapQuizDesc1       string      Wrap for the quiz description.                  <h3>
    -template.wrapQuizDesc2       string      Wrap for the quiz description.                  </h3>
    -template.wrapTagName1        string      Wrap for the tag name.                          <h4>
    -template.wrapTagName2        string      Wrap for the tag name.                          </h4>
    -template.wrapQuestionTitle1  string      Wrap for the question title.                    <div class="mx-auto"><h4>
    -template.wrapQuestionTitle2  string      Wrap for the question title.                    </h4></div>
    -template.wrapQuestionDesc1   string      Wrap for the question description.              <div class="mx-auto">
    -template.wrapQuestionDesc2   string      Wrap for the question description.              </div>
    -template.wrapDone1           string      Wrap for the done-msg at the final page.        <h4>
    -template.wrapDone2           string      Wrap for the done-msg at the final page.        </h4>
    -template.optionalMark        string      You can define a string for optional questions. -
    -chart.type                   string      You can choose between: pie, donut or bar.      pie
    -chart.width                  integer     Width of the chart.                             492
    -templateLayout               integer     See in chapter PageTSconfig**.                  -
    -overrideFlexformSettings...  string      Fields that should be overwritten if empty.     startPageUid,...
    -debug                        boolean     Show debug data at the page.                    0
    -typeNum                      integer     Type of the AJAX-call. Don´t change it.         190675
    -============================ =========== =============================================== ===========================
    +	============================ =========== =============================================== ===========================
    +	Property                     Data type   Description                                     Default
    +	============================ =========== =============================================== ===========================
    +	startPageUid                 integer     UID of the page where to restart (listPid).     -
    +	showPageUid                  integer     UID of the single-page of a quiz (detailPid).   -
    +	resultPageUid                integer     UID of the page where to show quiz results.     -
    +	highscorePageUid             integer     UID of the page where to show a highscore.      -
    +	defaultQuizUid               integer     UID of the quiz to show.                        -
    +    introContentUid              integer     Content element for the intro page.             -
    +    introNextAction              string      Action after the intro page: show or showByTag. show
    +	showAnswerPage               boolean     Show an answer page after every submit?         1
    +	showOwnAnswers               integer     Show the answers of the quiz taker? 0,1 or 2.   2
    +	showCorrectAnswers           integer     Show the correct answers? 0, 1 or 2.            1
    +	showEveryAnswer              integer     Show every answer? 0, 1 or 2 (see below).       0
    +	showAnswersAtFinalPage       boolean     Show solutions at the final page?               1
    +	showAllAnswers               boolean     Show finally all answers (no. of choices)?      1
    +	showPoints                   boolean     Show the possible/reached points if maximum>0?  1
    +	showPageNo                   boolean     Show the page number / number of pages?         1
    +	showQuestionNo               boolean     Show the question no. / no. of questions?       0
    +	checkAllStars                boolean     Check all stars on star rating by default?      0
    +	highscoreLimit               integer     Number of entries in the highscore              10
    +	allowHtml                    boolean     Allow HTML at question-answers from the BE?     0
    +	joker                        boolean     Enable a joker-button? Works only with AJAX.    0
    +	ajax                         boolean     Enable the AJAX-version* of the quiz?           0
    +	ajaxType                     string      POST or GET                                     POST
    +	setMetatags                  boolean     Set some metatags and change the title?         0
    +	user.ipSave                  boolean     Save the IP-address of a user?                  1
    +	user.ipAnonymous             boolean     Anonymize the IP-address?                       1
    +	user.useCookie               integer     Save the session in a cookie too? See below.    0
    +	user.checkFEuser             boolean     Check if a FEuser has already participated?     0
    +	user.askForData              integer     Ask for user data? 1: at the 1.; 2: intro page. 0
    +	user.defaultName             string      Default user name ({TIME} will be replaced).    default {TIME}
    +	user.defaultEmail            string      Default user email.                             -
    +	user.defaultHomepage         string      Default user homepage.                          -
    +	email.fromEmail              string      Your email-address.                             -
    +	email.fromName               string      Your name.                                      -
    +	email.adminEmail             string      Admin email-address.                            -
    +	email.adminName              string      Admin name.                                     -
    +	email.adminSubject           string      Subject of the admin-email.                     New poll/quiz-result
    +	email.userSubject            string      Subject of the email to the user.               Your poll/quiz-result
    +	email.sendToAdmin            boolean     Send an email to the admin at the final page?   0
    +	email.sendToUser             boolean     Send an email to the user at the final page?    0
    +	email.specific               string      Send email to specific admins (see below)?      -
    +	email.likeFinalPage          boolean     Handle the email like a final page?             0
    +	pagebrowser.itemsPerPage     integer     Number of questions on a page.                  1
    +	pagebrowser.insertAbove      boolean     You don´t need this.                            0
    +	pagebrowser.insertBelow      boolean     You don´t need this.                            0
    +	pagebrowser.maximumNum...    integer     You don´t need this.                            50
    +	template.colText             string      Class for a question with answers.              col-md-8
    +	template.colImage            string      Class for the image of a question.              col-md-4
    +	template.wrapQuizTitle1      string      Wrap for the quiz title.                        <h2>
    +	template.wrapQuizTitle2      string      Wrap for the quiz title.                        </h2>
    +	template.wrapQuizDesc1       string      Wrap for the quiz description.                  <h3>
    +	template.wrapQuizDesc2       string      Wrap for the quiz description.                  </h3>
    +	template.wrapTagName1        string      Wrap for the tag name.                          <h4>
    +	template.wrapTagName2        string      Wrap for the tag name.                          </h4>
    +	template.wrapQuestionTitle1  string      Wrap for the question title.                    <div class="mx-auto"><h4>
    +	template.wrapQuestionTitle2  string      Wrap for the question title.                    </h4></div>
    +	template.wrapQuestionDesc1   string      Wrap for the question description.              <div class="mx-auto">
    +	template.wrapQuestionDesc2   string      Wrap for the question description.              </div>
    +	template.wrapDone1           string      Wrap for the done-msg at the final page.        <h4>
    +	template.wrapDone2           string      Wrap for the done-msg at the final page.        </h4>
    +	chart.type                   string      You can choose between: pie, donut or bar.      pie
    +	chart.width                  integer     Width of the chart.                             492
    +	templateLayout               integer     See in chapter PageTSconfig**.                  -
    +	overrideFlexformSettings...  string      Fields that should be overwritten if empty.     startPageUid,...
    +	debug                        boolean     Show debug data at the page.                    0
    +	typeNum                      integer     Type of the AJAX-call. Don´t change it.         190675
    +	============================ =========== =============================================== ===========================
     
     AJAX*) If you enable AJAX, you should know this:
     
    -- The FlexForms will be ignored, because the AJAX-call does not know the plugin.
    +  - The FlexForms will be ignored, because the AJAX-call does not know the plugin.
     
    -- **Configure the quiz only by TypoScript**.
    -  You need to set the persistence.storagePid too!
    +  - **Configure the quiz only by TypoScript**.
    +    You need to set the persistence.storagePid too!
     
    -- The AJAX-solution is currently not supported in the action "show by tag".
    +  - The AJAX-solution is currently not supported in the action "show by tag".
     
    -- The AJAX-call calls an normal action and not an eID-script. Therefore it is necessary to set this TypoScript:
    -  plugin.tx_fpmasterquiz.features.requireCHashArgumentForActionArguments = 0
    -  This is set by default. You can change the value to 1, if you do not use the AJAX-version.
    -  If it is still not working, you can disable the cHash-check in the install tool:
    -  [FE][pageNotFoundOnCHashError] = false
    +  - The AJAX-call calls an normal action and not an eID-script. Therefore it is necessary to set this TypoScript: 
    +    plugin.tx_fpmasterquiz.features.requireCHashArgumentForActionArguments = 0 
    +    This is set by default. You can change the value to 1, if you do not use the AJAX-version.
    +    If it is still not working, you can disable the cHash-check in the install tool: 
    +    [FE][pageNotFoundOnCHashError] = false
       
    -- You have still problems? Then read the chapter "Known problems".
    +  - You have still problems? Then read the chapter "Known problems".
     
     Layout**) If you use template layout 1, you should know this:
     
    -- The charts settings will be ignored if you use another layout.
    +  - The charts settings will be ignored if you use another layout.
     
    -- The ApexCharts will be used automatically. More information: https://apexcharts.com/
    +  - The ApexCharts will be used automatically. More information: https://apexcharts.com/
     
     Note: if you enable a cookie or FEuser check, then an user cannot vote again, if he had already voted/participated.
     The participant will see his result of a poll/quiz instead of the checkboxes/radio buttons.
    @@ -198,42 +188,6 @@ Otherwise they are displayed at the final page too if showAnswersAtFinalPage is
     Note: this is tested only with checkboxes and radio buttons!
     
     
    -.. _allowEdit:
    -
    -allowEdit
    -"""""""""
    -
    -:typoscript:`plugin.tx_fpmasterquiz.settings.allowEdit = 1`
    -
    -If you enable this feature, links to all pages of a quiz are shown, so user can edit their answers.
    -Note: this works only for the action "show by tag" and questions of type radio, checkbox or text.
    -Note: this feature disables the answer-page!
    -
    -
    -.. _random:
    -
    -random
    -""""""
    -
    -:typoscript:`plugin.tx_fpmasterquiz.settings.random = 1`
    -
    -If you enable this feature, the tags will be shuffled. The changed order will be saved in the DB too.
    -Note: this works only for the action "show by tag", because tags and not questions are randomized.
    -
    -
    -.. _noFormCheck:
    -
    -noFormCheck
    -"""""""""""
    -
    -:typoscript:`plugin.tx_fpmasterquiz.settings.noFormCheck = 1`
    -
    -Normally every question needs to be answered before the page can be send. You can disable this check generally.
    -Since version 3.2.0 you can define at each question if it should be optional or not.
    -Note: only question of type radio, checkbox, select-box, input-field and textarea are checked. All answers to other type of
    -questions are optional (they will not be checked).
    -
    -
     .. _joker:
     
     joker
    @@ -278,21 +232,6 @@ Note furthermode: if enabling the cookies, these cookies will be saved: qsession
     This cookies are not bad! You don´t need a cookie bar for it, but you need to tell about it at your GDPR-site.
     
     
    -.. _user.askForData:
    -
    -user.askForData
    -""""""""""""""
    -
    -:typoscript:`plugin.tx_fpmasterquiz.settings.user.askForData = 3`
    -
    -4 options are available: 0, 1, 2 or 3. 0 means: don´t ask for user data like name oder email.
    -The other values enables a form, that ask the user for this data: name, email and homepage.
    -1: the form will appear at the first page of a quiz.
    -2: the form will appear at the intro page.
    -3: the form will appear at the final page of a quiz. Note: in this case you will need to define a closure page too!
    -Setting: closurePageUid. The form from the final page will redirect to this page. Note: this does not work in the AJAX version.
    -
    -
     .. _email.specific:
     
     email.specific
    @@ -343,10 +282,6 @@ FAQ
     
       This can be configured at every quiz.
     
    -- Optional questions are not marked. Why not?
    -
    -  You need to define the mark-symbol by yourself via the TypoScript-setting. E.g. settings.template.optionalMark = *.
    -
     - The text changes to english when I activate Ajax. Whats wrong?
     
       You need to add some more TypoScript to your page. See chapter "Known problems".
    
  • Documentation/Images/UserManual/BackendPlugin1.jpg+0 0 removed
  • Documentation/Images/UserManual/BackendPlugin2.jpg+0 0 removed
  • Documentation/Images/UserManual/BackendPlugin.png+0 0 added
  • Documentation/Images/UserManual/BackendView1.jpg+0 0 removed
  • Documentation/Images/UserManual/BackendView.png+0 0 added
  • Documentation/Index.rst+5 1 modified
    @@ -23,7 +23,8 @@ Master-Quiz
     		en,de
     
     	:Description:
    -		A modern extension that offers Quiz, Polls and Tests. 8 question-modes supported. Many features.
    +		A modern extension that offers Quiz, Polls and Tests. 7 question-modes supported.
    +		It is the official successor extension of myquizpoll, but it is not backward compatible! Many features.
     
     	:Keywords:
     		quiz,test,poll,myquizpoll,myquizandpoll
    @@ -34,6 +35,9 @@ Master-Quiz
     	:Author:
     		Kurt Gusbeth
     
    +	:Email:
    +		info@quizpalme.de
    +
     	:License:
     		This document is published under the Open Content License
     		available from https://www.opencontent.org/opl.shtml
    
  • Documentation/Introduction/Index.rst+3 6 modified
    @@ -21,12 +21,9 @@ A modern extension that offers Quiz, Polls and Tests. You can configure, which r
     The results can be displayed as a chart too. An evaluation is possible too.
     Automatic deletion of quiz takers via task possible. Supporting of Ajax.
     
    -Question types/modes: radio-box, checkbox, select-box, yes/no, text-field, textarea, star-rating, matrix
    -(only for polls and no detail evaluation available).
    +Question types/modes: radio-box, checkbox, select-box, yes/no, text-field, textarea, star-rating.
     
    -jQuery is required. Optimized for Bootstrap 4. 2 widgets for the dashboard available.
    -
    -Available languages: english and german/deutsch.
    +Avaiable languages: english and german/deutsch.
     
     It is the official successor extension of myquizpoll. It is not backward compatible, but there is a simple import-task.
     
    @@ -66,7 +63,7 @@ Here you find 4 examples and 2 more screenshots are in the user manual.
     Thanks to the
     -------------
     
    -`fixpunkt für digitales GmbH, Bonn <https://www.fixpunkt.com/webentwicklung/typo3/>`_
    +`fixpunkt werbeagentur gmbh, Bonn <https://www.fixpunkt.com/webentwicklung/typo3/>`_
     for giving me the possibility to realize (partly)
     `this extension <https://www.fixpunkt.com/webentwicklung/typo3/typo3-extensions/>`_
     and share it with the TYPO3 community.
    
  • Documentation/KnownProblems/Index.rst+2 5 modified
    @@ -17,9 +17,9 @@ The bug tracker is here:
     jQuery needed to be loaded in the head.
     
     There might be some problems, if you enable Ajax!
    -Sessions and Cookies are currently not supported if you enable Ajax.
    +User-data and cookies are currently not supported if you enable Ajax.
     
    -Note for versions < 3: it might be necessary to change the Quiz/Show.html template, if you will see the startpage
    +Note: it might be necessary to change the Quiz/Show.html template, if you will see the startpage
     instead of a question as a ajax result page. You could try to change the type from POST to GET in the $.ajax call.
     But you can change this via TypoScript too:
     
    @@ -41,6 +41,3 @@ Please note furthermore:
       This is set by default. Or if you disable the cHash-check globally: 
       $GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFoundOnCHashError'] = false
       in the install tool.
    -
    -- the AJAX-version ignores FlexForm-settings during the AJAX-call but not during the initialization.
    -  Therefore you should not set any FlexForms if you use AJAX or they should be equal.
    
  • Documentation/Settings.cfg+1 1 modified
    @@ -4,7 +4,7 @@
     # ...   (required) title (displayed in left sidebar (desktop) or top panel (mobile)
     # .................................................................................
     
    -project     = A modern extension that offers quiz, polls and tests. 8 question-modes supported.
    +project     = A modern extension that offers quiz, polls and tests. 7 question-modes supported.
     
     # .................................................................................
     # ...   (recommended) version, displayed next to title (desktop) and in <meta name="book-version"
    
  • Documentation/ToDoList/Index.rst+0 4 modified
    @@ -14,7 +14,3 @@ To-Do list
     The to-do list is short:
     
     - using of more cookie-sessions.
    -
    -- detail evaluation for the matrix mode.
    -
    -- Repair dashboard widgets in non-composer mode.
    \ No newline at end of file
    
  • Documentation/User/Index.rst+22 40 modified
    @@ -39,23 +39,17 @@ After you have created a quiz with some questions you can add the plugin at a pa
     
     This screenshots shows you a quiz in the list view and some FlexForm-settings of the plugin.
     
    -.. figure:: ../Images/UserManual/BackendView1.jpg
    -   :width: 486px
    +.. figure:: ../Images/UserManual/BackendView.png
    +   :width: 530px
        :alt: Backend view of a quiz
     
    -   Backend view of a quiz/poll.
    +   Backend view of a quiz.
     
    -.. figure:: ../Images/UserManual/BackendPlugin1.jpg
    -   :width: 348px
    +.. figure:: ../Images/UserManual/BackendPlugin.png
    +   :width: 530px
        :alt: Backend view of the plugin
     
    -   Backend view of the plugin (part 1). Many Flexform settings!
    -
    -.. figure:: ../Images/UserManual/BackendPlugin2.jpg
    -   :width: 322px
    -   :alt: Backend view of the plugin
    -
    -   Backend view of the plugin (part 2).
    +   Backend view of the plugin (early beta version).
     
     .. figure:: ../Images/UserManual/BackendQuiz2.jpg
        :width: 800px
    @@ -68,30 +62,26 @@ Actions
     
     You can select in the plugin-configuration via FlexForms between this actions:
     
    -- list: list of all quiz/poll/test of one folder with links to the single view
    +- List of all quiz/poll/test of one folder with links to the single view
     
    -- show: show a selected quiz/poll/test and use a pagebrowser
    +- Show a selected quiz/poll/test and use a pagebrowser
     
    -- showByTag: show a selected quiz/poll/test and order the questions by tag: on each page will be shown questions of one tag
    -  (Ajax-version is not working yet)
    +- Show a selected quiz/poll/test and order the questions by tag: on each page will be shown questions of one tag
    +  (Ajax-version is not working yet).
     
    -- intro: show an intro page and then a quiz
    +- Show an intro page and then a quiz.
     
    -- closure: show a closure page after finishing a quiz; this page is only shown when user.askForData=3
    +- Show a result of a quiz/poll/test
     
    -- result: show a result of a quiz/poll/test
    -
    -- highscore: show a highscore of a quiz
    +- Show a highscore of a quiz
     
     
     Question modes
     --------------
     
     You can choose between the following question modes:
     Multiple answers possible (check-box), Choose one answer (radio-button), Select one answer (select-options),
    -Enter an answer (text-field), Yes/no-boxes (2 radio-buttons), Enter a comment (textarea), Show a comment, Star rating
    -and a matrix of categories of one question for every answer (suitable only for polls; no detail evaluation implemented
    -yet).
    +Enter an answer (text-field), Yes/no-boxes (2 radio-buttons), Enter a comment (textarea), Show a comment, Star rating.
     
     Time period
     -----------
    @@ -115,17 +105,11 @@ a input-field or textarea in the frontend.
     Star-Rating
     -----------
     
    -A special case is the star rating feature. For that feature a CSS-file is included by default. If you do not need this
    -feature, you can remove the CSS-file like this for versions until 3.1.2::
    +A special case is the star rating feature. For that feature a CSS-file is included by default. If you do not need this feature, you can remove the CSS-file like this::
     
       page.includeCSS.fpMasterQuizRatingStar >
     
    -Since version 3.1.3 you can remove the css file via TypoScript (or in the template itself)::
    -
    - plugin.tx_fpmasterquiz.settings.includeRatingCSS = 0
    -
    -Otherwise you should know this: the star rating may not work correct with old browsers. It is a CSS only solution.
    -It looks like this:
    +Otherwise you should know this: the star rating may not work correct with old browsers. It is a CSS only solution. It looks like this:
     
     .. figure:: ../Images/UserManual/StarRating.png
        :width: 164px
    @@ -137,7 +121,7 @@ You can use it this way: because it uses radio-boxes in the background, you must
     Select the question mode "star rating" and than add as many answers as you like to have stars. If you want 5 stars, add 5 answers.
     The first answer is the highest rating (e.g. 5 stars) and and last answer is the lowest answer (1 star). 
     That is the opposite logic of the star rating in the extension myquizpoll.
    -Do not set the points. In the user-answer, the points shows how many stars were selected.
    +Do not set the points. In the user-answer, the points shows how many stars were seleced.
     With the setting checkAllStars you can define if one or all stars should be checked by default.
     
     .. important::
    @@ -149,18 +133,16 @@ With the setting checkAllStars you can define if one or all stars should be chec
     FAQ
     ---
     
    +- I need some features from myquizpoll. What can I do?
    +
    +  You can tell me, which feature you need.
    +
     - What about user data like name and email? Where can we ask for them?
     
       There is a special intro-page possible, where you can ask for the user-name, email and homepage.
    -  Or you can ask for the user data at the first page of a quiz. And: you can ask for user data at the final page.
    -  Then you would need a closure page too.
    +  Or you can ask for the user data at the first page of a quiz. Todo: ask for user data at the final page.
       If the user is logged in, this data will be taken from fe_users.
     
    -- What is the difference between the final page and the closure page?
    -
    -  The final page is the page you get when the quiz was completed. When "user.askForData = 3" then that form will
    -  redirect from the final page to the closure page. Only in that case you will need a closure page.
    -
     - There are some errors or I get a blank page. What can I do?
     
       If you use AJAX: disable it or read the Administration-manual. You can try this TypoScript too: config.contentObjectExceptionHandler = 0
    
  • ext_emconf.php+5 3 modified
    @@ -12,16 +12,18 @@
     
     $EM_CONF[$_EXTKEY] = [
         'title' => 'Master-Quiz',
    -    'description' => 'A modern extension that offers quiz, polls and tests. Ajax support. The result can be displayed as a chart too. Supports 8 question modes.',
    +    'description' => 'A modern extension that offers quiz, polls and tests. Ajax support. The result can be displayed as a chart too. Supports 7 question modes.',
         'category' => 'plugin',
         'author' => 'Kurt Gusbeth',
    +	'author_email' => 'info@quizpalme.de',
         'state' => 'stable',
    +    'uploadfolder' => 0,
         'createDirs' => '',
         'clearCacheOnLoad' => 0,
    -    'version' => '3.5.1',
    +    'version' => '2.2.1',
         'constraints' => [
             'depends' => [
    -            'typo3' => '10.4.6-11.5.99',
    +            'typo3' => '9.5.20-10.4.99',
             ],
             'conflicts' => [],
             'suggests' => [],
    
  • ext_localconf.php+18 15 modified
    @@ -6,13 +6,14 @@ function()
         {
     
             \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
    -            'FpMasterquiz',
    +            'Fixpunkt.FpMasterquiz',
                 'Pi1',
                 [
    -                \Fixpunkt\FpMasterquiz\Controller\QuizController::class => 'list, intro, default, show, showAjax, showByTag, closure, defaultres, result, highscore'
    +                'Quiz' => 'list, intro, default, show, showAjax, showByTag, random, defaultres, result, highscore'
                 ],
    +            // non-cacheable actions
                 [
    -                \Fixpunkt\FpMasterquiz\Controller\QuizController::class => 'default, show, showAjax, showByTag, closure, defaultres, result, highscore'
    +                'Quiz' => 'default, show, showAjax, showByTag, random, defaultres, result, highscore'
                 ]
             );
     
    @@ -37,10 +38,11 @@ function()
             );
             
     		$iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
    +		
     		$iconRegistry->registerIcon(
     			'fp_masterquiz-plugin-pi1',
     		    \TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
    -			['source' => 'EXT:fp_masterquiz/Resources/Public/Icons/user_plugin_pi1.gif']
    +			['source' => 'EXT:fp_masterquiz/ext_icon.gif']
     		);
     		$iconRegistry->registerIcon(
     		    'ext-fpmasterquiz-folder-icon',
    @@ -52,23 +54,24 @@ function()
     );
     ## EXTENSION BUILDER DEFAULTS END TOKEN - Everything BEFORE this line is overwritten with the defaults of the extension builder
     
    -if (TYPO3_MODE === 'BE') {
    -    // Page module hook
    -    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['fpmasterquiz_pi1']['fp_masterquiz'] =
    -        \Fixpunkt\FpMasterquiz\Hooks\PageLayoutView::class . '->getExtensionSummary';
    +// Page module hook
    +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['fpmasterquiz_pi1']['fp_masterquiz'] =
    +\Fixpunkt\FpMasterquiz\Hooks\PageLayoutView::class . '->getExtensionSummary';
     
    +if (TYPO3_MODE === 'BE') {
     	// Add deletion task (sheduler)
     	$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks']['Fixpunkt\\FpMasterquiz\\Task\\DeleteParticipantTask'] = array(
     			'extension' => 'fp_masterquiz',
     			'title' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.title',
     			'description' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.description',
     			'additionalFields' => 'Fixpunkt\\FpMasterquiz\\Task\\DeleteParticipantAdditionalFieldProvider'
     	);
    -	// CSV-export task
    -    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks']['Fixpunkt\\FpMasterquiz\\Task\\CsvExportTask'] = array(
    -        'extension' => 'fp_masterquiz',
    -        'title' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.exportTitle',
    -        'description' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.exportDescription',
    -        'additionalFields' => 'Fixpunkt\\FpMasterquiz\\Task\\CsvExportAdditionalFieldProvider'
    -    );
    +	// Add myquizpoll-import task (sheduler)
    +	$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks']['Fixpunkt\\FpMasterquiz\\Task\\ImportQuizTask'] = array(
    +			'extension' => 'fp_masterquiz',
    +			'title' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.titleImport',
    +			'description' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf:tasks.descriptionImport',
    +			'additionalFields' => 'Fixpunkt\\FpMasterquiz\\Task\\ImportQuizAdditionalFieldProvider'
    +	);
    +	// CSV-import task ist noch nicht fertig, kommt aber später hierhin
     }
    \ No newline at end of file
    
  • ext_tables.php+28 16 modified
    @@ -4,23 +4,34 @@
     call_user_func(
         function()
         {
    -        \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
    -            'FpMasterquiz',
    -            'web', // Make module a submodule of 'web'
    -            'mod1', // Submodule key
    -            '', // Position
    -            [
    -                \Fixpunkt\FpMasterquiz\Controller\QuizController::class => 'index,detail,charts',
    -                \Fixpunkt\FpMasterquiz\Controller\QuestionController::class => 'move',
    -                \Fixpunkt\FpMasterquiz\Controller\ParticipantController::class => 'list,detail,delete'
    -            ],
    -            [
    -                'access' => 'user,group',
    -                'icon'   => 'EXT:fp_masterquiz/Resources/Public/Icons/user_mod_mod1.gif',
    -                'labels' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf'
    -            ]
    +
    +        \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
    +            'Fixpunkt.FpMasterquiz',
    +            'Pi1',
    +            'Master-Quiz'
             );
     
    +        if (TYPO3_MODE === 'BE') {
    +
    +            \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
    +                'Fixpunkt.FpMasterquiz',
    +                'web', // Make module a submodule of 'web'
    +                'mod1', // Submodule key
    +                '', // Position
    +                [
    +                    'Quiz' => 'index,detail,charts',
    +                    'Participant' => 'list,detail,delete',
    +                    
    +                ],
    +                [
    +                    'access' => 'user,group',
    +                    'icon'   => 'EXT:fp_masterquiz/ext_icon.gif',
    +                    'labels' => 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf',
    +                ]
    +            );
    +
    +        }
    +
             \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('tx_fpmasterquiz_domain_model_quiz', 'EXT:fp_masterquiz/Resources/Private/Language/locallang_csh_tx_fpmasterquiz_domain_model_quiz.xlf');
             \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages('tx_fpmasterquiz_domain_model_quiz');
     
    @@ -41,5 +52,6 @@ function()
     
             \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('tx_fpmasterquiz_domain_model_tag', 'EXT:fp_masterquiz/Resources/Private/Language/locallang_csh_tx_fpmasterquiz_domain_model_tag.xlf');
             \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages('tx_fpmasterquiz_domain_model_tag');
    +
         }
    -);
    \ No newline at end of file
    +);
    
  • ext_tables.sql+0 7 modified
    @@ -63,7 +63,6 @@ CREATE TABLE tx_fpmasterquiz_domain_model_question (
     	bodytext text,
     	explanation text,
         tag int(11) unsigned DEFAULT '0',
    -    optional smallint(5) unsigned DEFAULT '0' NOT NULL,
     	answers int(11) unsigned DEFAULT '0' NOT NULL,
     
     	tstamp int(11) unsigned DEFAULT '0' NOT NULL,
    @@ -204,7 +203,6 @@ CREATE TABLE tx_fpmasterquiz_domain_model_participant (
     	ip varchar(255) DEFAULT '' NOT NULL,
     	session varchar(255) DEFAULT '' NOT NULL,
         sessionstart int(11) DEFAULT '0' NOT NULL,
    -    randompages varchar(255) DEFAULT '' NOT NULL,
     	points int(11) DEFAULT '0' NOT NULL,
     	maximum1 int(11) DEFAULT '0' NOT NULL,
     	maximum2 int(11) DEFAULT '0' NOT NULL,
    @@ -338,11 +336,6 @@ CREATE TABLE tx_fpmasterquiz_domain_model_answer (
     	categories int(11) unsigned DEFAULT '0' NOT NULL,
     );
     
    -CREATE TABLE tx_fpmasterquiz_domain_model_evaluation
    -(
    -    categories int(11) unsigned DEFAULT '0' NOT NULL,
    -);
    -
     #
     # Table structure for table 'tx_fpmasterquiz_domain_model_selected'
     #
    
  • .idea/workspace.xml+6 0 added
    @@ -0,0 +1,6 @@
    +<?xml version="1.0" encoding="UTF-8"?>
    +<project version="4">
    +  <component name="PropertiesComponent">
    +    <property name="last_opened_file_path" value="C:/xampp/htdocs/git" />
    +  </component>
    +</project>
    \ No newline at end of file
    
  • README.md+12 25 modified
    @@ -1,39 +1,26 @@
     # fp_masterquiz
     
    -version 3.5.1
    +version 2.2.1
     
     TYPO3 extension to create a quiz, poll or test. The participant result will be saved in the DB too and can be deleted automatically via Scheduler.
     
     The results can be displayed as a chart too. An evaluation is possible too.
     
     Features: a quiz, poll or test can be played by submitting a form or by submitting an AJAX-request.
     
    -8 question types/modes available: checkbox, radio-box, select-box, yes/no, text-field, textarea, star-rating, matrix.
    +7 question types/modes available: checkbox, radio-box, select-box, yes/no, text-field, textarea, star-rating.
     
    -This extension is not backward compatible to myquizpoll, but there is a simple import-task for myquizpoll-questions in older versions.
    -
    -jQuery is required. Optimized for Bootstrap 4.
    -
    -Dashboard widget available.
    -
    -CSV-export available via scheduler task.
    -
    -Available languages: english and german/deutsch.
    +This extension is not backward compatible to myquizpoll, but there is a simple import-task for myquizpoll-questions.
     
     You find the documentation at typo3.org: https://docs.typo3.org/p/fixpunkt/fp-masterquiz/master/en-us/
     
    +Changes in version 2.2.0:
    +- intro action and settings introContentUid, introNextAction added.
    +- date and time of the participant in the BE module.
    +- text-answers in the BE module.
    +- time period for a quiz.
    +- TCA-Bugfix for TYPO3 10.
     
    -Changes in version 3.4.0:
    -- The answer of textarea-fields is now checked too (it is no longer optional, but can be set to optional).
    -- CSV-export added as scheduler task.
    -- Dashboard no longer required in TYPO3 11.
    -- Layout optimizations.
    -
    -Changes in version 3.4.4:
    -- Bugfix: persist before evaluation.
    -- Bugfix: category evaluation.
    -- Bugfix: wrong Namespace in TemplateLayout corrected.
    -
    -Changes in version 3.5.0:
    -- Mandatory check with PHP too, if setting phpFormCheck=1.
    -- New question mode: matrix with categories of a question.
    +Changes in version 2.2.1:
    +- Security fix: checking participant against a session-key. Please read the section Administrator / Security fix in version 3.5.2.
    +- Bugfix: check if a quiz/poll is allowed on a page. Therefore, the defaultQuizUid was removed in the settings!
    \ No newline at end of file
    
  • Resources/Private/Backend/Layouts/Default.html+36 27 modified
    @@ -1,27 +1,36 @@
    -<html
    -		xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
    -		xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers"
    -		data-namespace-typo3-fluid="true">
    -
    -<be:moduleLayout>
    -	<f:be.pageRenderer
    -			includeRequireJsModules="{
    -            0:'TYPO3/CMS/Backend/ContextMenu'
    -        }"
    -	/>
    -
    -	<be:moduleLayout.menu identifier="FpMasterquizModuleMenu">
    -		<be:moduleLayout.menuItem label="---" uri="{f:uri.action(controller: 'Quiz', action: 'index')}"/>
    -		<be:moduleLayout.menuItem label="{f:translate(key: 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:index.quiz')}" uri="{f:uri.action(controller: 'Quiz', action: 'index')}"/>
    -		<be:moduleLayout.menuItem label="{f:translate(key: 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:index.participant')}" uri="{f:uri.action(controller: 'Participant', action: 'list')}"/>
    -	</be:moduleLayout.menu>
    -
    -	<be:moduleLayout.button.shortcutButton displayName="Create a shortcut" />
    -
    -	<div id="masterquiz-main-content">
    -		<f:flashMessages />
    -		<f:render section="Content" />
    -	</div>
    -</be:moduleLayout>
    -
    -</html>
    \ No newline at end of file
    +<html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
    +	<f:be.container>
    +		<div class="typo3-fullDoc">
    +			<div id="typo3-docheader">
    +				<div class="typo3-docheader-functions">
    +					<div class="left">
    +						<f:be.buttons.csh />
    +						<f:be.menus.actionMenu>
    +							<f:be.menus.actionMenuItem label="---" controller="Quiz" action="index" />
    +							<f:be.menus.actionMenuItem label="{f:translate(key: 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:index.quiz')}" controller="Quiz" action="index" />
    +							<f:be.menus.actionMenuItem label="{f:translate(key: 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:index.participant')}" controller="Participant" action="list" />
    +							<!-- f:be.menus.actionMenuItem label="{f:translate(key: 'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:index.charts')}" controller="Quiz" action="charts" / -->
    +						</f:be.menus.actionMenu>
    +					</div>
    +					<div class="right">
    +						<f:be.pagePath />
    +						<f:be.pageInfo />
    +					</div>
    +				</div>
    +				<div class="typo3-docheader-buttons">
    +					<div class="left">
    +					</div>
    +					<div class="right">
    +						<f:be.buttons.shortcut />
    +					</div>
    +				</div>
    +			</div>
    +			<div id="typo3-docbody">
    +				<div id="typo3-inner-docbody">
    +					<f:flashMessages />
    +					<f:render section="content" />
    +				</div>
    +			</div>
    +		</div>
    +	</f:be.container>
    +</html>
    
  • Resources/Private/Backend/Layouts/Widget/Default.html+0 18 removed
    @@ -1,18 +0,0 @@
    -<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
    -<div class="widget-content-title">
    -  <f:render section="title" optional="true">
    -    <span>{f:translate(id: configuration.title, default: configuration.title)}</span>
    -  </f:render>
    -</div>
    -
    -<div class="widget-content-main">
    -  <f:render section="main" optional="true"/>
    -</div>
    -
    -<f:variable name="footer" value="{f:render(section:'footer', optional: 'true')}"/>
    -<f:if condition="{footer -> f:spaceless()}">
    -  <div class="widget-content-footer">
    -    {footer -> f:format.raw()}
    -  </div>
    -</f:if>
    -</html>
    \ No newline at end of file
    
  • Resources/Private/Backend/Partials/Participant/Paginator.html+0 89 removed
    @@ -1,89 +0,0 @@
    -<nav class="pagination-wrap">
    -    <ul class="pagination">
    -        <f:if condition="{pagination.previousPageNumber} && {pagination.previousPageNumber} >= {pagination.firstPageNumber}">
    -            <f:then>
    -                <li class="page-item">
    -                    <a href="{f:uri.action(arguments:{currentPage: 1})}" title="{f:translate(key:'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:pagination.first')}" class="page-link">
    -                        <core:icon identifier="actions-view-paging-first" />
    -                    </a>
    -                </li>
    -                <li class="page-item">
    -                    <a href="{f:uri.action(arguments:{currentPage: pagination.previousPageNumber})}" title="{f:translate(key:'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:pagination.previous')}" class="page-link">
    -                        <core:icon identifier="actions-view-paging-previous" />
    -                    </a>
    -                </li>
    -            </f:then>
    -            <f:else>
    -                <li class="page-item disabled">
    -                    <span class="page-link">
    -                        <core:icon identifier="actions-view-paging-first" />
    -                    </span>
    -                </li>
    -                <li class="page-item disabled">
    -                    <span class="page-link">
    -                        <core:icon identifier="actions-view-paging-previous" />
    -                    </span>
    -                </li>
    -            </f:else>
    -        </f:if>
    -        <li class="page-item">
    -            <span class="page-link">
    -                <f:translate key="pagination.records" /> {pagination.startRecordNumber} - {pagination.endRecordNumber}
    -            </span>
    -        </li>
    -        <li class="page-item">
    -            <span class="page-link">
    -                <f:translate key="pagination.page" />
    -                <form style="display:inline;"
    -                      data-global-event="submit"
    -                      data-action-navigate="$form=~s/$value/"
    -                      data-navigate-value="{f:uri.action(arguments:'{currentPage: \'$[value]\'}')}"
    -                      data-value-selector="input[name='paginator-target-page']">
    -                    <input
    -                            min="{pagination.firstPageNumber}"
    -                            max="{pagination.lastPageNumber}"
    -                            data-number-of-pages="{paginator.numberOfPages}"
    -                            name="paginator-target-page"
    -                            class="form-control form-control-sm paginator-input"
    -                            size="5"
    -                            value="{paginator.currentPageNumber}"
    -                            type="number"
    -                    />
    -                </form>
    -                / {pagination.lastPageNumber}
    -            </span>
    -        </li>
    -
    -        <f:if condition="{pagination.nextPageNumber} && {pagination.nextPageNumber} <= {pagination.lastPageNumber}">
    -            <f:then>
    -                <li class="page-item">
    -                    <a href="{f:uri.action(arguments:{currentPage: pagination.nextPageNumber})}" title="{f:translate(key:'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:pagination.next')}" class="page-link">
    -                        <core:icon identifier="actions-view-paging-next" />
    -                    </a>
    -                </li>
    -                <li class="page-item">
    -                    <a href="{f:uri.action(arguments:{currentPage: pagination.lastPageNumber})}" title="{f:translate(key:'LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:pagination.last')}" class="page-link">
    -                        <core:icon identifier="actions-view-paging-last" />
    -                    </a>
    -                </li>
    -            </f:then>
    -            <f:else>
    -                <li class="page-item disabled">
    -                    <span class="page-link">
    -                        <core:icon identifier="actions-view-paging-next" />
    -                    </span>
    -                </li>
    -                <li class="page-item disabled">
    -                    <span class="page-link">
    -                        <core:icon identifier="actions-view-paging-last" />
    -                    </span>
    -                </li>
    -            </f:else>
    -        </f:if>
    -        <li class="page-item">
    -            <a href="{f:uri.action(arguments:{currentPage: paginator.currentPageNumber})}" title="refresh" class="page-link">
    -                <core:icon identifier="actions-refresh" />
    -            </a>
    -        </li>
    -    </ul>
    -</nav>
    \ No newline at end of file
    
  • Resources/Private/Backend/Partials/Quiz/Properties.html+1 9 modified
    @@ -27,12 +27,7 @@
       <f:for each="{quiz.questions}" as="question">
     	<tr>
     		<td>
    -			{question.title}<f:if condition="{question.optional}">*</f:if>
    -			<f:if condition="{question.qmode} == 8">
    -				<f:for each="{question.sortedCategoriesArray}" as="category">
    -					<br/>- {category.title}
    -				</f:for>
    -			</f:if>
    +			{question.title}
     		</td>
     		<td>
     			<f:format.html>{question.bodytext}</f:format.html>
    @@ -63,9 +58,6 @@
     				<f:case value="7">
     					<f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.qmode.7" />
     				</f:case>
    -				<f:case value="8">
    -					<f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.qmode.8" />
    -				</f:case>
     				<f:defaultCase>NOT yet supported</f:defaultCase>
     			</f:switch>
     		</td>
    
  • Resources/Private/Backend/Partials/Selected/Properties.html+1 9 modified
    @@ -53,9 +53,6 @@ <h4><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang
     				<f:case value="7">
     					<f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.qmode.7" />
     				</f:case>
    -				<f:case value="8">
    -					<f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.qmode.8" />
    -				</f:case>
     				<f:defaultCase>NOT yet supported</f:defaultCase>
     			</f:switch>
     		</td>
    @@ -68,12 +65,7 @@ <h4><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang
     			<f:defaultCase>
     				<div class="table-responsive"><table class="table">
     				<f:for each="{selection.answers}" as="answer">
    -					<tr><td>
    -						{answer.title}
    -						<f:if condition="{selection.question.qmode} == 8 && {answer.ownCategoryAnswer}">
    -							: {answer.ownCategoryAnswer.1}
    -						</f:if>
    -					</td><td><div class="pull-right">({answer.points})</div></td></tr>
    +					<tr><td>{answer.title}</td><td><div class="pull-right">({answer.points})</div></td></tr>
     				</f:for>
     				</table></div>
     			</f:defaultCase>
    
  • Resources/Private/Backend/Templates/Answer/List.html+14 1 modified
    @@ -1,9 +1,22 @@
     <html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
     <f:layout name="Default" />
     
    -<f:section name="Content">
    +This Template is responsible for creating a table of domain objects.
    +
    +If you modify this template, do not forget to change the overwrite settings
    +in /Configuration/ExtensionBuilder/settings.yaml:
    +  Resources:
    +    Private:
    +      Templates:
    +        List.html: keep
    +
    +Otherwise your changes will be overwritten the next time you save the extension in the extension builder
    +
    +<f:section name="content">
     <h1>Listing for Answer</h1>
     
    +<f:flashMessages />
    +
     <table  class="tx_fpmasterquiz" >
     	<tr>
     		<th><f:translate key="tx_fpmasterquiz_domain_model_answer.title" /></th>
    
  • Resources/Private/Backend/Templates/Answer/Show.html+13 1 modified
    @@ -1,9 +1,21 @@
     <html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
       <f:layout name="Default" />
     
    -  <f:section name="Content">
    +  This Template is responsible for displaying a single view for a domain object
    +
    +  If you modify this template, do not forget to change the overwrite settings
    +  in /Configuration/ExtensionBuilder/settings.yaml:
    +    Resources:
    +      Private:
    +        Templates:
    +          Show.html: keep
    +
    +  Otherwise your changes will be overwritten the next time you save the extension in the extension builder
    +
    +  <f:section name="content">
         <h1>Single View for Answer</h1>
     
    +    <f:flashMessages />
         <f:render partial="Answer/Properties" arguments="{answer:answer}" />
         <f:link.action action="list">Back to list</f:link.action><br />
         <f:link.action action="create">New Answer</f:link.action>
    
  • Resources/Private/Backend/Templates/Participant/Detail.html+3 2 modified
    @@ -1,8 +1,9 @@
     <html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
       <f:layout name="Default" />
    -  <f:section name="Content">
    +  <f:section name="content">
         <h1>{participant.name}</h1>
         <h3><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:quiz" />: {participant.quiz.name}</h3>
    +    <f:flashMessages />
         <h4><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:user" />:</h4>
         <div class="table-responsive">
     	<table class="table">
    @@ -19,7 +20,7 @@ <h4><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang
     		<tr>
     			<td>{participant.email}</td>
     			<td>{participant.homepage}</td>
    -			<td><f:if condition="{participant.user}">{participant.username} ({participant.user})</f:if></td>
    +			<td>{participant.user}</td>
     			<td>{participant.ip}</td>
     			<td>{participant.points}</td>
     			<td>{participant.maximum1}</td>
    
  • Resources/Private/Backend/Templates/Participant/List.html+11 12 modified
    @@ -1,12 +1,13 @@
     <html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
     <f:layout name="Default" />
    -<f:section name="Content">
    -	<h1><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:list-participants" default="Listing for" /> {pid}</h1>
    -
    -	<f:if condition="{settings.pagebrowser.insertAbove} && ({paginator.numberOfPages} > 1)">
    -		<f:render partial="Participant/Paginator" arguments="{_all}" />
    -	</f:if>
    -	<f:for each="{paginator.paginatedItems}" as="participant" iteration="iter">
    +<f:section name="content">
    +<h1><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:list-participants" default="Listing for" /> {pid}</h1>
    +<f:flashMessages />
    +<style>
    +ul.f3-widget-paginator li { float: left; margin-left: 15px; }
    +</style>
    +<f:widget.paginate objects="{participants}" as="paginatedParticipants" configuration="{settings.pagebrowser}">
    +	<f:for each="{paginatedParticipants}" as="participant" iteration="iter">
     	  <f:if condition="{iter.isFirst}">
     		<div class="table-responsive">
     		<table class="table">
    @@ -25,7 +26,7 @@ <h1><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang
     			<td>{participant.name}</td>
     			<td>{participant.email}</td>
     			<td>{participant.homepage}</td>
    -			<td><f:if condition="{participant.user}">{participant.username} ({participant.user})</f:if></td>
    +			<td>{participant.user}</td>
     			<td>{participant.points}</td>
     			<td>
     				{f:format.date(date: participant.startdate, format: 'd.m.y')}
    @@ -40,9 +41,7 @@ <h1><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang
     		</div>
     	  </f:if>
     	</f:for>
    -	<f:if condition="{settings.pagebrowser.insertBelow} && ({paginator.numberOfPages} > 1)">
    -		<f:render partial="Participant/Paginator" arguments="{_all}" />
    -	</f:if>
    -	<p style="clear:both;"><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:entries" />: {participants -> f:count()}.</p>
    +</f:widget.paginate>
    +<p style="clear:both;"><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:entries" />: {participants -> f:count()}.</p>
     </f:section>
     </html>
    \ No newline at end of file
    
  • Resources/Private/Backend/Templates/Question/List.html+46 0 added
    @@ -0,0 +1,46 @@
    +<html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
    +<f:layout name="Default" />
    +
    +This Template is responsible for creating a table of domain objects.
    +
    +If you modify this template, do not forget to change the overwrite settings
    +in /Configuration/ExtensionBuilder/settings.yaml:
    +  Resources:
    +    Private:
    +      Templates:
    +        List.html: keep
    +
    +Otherwise your changes will be overwritten the next time you save the extension in the extension builder
    +
    +<f:section name="content">
    +<h1>Listing for Question</h1>
    +
    +<f:flashMessages />
    +
    +<table  class="tx_fpmasterquiz" >
    +	<tr>
    +		<th><f:translate key="tx_fpmasterquiz_domain_model_question.title" /></th>
    +		<th><f:translate key="tx_fpmasterquiz_domain_model_question.qmode" /></th>
    +		<th><f:translate key="tx_fpmasterquiz_domain_model_question.image" /></th>
    +		<th><f:translate key="tx_fpmasterquiz_domain_model_question.bodytext" /></th>
    +		<th><f:translate key="tx_fpmasterquiz_domain_model_question.explanation" /></th>
    +		<th> </th>
    +		<th> </th>
    +	</tr>
    +
    +	<f:for each="{questions}" as="question">
    +		<tr>
    +			<td><f:link.action action="show" arguments="{question : question}"> {question.title}</f:link.action></td>
    +			<td><f:link.action action="show" arguments="{question : question}"> {question.qmode}</f:link.action></td>
    +			<td><f:link.action action="show" arguments="{question : question}"> {question.image.originalResource.name}</f:link.action></td>
    +			<td><f:link.action action="show" arguments="{question : question}"> {question.bodytext}</f:link.action></td>
    +			<td><f:link.action action="show" arguments="{question : question}"> {question.explanation}</f:link.action></td>
    +			<td><f:link.action action="edit" arguments="{question : question}">Edit</f:link.action></td>
    +			<td><f:link.action action="delete" arguments="{question : question}">Delete</f:link.action></td>
    +		</tr>
    +		</f:for>
    +</table>
    +
    +<f:link.action action="new">New Question</f:link.action>
    +	</f:section>
    +</html>
    \ No newline at end of file
    
  • Resources/Private/Backend/Templates/Question/Move.html+0 19 removed
    @@ -1,19 +0,0 @@
    -<html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
    -  <f:layout name="Default" />
    -  <f:section name="Content">
    -    <h1><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:moveQuestion" /></h1>
    -    <p>Quiz: {quiz.name}</p>
    -    <f:if condition="{question}">
    -      <f:then>
    -        <p><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:movedQuestion" /> {question.title}</p>
    -      </f:then>
    -    </f:if>
    -    <p><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:questionsInFolder" /></p>
    -    <f:for each="{questions}" as="question">
    -      <f:link.action controller="Question" action="move" arguments="{quiz : quiz, question : question}">{question.title}</f:link.action><br />
    -    </f:for>
    -    <br/>
    -    <p><f:link.action controller="Quiz" action="detail" arguments="{quiz : quiz}" class="btn btn-default"><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:backtoQuiz" default="Back to list" /></f:link.action></p>
    -    <p><f:link.action controller="Quiz" action="index" class="btn btn-default"><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:back" default="Back to list" /></f:link.action></p>
    -  </f:section>
    -</html>
    \ No newline at end of file
    
  • Resources/Private/Backend/Templates/Question/Show.html+23 0 added
    @@ -0,0 +1,23 @@
    +<html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
    +  <f:layout name="Default" />
    +
    +  This Template is responsible for displaying a single view for a domain object
    +
    +  If you modify this template, do not forget to change the overwrite settings
    +  in /Configuration/ExtensionBuilder/settings.yaml:
    +    Resources:
    +      Private:
    +        Templates:
    +          Show.html: keep
    +
    +  Otherwise your changes will be overwritten the next time you save the extension in the extension builder
    +
    +  <f:section name="content">
    +    <h1>Single View for Question</h1>
    +
    +    <f:flashMessages />
    +    <f:render partial="Question/Properties" arguments="{question:question}" />
    +    <f:link.action action="list">Back to list</f:link.action><br />
    +    <f:link.action action="create">New Question</f:link.action>
    +  </f:section>
    +</html>
    \ No newline at end of file
    
  • Resources/Private/Backend/Templates/Quiz/Charts.html+3 2 modified
    @@ -3,9 +3,9 @@
       <f:comment>
       Chart from https://speckyboy.com/code-snippets-css3-bar-graphs/
       </f:comment>
    -  <f:section name="Content">
    +  <f:section name="content">
         <style>
    -      hr {
    +      #typo3-inner-docbody hr {
             border-top: 1px dotted #666;
           }
           .chart {
    @@ -66,6 +66,7 @@
         </style>
     	<h1><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:charts-participants" default="Listing for" /> {pid}</h1>
         <h2>{quiz.name}</h2>
    +    <f:flashMessages />
         <f:for each="{quiz.questions}" as="question">
     	    <f:render partial="Question/Chart" arguments="{_all}" />
         </f:for>
    
  • Resources/Private/Backend/Templates/Quiz/Detail.html+3 7 modified
    @@ -1,7 +1,8 @@
     <html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
       <f:layout name="Default" />
    -  <f:section name="Content">
    +  <f:section name="content">
         <h1>{quiz.name}</h1>
    +    <f:flashMessages />
         <f:if condition="{updated}"><f:then></f:then><f:else>
         <f:render partial="Quiz/Properties" arguments="{quiz:quiz}" />
     	</f:else></f:if>
    @@ -11,15 +12,10 @@ <h3><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang
     		<f:form action="detail">
     		<f:form.hidden name="quiz" value="{quiz.uid}" />
     	   	<f:form.select name="lost" options="{lostArray}" />
    -			<br>
     	   	<f:form.button type="submit" name="quizGoOn" class="btn btn-primary"><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:addthis" default="add" /></f:form.button>
     	   	</f:form>
     	</f:if>
    -
    -	<p><f:link.action controller="Question" action="move" arguments="{quiz : quiz}" class="btn btn-primary"><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:moveQuestion" /></f:link.action></p>
    -
    +	
         <p><f:link.action action="index" class="btn btn-default"><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:back" default="Back to list" /></f:link.action></p>
    -
    -    <br><p>*: <f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf:tx_fpmasterquiz_domain_model_question.optional" /></p>
       </f:section>
     </html>
    \ No newline at end of file
    
  • Resources/Private/Backend/Templates/Quiz/Index.html+2 1 modified
    @@ -1,7 +1,8 @@
     <html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
     <f:layout name="Default" />
    -<f:section name="Content">
    +<f:section name="content">
     <h1><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:list" default="Listing for" /> {pid}</h1>
    +<f:flashMessages />
     <f:if condition="{quizzes -> f:count()} > 0">
     <f:then>
     <div class="table-responsive">
    
  • Resources/Private/Backend/Templates/Selected/List.html+14 1 modified
    @@ -1,9 +1,22 @@
     <html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
     <f:layout name="Default" />
     
    -<f:section name="Content">
    +This Template is responsible for creating a table of domain objects.
    +
    +If you modify this template, do not forget to change the overwrite settings
    +in /Configuration/ExtensionBuilder/settings.yaml:
    +  Resources:
    +    Private:
    +      Templates:
    +        List.html: keep
    +
    +Otherwise your changes will be overwritten the next time you save the extension in the extension builder
    +
    +<f:section name="content">
     <h1>Listing for Selected</h1>
     
    +<f:flashMessages />
    +
     <table  class="tx_fpmasterquiz" >
     	<tr>
     		<th><f:translate key="tx_fpmasterquiz_domain_model_selected.points" /></th>
    
  • Resources/Private/Backend/Templates/Widget/RecentParticipantsWidget.html+0 40 removed
    @@ -1,40 +0,0 @@
    -<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
    -<f:layout name="Widget/Default" />
    -<f:section name="title">
    -    <div class="widget-content-title-badge"><span>{f:translate(id: configuration.title, default: configuration.title)}</span></div>
    -</f:section>
    -
    -<f:section name="main">
    -    <table class="table">
    -        <tr>
    -            <th><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_participant.time" /></th>
    -            <th><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf:quiz" /></th>
    -            <th>1. <f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_question" /></th>
    -            <th>1. <f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_answer" /></th>
    -            <th><f:translate key="LLL:EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf:tx_fpmasterquiz_domain_model_answer.points" /></th>
    -        </tr>
    -        <f:for each="{participants}" as="participant" iteration="iter">
    -            <tr>
    -                <td class="{f:if(condition: '{iter.isOdd}', then: 'bg-warning', else: 'bg-success')}">
    -                    <f:format.date format="d.m.Y - H:i:s">{participant.startdate}</f:format.date>
    -                </td>
    -                <td class="{f:if(condition: '{iter.isOdd}', then: 'bg-warning', else: 'bg-success')}">
    -                    {participant.quizname}
    -                </td>
    -                <td class="{f:if(condition: '{iter.isOdd}', then: 'bg-warning', else: 'bg-success')}">
    -                    {participant.question1}
    -                </td>
    -                <td class="{f:if(condition: '{iter.isOdd}', then: 'bg-warning', else: 'bg-success')}">
    -                    {participant.answer1}
    -                </td>
    -                <td class="{f:if(condition: '{iter.isOdd}', then: 'bg-warning', else: 'bg-success')}">
    -                    {participant.points} / {participant.maximum2}
    -                </td>
    -            </tr>
    -        </f:for>
    -    </table>
    -</f:section>
    -
    -<f:section name="footer">
    -</f:section>
    -</html>
    \ No newline at end of file
    
  • Resources/Private/Language/de.locallang_be.xlf+17 117 modified
    @@ -1,6 +1,6 @@
     <?xml version="1.0" encoding="UTF-8"?>
     <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    -	<file source-language="en" target-language="de" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf" date="2022-08-19T12:56:31Z" product-name="fp_masterquiz">
    +	<file source-language="en" target-language="de" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf" date="2021-06-08T12:40:25Z" product-name="fp_masterquiz">
     		<header/>
     		<body>
     			<trans-unit id="template" resname="template">
    @@ -16,28 +16,24 @@
     				<target>Liste aller Quizze aus dem Ordner</target>
     			</trans-unit>
     			<trans-unit id="template.show" resname="template.show">
    -				<source>Show a selected quiz and use a pagebrowser (you need to select the storage folder too)</source>
    -				<target>Ein bestimmtes Quiz anzeigen und den Pagebrowser nutzen (Datensatzsammlung muss dennoch gewählt werden)</target>
    +				<source>Show a selected quiz and use a pagebrowser (save the plugin! | you need to select the storage folder too)</source>
    +				<target>Ein bestimmtes Quiz anzeigen und den Pagebrowser nutzen (speichern! | Datensatzsammlung muss dennoch gewählt werden)</target>
     			</trans-unit>
     			<trans-unit id="template.showByTag" resname="template.showByTag">
    -				<source>Show a selected quiz and order questions by tag (you need to select the storage folder too)</source>
    -				<target>Ein bestimmtes Quiz anzeigen und Fragen nach Tag sortieren (Datensatzsammlung muss dennoch gewählt werden)</target>
    +				<source>Show a selected quiz and order questions by tag (save the plugin! | you need to select the storage folder too)</source>
    +				<target>Ein bestimmtes Quiz anzeigen und Fragen nach Tag sortieren (speichern! | Datensatzsammlung muss dennoch gewählt werden)</target>
     			</trans-unit>
     			<trans-unit id="template.intro" resname="template.intro">
    -				<source>Show an intro page and then a quiz (you need to select the storage folder too)</source>
    -				<target>Eine Into-Seite und dann ein Quiz anzeigen (Datensatzsammlung muss dennoch gewählt werden)</target>
    +				<source>Show an intro page and then a quiz (save the plugin! | you need to select the storage folder too)</source>
    +				<target>Eine Into-Seite und dann ein Quiz anzeigen (speichern! | Datensatzsammlung muss dennoch gewählt werden)</target>
     			</trans-unit>
     			<trans-unit id="template.result" resname="template.result">
    -				<source>Show a result of a quiz (you need to select the storage folder too)</source>
    -				<target>Ergebnis eines Quiz anzeigen (Datensatzsammlung muss dennoch gewählt werden)</target>
    +				<source>Show a result of a quiz (save the plugin! | you need to select the storage folder too)</source>
    +				<target>Ergebnis eines Quiz anzeigen (speichern! | Datensatzsammlung muss dennoch gewählt werden)</target>
     			</trans-unit>
     			<trans-unit id="template.highscore" resname="template.highscore">
    -				<source>Show a highscore of a quiz (you need to select the storage folder too)</source>
    -				<target>Highscore eines Quiz anzeigen (Datensatzsammlung muss dennoch gewählt werden)</target>
    -			</trans-unit>
    -			<trans-unit id="template.closure" resname="template.closure">
    -				<source>Show a closure page after a quiz (you need to select the storage folder too)</source>
    -				<target>Eine Abschlussseite zeigen (Datensatzsammlung muss dennoch gewählt werden)</target>
    +				<source>Show a highscore of a quiz (save the plugin! | you need to select the storage folder too)</source>
    +				<target>Highscore eines Quiz anzeigen (speichern! | Datensatzsammlung muss dennoch gewählt werden)</target>
     			</trans-unit>
     			<trans-unit id="templateLayout" resname="templateLayout">
     				<source>Template layout (see manual):</source>
    @@ -55,10 +51,6 @@
     				<source>Single page of a quiz/poll (detailPid):</source>
     				<target>Singleseite für ein Quiz/Umfrage (detailPid):</target>
     			</trans-unit>
    -			<trans-unit id="settings.closurePageUid" resname="settings.closurePageUid">
    -				<source>Page for a closure after a quiz (when askForData=3):</source>
    -				<target>Abschlussseite zu der umgeleitet werden soll, wenn askForData=3</target>
    -			</trans-unit>
     			<trans-unit id="settings.resultPageUid" resname="settings.resultPageUid">
     				<source>Page where to show a result of a quiz/poll:</source>
     				<target>Ergebnisse eines Quiz/Umfrage hier anzeigen:</target>
    @@ -80,12 +72,12 @@
     				<target>Anzahl der Fragen pro Seite:</target>
     			</trans-unit>
     			<trans-unit id="settings.showAnswerPage" resname="settings.showAnswerPage">
    -				<source>Show a solution page with answered questions after every submit?</source>
    -				<target>Zeige eine Auswertung der beantworteten Fragen nach jedem absenden an?</target>
    +				<source>Show a solution page after every submit?</source>
    +				<target>Zeige eine Auswertung nach jedem absenden an?</target>
     			</trans-unit>
     			<trans-unit id="settings.showAnswersAtFinalPage" resname="settings.showAnswersAtFinalPage">
    -				<source>Show the answered questions (solutions) at the final page?</source>
    -				<target>Zeige die beantworteten Fragen (Auswertung) auf der Schlußseite an?</target>
    +				<source>Show the solutions at the final page?</source>
    +				<target>Zeige die Auswertung auf der Schlußseite an?</target>
     			</trans-unit>
     			<trans-unit id="settings.showOwnAnswers" resname="settings.showOwnAnswers">
     				<source>Show the own answers?</source>
    @@ -107,26 +99,6 @@
     				<source>Show the possible/reached points?</source>
     				<target>Zeige die möglichen/erreichten Punkte an?</target>
     			</trans-unit>
    -			<trans-unit id="settings.showDetailedCategoryEval" resname="settings.showDetailedCategoryEval">
    -				<source>Show detailed category evaluation if categories are used?</source>
    -				<target>Zeige eine detaillierte Kategorieauswertung an, wenn Kategorien benutzt werden?</target>
    -			</trans-unit>
    -			<trans-unit id="settings.noFormCheck" resname="settings.noFormCheck">
    -				<source>Disable form check (set all questions as non mandatory)?</source>
    -				<target>Fragen-Check ausschalten (Abfrage, ob alle Fragen beantwortet wurden)?</target>
    -			</trans-unit>
    -			<trans-unit id="settings.phpFormCheck" resname="settings.phpFormCheck">
    -				<source>Enable a form check (of mandatory questions) via PHP?</source>
    -				<target>Fragen-Check auch via PHP einschalten?</target>
    -			</trans-unit>
    -			<trans-unit id="settings.allowEdit" resname="settings.allowEdit">
    -				<source>Allow edit answered questions (works only for show by tag)?</source>
    -				<target>Erlaube es, Antworten zu editieren (funktioniert nur bei &quot;Fragen nach Tag sortieren&quot;)?</target>
    -			</trans-unit>
    -			<trans-unit id="settings.random" resname="settings.random">
    -				<source>Enable a random mode for tags (works only for show by tag)?</source>
    -				<target>Zufallsmodus für Tags aktivieren (funktioniert nur bei &quot;Fragen nach Tag sortieren&quot;)?</target>
    -			</trans-unit>
     			<trans-unit id="settings.ajax" resname="settings.ajax">
     				<source>Enable AJAX-version? Important: all FlexForm-settings will be ignored then.</source>
     				<target>AJAX-Version einschalten? WICHTIG: alle FlexForm-Einstellungen werden dann ignoriert!</target>
    @@ -151,10 +123,6 @@
     				<source>yes, but only at the intro page</source>
     				<target>ja, aber nur auf der Intro-Seite</target>
     			</trans-unit>
    -			<trans-unit id="settings.yesFinalPage" resname="settings.yesFinalPage">
    -				<source>yes, but only at the final page (save the plugin! | you need a closure page too!)</source>
    -				<target>ja, aber nur auf der Schluss-Seite (speichern! | man braucht auch eine Abschlussseite)</target>
    -			</trans-unit>
     			<trans-unit id="enables" resname="enables">
     				<source>Enable/disable</source>
     				<target>Ein-/Ausschalten</target>
    @@ -187,20 +155,12 @@
     				<source>Deletes all old participants of a folder.</source>
     				<target>Importiert myquizpoll-Einträge eines ausgewählten Ordners.</target>
     			</trans-unit>
    -			<trans-unit id="tasks.exportTitle" resname="tasks.exportTitle">
    -				<source>Export CSV-file with participants</source>
    -				<target>Exportiere CSV-Datei mit Teilnehmern</target>
    -			</trans-unit>
    -			<trans-unit id="tasks.exportDescription" resname="tasks.exportDescription">
    -				<source>Exports participants (with all data) of a folder.</source>
    -				<target>Exportiere die Teilnehmer eines Ordners</target>
    -			</trans-unit>
     			<trans-unit id="tasks.validate.page" resname="tasks.validate.page">
    -				<source>Page with quiz-elements (pages UID):</source>
    +				<source>Page with elements (pages UID):</source>
     				<target>Seite mit den Einträgen (Seiten-UID):</target>
     			</trans-unit>
     			<trans-unit id="tasks.validate.invalidPage" resname="tasks.validate.invalidPage">
    -				<source>Invalid pages uid, please enter a valid pages uid!</source>
    +				<source>Invalid pages uid or the page is not visible!</source>
     				<target>Diese Seite gibt es nicht oder sie ist nicht freigegeben!</target>
     			</trans-unit>
     			<trans-unit id="tasks.validate.days" resname="tasks.validate.days">
    @@ -247,26 +207,6 @@
     				<source>Ask for user data at the first page of a quiz?</source>
     				<target>Frage nach Teilnehmer-Daten auf der 1. Seite?</target>
     			</trans-unit>
    -			<trans-unit id="settings.user.checkFEuser" resname="settings.user.checkFEuser">
    -				<source>Check if a FE-user has already participated?</source>
    -				<target>Abfragen, ob ein FE-user schon teilgenommen hat?</target>
    -			</trans-unit>
    -			<trans-unit id="settings.user.useQuizPid" resname="settings.user.useQuizPid">
    -				<source>Use automatically the pid from the quiz?</source>
    -				<target>Benutze die PID des Quiz für den Teilnehmer?</target>
    -			</trans-unit>
    -			<trans-unit id="settings.user.ipSave" resname="settings.user.ipSave">
    -				<source>Save the IP-address of a user?</source>
    -				<target>IP-Adresse des Teilnehmers speichern?</target>
    -			</trans-unit>
    -			<trans-unit id="settings.user.ipAnonymous" resname="settings.user.ipAnonymous">
    -				<source>Anonymize the IP-address?</source>
    -				<target>Die IP-Adresse anonymisieren?</target>
    -			</trans-unit>
    -			<trans-unit id="settings.user.useCookie" resname="settings.user.useCookie">
    -				<source>Save the session in a cookie for X days? -1: sets a session cookie; 0: no cookie; &gt;0 X=days.</source>
    -				<target>Speichere die Session in einem Cookie für X Tage? -1: setzt ein Session-Cookie; 0: kein Cookie; &gt;0 X=Tage.</target>
    -			</trans-unit>
     			<trans-unit id="emailSettings" resname="emailSettings">
     				<source>Email settings</source>
     				<target>Email-Einstellungen</target>
    @@ -279,46 +219,6 @@
     				<source>Send an email to the user at the final page?</source>
     				<target>Sende eine Email an den Teilnehmer am Schluss?</target>
     			</trans-unit>
    -			<trans-unit id="dashboard.widget.fixpunktRecentParticipants.title" resname="dashboard.widget.fixpunktRecentParticipants.title">
    -				<source>fp_masterquiz: the recent 7 votes</source>
    -				<target>fp_masterquiz: die letzten 7 Teilnehmer</target>
    -			</trans-unit>
    -			<trans-unit id="dashboard.widget.fixpunktRecentParticipants.description" resname="dashboard.widget.fixpunktRecentParticipants.description">
    -				<source>Shows some details from recent votes by participant like date and the 1. answer</source>
    -				<target>Zeigt Details über die letzten Teilnehmer wie Datum und 1. Abstimmung</target>
    -			</trans-unit>
    -			<trans-unit id="dashboard.widget.fixpunktLastDays.title" resname="dashboard.widget.fixpunktLastDays.title">
    -				<source>fp_masterquiz: votes of the last 31 days</source>
    -				<target>fp_masterquiz: die letzten 31 Tage</target>
    -			</trans-unit>
    -			<trans-unit id="dashboard.widget.fixpunktLastDays.description" resname="dashboard.widget.fixpunktLastDays.description">
    -				<source>Shows a bar chart with number of votes for each day</source>
    -				<target>Zeigt ein Balkendiagramm mit der Anzahl der Abstimmungen pro Tag</target>
    -			</trans-unit>
    -			<trans-unit id="tasks.validate.csvfile" resname="tasks.validate.csvfile">
    -				<source>Path and name of the csv file (must begin with &quot;fileadmin/&quot;):</source>
    -				<target>Pfad und Name der CSV-Datei (muss mit &quot;fileadmin/&quot; beginnen):</target>
    -			</trans-unit>
    -			<trans-unit id="tasks.validate.separator" resname="tasks.validate.separator">
    -				<source>Separator:</source>
    -				<target>Begrenzungszeichen:</target>
    -			</trans-unit>
    -			<trans-unit id="tasks.validate.delimiter" resname="tasks.validate.delimiter">
    -				<source>Delimiter:</source>
    -				<target>Trennzeichen:</target>
    -			</trans-unit>
    -			<trans-unit id="tasks.validate.ansdelimiter" resname="tasks.validate.ansdelimiter">
    -				<source>Answers delimiter:</source>
    -				<target>Trennzeichen bei Antworten:</target>
    -			</trans-unit>
    -			<trans-unit id="tasks.validate.convert" resname="tasks.validate.convert">
    -				<source>Convert text from UTF-8 to ISO?</source>
    -				<target>Von UTF-8 nach ISO konvertieren?</target>
    -			</trans-unit>
    -			<trans-unit id="tasks.validate.invalidCsvfile" resname="tasks.validate.invalidCsvfile">
    -				<source>Invalid csv file, please enter a valid path to the csv file in the fileadmin folder!</source>
    -				<target>Der Name der CSV-Datei wird nicht akzeptiert!</target>
    -			</trans-unit>
     		</body>
     	</file>
     </xliff>
    
  • Resources/Private/Language/de.locallang_db.xlf+2 14 modified
    @@ -1,6 +1,6 @@
     <?xml version="1.0" encoding="UTF-8"?>
     <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    -	<file source-language="en" target-language="de" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf" date="2021-10-18T09:26:11Z" product-name="fp_masterquiz">
    +	<file source-language="en" target-language="de" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf" date="2021-05-17T15:10:15Z" product-name="fp_masterquiz">
     		<header/>
     		<body>
     			<trans-unit id="tx_fp_masterquiz_pi1.name" resname="tx_fp_masterquiz_pi1.name">
    @@ -71,10 +71,6 @@
     				<source>Tag</source>
     				<target>Tag</target>
     			</trans-unit>
    -			<trans-unit id="tx_fpmasterquiz_domain_model_question.optional" resname="tx_fpmasterquiz_domain_model_question.optional">
    -				<source>The answer is optional</source>
    -				<target>Die Beantwortung ist optional</target>
    -			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_question.answers" resname="tx_fpmasterquiz_domain_model_question.answers">
     				<source>Answers of this question</source>
     				<target>Antworten zu dieser Frage</target>
    @@ -97,7 +93,7 @@
     			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_evaluation.evaluate" resname="tx_fpmasterquiz_domain_model_evaluation.evaluate">
     				<source>Evaluate points (unchecked) or percentage (checked)?</source>
    -				<target>Werte die Punkte (nicht angekreuzt) oder die Prozente (angekreuzt) oder die Kategorien (eine Kategorie markiert) aus?</target>
    +				<target>Werte die Punkte (nicht angekreuzt) oder die Prozente (angekreuzt) aus?</target>
     			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_evaluation.minimum" resname="tx_fpmasterquiz_domain_model_evaluation.minimum">
     				<source>Minimum value</source>
    @@ -155,10 +151,6 @@
     				<source>Time in seconds for the first page</source>
     				<target>Zeit in Sekunden für die 1. Seite</target>
     			</trans-unit>
    -			<trans-unit id="tx_fpmasterquiz_domain_model_participant.randompages" resname="tx_fpmasterquiz_domain_model_participant.randompages">
    -				<source>Random page order</source>
    -				<target>Zufalls-Seiten-Reihenfolge</target>
    -			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_participant.points" resname="tx_fpmasterquiz_domain_model_participant.points">
     				<source>Reached points for this quiz</source>
     				<target>Erreichte Punktzahl</target>
    @@ -251,10 +243,6 @@
     				<source>Star rating</source>
     				<target>Bewertung mit Sternen</target>
     			</trans-unit>
    -			<trans-unit id="tx_fpmasterquiz_domain_model_question.qmode.8" resname="tx_fpmasterquiz_domain_model_question.qmode.8">
    -				<source>Question-Matrix with categories</source>
    -				<target>Matrix mit Kategorien einer Frage</target>
    -			</trans-unit>
     		</body>
     	</file>
     </xliff>
    
  • Resources/Private/Language/de.locallang_mod1.xlf+1 33 modified
    @@ -1,6 +1,6 @@
     <?xml version="1.0" encoding="UTF-8"?>
     <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    -	<file source-language="en" target-language="de" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf" date="2021-08-26T09:17:13Z" product-name="fp_masterquiz">
    +	<file source-language="en" target-language="de" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf" date="2021-04-29T13:59:11Z" product-name="fp_masterquiz">
     		<header/>
     		<body>
     			<trans-unit id="mlang_tabs_tab" resname="mlang_tabs_tab">
    @@ -79,26 +79,10 @@
     				<source>Add this question to this quiz!</source>
     				<target>Füge diese Frage zu diesem Quiz hinzu!</target>
     			</trans-unit>
    -			<trans-unit id="moveQuestion" resname="moveQuestion">
    -				<source>Move a question from another quiz to this one</source>
    -				<target>Verschiebe eine Frage von einem anderen Quiz zu diesem</target>
    -			</trans-unit>
    -			<trans-unit id="movedQuestion" resname="movedQuestion">
    -				<source>This question was moved to this quiz:</source>
    -				<target>Diese Frage wurde zu diesem Quiz verschoben:</target>
    -			</trans-unit>
    -			<trans-unit id="questionsInFolder" resname="questionsInFolder">
    -				<source>Questions in this current folder (click on a question to move it):</source>
    -				<target>Fragen im aktuelle Ordner (drauf klicken, um sie zu verschieben):</target>
    -			</trans-unit>
     			<trans-unit id="back" resname="back">
     				<source>Back to list</source>
     				<target>Zurück zur Übersicht</target>
     			</trans-unit>
    -			<trans-unit id="backtoQuiz" resname="backtoQuiz">
    -				<source>Back to the quiz</source>
    -				<target>Zurück zum Quiz</target>
    -			</trans-unit>
     			<trans-unit id="entries" resname="entries">
     				<source>Entries</source>
     				<target>Einträge</target>
    @@ -111,22 +95,6 @@
     				<source>Charts of participants for the folder</source>
     				<target>Charts der Quiz/Umfrage-Teilnehmer des Ordner</target>
     			</trans-unit>
    -			<trans-unit id="pagination.first" resname="pagination.first">
    -				<source>First page</source>
    -				<target>Erste Seite</target>
    -			</trans-unit>
    -			<trans-unit id="pagination.previous" resname="pagination.previous">
    -				<source>previous page</source>
    -				<target>vorherige Seite</target>
    -			</trans-unit>
    -			<trans-unit id="pagination.next" resname="pagination.next">
    -				<source>next page</source>
    -				<target>nächste Seite</target>
    -			</trans-unit>
    -			<trans-unit id="pagination.last" resname="pagination.last">
    -				<source>last page</source>
    -				<target>letzte Seite</target>
    -			</trans-unit>
     		</body>
     	</file>
     </xliff>
    
  • Resources/Private/Language/de.locallang.xlf+10 42 modified
    @@ -1,6 +1,6 @@
     <?xml version="1.0" encoding="UTF-8"?>
     <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    -	<file source-language="en" target-language="de" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf" date="2022-08-18T14:49:53Z" product-name="fp_masterquiz">
    +	<file source-language="en" target-language="de" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf" date="2021-06-08T12:21:04Z" product-name="fp_masterquiz">
     		<header/>
     		<body>
     			<trans-unit id="tx_fpmasterquiz_domain_model_quiz" resname="tx_fpmasterquiz_domain_model_quiz">
    @@ -59,10 +59,6 @@
     				<source>Explanation</source>
     				<target>Erklärung</target>
     			</trans-unit>
    -			<trans-unit id="tx_fpmasterquiz_domain_model_question.optional" resname="tx_fpmasterquiz_domain_model_question.optional">
    -				<source>The answer is optional</source>
    -				<target>Die Beantwortung ist optional</target>
    -			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_question.tag" resname="tx_fpmasterquiz_domain_model_question.tag">
     				<source>Tag</source>
     				<target>Tag</target>
    @@ -88,8 +84,8 @@
     				<target>Auswertung</target>
     			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_evaluation.evaluate" resname="tx_fpmasterquiz_domain_model_evaluation.evaluate">
    -				<source>Evaluate points (unchecked) or percentage (checked) or categories (a category is checked)?</source>
    -				<target>Werte Punkte (nicht markiert) oder Prozente (markiert) oder Kategorien (eine Kategorie markiert) aus?</target>
    +				<source>Evaluate points (unchecked) or percentage (checked)?</source>
    +				<target>Werte Punkte (nicht markiert) oder Prozente (markiert) aus?</target>
     			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_evaluation.minimum" resname="tx_fpmasterquiz_domain_model_evaluation.minimum">
     				<source>Minimum value</source>
    @@ -123,14 +119,6 @@
     				<source>Name</source>
     				<target>Name</target>
     			</trans-unit>
    -			<trans-unit id="tx_fpmasterquiz_domain_model_participant.sys_language_uid" resname="tx_fpmasterquiz_domain_model_participant.sys_language_uid">
    -				<source>Language</source>
    -				<target>Sprache</target>
    -			</trans-unit>
    -			<trans-unit id="tx_fpmasterquiz_domain_model_participant.crdate" resname="tx_fpmasterquiz_domain_model_participant.crdate">
    -				<source>Date</source>
    -				<target>Datum</target>
    -			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_participant.email" resname="tx_fpmasterquiz_domain_model_participant.email">
     				<source>E-Mail</source>
     				<target>E-Mail</target>
    @@ -251,14 +239,6 @@
     				<source>Homepage</source>
     				<target>Homepage</target>
     			</trans-unit>
    -			<trans-unit id="text.saveData" resname="text.saveData">
    -				<source>Save data</source>
    -				<target>Daten speichern</target>
    -			</trans-unit>
    -			<trans-unit id="text.dataSaved" resname="text.dataSaved">
    -				<source>Your data have been saved.</source>
    -				<target>Deine Angaben wurden gespeichert.</target>
    -			</trans-unit>
     			<trans-unit id="text.yes" resname="text.yes">
     				<source>yes</source>
     				<target>ja</target>
    @@ -355,9 +335,13 @@
     				<source>No quiz and no detail page was not found!</source>
     				<target>Es wurde kein Quiz und keine Startseite gesetzt! (Datensatzsammlung gesetzt?)</target>
     			</trans-unit>
    -			<trans-unit id="error.notAnswered" resname="error.notAnswered">
    -				<source>Error: mandatory questions not answered!</source>
    -				<target>Fehler: bitte die markierten Fragen beantworten!</target>
    +			<trans-unit id="error.quizNotAllowed" resname="error.quizNotAllowed">
    +				<source>The quiz was not allowed, because another default quiz is set in the Backend:</source>
    +				<target>Das Quiz ist nicht erlaubt, da ein anderes Quiz im Backend ausgewählt wurde:</target>
    +			</trans-unit>>
    +			<trans-unit id="error.invalidParameters" resname="error.invalidParameters">
    +				<source>Error: the parameters could not be validated!</source>
    +				<target>Fehler: die Parameter konnten nicht validiert werden!</target>
     			</trans-unit>
     			<trans-unit id="text.answer.input" resname="text.answer.input">
     				<source>Answer:</source>
    @@ -403,22 +387,6 @@
     				<source>The time has expired! The form will now be sent!</source>
     				<target>Die Zeit ist abgelaufen! Das Formular wird nun abgesendet!</target>
     			</trans-unit>
    -			<trans-unit id="text.optional" resname="text.optional">
    -				<source>: optional</source>
    -				<target>: optional</target>
    -			</trans-unit>
    -			<trans-unit id="text.detailEvaluation" resname="text.detailEvaluation">
    -				<source>The detailed evaluation of your answers leads to the result given below.</source>
    -				<target>Die detaillierte Auswertung deiner Antworten führt zu dem weiter unten angegebenen Ergebnis.</target>
    -			</trans-unit>
    -			<trans-unit id="text.categoryTitle" resname="text.categoryTitle">
    -				<source>Category</source>
    -				<target>Kategorie</target>
    -			</trans-unit>
    -			<trans-unit id="text.categoryCount" resname="text.categoryCount">
    -				<source>Clicked by you</source>
    -				<target>Von dir angeklickt</target>
    -			</trans-unit>
     		</body>
     	</file>
     </xliff>
    
  • Resources/Private/Language/locallang_be.xlf+10 85 modified
    @@ -1,6 +1,6 @@
     <?xml version="1.0" encoding="UTF-8"?>
     <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    -	<file source-language="en" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf" date="2022-08-19T12:56:31Z" product-name="fp_masterquiz">
    +	<file source-language="en" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang_be.xlf" date="2021-06-08T12:40:25Z" product-name="fp_masterquiz">
     		<header/>
     		<body>
     			<trans-unit id="template" resname="template">
    @@ -13,22 +13,19 @@
     				<source>List of all quiz of one folder</source>
     			</trans-unit>
     			<trans-unit id="template.show" resname="template.show">
    -				<source>Show a selected quiz and use a pagebrowser (you need to select the storage folder too)</source>
    +				<source>Show a selected quiz and use a pagebrowser (save the plugin! | you need to select the storage folder too)</source>
     			</trans-unit>
     			<trans-unit id="template.showByTag" resname="template.showByTag">
    -				<source>Show a selected quiz and order questions by tag (you need to select the storage folder too)</source>
    +				<source>Show a selected quiz and order questions by tag (save the plugin! | you need to select the storage folder too)</source>
     			</trans-unit>
     			<trans-unit id="template.intro" resname="template.intro">
    -				<source>Show an intro page and then a quiz (you need to select the storage folder too)</source>
    +				<source>Show an intro page and then a quiz (save the plugin! | you need to select the storage folder too)</source>
     			</trans-unit>
     			<trans-unit id="template.result" resname="template.result">
    -				<source>Show a result of a quiz (you need to select the storage folder too)</source>
    +				<source>Show a result of a quiz (save the plugin! | you need to select the storage folder too)</source>
     			</trans-unit>
     			<trans-unit id="template.highscore" resname="template.highscore">
    -				<source>Show a highscore of a quiz (you need to select the storage folder too)</source>
    -			</trans-unit>
    -			<trans-unit id="template.closure" resname="template.closure">
    -				<source>Show a closure page after a quiz (you need to select the storage folder too)</source>
    +				<source>Show a highscore of a quiz (save the plugin! | you need to select the storage folder too)</source>
     			</trans-unit>
     			<trans-unit id="templateLayout" resname="templateLayout">
     				<source>Template layout (see manual):</source>
    @@ -42,9 +39,6 @@
     			<trans-unit id="settings.showPageUid" resname="settings.showPageUid">
     				<source>Single page of a quiz/poll (detailPid):</source>
     			</trans-unit>
    -			<trans-unit id="settings.closurePageUid" resname="settings.closurePageUid">
    -				<source>Page for a closure after a quiz (when askForData=3):</source>
    -			</trans-unit>
     			<trans-unit id="settings.resultPageUid" resname="settings.resultPageUid">
     				<source>Page where to show a result of a quiz/poll:</source>
     			</trans-unit>
    @@ -61,10 +55,10 @@
     				<source>Number of questions per page:</source>
     			</trans-unit>
     			<trans-unit id="settings.showAnswerPage" resname="settings.showAnswerPage">
    -				<source>Show a solution page with answered questions after every submit?</source>
    +				<source>Show a solution page after every submit?</source>
     			</trans-unit>
     			<trans-unit id="settings.showAnswersAtFinalPage" resname="settings.showAnswersAtFinalPage">
    -				<source>Show the answered questions (solutions) at the final page?</source>
    +				<source>Show the solutions at the final page?</source>
     			</trans-unit>
     			<trans-unit id="settings.showOwnAnswers" resname="settings.showOwnAnswers">
     				<source>Show the own answers?</source>
    @@ -81,21 +75,6 @@
     			<trans-unit id="settings.showPoints" resname="settings.showPoints">
     				<source>Show the possible/reached points?</source>
     			</trans-unit>
    -			<trans-unit id="settings.showDetailedCategoryEval" resname="settings.showDetailedCategoryEval">
    -				<source>Show detailed category evaluation if categories are used?</source>
    -			</trans-unit>
    -			<trans-unit id="settings.noFormCheck" resname="settings.noFormCheck">
    -				<source>Disable form check (set all questions as non mandatory)?</source>
    -			</trans-unit>
    -			<trans-unit id="settings.phpFormCheck" resname="settings.phpFormCheck">
    -				<source>Enable a form check (of mandatory questions) via PHP?</source>
    -			</trans-unit>
    -			<trans-unit id="settings.allowEdit" resname="settings.allowEdit">
    -				<source>Allow edit answered questions (works only for show by tag)?</source>
    -			</trans-unit>
    -			<trans-unit id="settings.random" resname="settings.random">
    -				<source>Enable a random mode for tags (works only for show by tag)?</source>
    -			</trans-unit>
     			<trans-unit id="settings.ajax" resname="settings.ajax">
     				<source>Enable AJAX-version? Important: all FlexForm-settings will be ignored then.</source>
     			</trans-unit>
    @@ -114,9 +93,6 @@
     			<trans-unit id="settings.yesIntroPage" resname="settings.yesIntroPage">
     				<source>yes, but only at the intro page</source>
     			</trans-unit>
    -			<trans-unit id="settings.yesFinalPage" resname="settings.yesFinalPage">
    -				<source>yes, but only at the final page (save the plugin! | you need a closure page too!)</source>
    -			</trans-unit>
     			<trans-unit id="enables" resname="enables">
     				<source>Enable/disable</source>
     			</trans-unit>
    @@ -141,17 +117,11 @@
     			<trans-unit id="tasks.description" resname="tasks.description">
     				<source>Deletes all old participants of a folder.</source>
     			</trans-unit>
    -			<trans-unit id="tasks.exportTitle" resname="tasks.exportTitle">
    -				<source>Export CSV-file with participants</source>
    -			</trans-unit>
    -			<trans-unit id="tasks.exportDescription" resname="tasks.exportDescription">
    -				<source>Exports participants (with all data) of a folder.</source>
    -			</trans-unit>
     			<trans-unit id="tasks.validate.page" resname="tasks.validate.page">
    -				<source>Page with quiz-elements (pages UID):</source>
    +				<source>Page with elements (pages UID):</source>
     			</trans-unit>
     			<trans-unit id="tasks.validate.invalidPage" resname="tasks.validate.invalidPage">
    -				<source>Invalid pages uid, please enter a valid pages uid!</source>
    +				<source>Invalid pages uid or the page is not visible!</source>
     			</trans-unit>
     			<trans-unit id="tasks.validate.days" resname="tasks.validate.days">
     				<source>Delete entries older than ... days:</source>
    @@ -186,21 +156,6 @@
     			<trans-unit id="settings.user.askForData" resname="settings.user.askForData">
     				<source>Ask for user data at the first page of a quiz?</source>
     			</trans-unit>
    -			<trans-unit id="settings.user.checkFEuser" resname="settings.user.checkFEuser">
    -				<source>Check if a FE-user has already participated?</source>
    -			</trans-unit>
    -			<trans-unit id="settings.user.useQuizPid" resname="settings.user.useQuizPid">
    -				<source>Use automatically the pid from the quiz?</source>
    -			</trans-unit>
    -			<trans-unit id="settings.user.ipSave" resname="settings.user.ipSave">
    -				<source>Save the IP-address of a user?</source>
    -			</trans-unit>
    -			<trans-unit id="settings.user.ipAnonymous" resname="settings.user.ipAnonymous">
    -				<source>Anonymize the IP-address?</source>
    -			</trans-unit>
    -			<trans-unit id="settings.user.useCookie" resname="settings.user.useCookie">
    -				<source>Save the session in a cookie for X days? -1: sets a session cookie; 0: no cookie; &gt;0 X=days.</source>
    -			</trans-unit>
     			<trans-unit id="emailSettings" resname="emailSettings">
     				<source>Email settings</source>
     			</trans-unit>
    @@ -210,36 +165,6 @@
     			<trans-unit id="settings.email.sendToUser" resname="settings.email.sendToUser">
     				<source>Send an email to the user at the final page?</source>
     			</trans-unit>
    -			<trans-unit id="dashboard.widget.fixpunktRecentParticipants.title" resname="dashboard.widget.fixpunktRecentParticipants.title">
    -				<source>fp_masterquiz: the recent 7 votes</source>
    -			</trans-unit>
    -			<trans-unit id="dashboard.widget.fixpunktRecentParticipants.description" resname="dashboard.widget.fixpunktRecentParticipants.description">
    -				<source>Shows some details from recent votes by participant like date and the 1. answer</source>
    -			</trans-unit>
    -			<trans-unit id="dashboard.widget.fixpunktLastDays.title" resname="dashboard.widget.fixpunktLastDays.title">
    -				<source>fp_masterquiz: votes of the last 31 days</source>
    -			</trans-unit>
    -			<trans-unit id="dashboard.widget.fixpunktLastDays.description" resname="dashboard.widget.fixpunktLastDays.description">
    -				<source>Shows a bar chart with number of votes for each day</source>
    -			</trans-unit>
    -			<trans-unit id="tasks.validate.csvfile" resname="tasks.validate.csvfile">
    -				<source>Path and name of the csv file (must begin with &quot;fileadmin/&quot;):</source>
    -			</trans-unit>
    -			<trans-unit id="tasks.validate.separator" resname="tasks.validate.separator">
    -				<source>Separator:</source>
    -			</trans-unit>
    -			<trans-unit id="tasks.validate.delimiter" resname="tasks.validate.delimiter">
    -				<source>Delimiter:</source>
    -			</trans-unit>
    -			<trans-unit id="tasks.validate.ansdelimiter" resname="tasks.validate.ansdelimiter">
    -				<source>Answers delimiter:</source>
    -			</trans-unit>
    -			<trans-unit id="tasks.validate.convert" resname="tasks.validate.convert">
    -				<source>Convert text from UTF-8 to ISO?</source>
    -			</trans-unit>
    -			<trans-unit id="tasks.validate.invalidCsvfile" resname="tasks.validate.invalidCsvfile">
    -				<source>Invalid csv file, please enter a valid path to the csv file in the fileadmin folder!</source>
    -			</trans-unit>
     		</body>
     	</file>
     </xliff>
    
  • Resources/Private/Language/locallang_csh_tx_fpmasterquiz_domain_model_question.xlf+0 3 modified
    @@ -21,9 +21,6 @@
     			<trans-unit id="tag.description" resname="tag.description">
     				<source>Tag</source>
     			</trans-unit>
    -			<trans-unit id="optional.description" resname="optional.description">
    -				<source>The answer is optional</source>
    -			</trans-unit>
     			<trans-unit id="answers.description">
     				<source>Answers of this question</source>
     			</trans-unit>
    
  • Resources/Private/Language/locallang_db.xlf+2 11 modified
    @@ -1,6 +1,6 @@
     <?xml version="1.0" encoding="UTF-8"?>
     <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    -	<file source-language="en" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf" date="2021-10-18T09:26:11Z" product-name="fp_masterquiz">
    +	<file source-language="en" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang_db.xlf" date="2021-05-17T15:10:15Z" product-name="fp_masterquiz">
     		<header/>
     		<body>
     			<trans-unit id="tx_fp_masterquiz_pi1.name" resname="tx_fp_masterquiz_pi1.name">
    @@ -54,9 +54,6 @@
     			<trans-unit id="tx_fpmasterquiz_domain_model_question.tag" resname="tx_fpmasterquiz_domain_model_question.tag">
     				<source>Tag</source>
     			</trans-unit>
    -			<trans-unit id="tx_fpmasterquiz_domain_model_question.optional" resname="tx_fpmasterquiz_domain_model_question.optional">
    -				<source>The answer is optional</source>
    -			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_question.answers" resname="tx_fpmasterquiz_domain_model_question.answers">
     				<source>Answers of this question</source>
     			</trans-unit>
    @@ -73,7 +70,7 @@
     				<source>Evaluation</source>
     			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_evaluation.evaluate" resname="tx_fpmasterquiz_domain_model_evaluation.evaluate">
    -				<source>Evaluate points (unchecked) or percentage (checked) or categories (a category is checked)?</source>
    +				<source>Evaluate points (unchecked) or percentage (checked)?</source>
     			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_evaluation.minimum" resname="tx_fpmasterquiz_domain_model_evaluation.minimum">
     				<source>Minimum value</source>
    @@ -117,9 +114,6 @@
     			<trans-unit id="tx_fpmasterquiz_domain_model_participant.sessionstart" resname="tx_fpmasterquiz_domain_model_participant.sessionstart">
     				<source>Time in seconds for the first page</source>
     			</trans-unit>
    -			<trans-unit id="tx_fpmasterquiz_domain_model_participant.randompages" resname="tx_fpmasterquiz_domain_model_participant.randompages">
    -				<source>Random page order</source>
    -			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_participant.points" resname="tx_fpmasterquiz_domain_model_participant.points">
     				<source>Reached points for this quiz</source>
     			</trans-unit>
    @@ -189,9 +183,6 @@
     			<trans-unit id="tx_fpmasterquiz_domain_model_question.qmode.7" resname="tx_fpmasterquiz_domain_model_question.qmode.7">
     				<source>Star rating</source>
     			</trans-unit>
    -			<trans-unit id="tx_fpmasterquiz_domain_model_question.qmode.8" resname="tx_fpmasterquiz_domain_model_question.qmode.8">
    -				<source>Matrix with categories of a question</source>
    -			</trans-unit>
     		</body>
     	</file>
     </xliff>
    
  • Resources/Private/Language/locallang_mod1.xlf+1 25 modified
    @@ -1,6 +1,6 @@
     <?xml version="1.0" encoding="UTF-8"?>
     <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    -	<file source-language="en" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf" date="2021-08-26T09:17:13Z" product-name="fp_masterquiz">
    +	<file source-language="en" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang_mod1.xlf" date="2021-04-29T13:59:11Z" product-name="fp_masterquiz">
     		<header/>
     		<body>
     			<trans-unit id="mlang_tabs_tab" resname="mlang_tabs_tab">
    @@ -60,21 +60,9 @@
     			<trans-unit id="addthis" resname="addthis">
     				<source>Add this question to this quiz!</source>
     			</trans-unit>
    -			<trans-unit id="moveQuestion" resname="moveQuestion">
    -				<source>Move a question from another quiz to this one</source>
    -			</trans-unit>
    -			<trans-unit id="movedQuestion" resname="movedQuestion">
    -				<source>This question was moved to this quiz:</source>
    -			</trans-unit>
    -			<trans-unit id="questionsInFolder" resname="questionsInFolder">
    -				<source>Questions in this current folder (click on a question to move it):</source>
    -			</trans-unit>
     			<trans-unit id="back" resname="back">
     				<source>Back to list</source>
     			</trans-unit>
    -			<trans-unit id="backtoQuiz" resname="backtoQuiz">
    -				<source>Back to the quiz</source>
    -			</trans-unit>
     			<trans-unit id="entries" resname="entries">
     				<source>Entries</source>
     			</trans-unit>
    @@ -84,18 +72,6 @@
     			<trans-unit id="charts-participants" resname="charts-participants">
     				<source>Charts of participants for the folder</source>
     			</trans-unit>
    -			<trans-unit id="pagination.first" resname="pagination.first">
    -				<source>First page</source>
    -			</trans-unit>
    -			<trans-unit id="pagination.previous" resname="pagination.previous">
    -				<source>previous page</source>
    -			</trans-unit>
    -			<trans-unit id="pagination.next" resname="pagination.next">
    -				<source>next page</source>
    -			</trans-unit>
    -			<trans-unit id="pagination.last" resname="pagination.last">
    -				<source>last page</source>
    -			</trans-unit>
     		</body>
     	</file>
     </xliff>
    
  • Resources/Private/Language/locallang.xlf+7 31 modified
    @@ -1,6 +1,6 @@
     <?xml version="1.0" encoding="UTF-8"?>
     <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    -	<file source-language="en" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf" date="2022-08-18T14:49:53Z" product-name="fp_masterquiz">
    +	<file source-language="en" datatype="plaintext" original="EXT:fp_masterquiz/Resources/Private/Language/locallang.xlf" date="2021-06-08T12:21:04Z" product-name="fp_masterquiz">
     		<header/>
     		<body>
     			<trans-unit id="tx_fpmasterquiz_domain_model_quiz" resname="tx_fpmasterquiz_domain_model_quiz">
    @@ -45,9 +45,6 @@
     			<trans-unit id="tx_fpmasterquiz_domain_model_question.explanation" resname="tx_fpmasterquiz_domain_model_question.explanation">
     				<source>Explanation</source>
     			</trans-unit>
    -			<trans-unit id="tx_fpmasterquiz_domain_model_question.optional" resname="tx_fpmasterquiz_domain_model_question.optional">
    -				<source>The answer is optional</source>
    -			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_question.tag" resname="tx_fpmasterquiz_domain_model_question.tag">
     				<source>Tag</source>
     			</trans-unit>
    @@ -67,7 +64,7 @@
     				<source>Evaluation</source>
     			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_evaluation.evaluate" resname="tx_fpmasterquiz_domain_model_evaluation.evaluate">
    -				<source>Evaluate points (unchecked) or percentage (checked) or categories (a category is checked)?</source>
    +				<source>Evaluate points (unchecked) or percentage (checked)?</source>
     			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_evaluation.minimum" resname="tx_fpmasterquiz_domain_model_evaluation.minimum">
     				<source>Minimum value</source>
    @@ -93,12 +90,6 @@
     			<trans-unit id="tx_fpmasterquiz_domain_model_participant.name" resname="tx_fpmasterquiz_domain_model_participant.name">
     				<source>Name</source>
     			</trans-unit>
    -			<trans-unit id="tx_fpmasterquiz_domain_model_participant.sys_language_uid" resname="tx_fpmasterquiz_domain_model_participant.sys_language_uid">
    -				<source>Language</source>
    -			</trans-unit>
    -			<trans-unit id="tx_fpmasterquiz_domain_model_participant.crdate" resname="tx_fpmasterquiz_domain_model_participant.crdate">
    -				<source>Date</source>
    -			</trans-unit>
     			<trans-unit id="tx_fpmasterquiz_domain_model_participant.email" resname="tx_fpmasterquiz_domain_model_participant.email">
     				<source>E-Mail</source>
     			</trans-unit>
    @@ -189,12 +180,6 @@
     			<trans-unit id="text.homepage" resname="text.homepage">
     				<source>Homepage</source>
     			</trans-unit>
    -			<trans-unit id="text.saveData" resname="text.saveData">
    -				<source>Save data</source>
    -			</trans-unit>
    -			<trans-unit id="text.dataSaved" resname="text.dataSaved">
    -				<source>Your data have been saved.</source>
    -			</trans-unit>
     			<trans-unit id="text.yes" resname="text.yes">
     				<source>yes</source>
     			</trans-unit>
    @@ -267,8 +252,11 @@
     			<trans-unit id="error.quizDetailNotFound" resname="error.quizDetailNotFound">
     				<source>No quiz and no detail page was not found!</source>
     			</trans-unit>
    -			<trans-unit id="error.notAnswered" resname="error.notAnswered">
    -				<source>Error: mandatory questions not answered!</source>
    +			<trans-unit id="error.quizNotAllowed" resname="error.quizNotAllowed">
    +				<source>The quiz was not allowed, because another default quiz is set in the Backend:</source>
    +			</trans-unit>
    +			<trans-unit id="error.invalidParameters" resname="error.invalidParameters">
    +				<source>Error: the parameters could not be validated!</source>
     			</trans-unit>
     			<trans-unit id="text.answer.input" resname="text.answer.input">
     				<source>Answer:</source>
    @@ -303,18 +291,6 @@
     			<trans-unit id="text.expiredTime" resname="text.expiredTime">
     				<source>The time has expired! The form will now be sent!</source>
     			</trans-unit>
    -			<trans-unit id="text.optional" resname="text.optional">
    -				<source>: optional</source>
    -			</trans-unit>
    -			<trans-unit id="text.detailEvaluation" resname="text.detailEvaluation">
    -				<source>The detailed evaluation of your answers leads to the result given below.</source>
    -			</trans-unit>
    -			<trans-unit id="text.categoryTitle" resname="text.categoryTitle">
    -				<source>Category</source>
    -			</trans-unit>
    -			<trans-unit id="text.categoryCount" resname="text.categoryCount">
    -				<source>Clicked by you</source>
    -			</trans-unit>
     		</body>
     	</file>
     </xliff>
    
  • Resources/Private/Partials/Participant/Form.html+6 6 modified
    @@ -3,16 +3,16 @@
     	<br />
     	<p>{f:translate(key: "text.userData")}</p>
     	<div class="clearfix row form-group">
    -		<label class="control-label col-md-2 col-sm-4" for="name">{f:translate(key: "text.name")}:</label>
    -		<div class="col-md-4 vol-sm-6"><f:form.textfield name="name" value="{participant.name}" class="form-control" id="quiz-user-name" /></div>
    +		<label class="control-label col-sm-2 col-xs-4" for="name">{f:translate(key: "text.name")}:</label>
    +		<div class="col-sm-4 vol-xs-6"><f:form.textfield name="name" value="{participant.name}" class="form-control" id="quiz-user-name" /></div>
     	</div>
     	<div class="clearfix row form-group">
    -		<label class="control-label col-md-2 col-sm-4" for="email">{f:translate(key: "text.email")}:</label>
    -		<div class="col-md-4 vol-sm-6"><f:form.textfield name="email" value="{participant.email}" class="form-control" id="quiz-user-email" /></div>
    +		<label class="control-label col-sm-2 col-xs-4" for="email">{f:translate(key: "text.email")}:</label>
    +		<div class="col-sm-4 vol-xs-6"><f:form.textfield name="email" value="{participant.email}" class="form-control" id="quiz-user-email" /></div>
     	</div>
     	<div class="clearfix row form-group">
    -		<label class="control-label col-md-2 col-sm-4" for="homepage">{f:translate(key: "text.homepage")}:</label>
    -		<div class="col-md-4 vol-sm-6"><f:form.textfield name="homepage" value="{participant.homepage}" class="form-control" id="quiz-user-homepage" /></div>
    +		<label class="control-label col-sm-2 col-xs-4" for="homepage">{f:translate(key: "text.homepage")}:</label>
    +		<div class="col-sm-4 vol-xs-6"><f:form.textfield name="homepage" value="{participant.homepage}" class="form-control" id="quiz-user-homepage" /></div>
     	</div>
     </div>
     </html>
    \ No newline at end of file
    
  • Resources/Private/Partials/Question/Properties.html+18 54 modified
    @@ -1,6 +1,6 @@
     <html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
     <f:form.hidden name="quest_{question.uid}" value="1" />
    -<div class="card"><div class="card-body">
    +<div class="card">
     	<f:if condition="({settings.showPageNo} == 1) && ({settings.ajax} == 1) && ({pages} != 1)">
     	  <p class="quiz-progress">{f:translate(key: "text.page")} <span>{page}</span> {f:translate(key: "text.of")} {pages} ({pagePercent}%)</p>
     	</f:if>
    @@ -11,49 +11,30 @@
     		<br/>
     	</f:if>
     	<f:comment> {question -> f:debug(title: 'Members of question')} </f:comment>
    -	{settings.template.wrapQuestionTitle1 -> f:format.raw()}
    -		{question.title}<f:if condition="{settings.template.optionalMark}"><f:if condition="{question.optional} || ({question.qmode} == 4) || ({question.qmode} == 7)"><f:then>{settings.template.optionalMark -> f:format.raw()}</f:then><f:else></f:else></f:if></f:if>
    -	{settings.template.wrapQuestionTitle2 -> f:format.raw()}
    -	{settings.template.wrapQuestionDesc1 -> f:format.raw()}
    -		<f:format.html>{question.bodytext}</f:format.html>
    -	{settings.template.wrapQuestionDesc2 -> f:format.raw()}
    +	{settings.template.wrapQuestionTitle1 -> f:format.raw()}{question.title}{settings.template.wrapQuestionTitle2 -> f:format.raw()}
    +	{settings.template.wrapQuestionDesc1 -> f:format.raw()}<f:format.html>{question.bodytext}</f:format.html>{settings.template.wrapQuestionDesc2 -> f:format.raw()}
     	<div class="row">
    -		<div class="{f:if(condition: '{question.image.uid}', then: settings.template.colText, else: settings.template.col12)}">
    +		<div class="{settings.template.colText}">
     			<div class="text-buttons">
     				<div class="quiz-question-buttons">
     					<f:if condition="{question.qmode} == 7">
     						<div class="star-cb-group">
     					</f:if>
    -					<f:if condition="{question.qmode} == 8">
    -						<table class="quiz-table-matrix">
    -							<thead>
    -							<tr><th></th>
    -							<f:for each="{question.sortedCategoriesArray}" as="qcategory">
    -								<th>{qcategory.title}</th>
    -							</f:for>
    -							</tr>
    -							</thead>
    -							<tbody>
    -					</f:if>
     					<f:for each="{question.answers}" as="answer" iteration="nr">
     						<f:switch expression="{question.qmode}">
     							<f:case value="0">
    -								<div class="checkbox quiz-checkbox{f:if(condition: '{question.optional}', then: ' quiz-answer-optional')}{f:if(condition: '{answer.jokerAnswer}', then: ' d-none')}{f:if(condition: '{answer.ownAnswer}', then: ' quiz-answer-selected')}">
    +								<div class="checkbox quiz-checkbox {f:if(condition: '{answer.jokerAnswer}', then: 'd-none')}">
     									<label>
    -										<f:form.checkbox name="answer_{question.uid}_{answer.uid}" value="{answer.uid}" class="quiz-checkboxes" checked="{answer.ownAnswer}" />
    +										<f:form.checkbox name="answer_{question.uid}_{answer.uid}" value="{answer.uid}" class="quiz-checkboxes" />
     										<f:if condition="{settings.allowHtml} == 1"><f:then>{answer.title -> f:format.raw()}</f:then><f:else>{answer.title -> f:format.nl2br()}</f:else></f:if>
     									</label>
     								</div>
     							</f:case>
     							<f:case value="1">
    -								<div class="radio quiz-radio{f:if(condition: '{question.optional}', then: ' quiz-answer-optional')}{f:if(condition: '{answer.jokerAnswer}', then: ' d-none')}{f:if(condition: '{answer.ownAnswer}', then: ' quiz-answer-selected')}">
    +								<div class="radio quiz-radio {f:if(condition: '{answer.jokerAnswer}', then: 'd-none')}">
     									<label>
    -										<f:form.radio name="answer_{question.uid}" value="{answer.uid}" class="quiz-radiobox" checked="{answer.ownAnswer}" />
    -										<f:if condition="{settings.allowHtml} == 1"><f:then>
    -											{answer.title -> f:format.raw()}
    -										</f:then><f:else>
    -											{answer.title -> f:format.nl2br()}
    -										</f:else></f:if>
    +										<f:form.radio name="answer_{question.uid}" value="{answer.uid}" class="quiz-radiobox" />
    +										<f:if condition="{settings.allowHtml} == 1"><f:then>{answer.title -> f:format.raw()}</f:then><f:else>{answer.title -> f:format.nl2br()}</f:else></f:if>
     									</label>
     								</div>
     							</f:case>
    @@ -63,18 +44,17 @@
     							<f:case value="3">
     								<f:comment>When 'Enter an answer' in a text field</f:comment> 
     								<br/>
    -								<div class="quiz-input{f:if(condition: '{question.optional}', then: ' quiz-answer-optional')}{f:if(condition: '{answer.ownAnswer}', then: ' quiz-answer-selected')}">
    +								<div class="quiz-input">
     									<label>
    -										{f:translate(key: "text.answer.input")}
    -										<f:form.textfield name="answer_text_{question.uid}" value="{x->f:for(each:'{question.textAnswers}', as: 'x')}" class="quiz-inputbox" autofocus="autofocus" />
    +										{f:translate(key: "text.answer.input")} <f:form.textfield name="answer_text_{question.uid}" value="" class="quiz-inputbox" autofocus="autofocus" />
     									</label>
     								</div>
     							</f:case>
     							<f:case value="4">
    -								<div class="radio quiz-radio2{f:if(condition: '{answer.ownAnswer}', then: ' quiz-answer-selected')}">
    +								<div class="radio quiz-radio2">
     									<f:if condition="{settings.allowHtml} == 1"><f:then>{answer.title -> f:format.raw()}</f:then><f:else>{answer.title -> f:format.nl2br()}</f:else></f:if> &nbsp;
     									<label>
    -										<f:form.radio name="answer_{question.uid}_{answer.uid}" value="{answer.uid}" class="quiz-radiobox" checked="{answer.ownAnswer}" />
    +										<f:form.radio name="answer_{question.uid}_{answer.uid}" value="{answer.uid}" class="quiz-radiobox" />
     										{f:translate(key: "text.yes")} &nbsp;
     									</label>
     									<label>
    @@ -86,10 +66,9 @@
     							<f:case value="5">
     								<f:comment>When 'Enter an answer' in a textarea</f:comment> 
     								<br/>
    -								<div class="quiz-textarea{f:if(condition: '{question.optional}', then: ' quiz-answer-optional')}{f:if(condition: '{answer.ownAnswer}', then: ' quiz-answer-selected')}">
    +								<div class="quiz-textarea">
     									<label>
    -										{f:translate(key: "text.answer.textarea")}
    -										<f:form.textarea name="answer_text_{question.uid}" value="{x->f:for(each:'{question.textAnswers}', as: 'x')}" class="quiz-textbox" />
    +										{f:translate(key: "text.answer.textarea")} <f:form.textarea name="answer_text_{question.uid}" value="" class="quiz-textbox" />
     									</label>
     								</div>
     							</f:case>
    @@ -116,30 +95,15 @@
     								</f:else></f:if>
     								<label for="star_{question.uid}_{answer.uid}">{answer.title -> f:format.nl2br()}</label>
     							</f:case>
    -							<f:case value="8">
    -								<tr>
    -									<td><div class="radio quiz-radio8{f:if(condition: '{answer.ownAnswer}', then: ' quiz-answer-selected')}">
    -										<f:if condition="{settings.allowHtml} == 1"><f:then>{answer.title -> f:format.raw()}</f:then><f:else>{answer.title -> f:format.nl2br()}</f:else></f:if> &nbsp;
    -									</div></td>
    -									<f:for each="{question.sortedCategoriesArray}" as="qcategory">
    -									<td><label>
    -										<f:form.radio name="answer_{question.uid}_{answer.uid}" value="{qcategory.uid}" class="quiz-radiobox" checked="{answer.ownAnswer}" />
    -									</label></td>
    -									</f:for>
    -								</tr>
    -							</f:case>
     							<f:defaultCase>NOT yet supported</f:defaultCase>
     						</f:switch>
     					</f:for>
     					<f:if condition="{question.qmode} == 2">
    -						<f:form.select size="1" name="answer_{question.uid}" options="{question.selectOptions}" class="quiz-select{f:if(condition: '{question.optional}', then: ' quiz-answer-optional')}" />
    +						<f:form.select size="1" name="answer_{question.uid}" options="{question.selectOptions}" class="quiz-select" />
     					</f:if>
     					<f:if condition="{question.qmode} == 7">
     						</div>
     					</f:if>
    -					<f:if condition="{question.qmode} == 8">
    -						</tbody></table>
    -					</f:if>
     				</div>
     			</div>
     		</div>
    @@ -149,11 +113,11 @@
     			</f:if>
     		</div>
     	</div>
    -</div></div>
    +</div>
     <br />
     <f:comment>
     Hint
     You can use this inline-condition for odd/even effects:
      {f:if(condition: '{pageiterator.isOdd}', then: 'order-first')}
     </f:comment>
    -</html>
    +</html>
    \ No newline at end of file
    
  • Resources/Private/Partials/Question/PropertiesSent.html+9 12 modified
    @@ -1,6 +1,6 @@
     <html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
     <f:variable name="enablePoints">{selection.maximumPoints}</f:variable> 
    -<div class="card"><div class="card-body">
    +<div class="card">
     	<f:if condition="({settings.showPageNo} == 1) && ({settings.ajax} == 1) && ({pages} != 1) && ({final} == 0)">
     	  <p class="quiz-progress">{f:translate(key: "text.page")} <span>{page}</span> {f:translate(key: "text.of")} {pages} ({pagePercent}%)</p>
     	</f:if>
    @@ -13,7 +13,7 @@
     	{settings.template.wrapQuestionTitle1 -> f:format.raw()}{selection.question.title}{settings.template.wrapQuestionTitle2 -> f:format.raw()}
     	{settings.template.wrapQuestionDesc1 -> f:format.raw()}<f:format.html>{selection.question.bodytext}</f:format.html>{settings.template.wrapQuestionDesc2 -> f:format.raw()}
     	<div class="row">
    -		<div class="{f:if(condition: '{selection.question.image.uid}', then: settings.template.colText, else: settings.template.col12)}">
    +		<div class="{settings.template.colText}">
     			<div class="text-buttons">
     				<f:if condition="{selection.question.qmode} != 6">
     					<f:if condition="(({settings.showOwnAnswers} == 2) && ({final} == 0)) || ({settings.showOwnAnswers} == 1) || {isEmail}">
    @@ -35,11 +35,11 @@
     							<f:case value="3">
     								<f:comment>When 'Enter an answer' in a text field</f:comment> 
     								<f:comment> {answer -> f:debug(title: 'Members of answer')} / no HTML for entered Text allowed:	</f:comment>
    -								<ul><li>{selection.entered -> f:format.nl2br()}</li></ul>
    +								{selection.entered -> f:format.nl2br()}
     							</f:case>									
     							<f:case value="5">
     								<f:comment>When 'Enter an answer' in a textarea</f:comment>
    -								<ul><li>{selection.entered -> f:format.nl2br()}</li></ul>
    +								{selection.entered -> f:format.nl2br()}								
     							</f:case>
     							<f:case value="7">
     								<f:comment>Star rating</f:comment>
    @@ -60,9 +60,6 @@
     									<f:then>{answer.title -> f:format.raw()}</f:then>
     									<f:else>{answer.title -> f:format.nl2br()}</f:else>
     								</f:if>
    -								<f:if condition="{selection.question.qmode} == 8 && {answer.ownCategoryAnswer}">
    -									: {answer.ownCategoryAnswer.1}
    -								</f:if>
     								<f:if condition="{settings.showPoints} && {enablePoints}">
                                         ({answer.points} {f:translate(key: "text.points", default: 'P')})
                                     </f:if>
    @@ -135,17 +132,17 @@
     				</f:if>
     			</div>
     		</div>
    -		<f:if condition="{selection.question.image.uid}">
    -			<div class="{settings.template.colImage}">
    +		<div class="{settings.template.colImage}">
    +			<f:if condition="{selection.question.image.uid}">
     				<f:image src="{selection.question.image.uid}" treatIdAsReference="1" class="img-fluid" />
    -			</div>
    -		</f:if>
    +			</f:if>
    +		</div>
     	</div>
     	<f:if condition="{selection.question.explanation}">
     		<br />
     		<p>{f:translate(key: "text.explanation", default: 'Explanation: ')}</p>
     		<f:format.html>{selection.question.explanation}</f:format.html>
     	</f:if>
    -</div></div>
    +</div>
     <br />
     </html>
    
  • Resources/Private/Partials/Question/Result.html+4 14 modified
    @@ -22,20 +22,10 @@
     				<f:else>{answer3.title -> f:format.nl2br()}</f:else>
     			</f:if>
     			<f:if condition="{settings.showPoints}"> ({answer3.points} {f:translate(key: "text.points", default: 'P')})</f:if>
    -			({answer3.allAnswers}
    -			{f:translate(key: "text.choices")}<f:if condition="({answer3.ownAnswer} > 0) && ({question.qmode} != 3)">; {f:translate(key: "text.myChoice", default: 'my choice')})</f:if>)
    -			<br/>
    -			<f:comment>
    -			f:if condition="{question.qmode} == 8">
    -				f:then>
    -					f:for each="question.categoriesArray}" as="category">
    -						category.title}:<br/>
    -					/f:for>
    -				/f:then>
    -			</f:comment>
    -			<div class="progress">
    -				<div class="progress-bar" style="width:{answer3.allPercent}%">{answer3.allPercent} %</div>
    -			</div>
    +			({answer3.allAnswers} {f:translate(key: "text.choices")}; {answer3.allPercent} %)
    +			<f:if condition="({answer3.ownAnswer} > 0) && ({question.qmode} != 3)">
    +				({f:translate(key: "text.myChoice", default: 'my choice')})
    +			</f:if>
     		</f:else>
     		</f:if>
     	</li>
    
  • Resources/Private/Partials/Quiz/CheckFields.html+3 32 modified
    @@ -7,46 +7,17 @@
     			$(this).removeClass( 'quiz-answer-selected' );
     		});
     		closestRadio.addClass( 'quiz-answer-selected' );
    -		$(this).closest( ".card" ).removeAttr("style");
     	});
     	$( "#quiz-form"+ceuid+" .quiz-checkboxes" ).click(function() {
    -		// add/remove selected class to the selected checkbox answer
    -		var closestCheckbox = $(this).closest( ".quiz-checkbox" );
    -		var closestCheckboxParent = closestCheckbox.parent();
    -		$(closestCheckboxParent).find('.quiz-checkboxes').each(function() {
    -			if ($(this).is(':checked')) {
    -				$(this).closest( ".quiz-checkbox" ).addClass( 'quiz-answer-selected' );
    -				$(this).closest( ".card" ).removeAttr("style");
    -			} else {
    -				$(this).closest( ".quiz-checkbox" ).removeClass( 'quiz-answer-selected' );
    -			}
    -		});
    +		// add selected class to the selected answer
    +		$(this).closest( ".quiz-checkbox" ).addClass( 'quiz-answer-selected' );
     	});
     	$( "#quiz-form"+ceuid+" .quiz-select" ).change(function() {
     		// add selected class to the select if the selected val is not 0
     		if ($(this).val() == '0') {
    -			$(this).removeClass( 'quiz-answer-selected' );
    +			$(this).removeClass( 'quiz-answer-selected' );									
     		} else {
     			$(this).addClass( 'quiz-answer-selected' );
    -			$(this).closest( ".card" ).removeAttr("style");
    -		}
    -	});
    -	$( "#quiz-form"+ceuid+" .quiz-inputbox" ).change(function() {
    -		// add selected class to the input if there is a value
    -		if ($(this).val() == '') {
    -			$(this).closest( ".quiz-input" ).removeClass( 'quiz-answer-selected' );
    -		} else {
    -			$(this).closest( ".quiz-input" ).addClass( 'quiz-answer-selected' );
    -			$(this).closest( ".card" ).removeAttr("style");
    -		}
    -	});
    -	$( "#quiz-form"+ceuid+" .quiz-textbox" ).change(function() {
    -		// add selected class to the quiz-textarea if there is a value
    -		if ($(this).val() == '') {
    -			$(this).closest( ".quiz-textarea" ).removeClass( 'quiz-answer-selected' );
    -		} else {
    -			$(this).closest( ".quiz-textarea" ).addClass( 'quiz-answer-selected' );
    -			$(this).closest( ".card" ).removeAttr("style");
     		}
     	});
     }
    \ No newline at end of file
    
  • Resources/Private/Partials/Quiz/CheckForm.html+14 21 modified
    @@ -4,44 +4,37 @@
     	$('#quiz-form'+tempceuid+' .quiz-question-buttons').each(function() {
     		var noneSelected = true;
     		var selectedCounter = 0;
    -		// radio-buttons
     		$(this).find('.quiz-radio').each(function() {
     			selectedCounter++;
    -			if ($(this).hasClass('quiz-answer-selected') || $(this).hasClass('quiz-answer-optional')) {
    +			if ($(this).hasClass('quiz-answer-selected')) {
     				noneSelected = false;
    +			//	console.log('radio click gefunden');
     			}
     		});
    -		// Checkboxen
    +		if (selectedCounter>0 && noneSelected) {
    +			allSelected = false;
    +		}
    +		selectedCounter = 0;
     		$(this).find('.quiz-checkbox').each(function() {
     			selectedCounter++;
    -			if ($(this).hasClass('quiz-answer-selected') || $(this).hasClass('quiz-answer-optional')) {
    +			if ($(this).hasClass('quiz-answer-selected')) {
     				noneSelected = false;
    +			//	console.log('checkbox click gefunden');
     			}
     		});
    -		// Select-boxen
    +		if (selectedCounter>0 && noneSelected) {
    +			allSelected = false;
    +		}
    +		selectedCounter = 0;
     		$(this).find('.quiz-select').each(function() {
     			selectedCounter++;
    -			if ($(this).hasClass('quiz-answer-selected') || $(this).hasClass('quiz-answer-optional')) {
    -				noneSelected = false;
    -			}
    -		});
    -		// input-fields
    -		$(this).find('.quiz-input').each(function() {
    -			selectedCounter++;
    -			if ($(this).hasClass('quiz-answer-selected') || $(this).hasClass('quiz-answer-optional')) {
    -				noneSelected = false;
    -			}
    -		});
    -		// textarea
    -		$(this).find('.quiz-textarea').each(function() {
    -			selectedCounter++;
    -			if ($(this).hasClass('quiz-answer-selected') || $(this).hasClass('quiz-answer-optional')) {
    +			if ($(this).hasClass('quiz-answer-selected')) {
     				noneSelected = false;
    +			//	console.log('select click gefunden');
     			}
     		});
     		if (selectedCounter>0 && noneSelected) {
     			allSelected = false;
    -			$(this).closest('.card').attr("style", "border-color:#ff0000");
     		}
     	});
     	return allSelected;
    
  • Resources/Private/Partials/Quiz/FinalPage.html+0 18 modified
    @@ -6,15 +6,6 @@
     				<f:format.number decimals="2" decimalSeparator="," thousandsSeparator=".">{participant.percent2}</f:format.number>%.</p>
             	<br/>
     		</f:if></f:if>
    -		<f:if condition="{settings.showDetailedCategoryEval} && {finalCategories.uid}">
    -			<p><f:translate key="text.detailEvaluation" /></p>
    -			<table>
    -				<tr><th><f:translate key="text.categoryTitle" /></th><th><f:translate key="text.categoryCount" /></th></tr>
    -				<f:for each="{finalCategories.all}" as="oneCat">
    -					<tr><td>{oneCat.title}</td><td>{oneCat.count}x</td></tr>
    -				</f:for>
    -			</table>
    -		</f:if>
     		<f:if condition="{finalImageuid}">
     			<f:image src="{finalImageuid}" treatIdAsReference="1" class="img-fluid" />
     		</f:if>
    @@ -29,15 +20,6 @@
     				<f:render partial="Question/PropertiesSent" arguments="{_all}" />
     			</f:for>
     		</f:if>
    -		<f:if condition="({settings.user.askForData} == 3) && ({settings.closurePageUid})">
    -			<f:render partial="Participant/Form" arguments="{_all}" />
    -			<p><button class="btn btn-primary btn-lg" onclick="$('#quiz-form-page').val('999');this.form.submit();">
    -				<f:translate key="text.saveData" />
    -			</button></p>
    -			<script>
    -				setTimeout(function(){ $('#quiz-userData').show(); }, 1000);
    -			</script>
    -		</f:if>
     		<p>
     		<f:if condition="{settings.startPageUid}">
     		<f:then>
    
  • Resources/Private/Templates/Quiz/Closure.html+0 27 removed
    @@ -1,27 +0,0 @@
    -<html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
    -<f:layout name="Default" />
    -
    -<f:section name="content">
    -  <f:flashMessages />
    -  {settings.template.wrapQuizTitle1 -> f:format.raw()}{quiz.name}{settings.template.wrapQuizTitle2 -> f:format.raw()}
    -  <f:if condition="{quiz.media.0}">
    -    <f:media file="{quiz.media.0}" alt="{quiz.media.0.originalResource.name}" title="{quiz.media.0.originalResource.title}" class="img-fluid" />
    -  </f:if>
    -  <f:if condition="{quiz.about}">{settings.template.wrapQuizDesc1 -> f:format.raw()}{quiz.about}{settings.template.wrapQuizDesc2 -> f:format.raw()}</f:if>
    -
    -  <p>{f:translate(key: "text.dataSaved")}</p>
    -
    -  <f:if condition="{settings.resultPageUid}">
    -    <br />
    -    <f:link.action controller="Quiz" action="result" pageUid="{settings.resultPageUid}" arguments="{quiz:quiz}"
    -                   class="btn btn-info">{f:translate(key: "text.showResultPage")}</f:link.action>
    -  </f:if>
    -  <f:if condition="{settings.highscorePageUid}">
    -    <f:link.action controller="Quiz" action="highscore" pageUid="{settings.highscorePageUid}" arguments="{quiz:quiz}"
    -                   class="btn btn-info">{f:translate(key: "text.showHighscorePage")}</f:link.action>
    -  </f:if>
    -  <f:if condition="{settings.debug}">
    -    <pre>{debug}</pre>
    -  </f:if>
    -</f:section>
    -</html>
    \ No newline at end of file
    
  • Resources/Private/Templates/Quiz/Highscore.html+2 7 modified
    @@ -5,27 +5,22 @@
     		<f:flashMessages />
     		{settings.template.wrapQuizTitle1 -> f:format.raw()}{quiz.name}{settings.template.wrapQuizTitle2 -> f:format.raw()}
     		<f:if condition="{quiz.media.0}">
    -			<f:media file="{quiz.media.0}" alt="{quiz.media.0.originalResource.name}" title="{quiz.media.0.originalResource.title}" class="img-fluid" />
    +			<f:media file="{quiz.media.0}" alt="{quiz.media.0.originalResource.name}" title="{quiz.media.0.originalResource.title}" />
     		</f:if>
     		<f:if condition="{quiz.about}">{settings.template.wrapQuizDesc1 -> f:format.raw()}{quiz.about}{settings.template.wrapQuizDesc2 -> f:format.raw()}</f:if>
    -
    -		<table class="table">
    -			<thead class="thead-dark">
    +		<table>
     			<tr>
     				<th>{f:translate(key: "text.position")}</th>
     				<th>{f:translate(key: "text.participant")}</th>
     				<th>{f:translate(key: "text.points")}</th>
     			</tr>
    -			</thead>
    -			<tbody>
     			<f:for each="{participants}" as="participant" iteration="pageiterator">
     				<tr>
     					<td>{pageiterator.cycle}</td>
     					<td>{participant.name}</td>
     					<td>{participant.points}</td>
     				</tr>
     			</f:for>
    -			</tbody>
     		</table>
     		<f:if condition="{settings.debug}">
     			<pre>{debug}</pre>
    
  • Resources/Private/Templates/Quiz/Result.html+23 40 modified
    @@ -3,12 +3,6 @@
      
     	<f:section name="content">
     		<f:flashMessages />
    -		{settings.template.wrapQuizTitle1 -> f:format.raw()}{quiz.name}{settings.template.wrapQuizTitle2 -> f:format.raw()}
    -		<f:if condition="{quiz.media.0}">
    -			<f:media file="{quiz.media.0}" alt="{quiz.media.0.originalResource.name}" title="{quiz.media.0.originalResource.title}" class="img-fluid" />
    -		</f:if>
    -		<f:if condition="{quiz.about}">{settings.template.wrapQuizDesc1 -> f:format.raw()}{quiz.about}{settings.template.wrapQuizDesc2 -> f:format.raw()}</f:if>
    -
     		<f:if condition="{settings.templateLayout} == 1">
     			<!-- charts-layout -->
     			<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
    @@ -18,45 +12,34 @@
     			</script>
     		</f:if>
     		<f:for each="{quiz.questions}" as="question" iteration="pageiterator">
    -			<div class="card"><div class="card-body">
    +			<div class="card">
     				{settings.template.wrapQuestionTitle1 -> f:format.raw()}{question.title}{settings.template.wrapQuestionTitle2 -> f:format.raw()}
    +				{settings.template.wrapQuestionDesc1 -> f:format.raw()}<f:format.html>{question.bodytext}</f:format.html>{settings.template.wrapQuestionDesc2 -> f:format.raw()}
     				<div class="row">
    -					<div class="{f:if(condition: '{question.image.uid}', then: settings.template.colText, else: settings.template.col12)}">
    -						{settings.template.wrapQuestionDesc1 -> f:format.raw()}<f:format.html>{question.bodytext}</f:format.html>{settings.template.wrapQuestionDesc2 -> f:format.raw()}
    +					<div class="{settings.template.colText}">
    +						<div class="text-buttons">
    +							<f:if condition="{settings.templateLayout} == 1">
    +							<f:then>
    +								<f:render partial="Question/Chart" arguments="{settings:settings, question:question}" />
    +							</f:then>
    +							<f:else>
    +								<f:render partial="Question/Result" arguments="{settings:settings, question:question}" />
    +							</f:else>
    +							</f:if>
    +						</div>
    +						<f:if condition="{question.explanation}">
    +							<br />
    +							<p>{f:translate(key: "text.explanation", default: 'Explanation: ')}</p>
    +							<f:format.html>{question.explanation}</f:format.html>
    +						</f:if>
     					</div>
    -					<f:if condition="{question.image.uid}">
    -						<div class="{settings.template.colImage}">
    +					<div class="{settings.template.colImage}">
    +						<f:if condition="{question.image.uid}">
     							<f:image src="{question.image.uid}" treatIdAsReference="1" class="img-fluid" />
    -						</div>
    -					</f:if>
    -				</div>
    -				<div class="text-buttons">
    -					<f:if condition="{settings.templateLayout} == 1"><f:then>
    -						<f:if condition="({question.qmode} == 3) || ({question.qmode} == 5)"><f:then>
    -							<f:if condition="{question.qmode} == 3"><f:then>
    -								<f:for each="{question.answers}" as="answer3">
    -									{answer3.title}: {answer3.allAnswers} {f:translate(key: "text.choices")}<br/>
    -									<div class="progress">
    -										<div class="progress-bar" style="width:{answer3.allPercent}%">{answer3.allPercent} %</div>
    -									</div>
    -								</f:for>
    -							</f:then><f:else>
    -								--
    -							</f:else></f:if>
    -						</f:then><f:else>
    -							<f:render partial="Question/Chart" arguments="{settings:settings, question:question}" />
    -						</f:else></f:if>
    -					</f:then><f:else>
    -						<f:render partial="Question/Result" arguments="{settings:settings, question:question}" />
    -					</f:else></f:if>
    +						</f:if>
    +					</div>
     				</div>
    -				<f:if condition="{question.explanation}">
    -					<br />
    -					<p>{f:translate(key: "text.explanation", default: 'Explanation: ')}</p>
    -					<f:format.html>{question.explanation}</f:format.html>
    -				</f:if>
    -			</div></div>
    -			<br/>
    +			</div>
     		</f:for>
     			
     		<f:if condition="{settings.debug}">
    
  • Resources/Private/Templates/Quiz/ShowAjax.html+2 0 modified
    @@ -48,6 +48,7 @@
     			<script>
     			quizfinal = 0;
     			thisPage = {page};
    +			$('#quiz-form'+ceuid+' #quiz-form-session').val('{session}');
     			$('#quiz-form'+ceuid+' #quiz-form-parti').val('{participant.uid}');
     			$('#quiz-form'+ceuid+' #quiz-form-page').val('{nextPage}');
     			$('#quiz-form'+ceuid+' #quiz-form-answers').val('{showAnswersNext}');
    @@ -76,6 +77,7 @@
     
     				$( "#quiz-restart" ).click(function(ev) {
     					ev.preventDefault();
    +					$('#quiz-form-session').val('');
     					$('#quiz-form-parti').val('0');
     					$('#quiz-form-page').val('1');
     					$('#quiz-form-answers').val('0');
    
  • Resources/Private/Templates/Quiz/ShowByTag.html+8 35 modified
    @@ -18,9 +18,6 @@
                 </ul>
             </f:if>
         </f:form.validationResults>
    -    <f:if condition="{settings.includeRatingCSS}">
    -        <f:asset.css identifier="fpMasterQuizRatingStar" href="EXT:fp_masterquiz/Resources/Public/Css/RatingStar.css" />
    -    </f:if>
         <f:if condition="{settings.templateLayout} == 1">
             <!-- charts-layout -->
             <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
    @@ -32,10 +29,11 @@
     
         {settings.template.wrapQuizTitle1 -> f:format.raw()}{quiz.name}{settings.template.wrapQuizTitle2 -> f:format.raw()}
         <f:if condition="{quiz.media.0}">
    -        <f:media alt="{quiz.media.0.originalResource.name}" class="img-fluid"  file="{quiz.media.0}" title="{quiz.media.0.originalResource.title}"/>
    +        <f:media alt="{quiz.media.0.originalResource.name}" class="img-fluid"
    +                 file="{quiz.media.0}" title="{quiz.media.0.originalResource.title}"/>
         </f:if>
    -    <f:if condition="{quiz.about}">
    -        {settings.template.wrapQuizDesc1 -> f:format.raw()}{quiz.about}{settings.template.wrapQuizDesc2 -> f:format.raw()}
    +    <f:if condition="{quiz.about}">{settings.template.wrapQuizDesc1 ->
    +        f:format.raw()}{quiz.about}{settings.template.wrapQuizDesc2 -> f:format.raw()}
         </f:if>
     
         <f:if condition="{quiz.timeperiod} && ({final} == 0)">
    @@ -52,21 +50,20 @@
     
         <script>
             var ceuid = '{uidOfCE}';
    -        var noFormCheck = (({settings.noFormCheck} == 1) ? true : false);
             var quizfinal = 0;
             var tagTimePeriod = 0;
             var quizIntervalId = null;
    +        var text_errorEmpty = '{f:translate(key: "text.errorEmpty")}';
             var text_errorTimeUp = '{f:translate(key: "text.expiredTime")}';
         </script>
     
         <f:form id="quiz-form{uidOfCE}" method="POST">
             <f:form.hidden name="quiz" value="{quiz.uid}"/>
             <f:form.hidden name="participant" value="{participant.uid}"/>
    -        <f:form.hidden name="currentPage" value="{nextPage}" id="quiz-form-page"/>
    +        <f:form.hidden name="currentPage" value="{nextPage}"/>
             <f:form.hidden name="showAnswers" value="{showAnswersNext}"/>
             <f:form.hidden name="session" value="{session}"/>
             <f:form.hidden name="startTime" value="{startTime}" />
    -        <f:form.hidden name="randomPages" value="{randomPages}" />
     
             <f:if condition="{final} == 0">
                 <f:then>
    @@ -82,16 +79,6 @@
                         </p>
                     </f:if>
     
    -                <f:if condition="{settings.allowEdit}">
    -                    <f:for each="{tags}" key="oneKey" as="oneTag">
    -                        <button name="seite{oneKey}" class="btn btn-light {f:if(condition: '{page} == {oneKey}', then: 'active')}"
    -                                onclick="$('#quiz-form-page').val({oneKey});$('quiz-form{uidOfCE}').submit();">
    -                            {oneTag}
    -                        </button>
    -                    </f:for>
    -                    <br /><br />
    -                </f:if>
    -
                     <f:if condition="{showAnswers}">
                         <f:then>
     
    @@ -158,11 +145,6 @@
                                 <f:form.hidden name="homepage" value="{homepage}" />
                             </f:if>
     
    -                        <div id="quiz-error-msg" style="display:none;">
    -                            <div class="alert alert-danger" role="alert">
    -                                {f:translate(key: "text.errorEmpty")}
    -                            </div>
    -                        </div>
                             <div>
                                 <div class="pull-right quiz-subm">
                                     <f:form.button class="btn btn-primary btn-lg" id="quiz-GoOn" name="quizGoOn"
    @@ -214,13 +196,10 @@
                                     $("#quiz-GoOn").click(function () {
                                         // check if there are selected answers to all questions. if not, show an warning
                                         var allSelected = checkQuizForm();
    -                                    if (noFormCheck || allSelected) {
    +                                    if (allSelected) {
                                             $('#quiz-form' + ceuid).submit();
                                         } else {
    -                                        $('#quiz-error-msg').removeAttr("style");
    -                                        setTimeout(function() {
    -                                            $('#quiz-error-msg').hide();
    -                                        }, 5000);
    +                                        window.alert(text_errorEmpty);
                                         }
                                     });
                                 }, false);
    @@ -276,12 +255,6 @@
                                        pageUid="{settings.highscorePageUid}">{f:translate(key: "text.showHighscorePage")}
                         </f:link.action>
                     </f:if>
    -
    -                <f:if condition="{showAnswers}"><f:then></f:then><f:else>
    -                    <f:if condition="{settings.template.optionalMark}">
    -                        <br><p>{settings.template.optionalMark -> f:format.raw()}{f:translate(key: "text.optional")}</p>
    -                    </f:if>
    -                </f:else></f:if>
                 </f:then>
                 <f:else>
     
    
  • Resources/Private/Templates/Quiz/Show.html+23 48 modified
    @@ -18,9 +18,6 @@
     		    </ul>
     		  </f:if>
     		</f:form.validationResults>
    -		<f:if condition="{settings.includeRatingCSS}">
    -			<f:asset.css identifier="fpMasterQuizRatingStar" href="EXT:fp_masterquiz/Resources/Public/Css/RatingStar.css" />
    -		</f:if>
     		<f:if condition="{settings.templateLayout} == 1">
     			<!-- charts-layout -->
     			<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
    @@ -36,12 +33,6 @@
     		</f:if>
     		<f:if condition="{quiz.about}">{settings.template.wrapQuizDesc1 -> f:format.raw()}{quiz.about}{settings.template.wrapQuizDesc2 -> f:format.raw()}</f:if>
     
    -		<f:if condition="{mandatoryNotAnswered}">
    -			<ul class="errors">
    -				<li>{f:translate(key: "error.notAnswered")}</li>
    -			</ul>
    -		</f:if>
    -
     		<f:if condition="{quiz.timeperiod} && ({final} == 0)">
     			<script>
     				var quizTimePassed = parseInt({participant.timePassed});
    @@ -58,27 +49,29 @@
     			var ceuid = '{uidOfCE}';
     			var quizfinal = 0;
     			var quizend = false;
    -			var noFormCheck = (({settings.noFormCheck} == 1) ? true : false);
     			var ajaxVersion = false;
     			var quizIntervalId = null;
    +			var text_errorEmpty = '{f:translate(key: "text.errorEmpty")}';
     			var text_errorTimeUp = '{f:translate(key: "text.expiredTime")}';
     		</script>
     
     		<f:if condition="{settings.ajax} == 1">
     		<f:then>
     			<f:comment> This part is used only, if AJAX is enabled! </f:comment>
    -			<f:form id="quiz-form{uidOfCE}" method="POST" argumentsToBeExcludedFromQueryString="{0: 'cHash'}">
    -				<input type="hidden" name="type" value="{settings.typeNum}" id="quiz-form-type">
    +			<f:form id="quiz-form{uidOfCE}" method="POST" noCacheHash="1" argumentsToBeExcludedFromQueryString="{0: 'cHash'}">
    +				<input type="hidden" name="type" value="{settings.typeNum}">
     	            <input type="hidden" name="L" value="{sysLanguageUid}">
     	            <input type="hidden" name="id" value="{uidOfPage}">
     				<f:form.hidden name="action" value="showAjax" />
     				<f:form.hidden name="quiz" value="{quiz.uid}" />
     				<f:form.hidden name="uidOfCE" value="{uidOfCE}" />
    +				<f:form.hidden name="session" value="" id="quiz-form-session" />
     				<f:form.hidden name="startTime" value="{startTime}" id="quiz-form-time" />
     				<f:form.hidden name="participant" value="0" id="quiz-form-parti" />
     				<f:form.hidden name="currentPage" value="1" id="quiz-form-page" />
     				<f:form.hidden name="showAnswers" value="0" id="quiz-form-answers" />
     				<f:form.hidden name="useJoker" value="0" id="quiz-form-joker" />
    +	            <!--  f:form.hidden name="session" value="{session}" / -->
     	            
     	            <script>
     					ajaxVersion = true;
    @@ -91,7 +84,7 @@
     		            var text_goon = '{f:translate(key: "text.goon")}';
     		            var text_gofinal = '{f:translate(key: "text.gofinal")}';
     		        </script>
    -		        <script type="text/javascript">
    +		        <script language="javascript" type="text/javascript">
     		            if (ajaxTypeSetting == 'GET') {	ajaxType = 'GET'; }
     				</script>
     				
    @@ -106,11 +99,6 @@
     					<f:form.hidden name="homepage" value="{homepage}" />
     				</f:if>
     
    -				<div id="quiz-error-msg" style="display:none;">
    -					<div class="alert alert-danger" role="alert">
    -						{f:translate(key: "text.errorEmpty")}
    -					</div>
    -				</div>
     				<div id="quiz-button-wrap">
     					<div class="pull-right quiz-subm">
     						<f:form.submit value="{f:translate(key: 'text.goon')}" class="btn btn-primary btn-lg" name="quizGoOn" id="quiz-GoOn" />
    @@ -163,13 +151,10 @@
     			            form.submit(function (ev) {
     			                ev.preventDefault();
     			                var allSelected = checkQuizForm();
    -							if (quizend || noFormCheck || allSelected || ($('#quiz-form'+ceuid+' #quiz-form-joker').val() == '1')) {
    +							if (quizend || allSelected || ($('#quiz-form'+ceuid+' #quiz-form-joker').val() == '1')) {
     								service.ajaxCall($(this));
     							} else {
    -								$('#quiz-error-msg').removeAttr("style");
    -								setTimeout(function() {
    -									$('#quiz-error-msg').hide();
    -								}, 5000);
    +								window.alert(text_errorEmpty);
     							}
     			            });
     			            service.ajaxCall(form);
    @@ -194,7 +179,7 @@
     			<f:form action="show" id="quiz-form{uidOfCE}" method="POST">
     				<f:form.hidden name="quiz" value="{quiz.uid}" />
     				<f:form.hidden name="participant" value="{participant.uid}" />
    -				<f:form.hidden name="currentPage" value="{nextPage}" id="quiz-form-page" />
    +				<f:form.hidden name="@widget_0[currentPage]" value="{nextPage}" />
     				<f:form.hidden name="showAnswers" value="{showAnswersNext}" />
     				<f:form.hidden name="session" value="{session}" />
     				<f:form.hidden name="startTime" value="{startTime}" />
    @@ -216,10 +201,12 @@
     							<f:then>
     							
     								<!--  show answers after submit -->
    -								<f:for each="{participantPaginator.paginatedItems}" as="selection" iteration="pageiterator">
    -									<f:render partial="Question/PropertiesSent" arguments="{_all}" />
    -								</f:for>
    -
    +								<f:widget.paginate objects="{participant.selections}" as="paginatedSelections" configuration="{settings.pagebrowser}">
    +									<f:for each="{paginatedSelections}" as="selection" iteration="pageiterator">
    +										<f:render partial="Question/PropertiesSent" arguments="{_all}" />
    +									</f:for>
    +								</f:widget.paginate>
    +								
     								<f:if condition="{settings.showPoints} && ({participant.maximum1} > 0)">
     									<f:comment> {participant -> f:debug(title: 'Members of participant')} </f:comment> 
     									<p>{f:translate(key: "text.pointsYet")} {participant.points}/{participant.maximum1}.</p>
    @@ -244,9 +231,11 @@
     							<f:else>
     						
     								<!-- show questions -->
    -								<f:for each="{quizPaginator.paginatedItems}" as="question" iteration="pageiterator">
    -									<f:render partial="Question/Properties" arguments="{_all}" />
    -								</f:for>
    +								<f:widget.paginate objects="{quiz.questions}" as="paginatedQuestions" configuration="{settings.pagebrowser}">
    +									<f:for each="{paginatedQuestions}" as="question" iteration="pageiterator">
    +										<f:render partial="Question/Properties" arguments="{_all}" />
    +									</f:for>
    +								</f:widget.paginate>
     
     								<f:if condition="({settings.user.askForData} == 1) && ({page} == 1)">
     									<f:render partial="Participant/Form" arguments="{_all}" />
    @@ -256,12 +245,7 @@
     									<f:form.hidden name="email" value="{email}" />
     									<f:form.hidden name="homepage" value="{homepage}" />
     								</f:if>
    -
    -								<div id="quiz-error-msg" style="display:none;">
    -									<div class="alert alert-danger" role="alert">
    -										{f:translate(key: "text.errorEmpty")}
    -									</div>
    -								</div>
    +								
     								<div>
     									<div class="pull-right quiz-subm">
     										<f:form.button type="button" name="quizGoOn" id="quiz-GoOn" class="btn btn-primary btn-lg">
    @@ -289,13 +273,10 @@
                                             $( "#quiz-GoOn" ).click(function() {
                                                 // check if there are selected answers to all questions. if not, show an warning
                                                 var allSelected = checkQuizForm();
    -                                            if (noFormCheck || allSelected) {
    +                                            if (allSelected) {
                                                     $('#quiz-form'+ceuid).submit();
                                                 } else {
    -                                                $('#quiz-error-msg').removeAttr("style");
    -												setTimeout(function() {
    -													$('#quiz-error-msg').hide();
    -												}, 5000);
    +                                                window.alert(text_errorEmpty);
                                                 }
                                             });
     									}, false);
    @@ -312,12 +293,6 @@
     							<f:link.action controller="Quiz" action="highscore" pageUid="{settings.highscorePageUid}" arguments="{quiz:quiz}"
     										   class="btn btn-info">{f:translate(key: "text.showHighscorePage")}</f:link.action>
     						</f:if>
    -
    -						<f:if condition="{showAnswers}"><f:then></f:then><f:else>
    -							<f:if condition="{settings.template.optionalMark}">
    -								<br><p>{settings.template.optionalMark -> f:format.raw()}{f:translate(key: "text.optional")}</p>
    -							</f:if>
    -						</f:else></f:if>
     					</f:then>
     					<f:else>
     
    
  • Resources/Public/Icons/ext-fpmasterquiz-folder-icon-big.svg+8 0 added
    @@ -0,0 +1,8 @@
    +<?xml version="1.0" encoding="utf-8"?>
    +<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
    +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
    +	 width="298px" height="298px" viewBox="0 0 298 298" enable-background="new 0 0 298 298" xml:space="preserve">
    +<path fill="#06b193" d="M298,72.271v186.25H0v-223.5h130.375l24.213,37.25H298z"/>
    +<path opacity="0.43" fill="#003f9a" enable-background="new" d="M298,90.896H154.588l-24.213,37.25H0V72.271h298V90.896z"/>
    +</svg>
    
  • Resources/Public/Icons/relation.gif+0 0 added
  • Resources/Public/Icons/tx_fpmasterquiz_domain_model_tag.gif+0 0 modified
  • Resources/Public/Icons/user_mod_mod1.gif+0 0 removed
  • Resources/Public/Icons/user_plugin_pi1.gif+0 0 removed

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.