N°2060 [WIP] Initialisation of the portal application:

- Refactor of BrickCollection to store properties at the root level, hence having easier API
- Code cleanup (Coding conventions, PHPDoc)
- Extract ObjectController::HandleForm() into new "object_form_handler" service
- Migrate ObjectController and UserProfileBrickController to SF
- Remove route/action "Search hierarchy" from ObjectController as it was never implemented
This commit is contained in:
Molkobain
2019-07-04 15:14:46 +02:00
parent 1115cdd2ec
commit 260c15c6b6
24 changed files with 1356 additions and 1050 deletions

View File

@@ -0,0 +1,366 @@
<?php
/**
* Copyright (C) 2013-2019 Combodo SARL
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*
*
*/
namespace Combodo\iTop\Portal\Controller;
use Combodo\iTop\Portal\Helper\ObjectFormHandlerHelper;
use Exception;
use FileUploadException;
use IssueLog;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use utils;
use MetaModel;
use UserRights;
use Symfony\Component\HttpFoundation\Request;
use Combodo\iTop\Portal\Brick\UserProfileBrick;
use Combodo\iTop\Portal\Form\PreferencesFormManager;
use Combodo\iTop\Portal\Form\PasswordFormManager;
use Combodo\iTop\Renderer\Bootstrap\BsFormRenderer;
/**
* Class UserProfileBrickController
*
* @package Combodo\iTop\Portal\Controller
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @since 2.3.0
*/
class UserProfileBrickController extends BrickController
{
const ENUM_FORM_TYPE_PICTURE = 'picture';
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param $sBrickId
*
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \ArchivedObjectException
* @throws \Combodo\iTop\Portal\Brick\BrickNotFoundException
* @throws \CoreException
* @throws \OQLException
* @throws \Exception
*/
public function DisplayAction(Request $oRequest, $sBrickId)
{
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$oRequestManipulator = $this->get('request_manipulator');
/** @var \Combodo\iTop\Portal\Helper\ObjectFormHandlerHelper $ObjectFormHandler */
$ObjectFormHandler = $this->get('object_form_handler');
/** @var \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection */
$oBrickCollection = $this->get('brick_collection');
// If the brick id was not specified, we get the first one registered that is an instance of UserProfileBrick as default
if ($sBrickId === null)
{
/** @var \Combodo\iTop\Portal\Brick\PortalBrick $oTmpBrick */
foreach ($oBrickCollection->GetBricks() as $oTmpBrick)
{
if ($oTmpBrick instanceof UserProfileBrick)
{
$oBrick = $oTmpBrick;
}
}
// We make sure a UserProfileBrick was found
if (!isset($oBrick) || $oBrick === null)
{
$oBrick = new UserProfileBrick();
//throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'UserProfileBrick : Brick could not be loaded as there was no UserProfileBrick loaded in the application.');
}
}
else
{
$oBrick = $oBrickCollection->GetBrickById($sBrickId);
}
$aData = array();
// Setting form mode regarding the demo mode parameter
$bDemoMode = MetaModel::GetConfig()->Get('demo_mode');
$sFormMode = ($bDemoMode) ? ObjectFormHandlerHelper::ENUM_MODE_VIEW : ObjectFormHandlerHelper::ENUM_MODE_EDIT;
// If this is ajax call, we are just submitting preferences or password forms
if ($oRequest->isXmlHttpRequest())
{
$aCurrentValues = $oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW);
$sFormType = $aCurrentValues['form_type'];
if ($sFormType === PreferencesFormManager::FORM_TYPE)
{
$aData['form'] = $this->HandlePreferencesForm($oRequest, $sFormMode);
}
elseif ($sFormType === PasswordFormManager::FORM_TYPE)
{
$aData['form'] = $this->HandlePasswordForm($oRequest, $sFormMode);
}
elseif ($sFormType === static::ENUM_FORM_TYPE_PICTURE)
{
$aData['form'] = $this->HandlePictureForm($oRequest);
}
else
{
throw new Exception('Unknown form type.');
}
$oResponse = new JsonResponse($aData);
}
// Else, we are displaying page for first time
else
{
// Retrieving current contact
/** @var \DBObject $oCurContact */
$oCurContact = UserRights::GetContactObject();
$sCurContactClass = get_class($oCurContact);
$sCurContactId = $oCurContact->GetKey();
// Preparing forms
$aData['forms']['contact'] = $ObjectFormHandler->HandleForm($oRequest, $sFormMode, $sCurContactClass, $sCurContactId, $oBrick->GetForm());
$aData['forms']['preferences'] = $this->HandlePreferencesForm($oRequest, $sFormMode);
// - If user can change password, we display the form
$aData['forms']['password'] = (UserRights::CanChangePassword()) ? $this->HandlePasswordForm($oRequest, $sFormMode) : null;
$aData = $aData + array(
'oBrick' => $oBrick,
'sFormMode' => $sFormMode,
'bDemoMode' => $bDemoMode,
);
$oResponse = $this->render($oBrick->GetPageTemplatePath(), $aData);
}
return $oResponse;
}
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param string $sFormMode
*
* @return array
*
* @throws \Exception
*/
public function HandlePreferencesForm(Request $oRequest, $sFormMode)
{
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$oRequestManipulator = $this->get('request_manipulator');
/** @var \Combodo\iTop\Portal\Routing\UrlGenerator $oUrlGenerator */
$oUrlGenerator = $this->get('url_generator');
$aFormData = array();
// Handling form
$sOperation = $oRequestManipulator->ReadParam('operation', null);
// - Create
if ($sOperation === null)
{
// - Creating renderer
$oFormRenderer = new BsFormRenderer();
$oFormRenderer->SetEndpoint($_SERVER['REQUEST_URI']);
// - Creating manager
$oFormManager = new PreferencesFormManager();
$oFormManager->SetRenderer($oFormRenderer)
->Build();
// - Checking if we have to make the form read only
if ($sFormMode === ObjectFormHandlerHelper::ENUM_MODE_VIEW)
{
$oFormManager->GetForm()->MakeReadOnly();
}
}
// - Submit
else if ($sOperation === 'submit')
{
$sFormManagerClass = $oRequestManipulator->ReadParam('formmanager_class', null, FILTER_UNSAFE_RAW);
$sFormManagerData = $oRequestManipulator->ReadParam('formmanager_data', null, FILTER_UNSAFE_RAW);
if ($sFormManagerClass === null || $sFormManagerData === null)
{
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Parameters formmanager_class and formamanager_data must be defined.');
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Parameters formmanager_class and formmanager_data must be defined.');
}
// Rebuilding manager from json
$oFormManager = $sFormManagerClass::FromJSON($sFormManagerData);
// Applying modification to object
$aFormData['validation'] = $oFormManager->OnSubmit(array('currentValues' => $oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW)));
// Reloading page only if preferences were changed
if (($aFormData['validation']['valid'] === true) && !empty($aFormData['validation']['messages']['success']))
{
$aFormData['validation']['redirection'] = array(
'url' => $oUrlGenerator->generate('p_user_profile_brick'),
);
}
}
// Else, submit from another form
// Preparing field_set data
$aFieldSetData = array(
'fields_list' => $oFormManager->GetRenderer()->Render(),
'fields_impacts' => $oFormManager->GetForm()->GetFieldsImpacts(),
'form_path' => $oFormManager->GetForm()->GetId(),
);
// Preparing form data
$aFormData['id'] = $oFormManager->GetForm()->GetId();
$aFormData['formmanager_class'] = $oFormManager->GetClass();
$aFormData['formmanager_data'] = $oFormManager->ToJSON();
$aFormData['renderer'] = $oFormManager->GetRenderer();
$aFormData['fieldset'] = $aFieldSetData;
return $aFormData;
}
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param string $sFormMode
*
* @return array
*
* @throws \Exception
*/
public function HandlePasswordForm(Request $oRequest, $sFormMode)
{
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$oRequestManipulator = $this->get('request_manipulator');
$aFormData = array();
// Handling form
$sOperation = /** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$oRequestManipulator->ReadParam('operation', null);
// - Create
if ($sOperation === null)
{
// - Creating renderer
$oFormRenderer = new BsFormRenderer();
$oFormRenderer->SetEndpoint($_SERVER['REQUEST_URI']);
// - Creating manager
$oFormManager = new PasswordFormManager();
$oFormManager->SetRenderer($oFormRenderer)
->Build();
// - Checking if we have to make the form read only
if ($sFormMode === ObjectFormHandlerHelper::ENUM_MODE_VIEW)
{
$oFormManager->GetForm()->MakeReadOnly();
}
}
// - Submit
else if ($sOperation === 'submit')
{
$sFormManagerClass = $oRequestManipulator->ReadParam('formmanager_class', null, FILTER_UNSAFE_RAW);
$sFormManagerData = $oRequestManipulator->ReadParam('formmanager_data', null, FILTER_UNSAFE_RAW);
if ($sFormManagerClass === null || $sFormManagerData === null)
{
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Parameters formmanager_class and formamanager_data must be defined.');
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Parameters formmanager_class and formmanager_data must be defined.');
}
// Rebuilding manager from json
$oFormManager = $sFormManagerClass::FromJSON($sFormManagerData);
// Applying modification to object
$aFormData['validation'] = $oFormManager->OnSubmit(array('currentValues' => $oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW)));
}
// Else, submit from another form
// Preparing field_set data
$aFieldSetData = array(
'fields_list' => $oFormManager->GetRenderer()->Render(),
'fields_impacts' => $oFormManager->GetForm()->GetFieldsImpacts(),
'form_path' => $oFormManager->GetForm()->GetId(),
);
// Preparing form data
$aFormData['id'] = $oFormManager->GetForm()->GetId();
$aFormData['formmanager_class'] = $oFormManager->GetClass();
$aFormData['formmanager_data'] = $oFormManager->ToJSON();
$aFormData['renderer'] = $oFormManager->GetRenderer();
$aFormData['fieldset'] = $aFieldSetData;
return $aFormData;
}
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
*
* @return array
*
* @throws \Exception
*/
public function HandlePictureForm(Request $oRequest)
{
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$oRequestManipulator = $this->get('request_manipulator');
$aFormData = array();
$sPictureAttCode = 'picture';
// Handling form
$sOperation = $oRequestManipulator->ReadParam('operation', null);
// - No operation specified
if ($sOperation === null)
{
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Operation parameter must be specified.');
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Operation parameter must be specified.');
}
// - Submit
else if ($sOperation === 'submit')
{
$oRequestFiles = $oRequest->files;
$oPictureFile = $oRequestFiles->get($sPictureAttCode);
if ($oPictureFile === null)
{
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Parameter picture must be defined.');
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Parameter picture must be defined.');
}
try
{
// Retrieving image as an ORMDocument
$oImage = utils::ReadPostedDocument($sPictureAttCode);
// Retrieving current contact
/** @var \DBObject $oCurContact */
$oCurContact = UserRights::GetContactObject();
// Resizing image
$oAttDef = MetaModel::GetAttributeDef(get_class($oCurContact), $sPictureAttCode);
$aSize = utils::GetImageSize($oImage->GetData());
$oImage = utils::ResizeImageToFit($oImage, $aSize[0], $aSize[1], $oAttDef->Get('storage_max_width'), $oAttDef->Get('storage_max_height'));
// Setting it to the contact
$oCurContact->Set($sPictureAttCode, $oImage);
// Forcing allowed writing on the object if necessary.
$oCurContact->AllowWrite(true);
$oCurContact->DBUpdate();
}
catch (FileUploadException $e)
{
$aFormData['error'] = $e->GetMessage();
}
$aFormData['picture_url'] = $oImage->GetDownloadURL(get_class($oCurContact), $oCurContact->GetKey(), $sPictureAttCode);
$aFormData['validation'] = array(
'valid' => true,
'messages' => array(),
);
}
// Else, submit from another form
return $aFormData;
}
}