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

- Make ManageBrick work again!
- Make ObjectController::CreateFromFactory() work again
- Refactor object form rendering from Twig string (in memory) in the "object_form_handler" service
- Fix ApplicationHelper::GetLoadedListFromClass()
This commit is contained in:
Molkobain
2019-07-05 11:30:08 +02:00
parent 8fc4aa7240
commit e3ac4d1039
7 changed files with 296 additions and 220 deletions

View File

@@ -36,7 +36,7 @@ browse_brick:
manage_brick:
resource: 'routes/manage_brick.yaml'
p_aggregatepage_brick:
aggregatepage_brick:
resource: 'routes/aggregatepage_brick.yaml'
extensions_extra_routes:

View File

@@ -69,7 +69,7 @@ abstract class PortalBrick extends AbstractBrick
protected $sTitleHome;
protected $sTitleNavigationMenu;
static function GetRouteName()
public static function GetRouteName()
{
return static::$sRouteName;
}
@@ -77,7 +77,7 @@ abstract class PortalBrick extends AbstractBrick
/**
* Default attributes values of AbstractBrick are specified in the definition, not the constructor.
*/
function __construct()
public function __construct()
{
parent::__construct();

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;
@@ -28,9 +31,6 @@ use BinaryExpression;
use CMDBSource;
use Combodo\iTop\Portal\Brick\AbstractBrick;
use Combodo\iTop\Portal\Brick\ManageBrick;
use Combodo\iTop\Portal\Helper\ApplicationHelper;
use Combodo\iTop\Portal\Helper\ScopeValidatorHelper;
use Combodo\iTop\Portal\Helper\SecurityHelper;
use DBObject;
use DBObjectSet;
use DBSearch;
@@ -40,7 +40,7 @@ use FieldExpression;
use iPopupMenuExtension;
use JSButtonItem;
use MetaModel;
use Silex\Application;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use UnaryExpression;
use URLButtonItem;
@@ -50,40 +50,46 @@ use VariableExpression;
* Class ManageBrickController
*
* @package Combodo\iTop\Portal\Controller
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
* @author Eric Espie <eric.espie@combodo.com>
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @author Pierre Goiffon <pierre.goiffon@combodo.com>
* @author Eric Espie <eric.espie@combodo.com>
* @since 2.3.0
*/
class ManageBrickController extends BrickController
{
const EXCEL_EXPORT_TEMPLATE_PATH = 'itop-portal-base/portal/src/views/bricks/manage/popup-export-excel.html.twig';
const EXCEL_EXPORT_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig';
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param \Silex\Application $oApp
* @param string $sBrickId
* @param string $sGroupingTab
* @param string $sDisplayMode
*
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Exception
* @throws \CoreException
* @throws \DictExceptionMissingString
* @throws \MySQLException
* @throws \OQLException
*/
public function DisplayAction(Request $oRequest, Application $oApp, $sBrickId, $sGroupingTab, $sDisplayMode = null)
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param string $sBrickId
* @param string $sGroupingTab
* @param string $sDisplayMode
*
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Combodo\iTop\Portal\Brick\BrickNotFoundException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*/
public function DisplayAction(Request $oRequest, $sBrickId, $sGroupingTab, $sDisplayMode = null)
{
/** @var \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection */
$oBrickCollection = $this->get('brick_collection');
/** @var \Combodo\iTop\Portal\Brick\ManageBrick $oBrick */
$oBrick = ApplicationHelper::GetLoadedBrickFromId($oApp, $sBrickId);
$oBrick = $oBrickCollection->GetBrickById($sBrickId);
if (is_null($sDisplayMode))
{
$sDisplayMode = $oBrick->GetDefaultDisplayMode();
}
$aData = $this->GetData($oRequest, $oApp, $sBrickId, $sGroupingTab, $oBrick::AreDetailsNeededForDisplayMode($sDisplayMode));
$aData = $this->GetData($oRequest, $sBrickId, $sGroupingTab, $oBrick::AreDetailsNeededForDisplayMode($sDisplayMode));
$aExportFields = $oBrick->GetExportFields();
$aData = $aData + array(
@@ -93,36 +99,38 @@ class ManageBrickController extends BrickController
// Preparing response
if ($oRequest->isXmlHttpRequest())
{
$oResponse = $oApp->json($aData);
$oResponse = new JsonResponse($aData);
}
else
{
$sLayoutTemplate = $oBrick::GetPageTemplateFromDisplayMode($sDisplayMode);
$oResponse = $oApp['twig']->render($sLayoutTemplate, $aData);
$oResponse = $this->render($sLayoutTemplate, $aData);
}
return $oResponse;
}
/**
* Method for the brick's tile on home page
*
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param \Silex\Application $oApp
* @param string $sBrickId
*
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Exception
*/
public function TileAction(Request $oRequest, Application $oApp, $sBrickId)
/**
* Method for the brick's tile on home page
*
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param string $sBrickId
*
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Combodo\iTop\Portal\Brick\BrickNotFoundException
*/
public function TileAction(Request $oRequest, $sBrickId)
{
/** @var \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection */
$oBrickCollection = $this->get('brick_collection');
/** @var \Combodo\iTop\Portal\Brick\ManageBrick $oBrick */
$oBrick = ApplicationHelper::GetLoadedBrickFromId($oApp, $sBrickId);
$oBrick = $oBrickCollection->GetBrickById($sBrickId);
try
{
$aData = $this->GetData($oRequest, $oApp, $sBrickId, null);
$aData = $this->GetData($oRequest, $sBrickId, null);
}
catch (Exception $e)
{
@@ -130,31 +138,38 @@ class ManageBrickController extends BrickController
$aData = array();
}
return $oApp['twig']->render($oBrick->GetTileTemplatePath(), $aData);
return $this->render($oBrick->GetTileTemplatePath(), $aData);
}
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param \Silex\Application $oApp
* @param string $sBrickId
* @param string $sGroupingTab
* @param string $sGroupingArea
*
* @return \Symfony\Component\HttpFoundation\Request
*
* @throws \Exception
* @throws \DictExceptionMissingString
* @throws \MySQLException
* @throws \OQLException
*/
public function ExcelExportStartAction(
Request $oRequest, Application $oApp, $sBrickId, $sGroupingTab, $sGroupingArea
) {
/** @var ManageBrick $oBrick */
$oBrick = ApplicationHelper::GetLoadedBrickFromId($oApp, $sBrickId);
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param string $sBrickId
* @param string $sGroupingTab
* @param string $sGroupingArea
*
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Combodo\iTop\Portal\Brick\BrickNotFoundException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*/
public function ExcelExportStartAction(Request $oRequest, $sBrickId, $sGroupingTab, $sGroupingArea)
{
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator */
$oScopeValidator = $this->get('scope_validator');
/** @var \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection */
$oBrickCollection = $this->get('brick_collection');
/** @var \Combodo\iTop\Portal\Brick\ManageBrick $oBrick */
$oBrick = $oBrickCollection->GetBrickById($sBrickId);
$oQuery = DBSearch::FromOQL($oBrick->GetOql());
$sClass = $oQuery->GetClass();
$aData = $this->GetData($oRequest, $oApp, $sBrickId, $sGroupingTab, true);
$aData = $this->GetData($oRequest, $sBrickId, $sGroupingTab, true);
if (isset($aData['aQueries']) && count($aData['aQueries']) === 1)
{
@@ -165,11 +180,9 @@ class ManageBrickController extends BrickController
}
else
{
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeHelper */
$oScopeHelper = $oApp['scope_validator'];
$oScopeHelper->AddScopeToQuery($oQuery, $sClass);
$oScopeValidator->AddScopeToQuery($oQuery, $sClass);
$aData = array();
$this->ManageSearchValue($oApp, $aData, $oQuery, $sClass);
$this->ManageSearchValue($aData, $oQuery, $sClass);
// Grouping tab
if ($oBrick->HasGroupingTabs())
@@ -180,7 +193,7 @@ class ManageBrickController extends BrickController
if ($oBrick->IsGroupingTabsByDistinctValues())
{
$sGroupingTabAttCode = $aGroupingTabs['attribute'];
$aGroupingTabsValues = $this->GroupByAttribute($oQuery, $sGroupingTabAttCode, $oApp, $oBrick);
$aGroupingTabsValues = $this->GroupByAttribute($oQuery, $sGroupingTabAttCode, $oBrick);
$oQuery = $oQuery->Intersect($aGroupingTabsValues[$sGroupingTab]['condition']);
}
else
@@ -234,28 +247,44 @@ class ManageBrickController extends BrickController
'sOQL' => $oSearch->ToOQL(),
);
return $oApp['twig']->render(static::EXCEL_EXPORT_TEMPLATE_PATH, $aData);
return $this->render(static::EXCEL_EXPORT_TEMPLATE_PATH, $aData);
}
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param \Silex\Application $oApp
* @param string $sBrickId
* @param string $sGroupingTab
* @param bool $bNeedDetails
*
* @return array
*
* @throws \Exception
* @throws \CoreException
* @throws \DictExceptionMissingString
* @throws \MySQLException
* @throws \OQLException
*/
public function GetData(Request $oRequest, Application $oApp, $sBrickId, $sGroupingTab, $bNeedDetails = false)
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param string $sBrickId
* @param string $sGroupingTab
* @param bool $bNeedDetails
*
* @return array
*
* @throws \Combodo\iTop\Portal\Brick\BrickNotFoundException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MissingQueryArgument
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
*/
public function GetData(Request $oRequest, $sBrickId, $sGroupingTab, $bNeedDetails = false)
{
/** @var string $sPortalId */
$sPortalId = $this->getParameter('combodo.portal.instance.id');
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$oRequestManipulator = $this->get('request_manipulator');
/** @var \Combodo\iTop\Portal\Routing\UrlGenerator $oUrlGenerator */
$oUrlGenerator = $this->get('url_generator');
/** @var \Combodo\iTop\Portal\Helper\SecurityHelper $oSecurityHelper */
$oSecurityHelper = $this->get('security_helper');
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator */
$oScopeValidator = $this->get('scope_validator');
/** @var \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection */
$oBrickCollection = $this->get('brick_collection');
/** @var \Combodo\iTop\Portal\Brick\ManageBrick $oBrick */
$oBrick = ApplicationHelper::GetLoadedBrickFromId($oApp, $sBrickId);
$oBrick = $oBrickCollection->GetBrickById($sBrickId);
$aData = array();
$aGroupingTabsValues = array();
@@ -263,11 +292,11 @@ class ManageBrickController extends BrickController
$aQueries = array();
$bHasScope = true;
// Getting current dataloading mode (First from router parameter, then query parameter, then default brick value)
$sDataLoading = $oApp['request_manipulator']->ReadParam('sDataLoading', $oBrick->GetDataLoading());
// Getting current data loading mode (First from router parameter, then query parameter, then default brick value)
$sDataLoading = $oRequestManipulator->ReadParam('sDataLoading', $oBrick->GetDataLoading());
// - Retrieving the grouping areas to display
$sGroupingArea = $oApp['request_manipulator']->ReadParam('sGroupingArea', '');
$sGroupingArea = $oRequestManipulator->ReadParam('sGroupingArea', '');
if (!empty($sGroupingArea))
{
$bNeedDetails = true;
@@ -298,7 +327,7 @@ class ManageBrickController extends BrickController
if ($oBrick->IsGroupingTabsByDistinctValues())
{
$sGroupingTabAttCode = $aGroupingTabs['attribute'];
$aGroupingTabsValues = $this->GroupByAttribute($oQuery, $sGroupingTabAttCode, $oApp, $oBrick);
$aGroupingTabsValues = $this->GroupByAttribute($oQuery, $sGroupingTabAttCode, $oBrick);
foreach ($aGroupingTabsValues as $aResult)
{
$iCount += $aResult['count'];
@@ -312,9 +341,7 @@ class ManageBrickController extends BrickController
$oConditionQuery = $oQuery->Intersect(DBSearch::FromOQL($aGroup['condition']));
// - Restricting query to scope
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeHelper */
$oScopeHelper = $oApp['scope_validator'];
$bHasScope = $oScopeHelper->AddScopeToQuery($oConditionQuery, $oConditionQuery->GetClass());
$bHasScope = $oScopeValidator->AddScopeToQuery($oConditionQuery, $oConditionQuery->GetClass());
if ($bHasScope)
{
// - Building ObjectSet
@@ -339,7 +366,7 @@ class ManageBrickController extends BrickController
}
else
{
$oConditionQuery = $this->GetScopedQuery($oApp, $oBrick, $sClass);
$oConditionQuery = $this->GetScopedQuery($oBrick, $sClass);
if (!is_null($oConditionQuery))
{
$oSet = new DBObjectSet($oConditionQuery);
@@ -369,7 +396,7 @@ class ManageBrickController extends BrickController
}
// - Adding search clause if necessary
$this->ManageSearchValue($oApp, $aData, $oQuery, $sClass, $aColumnsAttrs);
$this->ManageSearchValue($aData, $oQuery, $sClass, $aColumnsAttrs);
// Preparing areas
// - We need to retrieve distinct values for the grouping attribute
@@ -382,7 +409,7 @@ class ManageBrickController extends BrickController
// For root classes
if (MetaModel::IsValidAttCode($sClass, $sGroupingAreaAttCode))
{
$oDistinctQuery = $this->GetScopedQuery($oApp, $oBrick, $sClass);
$oDistinctQuery = $this->GetScopedQuery($oBrick, $sClass);
// Adding grouping conditions
$oFieldExp = new FieldExpression($sGroupingAreaAttCode, $oDistinctQuery->GetClassAlias());
$sDistinctSql = $oDistinctQuery->MakeGroupByQuery(array(), array('grouped_by_1' => $oFieldExp), true);
@@ -435,9 +462,7 @@ class ManageBrickController extends BrickController
// Restricting query to allowed scope on each classes
// Note: Will need to moved the scope restriction on queries elsewhere when we consider grouping on something else than finalclass
// Note: We now get view scope instead of edit scope as we allowed users to view/edit objects in the brick regarding their rights
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeHelper */
$oScopeHelper = $oApp['scope_validator'];
$bHasScope = $oScopeHelper->AddScopeToQuery($oAreaQuery, $aGroupingAreasValue['value']);
$bHasScope = $oScopeValidator->AddScopeToQuery($oAreaQuery, $aGroupingAreasValue['value']);
if (!$bHasScope)
{
// if no scope apply does not allow any data
@@ -457,7 +482,7 @@ class ManageBrickController extends BrickController
// - Update $sDataLoading with its new value regarding the number of record and the threshold
$oCountSet = new DBObjectSet($oQuery);
$oCountSet->OptimizeColumnLoad(array());
$fThreshold = (float)MetaModel::GetModuleSetting($oApp['combodo.portal.instance.id'],
$fThreshold = (float)MetaModel::GetModuleSetting($sPortalId,
'lazy_loading_threshold');
$sDataLoading = ($oCountSet->Count() > $fThreshold) ? AbstractBrick::ENUM_DATA_LOADING_LAZY : AbstractBrick::ENUM_DATA_LOADING_FULL;
unset($oCountSet);
@@ -475,8 +500,8 @@ class ManageBrickController extends BrickController
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY)
{
// Retrieving parameters
$iPageNumber = (int)$oApp['request_manipulator']->ReadParam('iPageNumber', 1, FILTER_SANITIZE_NUMBER_INT);
$iListLength = (int)$oApp['request_manipulator']->ReadParam('iListLength', ManageBrick::DEFAULT_LIST_LENGTH, FILTER_SANITIZE_NUMBER_INT);
$iPageNumber = (int)$oRequestManipulator->ReadParam('iPageNumber', 1, FILTER_SANITIZE_NUMBER_INT);
$iListLength = (int)$oRequestManipulator->ReadParam('iListLength', ManageBrick::DEFAULT_LIST_LENGTH, FILTER_SANITIZE_NUMBER_INT);
// Getting total records number
$oCountSet = new DBObjectSet($oQuery);
@@ -509,7 +534,7 @@ class ManageBrickController extends BrickController
$oSet->OptimizeColumnLoad($aColumnsToLoad);
$oSet->SetOrderByClasses();
SecurityHelper::PreloadForCache($oApp, $oSet->GetFilter(),
$oSecurityHelper->PreloadForCache($oSet->GetFilter(),
$aColumnsToLoad[$oQuery->GetClassAlias()] /* preloading only extkeys from the main class */);
$aSets[$sKey] = $oSet;
}
@@ -554,13 +579,12 @@ class ManageBrickController extends BrickController
if ($sItemAttr === $sMainActionAttrCode)
{
// Checking if we can edit the object
if (($oBrick->GetOpeningMode() === ManageBrick::ENUM_ACTION_EDIT) && SecurityHelper::IsActionAllowed($oApp,
UR_ACTION_MODIFY, $sCurrentClass, $oCurrentRow->GetKey()))
if (($oBrick->GetOpeningMode() === ManageBrick::ENUM_ACTION_EDIT) && $oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY, $sCurrentClass, $oCurrentRow->GetKey()))
{
$sActionType = ManageBrick::ENUM_ACTION_EDIT;
}
// - Otherwise, check if view is allowed
elseif (SecurityHelper::IsActionAllowed($oApp, UR_ACTION_READ, $sCurrentClass,
elseif ($oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sCurrentClass,
$oCurrentRow->GetKey()))
{
$sActionType = ManageBrick::ENUM_ACTION_VIEW;
@@ -592,7 +616,7 @@ class ManageBrickController extends BrickController
if ($oCurrentRow->Get($sItemAttr) !== $oAttDef->GetNullValue())
{
// Checking if we can view the object
if ((SecurityHelper::IsActionAllowed($oApp, UR_ACTION_READ, $oAttDef->GetTargetClass(),
if (($oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $oAttDef->GetTargetClass(),
$oCurrentRow->Get($sItemAttr))))
{
$aActions[] = array(
@@ -609,7 +633,7 @@ class ManageBrickController extends BrickController
$oOrmDoc = $oCurrentRow->Get($sItemAttr);
if (is_object($oOrmDoc) && !$oOrmDoc->IsEmpty())
{
$sUrl = $oApp['url_generator']->generate('p_object_document_display', array('sObjectClass' => get_class($oCurrentRow), 'sObjectId' => $oCurrentRow->GetKey(), 'sObjectField' => $sItemAttr, 'cache' => 86400));
$sUrl = $oUrlGenerator->generate('p_object_document_display', array('sObjectClass' => get_class($oCurrentRow), 'sObjectId' => $oCurrentRow->GetKey(), 'sObjectField' => $sItemAttr, 'cache' => 86400));
}
else
{
@@ -648,7 +672,7 @@ class ManageBrickController extends BrickController
foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance)
{
foreach ($oExtensionInstance->EnumItems(iPopupMenuExtension::PORTAL_OBJLISTITEM_ACTIONS, array(
'portal_id' => $oApp['combodo.portal.instance.id'],
'portal_id' => $sPortalId,
'object' => $oCurrentRow
)) as $oMenuItem)
{
@@ -730,7 +754,7 @@ class ManageBrickController extends BrickController
'label' => $aValues['label'],
'label_html' => $aValues['label_html'],
);
$aUrls[] = $oApp['url_generator']->generate('p_manage_brick', array(
$aUrls[] = $oUrlGenerator->generate('p_manage_brick', array(
'sBrickId' => $sBrickId,
'sDisplayMode' => 'default',
'sGroupingTab' => $aValues['value']
@@ -767,20 +791,22 @@ class ManageBrickController extends BrickController
return $aData;
}
/**
* @param \Silex\Application $oApp
* @param array $aData
* @param \DBSearch $oQuery
* @param string $sClass
* @param array $aColumnsAttrs
*
* @throws \Exception
* @throws \CoreException
*/
protected function ManageSearchValue(Application $oApp, &$aData, DBSearch &$oQuery, $sClass, $aColumnsAttrs = array())
/**
* @param array $aData
* @param \DBSearch $oQuery
* @param string $sClass
* @param array $aColumnsAttrs
*
* @throws \CoreException
* @throws \Exception
*/
protected function ManageSearchValue(&$aData, DBSearch &$oQuery, $sClass, $aColumnsAttrs = array())
{
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$oRequestManipulator = $this->get('request_manipulator');
// Getting search value
$sSearchValue = $oApp['request_manipulator']->ReadParam('sSearchValue', '');
$sSearchValue = $oRequestManipulator->ReadParam('sSearchValue', '');
// - Adding search clause if necessary
// Note : This is a very naive search at the moment
@@ -829,30 +855,30 @@ class ManageBrickController extends BrickController
$aData['sSearchValue'] = $sSearchValue;
}
/**
* Get the groups using a given attribute code.
* If a limit is given, the remaining groups are aggregated (groupby result and search request).
*
* @param \DBSearch $oQuery Initial query
* @param string $sGroupingTabAttCode Attribute code to group by
* @param \Silex\Application $oApp
* @param \Combodo\iTop\Portal\Brick\ManageBrick $oBrick
*
* @return array of results from the groupby request and the corrsponding search.
*
* @throws \MySQLException
* @throws \OQLException
* @throws \Exception
*/
/**
* Get the groups using a given attribute code.
* If a limit is given, the remaining groups are aggregated (groupby result and search request).
*
* @param \DBSearch $oQuery Initial query
* @param string $sGroupingTabAttCode Attribute code to group by
* @param \Combodo\iTop\Portal\Brick\ManageBrick $oBrick
*
* @return array of results from the groupby request and the corrsponding search.
*
* @throws \CoreException
* @throws \MySQLException
* @throws \OQLException
*/
protected function GroupByAttribute(
DBSearch $oQuery, $sGroupingTabAttCode, Application $oApp, ManageBrick $oBrick
DBSearch $oQuery, $sGroupingTabAttCode, ManageBrick $oBrick
) {
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator */
$oScopeValidator = $this->get('scope_validator');
$aGroupingTabsValues = array();
$aDistinctResults = array();
$oDistinctQuery = DBSearch::FromOQL($oBrick->GetOql());
/** @var ScopeValidatorHelper $oScopeHelper */
$oScopeHelper = $oApp['scope_validator'];
$bHasScope = $oScopeHelper->AddScopeToQuery($oDistinctQuery, $oDistinctQuery->GetClass());
$bHasScope = $oScopeValidator->AddScopeToQuery($oDistinctQuery, $oDistinctQuery->GetClass());
if ($bHasScope)
{
// - Adding field condition
@@ -948,22 +974,22 @@ class ManageBrickController extends BrickController
return $aGroupingTabsValues;
}
/**
* @param \Silex\Application $oApp
* @param \Combodo\iTop\Portal\Brick\ManageBrick $oBrick
* @param string $sClass
*
* @return \DBSearch
*
* @throws \CoreException
* @throws \OQLException
*/
protected function GetScopedQuery(Application $oApp, ManageBrick $oBrick, $sClass)
/**
* @param \Combodo\iTop\Portal\Brick\ManageBrick $oBrick
* @param string $sClass
*
* @return \DBSearch
*
* @throws \CoreException
* @throws \OQLException
*/
protected function GetScopedQuery(ManageBrick $oBrick, $sClass)
{
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator */
$oScopeValidator = $this->get('scope_validator');
$oQuery = DBSearch::FromOQL($oBrick->GetOql());
/** @var ScopeValidatorHelper $oScopeHelper */
$oScopeHelper = $oApp['scope_validator'];
$oScopeHelper->AddScopeToQuery($oQuery, $sClass);
$oScopeValidator->AddScopeToQuery($oQuery, $sClass);
return $oQuery;
}

View File

@@ -380,12 +380,8 @@ class ObjectController extends AbstractController
$aRouteParams = array(
'sObjectClass' => get_class($oTargetObject)
);
$sRedirectRoute = $oUrlGenerator->generate('p_object_create', $aRouteParams);
// - Request
$oSubRequest = Request::create($sRedirectRoute, 'GET', $oRequest->query->all(), $oRequest->cookies->all(), array(), $oRequest->server->all());
// TODO: How do we do that in Symfony?
return $oApp->handle($oSubRequest, HttpKernelInterface::SUB_REQUEST, true);
return $this->forward($this->GetControllerNameFromRoute('p_object_create'), $aRouteParams, $oRequest->query->all());
}
/**
@@ -405,6 +401,9 @@ class ObjectController extends AbstractController
*/
public function ApplyStimulusAction(Request $oRequest, $sObjectClass, $sObjectId, $sStimulusCode)
{
/** @var array $aCombodoPortalInstanceConf */
$aCombodoPortalInstanceConf = $this->getParameter('combodo.portal.instance.conf');
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$oRequestManipulator = $this->get('request_manipulator');
/** @var \Combodo\iTop\Portal\Routing\UrlGenerator $oUrlGenerator */
@@ -442,7 +441,7 @@ class ObjectController extends AbstractController
$sOperation = $oRequestManipulator->ReadParam('operation', '');
// Retrieving form properties
$aStimuliForms = ApplicationHelper::GetLoadedFormFromClass($this->getParameter('combodo.portal.instance.conf')['forms'], $sObjectClass, 'apply_stimulus');
$aStimuliForms = ApplicationHelper::GetLoadedFormFromClass($aCombodoPortalInstanceConf['forms'], $sObjectClass, 'apply_stimulus');
if(array_key_exists($sStimulusCode, $aStimuliForms))
{
$aFormProperties = $aStimuliForms[$sStimulusCode];
@@ -717,6 +716,9 @@ class ObjectController extends AbstractController
*/
public function SearchFromAttributeAction(Request $oRequest, $sTargetAttCode, $sHostObjectClass, $sHostObjectId = null)
{
/** @var array $aCombodoPortalInstanceConf */
$aCombodoPortalInstanceConf = $this->getParameter('combodo.portal.instance.conf');
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$oRequestManipulator = $this->get('request_manipulator');
/** @var \Combodo\iTop\Portal\Helper\ContextManipulatorHelper $oContextManipulator */
@@ -829,7 +831,7 @@ class ObjectController extends AbstractController
}
// - Retrieving class attribute list
$aAttCodes = ApplicationHelper::GetLoadedListFromClass($sTargetObjectClass, 'list');
$aAttCodes = ApplicationHelper::GetLoadedListFromClass($aCombodoPortalInstanceConf['lists'], $sTargetObjectClass, 'list');
// - Adding friendlyname attribute to the list is not already in it
$sTitleAttCode = 'friendlyname';
if (($sTitleAttCode !== null) && !in_array($sTitleAttCode, $aAttCodes))
@@ -1362,4 +1364,20 @@ class ObjectController extends AbstractController
return $aObjectData;
}
/**
* Returns a string containing the controller and action name of a specific route, typically used for request forwarding.
*
* Example: 'p_object_create' returns 'Combodo\iTop\Portal\Controller\ObjectController::CreateAction'
*
* @param string $sRouteName
*
* @return string
*/
private function GetControllerNameFromRoute($sRouteName)
{
$oRouteCollection = $this->get('router')->getRouteCollection();
$aRouteDefaults = $oRouteCollection->get($sRouteName)->getDefaults();
return $aRouteDefaults['_controller'];
}
}

View File

@@ -247,10 +247,6 @@ class ObjectFormManager extends FormManager
*/
public function SetFormProperties($aFormProperties)
{
// echo '<pre>';
// print_r($aFormProperties);
// echo '</pre>';
// die();
$this->aFormProperties = $aFormProperties;
return $this;
}
@@ -399,10 +395,20 @@ class ObjectFormManager extends FormManager
// Checking if we need to render the template from twig to html in order to parse the fields
if ($this->aFormProperties['layout']['type'] === 'twig')
{
// Creating sandbox twig env. to load and test the custom form template
$oTwig = new \Twig_Environment(new \Twig_Loader_Array( array($oForm->GetId() => $this->aFormProperties['layout']['content']) ));
ApplicationHelper::RegisterTwigExtensions($oTwig);
$sRendered = $oTwig->render($oForm->GetId(), array('oRenderer' => $this->oRenderer, 'oObject' => $this->oObject));
if($this->oContainer !== null)
{
/** @var \Combodo\iTop\Portal\Helper\ObjectFormHandlerHelper $oObjectFormHandler */
$oObjectFormHandler = $this->oContainer->get('object_form_handler');
$sRendered = $oObjectFormHandler->RenderFormFromTwig(
$oForm->GetId(),
$this->aFormProperties['layout']['content'],
array('oRenderer' => $this->oRenderer, 'oObject' => $this->oObject)
);
}
else
{
$sRendered = 'Form not rendered because of missing container';
}
}
else
{
@@ -797,7 +803,7 @@ class ObjectFormManager extends FormManager
if ($this->oContainer !== null)
{
// Note : This snippet is inspired from AttributeLinkedSet::MakeFormField()
$aAttCodesToDisplay = ApplicationHelper::GetLoadedListFromClass($this->oContainer->getParameter('combodo.portal.instance.conf'), $oField->GetTargetClass(), 'list');
$aAttCodesToDisplay = ApplicationHelper::GetLoadedListFromClass($this->oContainer->getParameter('combodo.portal.instance.conf')['lists'], $oField->GetTargetClass(), 'list');
// - Adding friendlyname attribute to the list is not already in it
$sTitleAttCode = 'friendlyname';
if (($sTitleAttCode !== null) && !in_array($sTitleAttCode, $aAttCodesToDisplay))

View File

@@ -699,35 +699,34 @@ class ApplicationHelper
return $aForm;
}
/**
* Return the attribute list for the $sClassname in $sList.
*
* If not found, tries to find one from the closest parent class.
* Else returns a default attribute list based on zlist 'list'
*
* @param array $combodoPortalInstanceConf
* @param string $sClass Object class to find a list for
* @param string $sList List name to find
*
* @return string[] Array of attribute codes
*
* @throws \CoreException
*/
public static function GetLoadedListFromClass($combodoPortalInstanceConf, $sClass, $sList = 'default')
/**
* Return the attribute list for the $sClassname in $sList.
*
* If not found, tries to find one from the closest parent class.
* Else returns a default attribute list based on zlist 'list'
*
* @param array $aLists
* @param string $sClass Object class to find a list for
* @param string $sList List name to find
*
* @return string[] Array of attribute codes
*
* @throws \CoreException
*/
public static function GetLoadedListFromClass($aLists, $sClass, $sList = 'default')
{
$aLists = $combodoPortalInstanceConf['lists'];
$aList = null;
$aFoundList = null;
$aAttCodes = array();
// We try to find the list for that class
if (isset($aLists[$sClass]) && isset($aLists[$sClass][$sList]))
{
$aList = $aLists[$sClass][$sList];
$aFoundList = $aLists[$sClass][$sList];
}
// Else we try to found the default list for that class
elseif (isset($aLists[$sClass]) && isset($aLists[$sClass]['default']))
{
$aList = $aLists[$sClass]['default'];
$aFoundList = $aLists[$sClass]['default'];
}
// If not found, we try find one from the closest parent class
else
@@ -737,22 +736,22 @@ class ApplicationHelper
// Trying to find the right list
if (isset($aLists[$sParentClass]) && isset($aLists[$sParentClass][$sList]))
{
$aList = $aLists[$sParentClass][$sList];
$aFoundList = $aLists[$sParentClass][$sList];
break;
}
// Or the default list
elseif (isset($aLists[$sParentClass]) && isset($aLists[$sParentClass]['default']))
{
$aList = $aLists[$sParentClass]['default'];
$aFoundList = $aLists[$sParentClass]['default'];
break;
}
}
}
// If found, we flatten the list to keep only the attribute codes (not the rank)
if ($aList !== null)
if ($aFoundList !== null)
{
foreach ($aList as $aItem)
foreach ($aFoundList as $aItem)
{
$aAttCodes[] = $aItem['att_code'];
}

View File

@@ -24,6 +24,7 @@
namespace Combodo\iTop\Portal\Helper;
use Combodo\iTop\Portal\Form\ObjectFormManager;
use Combodo\iTop\Portal\Twig\AppExtension;
use Combodo\iTop\Renderer\Bootstrap\BsFormRenderer;
use DBObjectSet;
use Dict;
@@ -36,6 +37,8 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Twig_Environment;
use Twig_Loader_Array;
use URLButtonItem;
use UserRights;
@@ -66,22 +69,25 @@ class ObjectFormHandlerHelper
private $aCombodoPortalInstanceConf;
/** @var string $sPortalId */
private $sPortalId;
/** @var \Combodo\iTop\Portal\Twig\AppExtension */
private $oAppExtension;
/** @var \Symfony\Component\DependencyInjection\ContainerInterface */
private $oContainer;
/**
* 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 \Symfony\Component\Routing\Generator\UrlGeneratorInterface $oUrlGenerator
* @param array $aCombodoPortalInstanceConf
* @param string $sPortalId
* @param \Symfony\Component\DependencyInjection\ContainerInterface $oContainer
* @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 \Symfony\Component\Routing\Generator\UrlGeneratorInterface $oUrlGenerator
* @param array $aCombodoPortalInstanceConf
* @param string $sPortalId
* @param \Combodo\iTop\Portal\Twig\AppExtension $oAppExtension
* @param \Symfony\Component\DependencyInjection\ContainerInterface $oContainer
*/
public function __construct(RequestManipulatorHelper $oRequestManipulator, ContextManipulatorHelper $oContextManipulator, ScopeValidatorHelper $oScopeValidator, SecurityHelper $oSecurityHelper, UrlGeneratorInterface $oUrlGenerator, $aCombodoPortalInstanceConf, $sPortalId, ContainerInterface $oContainer)
public function __construct(RequestManipulatorHelper $oRequestManipulator, ContextManipulatorHelper $oContextManipulator, ScopeValidatorHelper $oScopeValidator, SecurityHelper $oSecurityHelper, UrlGeneratorInterface $oUrlGenerator, $aCombodoPortalInstanceConf, $sPortalId, AppExtension $oAppExtension, ContainerInterface $oContainer)
{
$this->oRequestManipulator = $oRequestManipulator;
$this->oContextManipulator = $oContextManipulator;
@@ -90,6 +96,7 @@ class ObjectFormHandlerHelper
$this->oUrlGenerator = $oUrlGenerator;
$this->aCombodoPortalInstanceConf = $aCombodoPortalInstanceConf;
$this->sPortalId = $sPortalId;
$this->oAppExtension = $oAppExtension;
$this->oContainer = $oContainer;
}
@@ -354,4 +361,24 @@ class ObjectFormHandlerHelper
return $aFormData;
}
public function RenderFormFromTwig($sId, $sTwigString, $aData)
{
// Creating sandbox twig env. to load and test the custom form template
$oTwig = new Twig_Environment(new Twig_Loader_Array( array($sId => $sTwigString) ));
// Manually registering filters and functions as we didn't find how to do it automatically
$aFilters = $this->oAppExtension->getFilters();
foreach($aFilters as $oFilter)
{
$oTwig->addFilter($oFilter);
}
$aFunctions = $this->oAppExtension->getFunctions();
foreach($aFunctions as $oFunction)
{
$oTwig->addFunction($oFunction);
}
return $oTwig->render($sId, $aData);
}
}