<?php /** * PHP version 7 * * Copyright (C) 2019 Leipzig University Library * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * @category VuFind * @package Controller * @author Gregor Gawol <gawol@ub.uni-leipzig.de> * @author Sebastian Kehr <kehr@ub.uni-leipzig.de> * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2 * @link https://vufind.org/wiki/development Wiki */ namespace fid\Controller; use fid\FormModel\PasswordChangeModel; use fid\FormModel\PasswordResetModel; use fid\FormModel\UserDeleteModel; use fid\FormModel\UsernameChangeModel; use fid\Service\Client; use fid\Service\ClientException; use fid\Service\DataTransferObject\Library; use fid\Service\DataTransferObject\Order; use fid\Service\DataTransferObject\User; use fid\Service\UserNotAuthorizedException; use VuFind\Auth\Manager as AuthManager; use VuFind\Controller\AbstractBase; use VuFind\Exception\Auth as AuthException; use Zend\Form\Element\Select; use Zend\Form\Form; use Zend\Http\PhpEnvironment\Request; use Zend\Http\PhpEnvironment\Response as HttpResponse; use Zend\Http\Response; use Zend\Mvc\Plugin\FlashMessenger\FlashMessenger; use Zend\ServiceManager\ServiceLocatorInterface; use Zend\View\Model\ViewModel; /** * User Controller * * @category VuFind * @package Controller * @author Gregor Gawol <gawol@ub.uni-leipzig.de> * @author Sebastian Kehr <kehr@ub.uni-leipzig.de> * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2 * @link https://vufind.org/wiki/development Wiki */ class UserController extends AbstractBase { /** * AuthManager * * @var AuthManager */ protected $authManager; /** * Fidis client * * @var Client */ protected $client; /** * Configuration * * @var array */ protected $config; /** * RegistrationController constructor. * * @param ServiceLocatorInterface $serviceLocator Service Locator * @param AuthManager $authManager Authentication Manager * @param Client $client fidis client * @param array $config Configuration */ public function __construct( ServiceLocatorInterface $serviceLocator, AuthManager $authManager, Client $client, array $config ) { parent::__construct($serviceLocator); $this->authManager = $authManager; $this->client = $client; $this->config = $config; } /** * Registration init (registration part 1) route action * Starting registration process * * @noinspection PhpUnused * @return ViewModel */ public function initAction() { /* @var Form $form */ /* @var Request $request */ $request = $this->getRequest(); $form = $this->serviceLocator->get('user-init-form'); $forwarded = $this->params()->fromRoute('forwarded', false); if ($submitted = $this->formWasSubmitted()) { $form->setData($request->getPost()); if (!$forwarded && $form->isValid()) { return $this->init($form); } } $action = $this->url()->fromRoute('fid/user/init'); $form->setAttribute('action', $action); $form->prepare(); $view = $this->createViewModel(); $view->setVariables(compact('form')); $view->setTemplate('fid/user/init'); return $view; } /** * Registration init (registration part 1) by requesting * email registration link via fidis after succeded formular validation. * * @param Form $form Formular * * @return mixed|Response */ protected function init(Form $form) { /* @var User $user */ $messenger = $this->getMessenger(); $user = $form->getHydrator()->hydrate($form->getData(), new User()); /* @noinspection PhpUndefinedFieldInspection */ $query['lng'] = $this->layout()->userLang; $username = $query['username'] = $user->getUsername(); $firstname = $query['firstname'] = $user->getFirstname(); $lastname = $query['lastname'] = $user->getLastname(); $baseUrl = $this->url()->fromRoute( 'fid/user/create', [], ['query' => $query, 'force_canonical' => true] ); try { $this->client->requestRegistrationLink( $baseUrl, $username, $firstname, $lastname ); } catch (ClientException $exception) { $message = $exception->getCode() === 400 ? 'fid::user_init_error_username' : 'fid::user_init_error'; $messenger->addErrorMessage($this->translate($message)); return $this->forward()->dispatch( self::class, [ 'action' => 'init', 'forwarded' => true ] ); } $message = $this->translate('fid::user_init_success'); $messenger->addSuccessMessage(sprintf($message, $username)); return $this->redirect()->toRoute('myresearch-home'); } /** * Get flash messenger * * @return FlashMessenger */ protected function getMessenger(): FlashMessenger { /* @noinspection PhpUndefinedMethodInspection */ /* @var FlashMessenger $messenger */ return $this->flashMessenger(); } /** * Create new user (registration part 2) route action. * Finish registration process. * Action is triggert by link receved by email * * @noinspection PhpUnused * @return Response|ViewModel */ public function createAction() { /* @var Form $form */ /* @var Request $request */ /* @var Select $homeLibraryElement */ $request = $this->getRequest(); $query = $request->getQuery(); $messenger = $this->getMessenger(); if ($credentials = $query->get('logon')) { try { $this->client->logon($credentials); } catch (ClientException $exception) { $message = $exception->getCode() === 401 ? 'fid::user_create_error_expired' : 'fid::user_create_error'; $messenger->addErrorMessage($this->translate($message)); return $this->redirect()->toRoute('fid/user/init'); } $query->offsetUnset('logon'); return $this->redirect()->toRoute( 'fid/user/create', [], [ 'query' => $query->toArray() ] ); } try { $libraries = array_map( function (Library $libary) { return $libary->getLabel(); }, $this->client->requestLibraryList() ); } catch (ClientException $exception) { $message = 'fid::user_create_error'; $messenger->addErrorMessage($this->translate($message)); return $this->redirect()->toRoute('fid/user/init'); } $form = $this->serviceLocator->get('user-create-form'); $homeLibraryElement = $form->get('home_library'); $homeLibraryElement->setValueOptions($libraries); $this->applyJobTitleOptions($form); if ($this->formWasSubmitted()) { $form->setData($request->getPost()); if ($form->isValid()) { return $this->create($form); } } else { $form->setData($query); } $action = $this->url()->fromRoute('fid/user/create'); $form->setAttribute('action', $action); $form->prepare(); $view = $this->createViewModel(); $view->setVariables(compact('form')); $view->setTemplate('fid/user/create'); return $view; } /** * Create new user (registration part 2) * via fidis after succeded formular validation. * * @param Form $form Formular * * @return Response */ protected function create(Form $form) { /* @var User $user */ $messenger = $this->getMessenger(); $user = $form->getHydrator()->hydrate($form->getData(), new User()); try { $this->client->requestUserCreation($user); $message = $this->translate('fid::user_create_success'); $messenger->addSuccessMessage($message); /* @noinspection PhpParamsInspection */ $this->authManager->create($this->getRequest()); } catch (ClientException $exception) { $message = $this->translate('fid::user_create_error'); $messenger->addErrorMessage($message); } catch (AuthException $e) { $message = $this->translate('fid::user_create_error_autologon'); $messenger->addWarningMessage($message); } return $this->redirect()->toRoute( 'myresearch-home', [], [ 'query' => ['redirect' => false] ] ); } /** * User / profile update route action * * @return Response|ViewModel * @throws UserNotAuthorizedException */ public function updateAction() { /* @var Form $form */ /* @var Request $request */ /* @var Select $homeLibraryElement */ try { $request = $this->getRequest(); $user = $this->client->requestUserDetails(); $libraries = array_map( function (Library $libary) { return $libary->getLabel(); }, $this->client->requestLibraryList() ); } catch (ClientException $exception) { $this->setFollowupUrlToReferer(); $message = $exception->getCode() === 401 ? 'fid::user_update_error_expired' : 'fid::user_update_error'; $this->getMessenger()->addErrorMessage($this->translate($message)); return $this->redirect()->toRoute('myresearch-home'); } $form = $this->serviceLocator->get('user-update-form'); $homeLibraryElement = $form->get('home_library'); $homeLibraryElement->setValueOptions($libraries); if ($this->formWasSubmitted()) { $form->setData($request->getPost()); if ($form->isValid()) { return $this->update($form); } } else { $form->setData($form->getHydrator()->extract($user)); } $action = $this->url()->fromRoute('fid/user/update'); $form->setAttribute('action', $action); $form->prepare(); $viewModel = $this->createViewModel(); // set cancel target if coming from lightbox if ($cancelUrl = $this->getFollowupUrl()) { $viewModel->setVariable('cancelUrl', $cancelUrl); } $viewModel->setVariables(compact('form')); $viewModel->setTemplate('fid/user/update'); return $viewModel; } /** * Finish user update via fidis after succeded formular validation * * @param Form $form Formular * @param string $redirect Route name * * @return Response * @throws UserNotAuthorizedException */ protected function update(Form $form, string $redirect = 'myresearch-home') { $data = $form->getData(); $messenger = $this->getMessenger(); try { $user = clone $this->client->requestUserDetails($data['id']); $form->getHydrator()->hydrate($data, $user); $this->client->requestUserUpdate($user); $message = $this->translate('fid::user_update_success'); // use InfoMessage instead of SuccessMessage to prevent hiding // rendered view (formular) in lightbox $messenger->addInfoMessage($message); } catch (ClientException $exception) { if (in_array($exception->getCode(), [403])) { $message = $this->translate( 'fid::user_update_error_' . $exception->getCode() ); } else { $message = $this->translate('fid::user_update_error'); } $messenger->addErrorMessage($message); } $this->client->flushUserList(); if ($followUp = $this->getFollowupUrl()) { $this->clearFollowupUrl(); return $this->redirect()->toUrl($followUp); } return $this->redirect()->toRoute( $redirect, [], [ 'query' => ['redirect' => false] ] ); } /** * Request change username email (update username part 1) route action * * @noinspection PhpUnused * @return ViewModel */ public function changeUsernameAction() { /* @var Request $request */ $request = $this->getRequest(); $form = $this->serviceLocator->get(UsernameChangeModel::class); $forwarded = $this->params()->fromRoute('forwarded', false); if ($submitted = $this->formWasSubmitted()) { $form->setData($request->getPost()); if (!$forwarded && $form->isValid()) { return $this->changeUsername($form); } } $view = $this->createViewModel(); $view->setVariables(compact('form')); $view->setTemplate('fid/user/username-change'); return $view; } /** * Request change username email (update username part 1) * via fidis after succeded formular validation. * * @param Form $form Formular * * @return mixed|Response */ protected function changeUsername(Form $form) { $messenger = $this->getMessenger(); $model = $form->getHydrator()->hydrate( $form->getData(), new UsernameChangeModel() ); /* @noinspection PhpUndefinedFieldInspection */ $query['lng'] = $this->layout()->userLang; $username = $query['username'] = $model->getUsername(); $baseUrl = $this->url()->fromRoute( 'fid/user/update-username', [], ['query' => $query, 'force_canonical' => true] ); try { $this->client->requestUsernameLink($baseUrl, $username); } catch (ClientException $exception) { $message = $exception->getCode() === 400 ? 'fid::username_change_error_username' : 'fid::username_change_error'; $messenger->addErrorMessage($this->translate($message)); return $this->forward()->dispatch( self::class, [ 'action' => 'changeUsername', 'forwarded' => true ] ); } $message = $this->translate('fid::username_change_success'); $messenger->addSuccessMessage(sprintf($message, $username)); return $this->redirect()->toRoute('myresearch-home'); } /** * Execute update username (update username part 2) route action. * Action is triggert by link receved by email * * @noinspection PhpUnused * @return Response */ public function updateUsernameAction() { /* @var Request $request */ $request = $this->getRequest(); $query = $request->getQuery(); $messenger = $this->getMessenger(); if ($credentials = $query->get('logon')) { try { $this->client->logon($credentials); } catch (ClientException $exception) { $message = $exception->getCode() === 401 ? 'fid::username_update_error_expired' : 'fid::username_update_error'; $messenger->addErrorMessage($this->translate($message)); return $this->redirect()->toRoute('fid/user/change-username'); } $query->offsetUnset('logon'); return $this->redirect()->toRoute( 'fid/user/update-username', [], [ 'query' => $query->toArray() ] ); } try { $user = clone $this->client->requestUserDetails(); $user->setUsername($query->get('username')); $this->client->requestUserUsernameUpdate($user); $message = $this->translate('fid::username_update_success'); $this->getMessenger()->addSuccessMessage($message); } catch (ClientException $exception) { $message = $this->translate('fid::username_update_error'); $this->getMessenger()->addErrorMessage($message); } return $this->redirect()->toRoute('myresearch-home'); } /** * Confirm delete profile route action * * @noinspection PhpUnused * @return Response */ public function deleteAction() { if (!$this->getUser()) { return $this->forceLogin(); } /* @var User $user */ $user = $this->client->requestUserDetails(null, true); if ($user->getData()['deleted'] ?? false) { $view = $this->createViewModel(); $messages['html'] = true; $messages['msg'] = $this->translate( "fid::user_delete_error_account_blocked", [ '%%fidname%%' => $this->translate("fid::acquisition_fid_name") ] ); $this->flashMessenger()->addMessage($messages, 'error'); $view->setTemplate('default/flash-message'); return $view; } /* @var Request $request */ $request = $this->getRequest(); /* @var Form $form */ $form = $this->serviceLocator->get(UserDeleteModel::class); $forwarded = $this->params()->fromRoute('forwarded', false); if ($submitted = $this->formWasSubmitted()) { $form->setData($request->getPost()); if (!$forwarded && $form->isValid()) { return $this->deleteUser($form); } } $view = $this->createViewModel(); $view->setVariables(compact('form')); $view->setTemplate('fid/user/user-delete'); return $view; } /** * Save user as deleted via fidis after succeded password confirmation. * And log out user. * * @param Form $form Formular * * @return Response|ViewModel * @throws ClientException * @throws UserNotAuthorizedException */ protected function deleteUser(Form $form) { $messenger = $this->getMessenger(); /* @var UserDeleteModel $model */ $model = $form->getHydrator() ->hydrate($form->getData(), new UserDeleteModel()); $error = []; try { /* @var User $user */ $user = $this->client->requestUserDetails(); if ($this->client->checkCredentials( $user->getUsername(), $model->getPasswordConfirmation() ) ) { $user->setDeleted(true); $user->setDeletedAt(date('Y-m-d H:i:s', time())); $user = $this->client->requestUserUpdate($user); if (!$user->isDeleted()) { $error['msg'] = $this ->translate('fid::user_delete_error_unknown'); } } else { $error['msg'] = $this ->translate('fid::user_delete_error_wrong_password'); } } catch (ClientException $exception) { $error['msg'] = $this->translate('fid::user_delete_error_unknown'); } if (!empty($error)) { $error['html'] = true; $messenger->addErrorMessage($error); return $this->redirect()->toRoute('fid/user/delete'); } $this->client->logoff(); $this->getAuthManager()->logout(""); $view = $this->createViewModel(); $view->setTemplate('myresearch/delete-success'); return $view; } /** * Display policy route action * * @return ViewModel */ public function policyAction() { $viewModel = $this->createViewModel(); $viewModel->setTemplate('fid/user/policy'); $this->setBackUrl($viewModel); return $viewModel; } /** * Display terms route action * * @return ViewModel */ public function termsAction() { $viewModel = $this->createViewModel(); $viewModel->setTemplate('fid/user/terms'); $this->setBackUrl($viewModel); return $viewModel; } /** * Request reset password mail (reset password part 1) route action * Allows the reset password form to appear, must be confirmed by user. * * @return ViewModel */ public function resetPasswordAction() { /* @var Form $form */ /* @var Request $request */ $request = $this->getRequest(); $form = $this->serviceLocator->get(PasswordResetModel::class); $forwarded = $this->params()->fromRoute('forwarded', false); if ($this->getUser()) { $form->get('username')->setAttribute('disabled', 'true'); $form->get('username') ->setValue($this->client->requestUserDetails()->getUsername()); $form->setValidationGroup(['submit']); } if ($submitted = $this->formWasSubmitted()) { $form->setData($request->getPost()); if (!$forwarded && $form->isValid()) { return $this->sendResetPassword($form); } } $view = $this->createViewModel(); $view->setVariables(compact('form')); $view->setTemplate('fid/user/password-reset'); return $view; } /** * Send reset password email via fidis to user * * @param Form $form Formular * * @return Response * @throws ClientException * @throws UserNotAuthorizedException */ protected function sendResetPassword(Form $form) { $messenger = $this->getMessenger(); if ($this->getUser()) { $username = $this->client->requestUserDetails()->getUsername(); } else { /* @var PasswordResetModel $model */ $model = $form->getHydrator()->hydrate( $form->getData(), new PasswordResetModel() ); $username = $model->getUsername(); } try { /* @noinspection PhpUndefinedFieldInspection */ $query['lng'] = $this->layout()->userLang; $baseUrl = $this->url()->fromRoute( 'fid/user/change-password', [], ['query' => $query, 'force_canonical' => true] ); $this->client->requestPasswordLink($baseUrl, $username); $message = $this->translate('fid::password_reset_success'); $messenger->addSuccessMessage(sprintf($message, $username)); } catch (ClientException $exception) { $message = $exception->getCode() === 400 ? $this->translate('fid::password_reset_error_username') : $this->translate('fid::password_reset_error'); $messenger->addErrorMessage(sprintf($message, $username)); return $this->redirect()->toRoute('fid/user/reset-password'); } return $this->redirect()->toRoute('myresearch-home'); } /** * Reset password route action (reset password part 2). * Action is triggerd by email link. * Allows the change password form to appear. * * @return Response|ViewModel */ public function changePasswordAction() { /* @var Request $request */ $request = $this->getRequest(); $query = $request->getQuery(); $messenger = $this->getMessenger(); if ($credentials = $query->get('logon')) { try { $this->client->logon($credentials); } catch (ClientException $exception) { $message = $exception->getCode() === 401 ? 'fid::password_change_error_expired' : 'fid::password_change_error'; $messenger->addErrorMessage($this->translate($message)); return $this->redirect()->toRoute('fid/user/reset-password'); } $query->offsetUnset('logon'); return $this->redirect()->toRoute( 'fid/user/change-password', [], [ 'query' => $query->toArray() ] ); } $form = $this->serviceLocator->get(PasswordChangeModel::class); if ($this->formWasSubmitted()) { $form->setData($request->getPost()); if ($form->isValid()) { return $this->changePassword($form); } } else { $form->setData($query); } $view = $this->createViewModel(); $view->setVariables(compact('form')); $view->setTemplate('fid/user/password-change'); return $view; } /** * Update password by passing it to user model * and run update password request to fidis * * @param Form $form Formular * * @return Response * @throws UserNotAuthorizedException * @throws \fid\Service\UserNotLoggedinException */ protected function changePassword(Form $form) { /* @var PasswordChangeModel $model */ $messenger = $this->getMessenger(); $model = $form->getHydrator()->hydrate( $form->getData(), new PasswordChangeModel() ); try { $user = clone $this->client->requestUserDetails(); $user->setPassword($password = $model->getPassword()); $this->client->requestUserPasswordUpdate($user); $message = $this->translate('fid::password_change_success'); $message = sprintf($message, $username = $user->getUsername()); $messenger->addSuccessMessage($message); /* @var Request $request */ $request = clone $this->getRequest(); $params = clone $request->getPost(); $params->set('username', $username); $params->set('password', $password); $request->setPost($params); $this->authManager->create($request); } catch (ClientException $exception) { $message = $this->translate('fid::password_change_error'); $messenger->addErrorMessage($message); } catch (AuthException $e) { $message = $this->translate('fid::password_change_error_autologon'); $messenger->addErrorMessage($message); } return $this->redirect()->toRoute( 'myresearch-home', [], [ 'query' => ['redirect' => false] ] ); } /** * Edit user route action. * Only for admins. * * @return mixed|Response|ViewModel * @throws UserNotAuthorizedException */ public function editAction() { if (!$this->getUser()) { return $this->forceLogin(); } /* @var Request $request */ $request = $this->getRequest(); $userId = $this->params()->fromRoute('userid'); if (empty($userId)) { // if no user ID is set the call is not valid // unless we are in submission state return $this->redirect()->toRoute('fid/admin/list'); } try { try { $user = $this->client->requestUserDetails($userId); } catch (UserNotAuthorizedException $ex) { // either user does not exist, or we are not allowed to edit it $this->getMessenger() ->addErrorMessage( $this->translate( 'fid::user_edit_not_allowed', ['%%userid%%' => $userId] ) ); return $this->redirect()->toRoute('fid/admin/list'); } catch (\Exception $ex) { $this->getMessenger() ->addErrorMessage( $this->translate( 'fid::user_read_error', ['%%userid%%' => $userId] ) ); return $this->redirect()->toRoute('fid/admin/list'); } $libraries = array_map( function (Library $libary) { return $libary->getLabel(); }, $this->client->requestLibraryList() ); } catch (ClientException $exception) { $this->setFollowupUrlToReferer(); $message = $exception->getCode() === 401 ? 'fid::user_update_error_expired' : 'fid::user_update_error'; $this->getMessenger()->addErrorMessage($this->translate($message)); return $this->redirect()->toRoute('fid/admin/list'); } /* @var Form $form */ /* @var Select $homeLibraryElement */ $form = $this->serviceLocator->get('admin-edit-form'); $homeLibraryElement = $form->get('home_library'); $homeLibraryElement->setValueOptions($libraries); $homeLibraryElement->setUnselectedValue($user->getHomeLibrary()); $this->applyJobTitleOptions($form); if ($this->formWasSubmitted()) { $form->setData($request->getPost()); if ($form->isValid()) { return $this->update($form, 'fid/admin/list'); } } else { $form->setData($form->getHydrator()->extract($user)); } $action = $this->url()->fromRoute( 'fid/admin/edit', [ 'userid' => $userId ] ); $form->setAttribute('action', $action); $form->prepare(); $config = $this->config; $viewModel = $this->createViewModel(); $viewModel->setVariables(compact('config', 'form', 'user')); $viewModel->setTemplate('fid/admin/edit'); return $viewModel; } /** * Display admins user list route action * * @return mixed|ViewModel */ public function listAction() { if (!$this->getUser()) { return $this->forceLogin(); } $viewModel = $this->createViewModel(); try { $list = $this->client->requestUserList(); $viewModel->setVariable('list', $list); } catch (UserNotAuthorizedException $exception) { $this->getMessenger() ->addErrorMessage('fid::read_user_list_not_allowed'); } catch (ClientException $exception) { $this->getMessenger()->addErrorMessage('fid::read_user_list_error'); } if ($fields = $this->config['Admin']['overview_fields']) { $viewModel->setVariable('fields', $fields); } $viewModel->setVariable('config', $this->config); $viewModel->setTemplate('fid/admin/list'); return $viewModel; } /** * Display users order list route action * * @return mixed|void|ViewModel * @throws UserNotAuthorizedException */ public function ordersAction() { if (!$this->getUser()) { return $this->forceLogin(); } try { $user = $this->client->requestUserDetails(null, true); $viewModel = $this->createViewModel(); $orders = $user->getOrders(); $displayCols = $this->config['OrderListUser']['displayCols']; $viewModel->setVariables(compact('orders', 'displayCols')); $viewModel->setTemplate('fid/order/order-list'); return $viewModel; } catch (ClientException $exception) { $this->getMessenger()->addErrorMessage('fid::orders_error'); $this->redirect()->toRoute('myresearch-profile'); } } /** * Display admins order list route action * * @return mixed|void|ViewModel */ public function adminOrdersAction() { if (!$this->getUser()) { return $this->forceLogin(); } try { $orders = $this->client->requestOrderList(); $viewModel = $this->createViewModel(); $displayCols = $this->config['OrderListAdmin']['displayCols']; $viewModel->setVariables(compact('orders', 'displayCols')); $viewModel->setTemplate('fid/order/order-list-admin'); return $viewModel; } catch (UserNotAuthorizedException $exception) { $this->getMessenger() ->addErrorMessage('fid::read_order_list_not_allowed'); } catch (ClientException $exception) { $this->getMessenger()->addErrorMessage('fid::read_order_list_error'); $this->redirect()->toRoute('myresearch-profile'); } } /** * Add back url to view model. * Get back url from query parameter or request header. * * @param ViewModel $viewModel View model * * @return bool */ protected function setBackUrl(ViewModel $viewModel): bool { if (!empty($query = $this->getRequest()->getQuery()) && !empty($query->get('backUrl')) ) { $viewModel->setVariable( 'backUrl', $this->getRequest()->getQuery()->get('backUrl') ); return true; } if (isset($_REQUEST['lbreferer'])) { $viewModel->setVariable('backUrl', $_REQUEST['lbreferer']); return true; } return false; } /** * Request download of user list route action * * @return HttpResponse * @throws ClientException * @throws UserNotAuthorizedException */ public function exportListAction() { $userList = $this->client->requestUserList(); $fields = $this->config['Admin']['export_fields'] ?? null; if (empty($fields)) { $fields = current($userList)->getFieldList(); } return $this->createExportFile( $userList, $fields ); } /** * Build user list export file * * @param User[] $userList User List * @param string[] $fields Fields to render * * @return HttpResponse */ protected function createExportFile($userList, $fields=null) { $response = new HttpResponse(); $prefix = $this->config['Admin']['user_list_export_file_prefix'] ?? 'export'; $response->getHeaders()->addHeaders( [ 'Content-type' => 'text/plain', 'Content-Disposition' => 'attachment; filename="' . $prefix . '_' . date('Ymd_His') . '.txt"' ] ); $output = implode("\t", $fields) . "\n"; /* @var User $user */ foreach ($userList as $user) { $output .= $user->export($fields) . "\n"; } $response->setContent($output); return $response; } /** * Helper method for appling job title options on job title form element * * @param Form $form Formular * * @return void */ protected function applyJobTitleOptions($form) { if ($jobTitleOptions = $this->config['Forms']['jobTitleOptions'] ?? null) { $options = []; foreach (explode(',', $jobTitleOptions) as $jobTitleOption) { $options[] = [ 'value' => $jobTitleOption, 'label' => 'job_title_' . $jobTitleOption, ]; } $jobTitleElement = $form->get('job_title'); $jobTitleElement->setValueOptions($options); } } /** * Edit single order route action * * @return mixed|Response|ViewModel * @throws \Exception */ public function editOrderAction() { if (!$this->getUser()) { return $this->forceLogin(); } /* @var Request $request */ $request = $this->getRequest(); $orderId = $this->params()->fromRoute('orderid'); if (empty($orderId)) { // if no order ID is set the call is not valid return $this->redirect()->toRoute('fid/admin/orders'); } try { $this->permission()->check('fid.EditOrder', 'exception'); $order = $this->client->requestOrder($orderId); } catch (\Exception $ex) { $this->getMessenger() ->addErrorMessage($this->translate('fid::edit_order_error')); return $this->redirect()->toRoute('fid/admin/orders'); } $recordId = $order->getRecordId(); $driver = $recordId ? $this->getRecordLoader()->load($recordId) : null; /* @var Form $form */ /* @var Select $statusElement */ $form = $this->config[$order->getType() . "Edit"]['form'] ? $this->serviceLocator->get( 'order-edit-form-' . $this->config[$order->getType() . "Edit"]['form'] ) : null; $this->applyStatusOptions($form, $order->getType()); if ($this->formWasSubmitted()) { $form->setData($request->getPost()); if ($form->isValid()) { return $this->updateOrder($form, $order); } } else { $form->setData($form->getHydrator()->extract($order)); } $action = $this->url()->fromRoute( 'fid/admin/editOrder', [ 'orderid' => $order->getId() ] ); $form->setAttribute('action', $action); $form->prepare(); $config = $this->config; $viewModel = $this->createViewModel(); $viewModel->setVariables(compact('config', 'form', 'order', 'driver')); $viewModel->setTemplate('fid/order/order-edit'); return $viewModel; } /** * Helper method for generating status options list and * applies it to update order status input element. * Display only options stored in configuration. * * @param Form $form Formular * @param string $type Acquisition type * * @return void */ protected function applyStatusOptions($form, $type) { if ($statusOptions = $this->config["{$type}Edit"]['statusOptions'] ?? null) { $options = []; foreach ($statusOptions as $statusOption) { $options[] = [ 'value' => $statusOption, 'label' => $this->translate('fid::status_' . $statusOption), ]; } $statusElement = $form->get('status'); $statusElement->setValueOptions($options); } } /** * Update order via fidis and redirect to order list * * @param Form $form Formular * @param Order $order Order object * * @return Response */ protected function updateOrder(Form $form, Order $order) { $data = $form->getData(); $messenger = $this->getMessenger(); try { $form->getHydrator()->hydrate($data, $order); $this->client->requestOrderUpdate($order); $message = $this->translate('fid::order_update_success'); $messenger->addSuccessMessage($message); } catch (\Exception $ex) { $message = $this->translate('fid::order_update_error'); $messenger->addErrorMessage($message); } return $this->redirect()->toRoute('fid/admin/orders'); } }