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

@@ -1,49 +0,0 @@
<?php
// Copyright (C) 2010-2015 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
// along with iTop. If not, see <http://www.gnu.org/licenses/>
namespace Combodo\iTop\Portal\Provider;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Combodo\iTop\Portal\Helper\UrlGenerator;
/**
* Based on Symfony Routing component Provider for URL generation.
*
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
*/
class UrlGeneratorServiceProvider implements ServiceProviderInterface
{
public function register(Container $oApp)
{
$oApp['url_generator'] = function ($oApp)
{
$oApp->flush();
return new UrlGenerator($oApp['routes'], $oApp['request_context']);
};
}
public function boot(Container $oApp)
{
}
}

View File

@@ -27,21 +27,21 @@ use Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfig
// Note: ModuleDesign service is not available yet as this script is processed before service generation,
// that's why we have to instantiate it manually.
$moduleDesign = new \ModuleDesign(PORTAL_ID);
$oModuleDesign = new ModuleDesign(PORTAL_ID);
// TODO: The following code needs to be refactored to more independent and atomic services.
//append into %combodo.portal.instance.conf%
$basicCompat = new Basic($moduleDesign);
$basicCompat->process($container);
// Append into %combodo.portal.instance.conf%
$oBasicCompat = new Basic($oModuleDesign);
$oBasicCompat->Process($container);
//create %combodo.portal.instance.conf%
$formsCompat = new Forms($moduleDesign);
$formsCompat->process($container);
// Append into %combodo.portal.instance.conf%
$oFormsCompat = new Forms($oModuleDesign);
$oFormsCompat->Process($container);
//append into %combodo.portal.instance.conf%
$listesCompat = new Lists($moduleDesign);
$listesCompat->process($container);
// Append into %combodo.portal.instance.conf%
$oListsCompat = new Lists($oModuleDesign);
$oListsCompat->Process($container);
// - Generating CSS files
$aImportPaths = array(COMBODO_PORTAL_BASE_ABSOLUTE_PATH.'css/');
@@ -55,9 +55,9 @@ foreach ($aPortalConf['properties']['themes'] as $key => $value)
else
{
$aValues = array();
foreach ($value as $sSubvalue)
foreach ($value as $sSubValue)
{
$aValues[] = COMBODO_ABSOLUTE_URL.utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$sSubvalue, $aImportPaths);
$aValues[] = COMBODO_ABSOLUTE_URL.utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$sSubValue, $aImportPaths);
}
$aPortalConf['properties']['themes'][$key] = $aValues;
}

View File

@@ -17,11 +17,11 @@
p_home:
path: '/'
controller: 'Combodo\iTop\Portal\Controller\DefaultController::homeAction'
controller: 'Combodo\iTop\Portal\Controller\DefaultController::HomeAction'
# Example route
#p_example:
# path: /url-pattern
# controller: 'Combodo\iTop\Portal\Controller\DefaultController::exampleAction'
# controller: 'Combodo\iTop\Portal\Controller\DefaultController::ExampleAction'
# _defaults:
# _fragment: 'string-to-be-append-to-the-pattern-after-a-#'

View File

@@ -59,13 +59,6 @@ p_object_search_autocomplete:
sHostObjectClass: ~
sHostObjectId: ~
p_object_search_hierarchy:
path: '/object/search/hierarchy/{sTargetAttCode}/{sHostObjectClass}/{sHostObjectId}'
defaults:
_controller: 'Combodo\\iTop\\Portal\\Controller\\ObjectController::SearchHierarchyAction'
sHostObjectClass: ~
sHostObjectId: ~
p_object_search_generic:
path: '/object/search/{sMode}/{sTargetAttCode}/{sHostObjectClass}/{sHostObjectId}'

View File

@@ -126,6 +126,9 @@ services:
url_generator:
alias: router
public: true
object_form_handler:
alias: Combodo\iTop\Portal\Helper\ObjectFormHandlerHelper
public: true
browse_brick:
alias: Combodo\iTop\Portal\Helper\BrowseBrickHelper
public: true

View File

@@ -19,14 +19,10 @@
*
*/
/**
* Created by Bruno DA SILVA, working for Combodo
* Date: 24/01/19
* Time: 17:28
*/
namespace Combodo\iTop\Portal\Brick;
use DOMFormatException;
use Exception;
use UserRights;
use ModuleDesign;
use Combodo\iTop\Portal\Helper\ApplicationHelper;
@@ -35,111 +31,155 @@ use Combodo\iTop\Portal\Helper\ApplicationHelper;
* Class BrickCollection
*
* @package Combodo\iTop\Portal\Brick
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @since 2.7.0
*/
class BrickCollection
{
/** @var array|null Lazily computed */
private $aAllowedBricksData;
/** @var \ModuleDesign */
private $oModuleDesign;
/** @var \ModuleDesign */
private $oModuleDesign;
/** @var array|null $aAllowedBricks Lazily computed */
private $aAllowedBricks;
/** @var int $iDisplayedInHome Lazily computed */
private $iDisplayedInHome;
/** @var int $iDisplayedInNavigationMenu Lazily computed */
private $iDisplayedInNavigationMenu;
/** @var array $aHomeOrdering */
private $aHomeOrdering;
/** @var array $aNavigationMenuOrdering */
private $aNavigationMenuOrdering;
public function __construct(ModuleDesign $oModuleDesign)
/**
* BrickCollection constructor.
*
* @param \ModuleDesign $oModuleDesign
*
* @throws \Exception
*/
public function __construct(ModuleDesign $oModuleDesign)
{
$this->oModuleDesign = $oModuleDesign;
$this->aAllowedBricks = null;
$this->iDisplayedInHome = 0;
$this->iDisplayedInNavigationMenu = 0;
$this->aHomeOrdering = array();
$this->aNavigationMenuOrdering = array();
$this->Load();
}
public function __call($method, $arguments)
/**
* @param $method
* @param $arguments
*
* @return array|\Combodo\iTop\Portal\Brick\PortalBrick[]|null
* @throws \Combodo\iTop\Portal\Brick\PropertyNotFoundException
* @throws \Exception
*/
public function __call($method, $arguments)
{
return $this->GetBrickProperty($method);
// Made for cleaner/easier access from twig (eg. app['brick_collection'].bricks)
switch($method)
{
case 'bricks':
return $this->GetBricks();
break;
case 'home_ordering':
return $this->GetHomeOrdering();
break;
case 'navigation_menu_ordering':
return $this->GetNavigationMenuOrdering();
break;
default:
throw new PropertyNotFoundException("The property '$method' do not exists in BricksCollection");
}
}
/**
* @param string $sId
*
* @return mixed
* @throws PropertyNotFoundException
*/
private function GetBrickProperty($sId)
/**
* @return \Combodo\iTop\Portal\Brick\PortalBrick[]|null
* @throws \Exception
*/
public function GetBricks()
{
if (array_key_exists($sId, $this->getBricks())) {
return $this->getBricks()[$sId];
}
throw new PropertyNotFoundException(
"The property '$sId' do not exists in BricksCollection with keys: ".array_keys($this->getBricks())
);
return $this->aAllowedBricks;
}
public function getBricks()
{
if (! isset($this->aAllowedBricksData)) {
$this->LazyLoad();
}
public function GetHomeOrdering()
{
return $this->aHomeOrdering;
}
return $this->aAllowedBricksData;
}
public function GetNavigationMenuOrdering()
{
return $this->aNavigationMenuOrdering;
}
public function getBrickById($id)
/**
* @param string $sId
*
* @return \Combodo\iTop\Portal\Brick\PortalBrick
* @throws \Combodo\iTop\Portal\Brick\BrickNotFoundException
* @throws \Exception
*/
public function GetBrickById($sId)
{
foreach ($this->getBricks()['bricks'] as $brick) {
if ($brick->GetId() === $id)
foreach ($this->GetBricks() as $oBrick) {
if ($oBrick->GetId() === $sId)
{
return $brick;
return $oBrick;
}
}
throw new BrickNotFoundException('Brick with id = "'.$id.'" was not found among loaded bricks.');
throw new BrickNotFoundException('Brick with id = "'.$sId.'" was not found among loaded bricks.');
}
private function LazyLoad()
/**
* @throws \Exception
*/
private function Load()
{
$aRawBrickList = $this->GetRawBrickList();
// TODO: Are bricks_* still used? Didn't find any references in files. Maybe they could be deprecated.
$this->aAllowedBricksData = array(
'bricks' => array(),
'bricks_total_width' => 0,
'bricks_home_count' => 0,
'bricks_navigation_menu_count' => 0
);
foreach ($aRawBrickList as $oBrick) {
ApplicationHelper::LoadBrickSecurity($oBrick);
if ($oBrick->GetActive() && $oBrick->IsGrantedForProfiles(UserRights::ListProfiles()))
{
$this->aAllowedBricksData['bricks'][] = $oBrick;
$this->aAllowedBricksData['bricks_total_width'] += $oBrick->GetWidth();
$this->aAllowedBricks[] = $oBrick;
if ($oBrick->GetVisibleHome())
{
$this->aAllowedBricksData['bricks_home_count']++;
$this->iDisplayedInHome++;
}
if ($oBrick->GetVisibleNavigationMenu())
{
$this->aAllowedBricksData['bricks_navigation_menu_count']++;
$this->iDisplayedInNavigationMenu++;
}
}
}
// - Sorting bricks by rank
$this->aAllowedBricksData['bricks_ordering'] = array();
// - Home
$this->aAllowedBricksData['bricks_ordering']['home'] = $this->aAllowedBricksData['bricks'];
usort($this->aAllowedBricksData['bricks_ordering']['home'], function (PortalBrick $a, PortalBrick $b) {
$this->aHomeOrdering = $this->aAllowedBricks;
usort($this->aHomeOrdering, function (PortalBrick $a, PortalBrick $b) {
return $a->GetRankHome() > $b->GetRankHome();
});
// - Navigation menu
$this->aAllowedBricksData['bricks_ordering']['navigation_menu'] = $this->aAllowedBricksData['bricks'];
usort($this->aAllowedBricksData['bricks_ordering']['navigation_menu'], function (PortalBrick $a, PortalBrick $b) {
$this->aNavigationMenuOrdering = $this->aAllowedBricks;
usort($this->aNavigationMenuOrdering, function (PortalBrick $a, PortalBrick $b) {
return $a->GetRankNavigationMenu() > $b->GetRankNavigationMenu();
});
}
private function GetRawBrickList()
/**
* @return array
* @throws \Exception
*/
private function GetRawBrickList()
{
$aBricks = array();
foreach ($this->oModuleDesign->GetNodes('/module_design/bricks/brick') as $oBrickNode)
/** @var \Combodo\iTop\DesignElement $oBrickNode */
foreach ($this->oModuleDesign->GetNodes('/module_design/bricks/brick') as $oBrickNode)
{
$sBrickClass = $oBrickNode->getAttribute('xsi:type');
try

View File

@@ -1,21 +1,24 @@
<?php
// Copyright (C) 2010-2018 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
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* 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;

View File

@@ -37,19 +37,19 @@ use Symfony\Component\HttpFoundation\Response;
class DefaultController extends AbstractController
{
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param \Combodo\iTop\Portal\Brick\BrickCollection $bricksCollection
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param \Combodo\iTop\Portal\Brick\BrickCollection $oBricksCollection
*
* @return \Symfony\Component\HttpFoundation\Response
* @throws \Exception
*/
public function homeAction(Request $oRequest, BrickCollection $bricksCollection)
public function HomeAction(Request $oRequest, BrickCollection $oBricksCollection)
{
$aData = array();
// Rendering tiles
$aData['aTilesRendering'] = array();
/** @var \Combodo\iTop\Portal\Brick\PortalBrick $oBrick */
foreach($bricksCollection->getBricks()['bricks'] as $oBrick)
foreach($oBricksCollection->GetBricks() as $oBrick)
{
// Doing it only for tile visible on home page to avoid unnecessary rendering
if (($oBrick->GetVisibleHome() === true) && ($oBrick->GetTileControllerAction() !== null))
@@ -76,9 +76,9 @@ class DefaultController extends AbstractController
}
// Home page template
$template = $this->getParameter('combodo.portal.instance.conf')['properties']['templates']['home'];
$sTemplatePath = $this->getParameter('combodo.portal.instance.conf')['properties']['templates']['home'];
return $this->render($template, $aData);
return $this->render($sTemplatePath, $aData);
}
}

View File

@@ -1,33 +1,38 @@
<?php
// Copyright (C) 2010-2018 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
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* 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 Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Combodo\iTop\Portal\Helper\ApplicationHelper;
use Combodo\iTop\Portal\Brick\UserProfileBrick;
use Combodo\iTop\Portal\Form\PreferencesFormManager;
use Combodo\iTop\Portal\Form\PasswordFormManager;
@@ -44,27 +49,32 @@ class UserProfileBrickController extends BrickController
{
const ENUM_FORM_TYPE_PICTURE = 'picture';
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param \Silex\Application $oApp
* @param $sBrickId
*
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Exception
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \OQLException
* @throws \Twig_Error_Loader
* @throws \Twig_Error_Runtime
* @throws \Twig_Error_Syntax
*/
public function DisplayAction(Request $oRequest, Application $oApp, $sBrickId)
/**
* @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)
{
foreach ($oApp['combodo.portal.instance.conf']['bricks'] as $oTmpBrick)
/** @var \Combodo\iTop\Portal\Brick\PortalBrick $oTmpBrick */
foreach ($oBrickCollection->GetBricks() as $oTmpBrick)
{
if ($oTmpBrick instanceof UserProfileBrick)
{
@@ -76,84 +86,89 @@ class UserProfileBrickController extends BrickController
if (!isset($oBrick) || $oBrick === null)
{
$oBrick = new UserProfileBrick();
//$oApp->abort(500, 'UserProfileBrick : Brick could not be loaded as there was no UserProfileBrick loaded in the application.');
//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 = ApplicationHelper::GetLoadedBrickFromId($oApp, $sBrickId);
$oBrick = $oBrickCollection->GetBrickById($sBrickId);
}
$aData = array();
// Setting form mode regarding the demo mode parameter
$bDemoMode = MetaModel::GetConfig()->Get('demo_mode');
$sFormMode = ($bDemoMode) ? ObjectController::ENUM_MODE_VIEW : ObjectController::ENUM_MODE_EDIT;
$sFormMode = ($bDemoMode) ? ObjectFormHandlerHelper::ENUM_MODE_VIEW : ObjectFormHandlerHelper::ENUM_MODE_EDIT;
// If this is ajax call, we are just submiting preferences or password forms
// If this is ajax call, we are just submitting preferences or password forms
if ($oRequest->isXmlHttpRequest())
{
$aCurrentValues = $oApp['request_manipulator']->ReadParam('current_values', array(), FILTER_UNSAFE_RAW);
$aCurrentValues = $oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW);
$sFormType = $aCurrentValues['form_type'];
if ($sFormType === PreferencesFormManager::FORM_TYPE)
{
$aData['form'] = $this->HandlePreferencesForm($oRequest, $oApp, $sFormMode);
$aData['form'] = $this->HandlePreferencesForm($oRequest, $sFormMode);
}
elseif ($sFormType === PasswordFormManager::FORM_TYPE)
{
$aData['form'] = $this->HandlePasswordForm($oRequest, $oApp, $sFormMode);
$aData['form'] = $this->HandlePasswordForm($oRequest, $sFormMode);
}
elseif ($sFormType === static::ENUM_FORM_TYPE_PICTURE)
{
$aData['form'] = $this->HandlePictureForm($oRequest, $oApp);
$aData['form'] = $this->HandlePictureForm($oRequest);
}
else
{
throw new Exception('Unknown form type.');
}
$oResponse = $oApp->json($aData);
$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'] = ObjectController::HandleForm($oRequest, $oApp, $sFormMode, $sCurContactClass, $sCurContactId, $oBrick->GetForm());
$aData['forms']['preferences'] = $this->HandlePreferencesForm($oRequest, $oApp, $sFormMode);
$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, $oApp, $sFormMode) : null;
$aData['forms']['password'] = (UserRights::CanChangePassword()) ? $this->HandlePasswordForm($oRequest, $sFormMode) : null;
$aData = $aData + array(
'oBrick' => $oBrick,
'sFormMode' => $sFormMode,
'bDemoMode' => $bDemoMode
'bDemoMode' => $bDemoMode,
);
$oResponse = $oApp['twig']->render($oBrick->GetPageTemplatePath(), $aData);
$oResponse = $this->render($oBrick->GetPageTemplatePath(), $aData);
}
return $oResponse;
}
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param \Silex\Application $oApp
* @param string $sFormMode
*
* @return array
*
* @throws \Exception
*/
public function HandlePreferencesForm(Request $oRequest, Application $oApp, $sFormMode)
/**
* @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 = $oApp['request_manipulator']->ReadParam('operation', null);
$sOperation = $oRequestManipulator->ReadParam('operation', null);
// - Create
if ($sOperation === null)
{
@@ -165,7 +180,7 @@ class UserProfileBrickController extends BrickController
$oFormManager->SetRenderer($oFormRenderer)
->Build();
// - Checking if we have to make the form read only
if ($sFormMode === ObjectController::ENUM_MODE_VIEW)
if ($sFormMode === ObjectFormHandlerHelper::ENUM_MODE_VIEW)
{
$oFormManager->GetForm()->MakeReadOnly();
}
@@ -173,23 +188,23 @@ class UserProfileBrickController extends BrickController
// - Submit
else if ($sOperation === 'submit')
{
$sFormManagerClass = $oApp['request_manipulator']->ReadParam('formmanager_class', null, FILTER_UNSAFE_RAW);
$sFormManagerData = $oApp['request_manipulator']->ReadParam('formmanager_data', null, FILTER_UNSAFE_RAW);
$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.');
$oApp->abort(500, 'Parameters formmanager_class and formmanager_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' => $oApp['request_manipulator']->ReadParam('current_values', array(), FILTER_UNSAFE_RAW)));
$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' => $oApp['url_generator']->generate('p_user_profile_brick'),
'url' => $oUrlGenerator->generate('p_user_profile_brick'),
);
}
}
@@ -199,7 +214,7 @@ class UserProfileBrickController extends BrickController
$aFieldSetData = array(
'fields_list' => $oFormManager->GetRenderer()->Render(),
'fields_impacts' => $oFormManager->GetForm()->GetFieldsImpacts(),
'form_path' => $oFormManager->GetForm()->GetId()
'form_path' => $oFormManager->GetForm()->GetId(),
);
// Preparing form data
@@ -212,21 +227,24 @@ class UserProfileBrickController extends BrickController
return $aFormData;
}
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param \Silex\Application $oApp
* @param string $sFormMode
*
* @return array
*
* @throws \Exception
*/
public function HandlePasswordForm(Request $oRequest, Application $oApp, $sFormMode)
/**
* @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 = $oApp['request_manipulator']->ReadParam('operation', null);
$sOperation = /** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$oRequestManipulator->ReadParam('operation', null);
// - Create
if ($sOperation === null)
{
@@ -238,7 +256,7 @@ class UserProfileBrickController extends BrickController
$oFormManager->SetRenderer($oFormRenderer)
->Build();
// - Checking if we have to make the form read only
if ($sFormMode === ObjectController::ENUM_MODE_VIEW)
if ($sFormMode === ObjectFormHandlerHelper::ENUM_MODE_VIEW)
{
$oFormManager->GetForm()->MakeReadOnly();
}
@@ -246,18 +264,18 @@ class UserProfileBrickController extends BrickController
// - Submit
else if ($sOperation === 'submit')
{
$sFormManagerClass = $oApp['request_manipulator']->ReadParam('formmanager_class', null, FILTER_UNSAFE_RAW);
$sFormManagerData = $oApp['request_manipulator']->ReadParam('formmanager_data', null, FILTER_UNSAFE_RAW);
$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.');
$oApp->abort(500, 'Parameters formmanager_class and formmanager_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' => $oApp['request_manipulator']->ReadParam('current_values', array(), FILTER_UNSAFE_RAW)));
$aFormData['validation'] = $oFormManager->OnSubmit(array('currentValues' => $oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW)));
}
// Else, submit from another form
@@ -265,7 +283,7 @@ class UserProfileBrickController extends BrickController
$aFieldSetData = array(
'fields_list' => $oFormManager->GetRenderer()->Render(),
'fields_impacts' => $oFormManager->GetForm()->GetFieldsImpacts(),
'form_path' => $oFormManager->GetForm()->GetId()
'form_path' => $oFormManager->GetForm()->GetId(),
);
// Preparing form data
@@ -278,26 +296,28 @@ class UserProfileBrickController extends BrickController
return $aFormData;
}
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param \Silex\Application $oApp
*
* @return array
*
* @throws \Exception
*/
public function HandlePictureForm(Request $oRequest, Application $oApp)
/**
* @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 = $oApp['request_manipulator']->ReadParam('operation', null);
$sOperation = $oRequestManipulator->ReadParam('operation', null);
// - No operation specified
if ($sOperation === null)
{
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Operation parameter must be specified.');
$oApp->abort(500, 'Operation parameter must be specified.');
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Operation parameter must be specified.');
}
// - Submit
else if ($sOperation === 'submit')
@@ -307,14 +327,15 @@ class UserProfileBrickController extends BrickController
if ($oPictureFile === null)
{
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Parameter picture must be defined.');
$oApp->abort(500, '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);
@@ -334,7 +355,7 @@ class UserProfileBrickController extends BrickController
$aFormData['picture_url'] = $oImage->GetDownloadURL(get_class($oCurContact), $oCurContact->GetKey(), $sPictureAttCode);
$aFormData['validation'] = array(
'valid' => true,
'messages' => array()
'messages' => array(),
);
}
// Else, submit from another form

View File

@@ -1,31 +1,57 @@
<?php
/**
* Created by Bruno DA SILVA, working for Combodo
* Date: 24/01/19
* Time: 16:59
* 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\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration;
use ModuleDesign;
/**
* Class AbstractConfiguration
*
* @package Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @since 2.7.0
*/
class AbstractConfiguration
{
/**
* @var \ModuleDesign
*/
private $moduleDesign;
/** @var \ModuleDesign $oModuleDesign */
private $oModuleDesign;
public function __construct(\ModuleDesign $moduleDesign)
/**
* AbstractConfiguration constructor.
*
* @param \ModuleDesign $oModuleDesign
*/
public function __construct(ModuleDesign $oModuleDesign)
{
$this->moduleDesign = $moduleDesign;
$this->oModuleDesign = $oModuleDesign;
}
/**
* @return \ModuleDesign
*/
public function getModuleDesign()
public function GetModuleDesign()
{
return $this->moduleDesign;
return $this->oModuleDesign;
}
}

View File

@@ -19,15 +19,10 @@
*
*/
/**
* Created by Bruno DA SILVA, working for Combodo
* Date: 24/01/19
* Time: 15:55
*/
namespace Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration;
use Combodo\iTop\DesignElement;
use iPortalUIExtension;
use Symfony\Component\DependencyInjection\Container;
use Exception;
use utils;
@@ -35,39 +30,51 @@ use UserRights;
use MetaModel;
use DOMFormatException;
/**
* Class Basic
*
* @package Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @since 2.7.0
*/
class Basic extends AbstractConfiguration
{
public function process(Container $container)
/**
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @throws \Exception
*/
public function Process(Container $oContainer)
{
try
{
// Parsing file
// - Default values
$aPortalConf = $this->getInitialPortalConf();
$aPortalConf = $this->GetInitialPortalConf();
// - Global portal properties
$aPortalConf = $this->ParseGlobalProperties($aPortalConf);
// - Rectifying portal logo url
$aPortalConf = $this->appendLogoUri($aPortalConf);
$aPortalConf = $this->AppendLogoUri($aPortalConf);
// - User allowed portals
$aPortalConf['portals'] = UserRights::GetAllowedPortals();
// - class list
$aPortalConf['ui_extensions'] = $this->getUiExtensions($container);
$aPortalConf['ui_extensions'] = $this->GetUiExtensions($oContainer);
}
catch (Exception $e)
catch (Exception $oException)
{
throw new Exception('Error while parsing portal configuration file : '.$e->getMessage());
throw new Exception('Error while parsing portal configuration file : '.$oException->getMessage());
}
$container->setParameter('combodo.portal.instance.conf', $aPortalConf);
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
}
/**
* Returns an array containing the initial portal configuration with all default values
*
* @return array
*/
private function getInitialPortalConf()
private function GetInitialPortalConf()
{
$aPortalConf = array(
'properties' => array(
@@ -81,12 +88,12 @@ class Basic extends AbstractConfiguration
),
'templates' => array(
'layout' => 'itop-portal-base/portal/templates/layout.html.twig',
'home' => 'itop-portal-base/portal/templates/home/layout.html.twig'
'home' => 'itop-portal-base/portal/templates/home/layout.html.twig',
),
'urlmaker_class' => null,
'triggers_query' => null,
'attachments' => array(
'allow_delete' => true
'allow_delete' => true,
),
'allowed_portals' => array(
'opening_mode' => null,
@@ -108,16 +115,19 @@ class Basic extends AbstractConfiguration
return $aPortalConf;
}
/**
* @param ModuleDesign $oDesign
* @param array $aPortalConf
*
* @return array
*/
/**
* @param array $aPortalConf
*
* @return array
* @throws \DOMFormatException
*/
private function ParseGlobalProperties(array $aPortalConf)
{
foreach ($this->getModuleDesign()->GetNodes('/module_design/properties/*') as $oPropertyNode) {
switch ($oPropertyNode->nodeName) {
/** @var \MFElement $oPropertyNode */
foreach ($this->GetModuleDesign()->GetNodes('/module_design/properties/*') as $oPropertyNode)
{
switch ($oPropertyNode->nodeName)
{
case 'name':
case 'urlmaker_class':
case 'triggers_query':
@@ -146,26 +156,32 @@ class Basic extends AbstractConfiguration
return $aPortalConf;
}
/**
* @param array $aPortalConf
* @param $oPropertyNode
*
* @return array
*/
private function ParseTemplateAndTheme(array $aPortalConf, $oPropertyNode)
/**
* @param array $aPortalConf
* @param \Combodo\iTop\DesignElement $oPropertyNode
*
* @return array
* @throws \DOMFormatException
*/
private function ParseTemplateAndTheme(array $aPortalConf, DesignElement $oPropertyNode)
{
foreach ($oPropertyNode->GetNodes('template|theme') as $oSubNode) {
if (!$oSubNode->hasAttribute('id') || $oSubNode->GetText(null) === null) {
/** @var \MFElement $oSubNode */
foreach ($oPropertyNode->GetNodes('template|theme') as $oSubNode)
{
if (!$oSubNode->hasAttribute('id') || $oSubNode->GetText(null) === null)
{
throw new DOMFormatException(
'Tag '.$oSubNode->nodeName.' must have a "id" attribute as well as a value',
'Tag ' . $oSubNode->nodeName.' must have a "id" attribute as well as a value',
null, null, $oSubNode
);
}
$sNodeId = $oSubNode->getAttribute('id');
switch ($oSubNode->nodeName) {
switch ($oSubNode->nodeName)
{
case 'theme':
switch ($sNodeId) {
switch ($sNodeId)
{
case 'bootstrap':
case 'portal':
case 'custom':
@@ -177,7 +193,8 @@ class Basic extends AbstractConfiguration
}
break;
case 'template':
switch ($sNodeId) {
switch ($sNodeId)
{
case 'layout':
case 'home':
$aPortalConf['properties']['templates'][$sNodeId] = $oSubNode->GetText(null);
@@ -194,23 +211,27 @@ class Basic extends AbstractConfiguration
}
return $aPortalConf;
}
}
/**
* @param array $aPortalConf
* @param $oPropertyNode
*
* @return array
*/
private function ParseAttachments(array $aPortalConf, $oPropertyNode)
/**
* @param array $aPortalConf
* @param \Combodo\iTop\DesignElement $oPropertyNode
*
* @return array
*/
private function ParseAttachments(array $aPortalConf, DesignElement $oPropertyNode)
{
foreach ($oPropertyNode->GetNodes('*') as $oSubNode) {
switch ($oSubNode->nodeName) {
/** @var \MFElement $oSubNode */
foreach ($oPropertyNode->GetNodes('*') as $oSubNode)
{
switch ($oSubNode->nodeName)
{
case 'allow_delete':
$sValue = $oSubNode->GetText();
// If the text is null, we keep the default value
// Else we set it
if ($sValue !== null) {
if ($sValue !== null)
{
$aPortalConf['properties']['attachments'][$oSubNode->nodeName] = ($sValue === 'true') ? true : false;
}
break;
@@ -218,23 +239,27 @@ class Basic extends AbstractConfiguration
}
return$aPortalConf;
}
}
/**
* @param array $aPortalConf
* @param $oPropertyNode
*
* @return array
*/
private function ParseAllowedPortals(array $aPortalConf, $oPropertyNode)
/**
* @param array $aPortalConf
* @param \Combodo\iTop\DesignElement $oPropertyNode
*
* @return array
*/
private function ParseAllowedPortals(array $aPortalConf, DesignElement $oPropertyNode)
{
foreach ($oPropertyNode->GetNodes('*') as $oSubNode) {
switch ($oSubNode->nodeName) {
/** @var \MFElement $oSubNode */
foreach ($oPropertyNode->GetNodes('*') as $oSubNode)
{
switch ($oSubNode->nodeName)
{
case 'opening_mode':
$sValue = $oSubNode->GetText();
// If the text is null, we keep the default value
// Else we set it
if ($sValue !== null) {
if ($sValue !== null)
{
$aPortalConf['properties']['allowed_portals'][$oSubNode->nodeName] = ($sValue === 'self') ? 'self' : 'tab';
}
break;
@@ -242,17 +267,19 @@ class Basic extends AbstractConfiguration
}
return $aPortalConf;
}
}
/**
* @param array $aPortalConf
*
* @return array
*/
private function appendLogoUri(array $aPortalConf)
/**
* @param array $aPortalConf
*
* @return array
* @throws \Exception
*/
private function AppendLogoUri(array $aPortalConf)
{
$sLogoUri = $aPortalConf['properties']['logo'];
if (!preg_match('/^http/', $sLogoUri)) {
if (!preg_match('/^http/', $sLogoUri))
{
// We prefix it with the server base url
$sLogoUri = utils::GetAbsoluteUrlAppRoot().'env-'.utils::GetCurrentEnvironment().'/'.$sLogoUri;
}
@@ -261,7 +288,13 @@ class Basic extends AbstractConfiguration
return $aPortalConf;
}
private function getUiExtensions($container)
/**
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @return array
* @throws \Exception
*/
private function GetUiExtensions(Container $oContainer)
{
$aUIExtensions = array(
'css_files' => array(),
@@ -271,22 +304,22 @@ class Basic extends AbstractConfiguration
'html' => array(),
);
$aUIExtensionHooks = array(
\iPortalUIExtension::ENUM_PORTAL_EXT_UI_BODY,
\iPortalUIExtension::ENUM_PORTAL_EXT_UI_NAVIGATION_MENU,
\iPortalUIExtension::ENUM_PORTAL_EXT_UI_MAIN_CONTENT,
iPortalUIExtension::ENUM_PORTAL_EXT_UI_BODY,
iPortalUIExtension::ENUM_PORTAL_EXT_UI_NAVIGATION_MENU,
iPortalUIExtension::ENUM_PORTAL_EXT_UI_MAIN_CONTENT,
);
/** @var iPortalUIExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iPortalUIExtension') as $oExtensionInstance)
{
// Adding CSS files
$aImportPaths = array($container->getParameter('combodo.portal.base.absolute_path').'css/');
foreach($oExtensionInstance->GetCSSFiles($container) as $sCSSFile)
$aImportPaths = array($oContainer->getParameter('combodo.portal.base.absolute_path').'css/');
foreach($oExtensionInstance->GetCSSFiles($oContainer) as $sCSSFile)
{
// Removing app root url as we need to pass a path on the file system (relative to app root)
$sCSSFilePath = str_replace(utils::GetAbsoluteUrlAppRoot(), '', $sCSSFile);
// Compiling SCSS file
$sCSSFileCompiled = $container->getParameter('combodo.absolute_url').utils::GetCSSFromSASS($sCSSFilePath,
$sCSSFileCompiled = $oContainer->getParameter('combodo.absolute_url').utils::GetCSSFromSASS($sCSSFilePath,
$aImportPaths);
if(!in_array($sCSSFileCompiled, $aUIExtensions['css_files']))
@@ -296,7 +329,7 @@ class Basic extends AbstractConfiguration
}
// Adding CSS inline
$sCSSInline = $oExtensionInstance->GetCSSInline($container);
$sCSSInline = $oExtensionInstance->GetCSSInline($oContainer);
if ($sCSSInline !== null)
{
$aUIExtensions['css_inline'] .= "\n\n".$sCSSInline;
@@ -304,10 +337,10 @@ class Basic extends AbstractConfiguration
// Adding JS files
$aUIExtensions['js_files'] = array_merge($aUIExtensions['js_files'],
$oExtensionInstance->GetJSFiles($container));
$oExtensionInstance->GetJSFiles($oContainer));
// Adding JS inline
$sJSInline = $oExtensionInstance->GetJSInline($container);
$sJSInline = $oExtensionInstance->GetJSInline($oContainer);
if ($sJSInline !== null)
{
// Note: Semi-colon is to prevent previous script that would have omitted it.
@@ -318,7 +351,7 @@ class Basic extends AbstractConfiguration
foreach ($aUIExtensionHooks as $sUIExtensionHook)
{
$sFunctionName = 'Get'.$sUIExtensionHook.'HTML';
$sHTML = $oExtensionInstance->$sFunctionName($container);
$sHTML = $oExtensionInstance->$sFunctionName($oContainer);
if ($sHTML !== null)
{
if (!array_key_exists($sUIExtensionHook, $aUIExtensions['html']))

View File

@@ -19,28 +19,34 @@
*
*/
/**
* Created by Bruno DA SILVA, working for Combodo
* Date: 24/01/19
* Time: 16:52
*/
namespace Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Container;
use DOMFormatException;
use Exception;
use utils;
use Combodo\iTop\Portal\Helper\ApplicationHelper;
use MetaModel;
/**
* Class Forms
*
* @package Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @since 2.7.0
*/
class Forms extends AbstractConfiguration
{
public function process(ContainerBuilder $container)
/**
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @throws \Exception
*/
public function Process(Container $oContainer)
{
$aForms = array();
foreach ($this->getModuleDesign()->GetNodes('/module_design/forms/form') as $oFormNode)
/** @var \MFElement $oFormNode */
foreach ($this->GetModuleDesign()->GetNodes('/module_design/forms/form') as $oFormNode)
{
try
{
@@ -63,7 +69,8 @@ class Forms extends AbstractConfiguration
);
if ($oFormNode->GetOptionalElement('properties') !== null)
{
foreach ($oFormNode->GetOptionalElement('properties')->childNodes as $oPropertyNode)
/** @var \MFElement $oPropertyNode */
foreach ($oFormNode->GetOptionalElement('properties')->childNodes as $oPropertyNode)
{
switch ($oPropertyNode->nodeName)
{
@@ -77,12 +84,13 @@ class Forms extends AbstractConfiguration
}
}
// Parsing availables modes for that form (view, edit, create, apply_stimulus)
// Parsing available modes for that form (view, edit, create, apply_stimulus)
$aFormStimuli = array();
if (($oFormNode->GetOptionalElement('modes') !== null) && ($oFormNode->GetOptionalElement('modes')->GetNodes('mode')->length > 0))
{
$aModes = array();
foreach ($oFormNode->GetOptionalElement('modes')->GetNodes('mode') as $oModeNode)
/** @var \MFElement $oModeNode */
foreach ($oFormNode->GetOptionalElement('modes')->GetNodes('mode') as $oModeNode)
{
if ($oModeNode->getAttribute('id') !== '')
{
@@ -101,7 +109,8 @@ class Forms extends AbstractConfiguration
// if stimuli are defined, we overwrite the form that could have been set by the generic form
if ($oStimuliNode !== null)
{
foreach ($oStimuliNode->GetNodes('stimulus') as $oStimulusNode)
/** @var \MFElement $oStimulusNode */
foreach ($oStimuliNode->GetNodes('stimulus') as $oStimulusNode)
{
$sStimulusCode = $oStimulusNode->getAttribute('id');
@@ -130,7 +139,7 @@ class Forms extends AbstractConfiguration
'type' => null,
'properties' => $aFormProperties,
'fields' => null,
'layout' => null
'layout' => null,
);
// ... either enumerated fields ...
if ($oFormNode->GetOptionalElement('fields') !== null)
@@ -138,7 +147,8 @@ class Forms extends AbstractConfiguration
$aFields['type'] = 'custom_list';
$aFields['fields'] = array();
foreach ($oFormNode->GetOptionalElement('fields')->GetNodes('field') as $oFieldNode)
/** @var \MFElement $oFieldNode */
foreach ($oFormNode->GetOptionalElement('fields')->GetNodes('field') as $oFieldNode)
{
$sFieldId = $oFieldNode->getAttribute('id');
if ($sFieldId !== '')
@@ -178,13 +188,13 @@ class Forms extends AbstractConfiguration
if ($oFormNode->GetOptionalElement('twig') !== null)
{
// Extracting the twig template and removing the first and last lines (twig tags)
$sXml = $this->getModuleDesign()->saveXML($oFormNode->GetOptionalElement('twig'));
$sXml = $this->GetModuleDesign()->saveXML($oFormNode->GetOptionalElement('twig'));
$sXml = preg_replace('/^.+\n/', '', $sXml);
$sXml = preg_replace('/\n.+$/', '', $sXml);
$aFields['layout'] = array(
'type' => (preg_match('/\{\{|\{\#|\{\%/', $sXml) === 1) ? 'twig' : 'xhtml',
'content' => $sXml
'content' => $sXml,
);
}
@@ -242,30 +252,28 @@ class Forms extends AbstractConfiguration
}
else
{
throw new \DOMFormatException('There is already a form for the class "'.$sFormClass.'" in "'.$sMode.'"',
throw new DOMFormatException('There is already a form for the class "'.$sFormClass.'" in "'.$sMode.'"',
null, null, $oFormNode);
}
}
}
else
{
throw new \DOMFormatException('Class tag must be defined', null, null, $oFormNode);
throw new DOMFormatException('Class tag must be defined', null, null, $oFormNode);
}
}
catch (\DOMFormatException $e)
catch (DOMFormatException $e)
{
throw new \Exception('Could not create from [id="'.$oFormNode->getAttribute('id').'"] from XML because of a DOM problem : '.$e->getMessage());
throw new Exception('Could not create from [id="'.$oFormNode->getAttribute('id').'"] from XML because of a DOM problem : '.$e->getMessage());
}
catch (\Exception $e)
catch (Exception $e)
{
throw new \Exception('Could not create from from XML : '.$oFormNode->Dump().' '.$e->getMessage());
throw new Exception('Could not create from from XML : '.$oFormNode->Dump().' '.$e->getMessage());
}
}
$aPortalConf = $container->getParameter('combodo.portal.instance.conf');
$aPortalConf = $oContainer->getParameter('combodo.portal.instance.conf');
$aPortalConf['forms'] = $aForms;
$container->setParameter('combodo.portal.instance.conf', $aPortalConf);
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
}
}

View File

@@ -1,27 +1,52 @@
<?php
/**
* Created by Bruno DA SILVA, working for Combodo
* Date: 24/01/19
* Time: 16:52
* 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\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration;
use DOMFormatException;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Exception;
use utils;
/**
* Class Lists
*
* @package Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @since 2.7.0
*/
class Lists extends AbstractConfiguration
{
public function process(ContainerBuilder $container)
/**
* @param \Symfony\Component\DependencyInjection\Container $oContainer
*
* @throws \DOMFormatException
*/
public function Process(Container $oContainer)
{
$iDefaultItemRank = 0;
$aClassesLists = array();
// Parsing XML file
// - Each classes
foreach ($this->getModuleDesign()->GetNodes('/module_design/classes/class') as $oClassNode)
/** @var \MFElement $oClassNode */
foreach ($this->GetModuleDesign()->GetNodes('/module_design/classes/class') as $oClassNode)
{
$aClassLists = array();
$sClassId = $oClassNode->getAttribute('id');
@@ -31,7 +56,8 @@ class Lists extends AbstractConfiguration
}
// - Each lists
foreach ($oClassNode->GetNodes('./lists/list') as $oListNode)
/** @var \MFElement $oListNode */
foreach ($oClassNode->GetNodes('./lists/list') as $oListNode)
{
$aListItems = array();
$sListId = $oListNode->getAttribute('id');
@@ -42,7 +68,8 @@ class Lists extends AbstractConfiguration
}
// - Each items
foreach ($oListNode->GetNodes('./items/item') as $oItemNode)
/** @var \MFElement $oItemNode */
foreach ($oListNode->GetNodes('./items/item') as $oItemNode)
{
$sItemId = $oItemNode->getAttribute('id');
if ($sItemId === null)
@@ -53,7 +80,7 @@ class Lists extends AbstractConfiguration
$aItem = array(
'att_code' => $sItemId,
'rank' => $iDefaultItemRank
'rank' => $iDefaultItemRank,
);
$oRankNode = $oItemNode->GetOptionalElement('rank');
@@ -77,10 +104,9 @@ class Lists extends AbstractConfiguration
$aClassesLists[$sClassId] = $aClassLists;
}
}
$aPortalConf = $container->getParameter('combodo.portal.instance.conf');
$aPortalConf['lists'] = $aClassLists;
$container->setParameter('combodo.portal.instance.conf', $aPortalConf);
$aPortalConf = $oContainer->getParameter('combodo.portal.instance.conf');
$aPortalConf['lists'] = $aClassLists;
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
}
}

View File

@@ -1,21 +1,24 @@
<?php
// Copyright (C) 2010-2018 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
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* 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\Form;
@@ -45,10 +48,10 @@ use UserRights;
use utils;
/**
* Description of objectformmanager
* Description of ObjectFormManager
*
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @since iTop 2.3.0
* @since 2.3.0
*/
class ObjectFormManager extends FormManager
{
@@ -159,7 +162,7 @@ class ObjectFormManager extends FormManager
* @param \Silex\Application $oApp
* @return \Combodo\iTop\Portal\Form\ObjectFormManager
*/
public function SetApplication(Application $oApp)
public function SetApplication($oApp)
{
$this->oApp = $oApp;
return $this;

View File

@@ -1,21 +1,24 @@
<?php
// Copyright (C) 2010-2018 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
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* 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\Form;
@@ -29,9 +32,10 @@ use Combodo\iTop\Form\Field\HiddenField;
use Combodo\iTop\Form\Field\PasswordField;
/**
* Description of passwordformmanager
* Description of PasswordFormManager
*
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @since 2.3.0
*/
class PasswordFormManager extends FormManager
{

View File

@@ -1,21 +1,24 @@
<?php
// Copyright (C) 2010-2018 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
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* 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\Form;
@@ -30,9 +33,10 @@ use Combodo\iTop\Form\Field\HiddenField;
use Combodo\iTop\Form\Field\SelectField;
/**
* Description of preferencesformmanager
* Description of PreferencesFormManager
*
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @since 2.3.0
*/
class PreferencesFormManager extends FormManager
{
@@ -117,6 +121,7 @@ class PreferencesFormManager extends FormManager
$iFieldChanged = 0;
// Updating user
/** @var \cmdbAbstractObject $oCurUser */
$oCurUser = UserRights::GetUserObject();
// - Language
$sLanguage = $this->oForm->GetField('language')->GetCurrentValue();

View File

@@ -709,7 +709,7 @@ class ApplicationHelper
* @param string $sClass Object class to find a list for
* @param string $sList List name to find
*
* @return array Array of attribute codes
* @return string[] Array of attribute codes
*
* @throws \CoreException
*/

View File

@@ -412,7 +412,7 @@ class ContextManipulatorHelper
break;
case static::ENUM_RULE_CALLBACK_GOTO:
$oBrick = $this->oBrickCollection->getBrickById($aRule[$sCallbackName]['brick_id']);
$oBrick = $this->oBrickCollection->GetBrickById($aRule[$sCallbackName]['brick_id']);
$sCallbackUrl = $this->oRouter->generate($oBrick->GetRouteName(), array('sBrickId' => $oBrick->GetId()));
break;

View File

@@ -0,0 +1,358 @@
<?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\Helper;
use Combodo\iTop\Portal\Form\ObjectFormManager;
use Combodo\iTop\Portal\Routing\UrlGenerator;
use Combodo\iTop\Portal\VariableAccessor\CombodoPortalInstanceConf;
use Combodo\iTop\Renderer\Bootstrap\BsFormRenderer;
use DBObjectSet;
use Dict;
use iPopupMenuExtension;
use IssueLog;
use JSButtonItem;
use MetaModel;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use URLButtonItem;
use UserRights;
/**
* Class ObjectFormHandlerHelper
*
* @package Combodo\iTop\Portal\Helper
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @since 2.7.0
*/
class ObjectFormHandlerHelper
{
const ENUM_MODE_VIEW = 'view';
const ENUM_MODE_EDIT = 'edit';
const ENUM_MODE_CREATE = 'create';
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper */
private $oRequestManipulator;
/** @var \Combodo\iTop\Portal\Helper\ContextManipulatorHelper */
private $oContextManipulator;
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper */
private $oScopeValidator;
/** @var \Combodo\iTop\Portal\Helper\SecurityHelper */
private $oSecurityHelper;
/** @var \Combodo\iTop\Portal\Routing\UrlGenerator */
private $oUrlGenerator;
/** @var \Combodo\iTop\Portal\VariableAccessor\CombodoPortalInstanceConf */
private $aCombodoPortalInstanceConf;
/** @var string $sPortalId */
private $sPortalId;
/**
* ObjectFormHandlerHelper constructor.
*
* @param \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator
* @param \Combodo\iTop\Portal\Helper\ContextManipulatorHelper $oContextManipulator
* @param \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator
* @param \Combodo\iTop\Portal\Helper\SecurityHelper $oSecurityHelper
* @param \Combodo\iTop\Portal\Routing\UrlGenerator $oUrlGenerator
* @param \Combodo\iTop\Portal\VariableAccessor\CombodoPortalInstanceConf $aCombodoPortalInstanceConf
* @param string $sPortalId
*/
public function __construct(RequestManipulatorHelper $oRequestManipulator, ContextManipulatorHelper $oContextManipulator, ScopeValidatorHelper $oScopeValidator, SecurityHelper $oSecurityHelper, UrlGeneratorInterface $oUrlGenerator, CombodoPortalInstanceConf $aCombodoPortalInstanceConf, $sPortalId)
{
$this->oRequestManipulator = $oRequestManipulator;
$this->oContextManipulator = $oContextManipulator;
$this->oScopeValidator = $oScopeValidator;
$this->oSecurityHelper = $oSecurityHelper;
$this->oUrlGenerator = $oUrlGenerator;
$this->aCombodoPortalInstanceConf = $aCombodoPortalInstanceConf;
$this->sPortalId = $sPortalId;
}
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param string $sMode
* @param string $sObjectClass
* @param string $sObjectId
* @param string $aFormProperties
*
* @return array
*
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \OQLException
* @throws \Exception
*/
public function HandleForm(Request $oRequest, $sMode, $sObjectClass, $sObjectId = null, $aFormProperties = null)
{
$aFormData = array();
$sOperation = $this->oRequestManipulator->ReadParam('operation', '');
$bModal = ($oRequest->isXmlHttpRequest() && empty($sOperation));
// - Retrieve form properties
if ($aFormProperties === null)
{
$aFormProperties = ApplicationHelper::GetLoadedFormFromClass($this->aCombodoPortalInstanceConf['forms'], $sObjectClass, $sMode);
}
// - Create and
if (empty($sOperation))
{
// Retrieving action rules
//
// Note : The action rules must be a base64-encoded JSON object, this is just so users are tempted to changes values.
// But it would not be a security issue as it only presets values in the form.
$sActionRulesToken = $this->oRequestManipulator->ReadParam('ar_token', '');
$aActionRules = (!empty($sActionRulesToken)) ? ContextManipulatorHelper::DecodeRulesToken($sActionRulesToken) : array();
// Preparing object
if ($sObjectId === null)
{
// Create new UserRequest
$oObject = MetaModel::NewObject($sObjectClass);
// Retrieve action rules information to auto-fill the form if available
// Preparing object
$this->oContextManipulator->PrepareObject($aActionRules, $oObject);
$aPrefillFormParam = array( 'user' => $_SESSION["auth_user"],
'origin' => 'portal');
$oObject->PrefillForm('creation_from_0', $aPrefillFormParam);
}
else
{
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, true, $this->oScopeValidator->IsAllDataAllowedForScope(UserRights::ListProfiles(), $sObjectClass));
}
// Preparing buttons
$aFormData['buttons'] = array(
'transitions' => array(),
'actions' => array(),
'links' => array(),
'submit' => array(
'label' => Dict::S('Portal:Button:Submit'),
),
);
if ($sMode !== 'apply_stimulus')
{
// Add transition buttons
$oSetToCheckRights = DBObjectSet::FromObject($oObject);
$aStimuli = Metamodel::EnumStimuli($sObjectClass);
foreach ($oObject->EnumTransitions() as $sStimulusCode => $aTransitionDef)
{
if($this->oSecurityHelper->IsStimulusAllowed($sStimulusCode, $sObjectClass, $oSetToCheckRights))
{
$aFormData['buttons']['transitions'][$sStimulusCode] = $aStimuli[$sStimulusCode]->GetLabel();
}
}
// Add plugin buttons
/** @var \iPopupMenuExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance)
{
foreach($oExtensionInstance->EnumItems(iPopupMenuExtension::PORTAL_OBJDETAILS_ACTIONS, array('portal_id' => $this->sPortalId, 'object' => $oObject, 'mode' => $sMode)) as $oMenuItem)
{
if (is_object($oMenuItem))
{
if($oMenuItem instanceof JSButtonItem)
{
$aFormData['buttons']['actions'][] = $oMenuItem->GetMenuItem() + array('js_files' => $oMenuItem->GetLinkedScripts());
}
elseif($oMenuItem instanceof URLButtonItem)
{
$aFormData['buttons']['links'][] = $oMenuItem->GetMenuItem();
}
}
}
}
// Hiding submit button or changing its label if necessary
if(!empty($aFormData['buttons']['transitions']) && isset($aFormProperties['properties']) &&$aFormProperties['properties']['always_show_submit'] === false)
{
unset($aFormData['buttons']['submit']);
}
elseif($sMode === static::ENUM_MODE_EDIT)
{
$aFormData['buttons']['submit']['label'] = Dict::S('Portal:Button:Apply');
}
}
else
{
$aPrefillFormParam = array(
'user' => $_SESSION["auth_user"],
'origin' => 'portal',
'stimulus' => $this->oRequestManipulator->ReadParam('apply_stimulus', null)['code'],
);
$oObject->PrefillForm('state_change', $aPrefillFormParam);
}
// Preparing callback urls
$aCallbackUrls = $this->oContextManipulator->GetCallbackUrls($aActionRules, $oObject, $bModal);
$aFormData['submit_callback'] = $aCallbackUrls['submit'];
$aFormData['cancel_callback'] = $aCallbackUrls['cancel'];
// Preparing renderer
// Note : We might need to distinguish form & renderer endpoints
if (in_array($sMode, array('create', 'edit', 'view')))
{
$sFormEndpoint = $this->oUrlGenerator->generate('p_object_' . $sMode, array('sObjectClass' => $sObjectClass, 'sObjectId' => $sObjectId));
}
else
{
$sFormEndpoint = $_SERVER['REQUEST_URI'];
}
$oFormRenderer = new BsFormRenderer();
$oFormRenderer->SetEndpoint($sFormEndpoint);
// TODO: Remove this when ObjectFormManager fixed.
$oApp = null;
$oFormManager = new ObjectFormManager();
$oFormManager->SetApplication($oApp)
->SetObject($oObject)
->SetMode($sMode)
->SetActionRulesToken($sActionRulesToken)
->SetRenderer($oFormRenderer)
->SetFormProperties($aFormProperties);
$oFormManager->Build();
// Check the number of editable fields
$aFormData['editable_fields_count'] = $oFormManager->GetForm()->GetEditableFieldCount();
}
else
{
// Update / Submit / Cancel
$sFormManagerClass = $this->oRequestManipulator->ReadParam('formmanager_class', '', FILTER_UNSAFE_RAW);
$sFormManagerData = $this->oRequestManipulator->ReadParam('formmanager_data', '', FILTER_UNSAFE_RAW);
if ( empty($sFormManagerClass) || empty($sFormManagerData) )
{
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.');
}
// TODO: Remove this when ObjectFormManager fixed.
$oApp = null;
/** @var \Combodo\iTop\Portal\Form\ObjectFormManager $oFormManager */
$oFormManager = $sFormManagerClass::FromJSON($sFormManagerData);
$oFormManager->SetApplication($oApp);
// Applying action rules if present
if (($oFormManager->GetActionRulesToken() !== null) && ($oFormManager->GetActionRulesToken() !== ''))
{
$aActionRules = ContextManipulatorHelper::DecodeRulesToken($oFormManager->GetActionRulesToken());
$oObj = $oFormManager->GetObject();
$this->oContextManipulator->PrepareObject($aActionRules, $oObj);
$oFormManager->SetObject($oObj);
}
switch ($sOperation)
{
case 'submit':
// Applying modification to object
$aFormData['validation'] = $oFormManager->OnSubmit(
array(
'currentValues' => $this->oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW),
'attachmentIds' => $this->oRequestManipulator->ReadParam('attachment_ids', array(), FILTER_UNSAFE_RAW),
'formProperties' => $aFormProperties,
'applyStimulus' => $this->oRequestManipulator->ReadParam('apply_stimulus', null)
)
);
if ($aFormData['validation']['valid'] === true)
{
// Note : We don't use $sObjectId there as it can be null if we are creating a new one. Instead we use the id from the created object once it has been seralized
// Check if stimulus has to be applied
$sStimulusCode = $this->oRequestManipulator->ReadParam('stimulus_code', '');
if (!empty($sStimulusCode))
{
$aFormData['validation']['redirection'] = array(
'url' => $this->oUrlGenerator->generate('p_object_apply_stimulus', array('sObjectClass' => $sObjectClass, 'sObjectId' => $oFormManager->GetObject()->GetKey(), 'sStimulusCode' => $sStimulusCode)),
'ajax' => true,
);
}
// Otherwise, we show the object if there is no default
// else
// {
// $aFormData['validation']['redirection'] = array(
// 'alternative_url' => $this->oUrlGenerator->generate('p_object_edit', array('sObjectClass' => $sObjectClass, 'sObjectId' => $oFormManager->GetObject()->GetKey()))
// );
// }
}
break;
case 'update':
$oFormManager->OnUpdate(array('currentValues' => $this->oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW), 'formProperties' => $aFormProperties));
break;
case 'cancel':
$oFormManager->OnCancel();
break;
}
}
// Preparing field_set data
$aFieldSetData = array(
//'fields_list' => $oFormManager->GetRenderer()->Render(), // GLA : This should be done just after in the if statement.
'fields_impacts' => $oFormManager->GetForm()->GetFieldsImpacts(),
'form_path' => $oFormManager->GetForm()->GetId(),
);
// Preparing fields list regarding the operation
if ($sOperation === 'update')
{
$aRequestedFields = $this->oRequestManipulator->ReadParam('requested_fields', array(), FILTER_UNSAFE_RAW);
$sFormPath = $this->oRequestManipulator->ReadParam('form_path', '');
// Checking if the update was on a subform, if so we need to make the rendering for that part only
if ( !empty($sFormPath) && $sFormPath !== $oFormManager->GetForm()->GetId() )
{
$oSubForm = $oFormManager->GetForm()->FindSubForm($sFormPath);
$oSubFormRenderer = new BsFormRenderer($oSubForm);
$oSubFormRenderer->SetEndpoint($oFormManager->GetRenderer()->GetEndpoint());
$aFormData['updated_fields'] = $oSubFormRenderer->Render($aRequestedFields);
}
else
{
$aFormData['updated_fields'] = $oFormManager->GetRenderer()->Render($aRequestedFields);
}
}
else
{
$aFieldSetData['fields_list'] = $oFormManager->GetRenderer()->Render();
}
// Preparing form data
$aFormData['id'] = $oFormManager->GetForm()->GetId();
$aFormData['transaction_id'] = $oFormManager->GetForm()->GetTransactionId();
$aFormData['formmanager_class'] = $oFormManager->GetClass();
$aFormData['formmanager_data'] = $oFormManager->ToJSON();
$aFormData['renderer'] = $oFormManager->GetRenderer();
$aFormData['object_name'] = $oFormManager->GetObject()->GetName();
$aFormData['object_class'] = get_class($oFormManager->GetObject());
$aFormData['object_id'] = $oFormManager->GetObject()->GetKey();
$aFormData['object_state'] = $oFormManager->GetObject()->GetState();
$aFormData['fieldset'] = $aFieldSetData;
$aFormData['display_mode'] = (isset($aFormProperties['properties'])) ? $aFormProperties['properties']['display_mode'] : ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE;
return $aFormData;
}
}

View File

@@ -19,19 +19,21 @@
*
*/
/**
* Created by Bruno DA SILVA, working for Combodo
* Date: 30/01/19
* Time: 16:38
*/
namespace Combodo\iTop\Portal\Twig;
use ArrayAccess;
use Symfony\Bridge\Twig\AppVariable as DecoratedAppVariable;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class AppVariable implements \ArrayAccess
/**
* Class AppVariable
*
* @package Combodo\iTop\Portal\Twig
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @since 2.7.0
*/
class AppVariable implements ArrayAccess
{
/** @var ContainerInterface */
private $container;

View File

@@ -134,7 +134,7 @@
<div class="form_buttons">
{% block pUserProfileFormButtons %}
<div class="form_btn_regular">
{% if sFormMode == constant('\\Combodo\\iTop\\Portal\\Controller\\ObjectController::ENUM_MODE_EDIT') %}
{% if sFormMode == constant('\\Combodo\\iTop\\Portal\\Helper\\ObjectFormHandlerHelper::ENUM_MODE_EDIT') %}
<input class="btn btn-primary form_btn_submit" type="submit" value="{{ 'Portal:Button:Submit'|dict_s }}">
{% endif %}
</div>

View File

@@ -10,7 +10,7 @@
<div class="row">
<div class="col-xs-12 col-sm-9 col-md-10 col-sm-offset-3 col-md-offset-2">
<section class="row tiles_wrapper">
{% for brick in app['brick_collection'].bricks_ordering.home %}
{% for brick in app['brick_collection'].home_ordering %}
{% if brick.GetVisibleHome %}
{% if aTilesRendering[brick.GetId] is defined %}
{{ aTilesRendering[brick.GetId]|raw }}

View File

@@ -195,7 +195,7 @@
{{ 'Page:Home'|dict_s }}
</a>
</li>
{% for brick in app['brick_collection'].bricks_ordering.navigation_menu %}
{% for brick in app['brick_collection'].navigation_menu_ordering %}
{% if brick.GetActive and brick.GetVisibleNavigationMenu and brick.GetRouteName is not null %}
<li class="brick_menu_item {% if oBrick is defined and brick.id == oBrick.id %}active{% endif %}" data-brick-id="{{ brick.GetId }}">
<a href="{{ app.url_generator.generate(brick.GetRouteName, {sBrickId: brick.GetId}) }}{% if app['combodo.portal.instance.routes'][brick.GetRouteName]['hash'] is defined %}#{{ app['combodo.portal.instance.routes'][brick.GetRouteName]['hash'] }}{% endif %}" {% if app['combodo.portal.instance.routes'][brick.GetRouteName]['navigation_menu_attr'] is defined %}{% for key, value in app['combodo.portal.instance.routes'][brick.GetRouteName]['navigation_menu_attr'] %} {{ key }}="{{ value }}"{% endfor %}{% endif %} {% if brick.GetModal %}data-toggle="modal" data-target="#modal-for-all"{% endif %}>
@@ -272,7 +272,7 @@
{{ 'Page:Home'|dict_s }}
</a>
</li>
{% for brick in app['brick_collection'].bricks_ordering.navigation_menu %}
{% for brick in app['brick_collection'].navigation_menu_ordering %}
{% if brick.GetActive and brick.GetVisibleNavigationMenu and brick.GetRouteName is not null %}
<li class="brick_menu_item {% if oBrick is defined and brick.id == oBrick.id %}active{% endif %}" data-brick-id="{{ brick.GetId }}">
<a href="{{ app.url_generator.generate(brick.GetRouteName, {sBrickId: brick.GetId}) }}{% if app['combodo.portal.instance.routes'][brick.GetRouteName]['hash'] is defined %}#{{ app['combodo.portal.instance.routes'][brick.GetRouteName]['hash'] }}{% endif %}" {% if app['combodo.portal.instance.routes'][brick.GetRouteName]['navigation_menu_attr'] is defined %}{% for key, value in app['combodo.portal.instance.routes'][brick.GetRouteName]['navigation_menu_attr'] %} {{ key }}="{{ value }}"{% endfor %}{% endif %} {% if brick.GetModal %}data-toggle="modal" data-target="#modal-for-all"{% endif %}>