_doc->getView()->addHelperPath('App/Form/View/Helper/', 'App\Form\View\Helper\\'); $this->step = $this->_doc->getOption('xStep'); // init steps $this->getSteps(); if ($this->isPaymentDisabled()) { $this->removeStep(self::STEP_PAYMENT); } if (!in_array($this->step, array_column($this->getSteps(), 'name'))) { throw new Exception('Unknown step "' . $this->step . '"'); } if ($this->step === self::STEP_COMPLETED) { $this->setStep( [ self::STEP_APPLICANT, self::STEP_QUESTIONNAIRE, self::STEP_BACKGROUND, self::STEP_REFERENCES, self::STEP_PAYMENT, self::STEP_SUBMISSION, ], 'enabled', false ); } else if (!$this->isPreviousStepCompleted()) { $this->redirectToStep($this->getPreviousStepName()); } if (!Qs_Request::isXmlHttpRequest()) { switch ($this->step) { case self::STEP_REFERENCES: $this->getEventManager()->attach('process', [$this, 'onReferencesStep']); break; case self::STEP_SUBMISSION: $this->getEventManager()->attach('process', [$this, 'onPaymentStep']); break; } } return parent::exec(); } protected function _doStepAjax() { $form = $this->getStepForm(Qs_Request::getPost()); $response = $form->validateAjax(); $this->_displayJson($response); } protected function _doStep() { $step = $this->getCurrentStep(); if (array_key_exists('form', $step)) { $stepData = Qs_Request::isPost() ? Qs_Request::getPost() : $this->getStepData(); $this->getEventManager()->trigger('initFormData', null, ['data' => &$stepData]); /** @var \Qs_Form $form */ $form = $this->getStepForm($stepData); $form->setDefaults(); if (Qs_Request::isPost() && $form->validate()) { $data = $form->getValues(); $this->saveStepData($this->step, $data); $this->getEventManager()->trigger('process'); if (($nextStep = $this->getNextStepName())) { $this->redirectToStep($nextStep); } } $content = $form->render(); } else { $content = ''; } $placeholders = [ 'stepProgress' => $this->renderProgressBar(), 'stepTitleBar' => $this->renderStepTitle(), 'stepContent' => $content, ]; if (Qs_Request::isGet()) { $this->getEventManager()->trigger('initPlaceholders', null, ['placeholders' => &$placeholders]); } $this->_doc->setModulePlaceholders($this->getOption('type'), $placeholders); $this->_doc->addStylesheet('css/modules/employee.css'); return $this; } protected function getStepForm(array $defaults = []) { $options = []; $options['class'] = $this->getApplicationName() . ' progress-form__form step-' . $this->step; if (($previousStep = $this->getPreviousStepName($this->step)) && $this->getStep($previousStep, 'enabled') && ($url = self::getStepUrl($previousStep)) ) { $options['cancelUrl'] = $url; } if (!($className = $this->getCurrentStep('form'))) { throw new Exception('Step (' . $this->step . ') form is not defined'); } $options = array_merge($this->_getFormOptions(), $options); $options['defaults'] = $defaults; // check if form implements interface through reflection class since it initializes itself in constructor $reflection = new \ReflectionClass($className); if ($reflection->implementsInterface(QuestionnaireAwareInterface::class)) { $options['questions'] = $this->getModel()->getQuestions(['enabled' => 'y']); } if ($reflection->implementsInterface(PaymentFormInterface::class)) { $options['paymentSummary'] = $this->_doc->fetchItem([ 'summary' => $this->getPaymentSummary(), 'tpl' => $this->getTemplate('payment-summary.tpl'), ]); $options['bankApiUrl'] = BankApiView::getPage('fullAlias'); } $form = new $className($options); return $form; } private function getPaymentSummary($field = null) { $subtotal = App_Settings_Obj::get('employeeApplicationFee'); $adminFee = App_Settings_Obj::get('employeeApplicationAdminFee'); $total = Zend_Locale_Math::Add($subtotal, $adminFee, 0); return Qs_Array::get([ 'subtotal' => $subtotal, 'adminFee' => $adminFee, 'total' => $total, ], $field); } protected function getPartRenderingForm(array $defaults = []) { return $this->getStepForm($defaults); } public static function getStepUrl($step) { if (false === ($page = Qs_SiteMap::findFirst(['xStep' => $step], ['type' => 'Employee\\']))) { throw new Exception('Can not find "' . $step . '" step url'); } return $page['url']; } protected function renderStepTitle() { $step = $this->getCurrentStep(); $item = [ 'currentStep' => $step, 'stepsCount' => count($this->getSteps()), 'tpl' => $this->getTemplate('step-title-bar.tpl'), ]; return $this->_doc->fetchItem($item); } public function onReferencesStep() { $this->handleFiles(); return $this; } private function handleFiles() { $session = new Qs_Session_Namespace(CURRENT_PAGE); if (isset($session->files) && !empty($session->files)) { $adapter = new Qs_File_Transfer_Adapter_Db(); foreach ($session->files as $file => $name) { $adapter->delete($file, $name); } unset($session->files); } return $this; } public function onPaymentStep() { $employee = $this->createEntity(); try { $db = Qs_Db::getInstance(); $db->beginTransaction(); $this->getModel()->setTransactionEnabled(false)->insert($employee); $this->processPayment($this->getStepData(self::STEP_PAYMENT), $employee); $this->notify($employee); $this->clearSession(); $db->commit(); } catch (IntegrityPaymentException $e) { $this->_setBackUrl(self::getStepUrl(self::STEP_PAYMENT)); $this->_setBackError($e->getMessage()); } catch (SpsException $e) { $this->_setBackUrl(self::getStepUrl(self::STEP_PAYMENT)); $this->_setBackError('SPS Error: ' . $e->getMessage()); } return $this; } private function isPaymentDisabled() { return App_Settings_Obj::get('employeeApplicationFee') <= 0; } private function processPayment(array $payment, array $employee) { if ($this->isPaymentDisabled()) { return $this; } $total = $this->getPaymentSummary('total'); if ($total <= 0) { return $this; } $description = 'Empl. #' . $employee['id']; switch ($employee['paymentMethod']) { case PaymentEntity::PAYMENT_METHOD_CC: $client = IpsFactory::create(); $paymentEntity = new PaymentEntity(Qs_Array::map($payment, [ 'ccNumber', 'ccExpirationDate', 'ccSecurityCode', ])); $paymentEntity->setAmount($total); $paymentEntity->setDescription($description); $request = $paymentEntity->toIpsRequest(); $transactionId = $client->sale($request); break; case PaymentEntity::PAYMENT_METHOD_CHECK: $client = SpsFactory::create(); $paymentEntity = new PaymentEntity(Qs_Array::map($payment, [ 'checkType', 'accountName', 'routingNumber', 'accountNumber', ])); $paymentEntity->setAmount($total); $paymentEntity->setDescription($description); $paymentEntity->setPhone($employee['mobilePhone']); $transactionId = $client->pay($paymentEntity->toSpsPacket()); break; default: throw new Exception('Unsupported Payment Method: ' . $employee['paymentMethod']); } $transactionTime = date('Y-m-d H:i:s'); $this->getModel()->update(compact('transactionId', 'transactionTime'), ['id' => $employee['id']]); return $this; } private function createEntity() { $employee = []; foreach ($this->getSteps() as $step) { $employee = array_merge($employee, $this->getStepData($step['name'])); } if (!empty($employee['ccNumber'])) { $employee['ccNumber'] = $this->_doc->getView()->maskCreditCard($employee['ccNumber']); } if (!empty($employee['accountNumber'])) { $employee['accountNumber'] = $this->_doc->getView()->maskCheckAccountNumber($employee['accountNumber']); } return $employee; } private function notify(array $employee) { $this->getModel()->injectStaticDependencies($employee); Mail::sendApplicationSubmittedToAdmin($employee); Mail::sendApplicationSubmittedToUser($employee); return $this; } }