_initApplication(); return parent::_initAction(); } /** * urls: * admin end: * - /$testId * - /$testId/$slideId * * user end: * - /$testId */ protected function _initApplication() { if ($this->_doc->isPagePreviewMode()) { return $this->_initCmsPreviewApplication(); } $auth = $this->_doc->getAuth(); if ($auth instanceof App_Admin_Auth) { $this->_initAdminApplication(); } else { $this->_initUserApplication(); } return $this; } protected function _initCmsPreviewApplication() { $obj = $this->_getDataObj(); $entity = new Entity(); $obj->setEntity($entity); $entity->setMode(Model::MODE_ADMIN); $entity->setTestId(0); return $this; } protected function _initAdminApplication() { $auth = App_Admin_Auth::getInstance(); if (!$auth->isLoggedIn()) { $this->trigger404(); exit; } $this->_userRole = self::ROLE_ADMIN; $obj = $this->_getDataObj(); $params = $this->getRestParams(); $paramCount = count($params); $entity = new Entity(); $obj->setEntity($entity); $entity->setMode(Model::MODE_ADMIN); if (1 === $paramCount && is_numeric($params[0])) { $entity->setTestId($params[0]); } elseif (2 === $paramCount && is_numeric($params[0]) && is_numeric($params[1])) { $entity->setTestId($params[0]); $entity->setSlideId($params[1]); } else { $this->trigger404(); } $forceNew = (null == Qs_Request::getRequestValue('action')); $obj->initState($forceNew); return $this; } protected function _initUserApplication() { $auth = UserAuth::getInstance(); if (!$auth->isLoggedIn()) { $this->trigger404(); exit; } $this->_userRole = self::ROLE_USER; $user = new UserEntity($auth->getData()); $obj = $this->_getDataObj(); $obj->setUser($user); $params = $this->getRestParams(); $paramCount = count($params); $entity = new Entity(); $obj->setEntity($entity); $entity->setMode(Model::MODE_TRAINING); if (1 === $paramCount && is_numeric($params[0])) { $entity->setTestId($params[0]); } else { $this->trigger404(); } if (($state = $obj->getStoredState()) && $state->resultId) { $this->_action = 'complete'; } else { $obj->initState(); } return $this; } protected function _initPrimaryKey() { // no primary key initialization return $this; } protected function _getBaseViewItem() { $item = [ 'containerId' => 'training-test', 'slideContainerId' => 'training-slide', 'playerId' => 'slide-player', 'tpl' => $this->getTemplate('view.tpl'), ]; return $item; } protected function _addViewItem() { $item = $this->_getBaseViewItem(); if ($this->_doc->isPagePreviewMode()) { $item = array_merge($item, $this->getConfigArray('previewData', [])); $this->_addItem($item); return $this; } $obj = $this->_getDataObj(); $entity = $obj->getEntity(); $test = null; if ($entity->getTestId() && null == ($test = $obj->getTest())) { return $this->trigger404(); } if ($test) { $this->_initPageSeo($test); } if ($entity->mode === Model::MODE_TRAINING && !Model::getHasAnotherTry($obj->getUser()->id, $entity->testId)) { $info = static::getStartTargetInfo(true); Qs_Http::redirect($info['url']); exit; } $state = $obj->getState(); $slideId = $state->slideId; $slideIds = $state->slideIds; if (null == $slideIds || null == ($slide = $obj->getSlide($slideId))) { return $this->trigger404(); } $slideIndex = array_search($slideId, $slideIds); $slideCount = count($slideIds); $slideState = isset($state->slideData[$state->slideId]) ? $state->slideData[$state->slideId] : null; $item['trainingMode'] = $state->mode; $item['entity'] = $entity; $item['test'] = $test; $item['slide'] = $slide; $item['slideState'] = $slideState; $item['nav'] = [ 'slideNumber' => $slideIndex + 1, 'slideCount' => $slideCount, ]; $options = [ 'containerId' => $item['containerId'], 'slideContainerId' => $item['slideContainerId'], 'playerId' => $item['playerId'], 'requestUrl' => $this->url(), 'slideId' => $slideId, 'slideIndex' => $slideIndex, 'slideCount' => $slideCount, 'parentType' => $entity->testId ? 'test' : null, ]; $this->_doc->addScript('//www.youtube.com/iframe_api'); $this->_doc->addScript('js/jquery.blockUI.js'); $this->_doc->addScript('js/app/training/training.js'); $this->_doc->addReadyObject('app.training.Training', [$options, $slideState]); if (self::ROLE_ADMIN == $this->_userRole) { $this->_initNavigation($test, $slide); } $this->_addItem($item); return $this; } protected function _initNavigation(array $test, array $slide) { $this->_doc->setHeader(null); $module = new TestModule(); $slideId = $this->_getDataObj()->getEntity()->getSlideId(); /** @var Navigation $testNavigation */ $testNavigation = $module->getService('testAdminNavigation'); $testNavigation->setEntity($test); if ($slideId) { $testNavigation->showItem(); } else { $testNavigation->setAction('view'); } $testNavigation->exec(); if ($slideId) { /** @var Navigation $slideNavigation */ $slideNavigation = $module->getService('testSlideAdminNavigation', ['testId' => $test['id']]); $slideNavigation->setAction('view'); $slideNavigation->setEntity($slide); $slideNavigation->exec(); } return $this; } protected function _doSlide() { exit; } /** * method: POST * param int slideIndex * param int oldIndex * param json oldState */ protected function _doSlideAjax() { $slideIndex = (int) Qs_Request::getPostValue('slideIndex'); $oldIndex = (int) Qs_Request::getPostValue('oldIndex'); $oldState = Qs_Request::getPostValue('oldState'); $oldState = ($oldState) ? json_decode($oldState, true) : null; $obj = $this->_getDataObj(); $state = $obj->getState(); $slideCount = count($state->slideIds); // save slide state if ($state->slideIds[$oldIndex]) { $oldSlideId = $state->slideIds[$oldIndex]; if ($oldState) { $oldState = (array) $oldState; $oldState['changed'] = date('Y-m-d H:i:s'); $oldState['added'] = empty($state->slideData[$oldSlideId]['added']) ? $oldState['changed'] : $state->slideData[$oldSlideId]['added']; } $state->slideData[$oldSlideId] = $oldState; if ($slideIndex > $oldIndex && $slideIndex < $slideCount) { $result = $obj->checkSlideResult($oldSlideId); if ($result['success'] === false) { // prematurely failed training (user will not be able to earn necessary score) $result = $obj->checkTrainingResult($slideIndex); $item = $this->_getResultItem($result); $this->_doc->assign('item', new Qs_Doc_Item($item)); $html = $this->_doc->fetchTemplate($item['tpl']); if ($state->mode === Model::MODE_ADMIN) { $obj->clearState(); } $this->_displayJson([ 'mode' => 'result', 'html' => $html, ]); exit; } } } // result page if ($slideIndex == $slideCount) { $item = $this->_getResultItem($obj->checkTrainingResult($slideIndex)); $this->_doc->assign('item', new Qs_Doc_Item($item)); $html = $this->_doc->fetchTemplate($item['tpl']); if ($state->mode === Model::MODE_ADMIN) { $obj->clearState(); } $this->_displayJson([ 'mode' => 'result', 'html' => $html, ]); exit; } // prev/next slide if ($slideIndex < 0 && $slideIndex >= $slideCount) { Qs_Http::header(400); exit; } if (empty($state->slideIds[$slideIndex])) { Qs_Http::header(400); exit; } $state->slideId = $state->slideIds[$slideIndex]; $slide = $obj->getSlide($state->slideId); $slideState = isset($state->slideData[$state->slideId]) ? $state->slideData[$state->slideId] : null; $item = []; $item['trainingMode'] = $state->mode; $item['slide'] = $slide; $item['slideState'] = $slideState; $item['nav'] = [ 'slideNumber' => $slideIndex + 1, 'slideCount' => $slideCount, ]; $item['tpl'] = $this->getTemplate('slide.tpl'); $this->_doc->assign('item', new Qs_Doc_Item($item)); $html = $this->_doc->fetchTemplate($item['tpl']); $this->_displayJson([ 'mode' => 'slide', 'slideId' => $state->slideId, 'slideIndex' => $slideIndex, 'slideState' => $slideState, 'slideHtml' => $html, ]); exit; } protected function _getResultItem($result) { $obj = $this->_getDataObj(); $state = $obj->getState(); $item = []; $item['test'] = $obj->getTest(); $item['result'] = $result; $item['trainingMode'] = $state->mode; $item['url'] = $this->url(); if ($state->mode === Model::MODE_TRAINING) { $item['user'] = $obj->getUser(); $item['continueInfo'] = Model::getContinuePage($state->user->id, $state->testId); } elseif ($state->mode === Model::MODE_ADMIN) { $item['testListUrl'] = Qs_SiteMap::findFirst(null, ['type' => 'Test\\Admin\\'], null, 'url'); } $item['tpl'] = $this->getTemplate('result.tpl'); return $item; } protected function _doComplete() { $obj = $this->_getDataObj(); if ($obj->getEntity()->getMode() === Model::MODE_ADMIN) { exit; } if (Qs_Request::isPost() && ($comments = trim(Qs_Request::getPostValue('comments')))) { $obj->saveComments($comments); } $obj->clearState(); $url = null; // 'test' | 'list' | 'close' $go = Qs_Request::getGetValue('go'); if ($go === 'close') { $url = BASE_URL; UserAuth::getInstance()->clearIdentity(); Zend_Session::destroy(); } else { $url = $this->getContinueUrl($obj->getUser()->id, $obj->getEntity()->testId, $go); } Qs_Http::redirect($url); exit; } /** * If there are one test - return home page otherwise return Trainings page url; * if there are one test and no training attempts left - return home page * * @return null|string * @throws \Exception */ public static function getStartUrl() { $info = static::getStartTargetInfo(); return $info['url']; } public static function getStartTargetInfo($clearAuth = false) { $auth = UserAuth::getInstance(); if (!$auth->isLoggedIn() || null == ($userId = $auth->getData('id'))) { throw new \Exception('User should be logged in'); } $target = Model::getStartPage($userId); if (is_numeric($target)) { $url = static::getPageLocal('url') . '/' . $target; } elseif ($target === Model::SHOW_LIST) { $url = TestView::getPageLocal('url'); } else { $url = BASE_URL; if ($clearAuth) { UserAuth::getInstance()->clearIdentity(); Zend_Session::destroy(); } } return [ 'target' => $target, 'url' => $url, ]; } /** * @param int $userId * @param int $testId * @param string $go ex. 'test' | 'list' * * @return mixed|null|string */ public function getContinueUrl($userId, $testId, $go = null) { if (empty($testId) || empty($userId)) { return BASE_URL; } $info = Model::getContinuePage($userId, $testId); $target = $info['target']; if ($go === 'test' && is_numeric($target)) { return static::getPageLocal('url') . '/' . $target; } elseif ($go === 'list' && $info['showList']) { return TestView::getPageLocal('url'); } else { if (is_numeric($target)) { return static::getPageLocal('url') . '/' . $target; } elseif ($target === Model::SHOW_LIST) { return TestView::getPageLocal('url'); } } return BASE_URL; } }