mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-21 16:22:20 +02:00
Merge branch 'support/3.2' into develop
This commit is contained in:
@@ -43,34 +43,34 @@ use ModuleDesign;
|
||||
abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
{
|
||||
/** @var string ENUM_DATA_LOADING_LAZY */
|
||||
const ENUM_DATA_LOADING_LAZY = 'lazy';
|
||||
public const ENUM_DATA_LOADING_LAZY = 'lazy';
|
||||
/** @var string ENUM_DATA_LOADING_FULL */
|
||||
const ENUM_DATA_LOADING_FULL = 'full';
|
||||
public const ENUM_DATA_LOADING_FULL = 'full';
|
||||
/** @var string ENUM_DATA_LOADING_AUTO */
|
||||
const ENUM_DATA_LOADING_AUTO = 'auto';
|
||||
public const ENUM_DATA_LOADING_AUTO = 'auto';
|
||||
|
||||
/** @var bool DEFAULT_MANDATORY */
|
||||
const DEFAULT_MANDATORY = true;
|
||||
public const DEFAULT_MANDATORY = true;
|
||||
/** @var bool DEFAULT_ACTIVE */
|
||||
const DEFAULT_ACTIVE = true;
|
||||
public const DEFAULT_ACTIVE = true;
|
||||
/** @var bool DEFAULT_VISIBLE */
|
||||
const DEFAULT_VISIBLE = true;
|
||||
public const DEFAULT_VISIBLE = true;
|
||||
/** @var float DEFAULT_RANK */
|
||||
const DEFAULT_RANK = 1.0;
|
||||
public const DEFAULT_RANK = 1.0;
|
||||
/** @var string|null DEFAULT_PAGE_TEMPLATE_PATH @deprecated since 3.2.1 */
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = null;
|
||||
public const DEFAULT_PAGE_TEMPLATE_PATH = null;
|
||||
/** @var string DEFAULT_TITLE */
|
||||
const DEFAULT_TITLE = '';
|
||||
public const DEFAULT_TITLE = '';
|
||||
/** @var string|null DEFAULT_DESCRIPTION */
|
||||
const DEFAULT_DESCRIPTION = null;
|
||||
public const DEFAULT_DESCRIPTION = null;
|
||||
/** @var string DEFAULT_DATA_LOADING */
|
||||
const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_AUTO;
|
||||
public const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_AUTO;
|
||||
/** @var string DEFAULT_ALLOWED_PROFILES_OQL */
|
||||
const DEFAULT_ALLOWED_PROFILES_OQL = '';
|
||||
public const DEFAULT_ALLOWED_PROFILES_OQL = '';
|
||||
/** @var string DEFAULT_DENIED_PROFILES_OQL */
|
||||
const DEFAULT_DENIED_PROFILES_OQL = '';
|
||||
public const DEFAULT_DENIED_PROFILES_OQL = '';
|
||||
/** @var string TEMPLATES_BASE_PATH */
|
||||
const TEMPLATES_BASE_PATH = 'itop-portal-base/portal/templates/bricks/';
|
||||
public const TEMPLATES_BASE_PATH = 'itop-portal-base/portal/templates/bricks/';
|
||||
|
||||
/** @var string $sId */
|
||||
protected $sId;
|
||||
@@ -105,8 +105,9 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'layout.html.twig'),
|
||||
$oTemplatesRegister->RegisterTemplates(
|
||||
self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH.'layout.html.twig'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -135,9 +136,9 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static function GetEnumDataLoadingValues()
|
||||
public static function GetEnumDataLoadingValues()
|
||||
{
|
||||
return array(self::ENUM_DATA_LOADING_LAZY, self::ENUM_DATA_LOADING_FULL, self::ENUM_DATA_LOADING_AUTO);
|
||||
return [self::ENUM_DATA_LOADING_LAZY, self::ENUM_DATA_LOADING_FULL, self::ENUM_DATA_LOADING_AUTO];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,8 +156,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
$this->sTitle = static::DEFAULT_TITLE;
|
||||
$this->sDescription = static::DEFAULT_DESCRIPTION;
|
||||
$this->sDataLoading = static::DEFAULT_DATA_LOADING;
|
||||
$this->aAllowedProfiles = array();
|
||||
$this->aDeniedProfiles = array();
|
||||
$this->aAllowedProfiles = [];
|
||||
$this->aDeniedProfiles = [];
|
||||
$this->sAllowedProfilesOql = static::DEFAULT_ALLOWED_PROFILES_OQL;
|
||||
$this->sDeniedProfilesOql = static::DEFAULT_DENIED_PROFILES_OQL;
|
||||
}
|
||||
@@ -297,8 +298,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
* Sets the brick id
|
||||
*
|
||||
* @param string $sId
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function SetId($sId)
|
||||
{
|
||||
@@ -310,8 +311,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
* Sets if the brick is mandatory
|
||||
*
|
||||
* @param boolean $bMandatory
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function SetMandatory($bMandatory)
|
||||
{
|
||||
@@ -336,8 +337,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
* Sets if the brick is active
|
||||
*
|
||||
* @param boolean $bActive
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function SetActive($bActive)
|
||||
{
|
||||
@@ -349,8 +350,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
* Sets the rank of the brick
|
||||
*
|
||||
* @param float $fRank
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function SetRank($fRank)
|
||||
{
|
||||
@@ -362,15 +363,15 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
* Sets the page template path of the brick
|
||||
*
|
||||
* @param string $sPageTemplatePath
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @deprecated since 3.2.1 use SetTemplatePath('page') instead
|
||||
*/
|
||||
public function SetPageTemplatePath($sPageTemplatePath)
|
||||
{
|
||||
$this->sPageTemplatePath = $sPageTemplatePath;
|
||||
$this->SetTemplatePath( 'page', $sPageTemplatePath);
|
||||
$this->SetTemplatePath('page', $sPageTemplatePath);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -378,8 +379,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
* Sets the title of the brick
|
||||
*
|
||||
* @param string $sTitle
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function SetTitle($sTitle)
|
||||
{
|
||||
@@ -391,8 +392,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
* Sets the description of the brick
|
||||
*
|
||||
* @param string $sDescription
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function SetDescription($sDescription)
|
||||
{
|
||||
@@ -404,8 +405,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
* Sets the data loading mode of the brick
|
||||
*
|
||||
* @param string $sDataLoading
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function SetDataLoading($sDataLoading)
|
||||
{
|
||||
@@ -444,8 +445,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
* Sets the allowed profiles oql query for the brick
|
||||
*
|
||||
* @param string $sAllowedProfilesOql
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function SetAllowedProfilesOql($sAllowedProfilesOql)
|
||||
{
|
||||
@@ -457,8 +458,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
* Sets the denied profiles oql query for the brick
|
||||
*
|
||||
* @param string $sDeniedProfilesOql
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function SetDeniedProfilesOql($sDeniedProfilesOql)
|
||||
{
|
||||
@@ -489,8 +490,7 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
*/
|
||||
public function RemoveAllowedProfile($sProfile)
|
||||
{
|
||||
if (isset($this->aAllowedProfiles[$sProfile]))
|
||||
{
|
||||
if (isset($this->aAllowedProfiles[$sProfile])) {
|
||||
unset($this->aAllowedProfiles[$sProfile]);
|
||||
}
|
||||
|
||||
@@ -530,8 +530,7 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
*/
|
||||
public function RemoveDeniedProfile($sProfile)
|
||||
{
|
||||
if (isset($this->aDeniedProfiles[$sProfile]))
|
||||
{
|
||||
if (isset($this->aDeniedProfiles[$sProfile])) {
|
||||
unset($this->aDeniedProfiles[$sProfile]);
|
||||
}
|
||||
|
||||
@@ -560,7 +559,7 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
*/
|
||||
public function IsGrantedForProfile($sProfile)
|
||||
{
|
||||
return $this->IsGrantedForProfiles(array($sProfile));
|
||||
return $this->IsGrantedForProfiles([$sProfile]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -577,27 +576,21 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
{
|
||||
$bGranted = true;
|
||||
|
||||
if ($this->HasAllowedProfiles())
|
||||
{
|
||||
if ($this->HasAllowedProfiles()) {
|
||||
// We set $bGranted to false as the user must explicitly have an allowed profile to be granted
|
||||
$bGranted = false;
|
||||
|
||||
foreach ($aProfiles as $sProfile)
|
||||
{
|
||||
if (in_array($sProfile, $this->aAllowedProfiles))
|
||||
{
|
||||
foreach ($aProfiles as $sProfile) {
|
||||
if (in_array($sProfile, $this->aAllowedProfiles)) {
|
||||
$bGranted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->HasDeniedProfiles())
|
||||
{
|
||||
foreach ($aProfiles as $sProfile)
|
||||
{
|
||||
if (in_array($sProfile, $this->aDeniedProfiles))
|
||||
{
|
||||
if ($this->HasDeniedProfiles()) {
|
||||
foreach ($aProfiles as $sProfile) {
|
||||
if (in_array($sProfile, $this->aDeniedProfiles)) {
|
||||
$bGranted = false;
|
||||
break;
|
||||
}
|
||||
@@ -629,18 +622,15 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
public function LoadFromXml(DesignElement $oMDElement)
|
||||
{
|
||||
// Checking mandatory elements
|
||||
if (!$oMDElement->hasAttribute('id'))
|
||||
{
|
||||
if (!$oMDElement->hasAttribute('id')) {
|
||||
throw new DOMFormatException('Brick node must have both id and xsi:type attributes defined', 0, null, $oMDElement);
|
||||
}
|
||||
$this->SetId($oMDElement->getAttribute('id'));
|
||||
|
||||
// Checking others elements
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
|
||||
{
|
||||
switch ($oBrickSubNode->nodeName)
|
||||
{
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode) {
|
||||
switch ($oBrickSubNode->nodeName) {
|
||||
case 'mandatory':
|
||||
$this->SetMandatory(($oBrickSubNode->GetText() === 'no') ? false : true);
|
||||
break;
|
||||
@@ -649,15 +639,13 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
break;
|
||||
case 'rank':
|
||||
$oOptionalNode = $oBrickSubNode->GetOptionalElement('default');
|
||||
if ($oOptionalNode !== null)
|
||||
{
|
||||
if ($oOptionalNode !== null) {
|
||||
$this->SetRank((float)$oOptionalNode->GetText(static::DEFAULT_RANK));
|
||||
}
|
||||
break;
|
||||
case 'templates':
|
||||
$oTemplateNodeList = $oBrickSubNode->GetNodes('template[@id='.ModuleDesign::XPathQuote('page').']');
|
||||
if ($oTemplateNodeList->length > 0)
|
||||
{
|
||||
if ($oTemplateNodeList->length > 0) {
|
||||
/** @var \Combodo\iTop\DesignElement $oTemplateNode */
|
||||
$oTemplateNode = $oTemplateNodeList->item(0);
|
||||
$this->SetTemplatePath('page', $oTemplateNode->GetText(static::DEFAULT_PAGE_TEMPLATE_PATH));
|
||||
@@ -665,8 +653,7 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
break;
|
||||
case 'title':
|
||||
$oOptionalNode = $oBrickSubNode->GetOptionalElement('default');
|
||||
if ($oOptionalNode !== null)
|
||||
{
|
||||
if ($oOptionalNode !== null) {
|
||||
$this->SetTitle($oOptionalNode->GetText(static::DEFAULT_TITLE));
|
||||
}
|
||||
break;
|
||||
@@ -678,16 +665,17 @@ abstract class AbstractBrick implements TemplatesProviderInterface
|
||||
break;
|
||||
case 'security':
|
||||
/** @var \Combodo\iTop\DesignElement $oSecurityNode */
|
||||
foreach ($oBrickSubNode->GetNodes('*') as $oSecurityNode)
|
||||
{
|
||||
if ($oSecurityNode->nodeType === XML_TEXT_NODE && $oSecurityNode->GetText() === '')
|
||||
{
|
||||
throw new DOMFormatException('Brick security node "'.$oSecurityNode->nodeName.'" must contain an OQL query, it cannot be empty',
|
||||
null, null, $oMDElement);
|
||||
foreach ($oBrickSubNode->GetNodes('*') as $oSecurityNode) {
|
||||
if ($oSecurityNode->nodeType === XML_TEXT_NODE && $oSecurityNode->GetText() === '') {
|
||||
throw new DOMFormatException(
|
||||
'Brick security node "'.$oSecurityNode->nodeName.'" must contain an OQL query, it cannot be empty',
|
||||
null,
|
||||
null,
|
||||
$oMDElement
|
||||
);
|
||||
}
|
||||
|
||||
switch ($oSecurityNode->nodeName)
|
||||
{
|
||||
switch ($oSecurityNode->nodeName) {
|
||||
case 'denied_profiles':
|
||||
$this->SetDeniedProfilesOql($oSecurityNode->GetText());
|
||||
break;
|
||||
|
||||
@@ -38,11 +38,11 @@ use DOMFormatException;
|
||||
class AggregatePageBrick extends PortalBrick
|
||||
{
|
||||
// Overloaded constants
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-tachometer-alt';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-tachometer-alt fa-2x';
|
||||
public const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-tachometer-alt';
|
||||
public const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-tachometer-alt fa-2x';
|
||||
|
||||
/** @var string @deprecated since 3.2.1 */
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/aggregate-page/layout.html.twig';
|
||||
public const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/aggregate-page/layout.html.twig';
|
||||
|
||||
// Overloaded variables
|
||||
public static $sRouteName = 'p_aggregatepage_brick';
|
||||
@@ -50,21 +50,22 @@ class AggregatePageBrick extends PortalBrick
|
||||
/**
|
||||
* @var string[] list of bricks to use, ordered by rank (key=id, value=rank)
|
||||
*/
|
||||
private $aAggregatePageBricks = array();
|
||||
private $aAggregatePageBricks = [];
|
||||
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'aggregate-page/layout.html.twig')
|
||||
$oTemplatesRegister->RegisterTemplates(
|
||||
self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH.'aggregate-page/layout.html.twig')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* AggregatePageBrick constructor.
|
||||
*/
|
||||
function __construct()
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
@@ -83,25 +84,24 @@ class AggregatePageBrick extends PortalBrick
|
||||
parent::LoadFromXml($oMDElement);
|
||||
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
|
||||
{
|
||||
switch ($oBrickSubNode->nodeName)
|
||||
{
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode) {
|
||||
switch ($oBrickSubNode->nodeName) {
|
||||
case 'aggregate_page_bricks':
|
||||
/** @var \Combodo\iTop\DesignElement $oAggregatePageBrickNode */
|
||||
foreach ($oBrickSubNode->GetNodes('./aggregate_page_brick') as $oAggregatePageBrickNode)
|
||||
{
|
||||
if (!$oAggregatePageBrickNode->hasAttribute('id'))
|
||||
{
|
||||
throw new DOMFormatException('AggregatePageBrick : must have an id attribute', 0,
|
||||
null, $oAggregatePageBrickNode);
|
||||
foreach ($oBrickSubNode->GetNodes('./aggregate_page_brick') as $oAggregatePageBrickNode) {
|
||||
if (!$oAggregatePageBrickNode->hasAttribute('id')) {
|
||||
throw new DOMFormatException(
|
||||
'AggregatePageBrick : must have an id attribute',
|
||||
0,
|
||||
null,
|
||||
$oAggregatePageBrickNode
|
||||
);
|
||||
}
|
||||
$sBrickName = $oAggregatePageBrickNode->getAttribute('id');
|
||||
|
||||
$iBrickRank = static::DEFAULT_RANK;
|
||||
$oOptionalNode = $oAggregatePageBrickNode->GetOptionalElement('rank');
|
||||
if ($oOptionalNode !== null)
|
||||
{
|
||||
if ($oOptionalNode !== null) {
|
||||
$iBrickRank = $oOptionalNode->GetText();
|
||||
}
|
||||
|
||||
@@ -123,5 +123,4 @@ class AggregatePageBrick extends PortalBrick
|
||||
return $this->aAggregatePageBricks;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -67,8 +68,8 @@ class BrickCollection
|
||||
$this->aAllowedBricks = null;
|
||||
$this->iDisplayedInHome = 0;
|
||||
$this->iDisplayedInNavigationMenu = 0;
|
||||
$this->aHomeOrdering = array();
|
||||
$this->aNavigationMenuOrdering = array();
|
||||
$this->aHomeOrdering = [];
|
||||
$this->aNavigationMenuOrdering = [];
|
||||
|
||||
$this->Load();
|
||||
}
|
||||
@@ -84,8 +85,7 @@ class BrickCollection
|
||||
public function __call($method, $arguments)
|
||||
{
|
||||
// Made for cleaner/easier access from twig (eg. app['brick_collection'].bricks)
|
||||
switch ($method)
|
||||
{
|
||||
switch ($method) {
|
||||
case 'bricks':
|
||||
return $this->GetBricks();
|
||||
break;
|
||||
@@ -128,10 +128,8 @@ class BrickCollection
|
||||
*/
|
||||
public function GetBrickById($sId)
|
||||
{
|
||||
foreach ($this->GetBricks() as $oBrick)
|
||||
{
|
||||
if ($oBrick->GetId() === $sId)
|
||||
{
|
||||
foreach ($this->GetBricks() as $oBrick) {
|
||||
if ($oBrick->GetId() === $sId) {
|
||||
return $oBrick;
|
||||
}
|
||||
}
|
||||
@@ -146,19 +144,15 @@ class BrickCollection
|
||||
{
|
||||
$aRawBrickList = $this->GetRawBrickList();
|
||||
|
||||
foreach ($aRawBrickList as $oBrick)
|
||||
{
|
||||
foreach ($aRawBrickList as $oBrick) {
|
||||
ApplicationHelper::LoadBrickSecurity($oBrick);
|
||||
|
||||
if ($oBrick->GetActive() && $oBrick->IsGrantedForProfiles(UserRights::ListProfiles()))
|
||||
{
|
||||
if ($oBrick->GetActive() && $oBrick->IsGrantedForProfiles(UserRights::ListProfiles())) {
|
||||
$this->aAllowedBricks[] = $oBrick;
|
||||
if ($oBrick->GetVisibleHome())
|
||||
{
|
||||
if ($oBrick->GetVisibleHome()) {
|
||||
$this->iDisplayedInHome++;
|
||||
}
|
||||
if ($oBrick->GetVisibleNavigationMenu())
|
||||
{
|
||||
if ($oBrick->GetVisibleNavigationMenu()) {
|
||||
$this->iDisplayedInNavigationMenu++;
|
||||
}
|
||||
}
|
||||
@@ -191,35 +185,30 @@ class BrickCollection
|
||||
*/
|
||||
private function GetRawBrickList()
|
||||
{
|
||||
$aBricks = array();
|
||||
$aBricks = [];
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickNode */
|
||||
foreach ($this->oModuleDesign->GetNodes('/module_design/bricks/brick') as $oBrickNode)
|
||||
{
|
||||
foreach ($this->oModuleDesign->GetNodes('/module_design/bricks/brick') as $oBrickNode) {
|
||||
$sBrickClass = $oBrickNode->getAttribute('xsi:type');
|
||||
try
|
||||
{
|
||||
if (class_exists($sBrickClass))
|
||||
{
|
||||
try {
|
||||
if (class_exists($sBrickClass)) {
|
||||
/** @var \Combodo\iTop\Portal\Brick\PortalBrick $oBrick */
|
||||
$oBrick = new $sBrickClass();
|
||||
|
||||
|
||||
// Load the brick specific properties from its XML definition
|
||||
$oBrick->LoadFromXml($oBrickNode);
|
||||
|
||||
$aBricks[] = $oBrick;
|
||||
} else {
|
||||
throw new DOMFormatException(
|
||||
'Unknown brick class "'.$sBrickClass.'" from xsi:type attribute',
|
||||
null,
|
||||
null,
|
||||
$oBrickNode
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('Unknown brick class "'.$sBrickClass.'" from xsi:type attribute', null,
|
||||
null, $oBrickNode);
|
||||
}
|
||||
}
|
||||
catch (DOMFormatException $e)
|
||||
{
|
||||
} catch (DOMFormatException $e) {
|
||||
throw new Exception('Could not create brick ('.$sBrickClass.') from XML because of a DOM problem : '.$e->getMessage());
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
throw new Exception('Could not create brick ('.$sBrickClass.') from XML : '.$oBrickNode->Dump().' '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
@@ -227,4 +216,4 @@ class BrickCollection
|
||||
return $aBricks;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -30,5 +31,4 @@ use Exception;
|
||||
*/
|
||||
class BrickNotFoundException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,77 +35,76 @@ use DOMFormatException;
|
||||
class BrowseBrick extends PortalBrick
|
||||
{
|
||||
/**
|
||||
* @var string DEFAULT_PAGE_TEMPLATE_PATH
|
||||
* @var string DEFAULT_PAGE_TEMPLATE_PATH
|
||||
* @deprecated 3.2.1
|
||||
*/
|
||||
const DEFAULT_MODE_LIST_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_list.html.twig';
|
||||
public const DEFAULT_MODE_LIST_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_list.html.twig';
|
||||
/**
|
||||
* @var string DEFAULT_MODE_MOSAIC_TEMPLATE_PATH
|
||||
* @deprecated 3.2.1
|
||||
*/
|
||||
const DEFAULT_MODE_MOSAIC_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_mosaic.html.twig';
|
||||
public const DEFAULT_MODE_MOSAIC_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_mosaic.html.twig';
|
||||
/**
|
||||
* @var string DEFAULT_MODE_TREE_TEMPLATE_PATH
|
||||
* @deprecated 3.2.1
|
||||
*/
|
||||
const DEFAULT_MODE_TREE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_tree.html.twig';
|
||||
|
||||
public const DEFAULT_MODE_TREE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_tree.html.twig';
|
||||
|
||||
/** @var string ENUM_BROWSE_MODE_LIST */
|
||||
const ENUM_BROWSE_MODE_LIST = 'list';
|
||||
public const ENUM_BROWSE_MODE_LIST = 'list';
|
||||
/** @var string ENUM_BROWSE_MODE_TREE */
|
||||
const ENUM_BROWSE_MODE_TREE = 'tree';
|
||||
public const ENUM_BROWSE_MODE_TREE = 'tree';
|
||||
/** @var string ENUM_BROWSE_MODE_MOSAIC */
|
||||
const ENUM_BROWSE_MODE_MOSAIC = 'mosaic';
|
||||
public const ENUM_BROWSE_MODE_MOSAIC = 'mosaic';
|
||||
|
||||
/** @var string ENUM_ACTION_VIEW */
|
||||
const ENUM_ACTION_VIEW = 'view';
|
||||
public const ENUM_ACTION_VIEW = 'view';
|
||||
/** @var string ENUM_ACTION_EDIT */
|
||||
const ENUM_ACTION_EDIT = 'edit';
|
||||
public const ENUM_ACTION_EDIT = 'edit';
|
||||
/** @var string ENUM_ACTION_DRILLDOWN */
|
||||
const ENUM_ACTION_DRILLDOWN = 'drilldown';
|
||||
public const ENUM_ACTION_DRILLDOWN = 'drilldown';
|
||||
/** @var string ENUM_ACTION_CREATE_FROM_THIS */
|
||||
const ENUM_ACTION_CREATE_FROM_THIS = 'create_from_this';
|
||||
public const ENUM_ACTION_CREATE_FROM_THIS = 'create_from_this';
|
||||
|
||||
/** @var string ENUM_ACTION_ICON_CLASS_VIEW */
|
||||
const ENUM_ACTION_ICON_CLASS_VIEW = 'glyphicon glyphicon-list-alt';
|
||||
public const ENUM_ACTION_ICON_CLASS_VIEW = 'glyphicon glyphicon-list-alt';
|
||||
/** @var string ENUM_ACTION_ICON_CLASS_EDIT */
|
||||
const ENUM_ACTION_ICON_CLASS_EDIT = 'glyphicon glyphicon-pencil';
|
||||
public const ENUM_ACTION_ICON_CLASS_EDIT = 'glyphicon glyphicon-pencil';
|
||||
/** @var string ENUM_ACTION_ICON_CLASS_DRILLDOWN */
|
||||
const ENUM_ACTION_ICON_CLASS_DRILLDOWN = 'glyphicon glyphicon-menu-down';
|
||||
public const ENUM_ACTION_ICON_CLASS_DRILLDOWN = 'glyphicon glyphicon-menu-down';
|
||||
/** @var string ENUM_ACTION_ICON_CLASS_CREATE_FROM_THIS */
|
||||
const ENUM_ACTION_ICON_CLASS_CREATE_FROM_THIS = 'glyphicon glyphicon-edit';
|
||||
public const ENUM_ACTION_ICON_CLASS_CREATE_FROM_THIS = 'glyphicon glyphicon-edit';
|
||||
|
||||
/** @var string ENUM_FACTORY_TYPE_METHOD */
|
||||
const ENUM_FACTORY_TYPE_METHOD = 'method';
|
||||
public const ENUM_FACTORY_TYPE_METHOD = 'method';
|
||||
/** @var string ENUM_FACTORY_TYPE_CLASS */
|
||||
const ENUM_FACTORY_TYPE_CLASS = 'class';
|
||||
public const ENUM_FACTORY_TYPE_CLASS = 'class';
|
||||
|
||||
// Overloaded constants
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-map';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-map fa-2x';
|
||||
const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_FULL;
|
||||
public const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-map';
|
||||
public const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-map fa-2x';
|
||||
public const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_FULL;
|
||||
|
||||
/** @var string DEFAULT_LEVEL_NAME_ATT */
|
||||
const DEFAULT_LEVEL_NAME_ATT = 'name';
|
||||
public const DEFAULT_LEVEL_NAME_ATT = 'name';
|
||||
/** @var string DEFAULT_BROWSE_MODE */
|
||||
const DEFAULT_BROWSE_MODE = self::ENUM_BROWSE_MODE_LIST;
|
||||
public const DEFAULT_BROWSE_MODE = self::ENUM_BROWSE_MODE_LIST;
|
||||
/** @var string DEFAULT_ACTION */
|
||||
const DEFAULT_ACTION = self::ENUM_ACTION_DRILLDOWN;
|
||||
public const DEFAULT_ACTION = self::ENUM_ACTION_DRILLDOWN;
|
||||
/** @var string DEFAULT_ACTION_OPENING_TARGET */
|
||||
const DEFAULT_ACTION_OPENING_TARGET = self::ENUM_OPENING_TARGET_MODAL;
|
||||
public const DEFAULT_ACTION_OPENING_TARGET = self::ENUM_OPENING_TARGET_MODAL;
|
||||
/** @var int DEFAULT_LIST_LENGTH */
|
||||
const DEFAULT_LIST_LENGTH = 20;
|
||||
public const DEFAULT_LIST_LENGTH = 20;
|
||||
|
||||
// Overloaded variables
|
||||
public static $sRouteName = 'p_browse_brick';
|
||||
|
||||
/** @var array $aBrowseModes */
|
||||
public static $aBrowseModes = array(
|
||||
public static $aBrowseModes = [
|
||||
self::ENUM_BROWSE_MODE_LIST,
|
||||
self::ENUM_BROWSE_MODE_TREE,
|
||||
self::ENUM_BROWSE_MODE_MOSAIC,
|
||||
);
|
||||
];
|
||||
|
||||
/** @var array $aLevels */
|
||||
protected $aLevels;
|
||||
@@ -120,11 +119,12 @@ class BrowseBrick extends PortalBrick
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'browse/layout.html.twig'),
|
||||
TemplateDefinitionDto::Create('page_list', static::TEMPLATES_BASE_PATH . 'browse/mode_list.html.twig'),
|
||||
TemplateDefinitionDto::Create('page_tree', static::TEMPLATES_BASE_PATH . 'browse/mode_tree.html.twig'),
|
||||
TemplateDefinitionDto::Create('page_mosaic', static::TEMPLATES_BASE_PATH . 'browse/mode_mosaic.html.twig'),
|
||||
$oTemplatesRegister->RegisterTemplates(
|
||||
self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH.'browse/layout.html.twig'),
|
||||
TemplateDefinitionDto::Create('page_list', static::TEMPLATES_BASE_PATH.'browse/mode_list.html.twig'),
|
||||
TemplateDefinitionDto::Create('page_tree', static::TEMPLATES_BASE_PATH.'browse/mode_tree.html.twig'),
|
||||
TemplateDefinitionDto::Create('page_mosaic', static::TEMPLATES_BASE_PATH.'browse/mode_mosaic.html.twig'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -135,15 +135,15 @@ class BrowseBrick extends PortalBrick
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->aLevels = array();
|
||||
$this->aAvailablesBrowseModes = array();
|
||||
$this->aLevels = [];
|
||||
$this->aAvailablesBrowseModes = [];
|
||||
$this->sDefaultBrowseMode = static::DEFAULT_BROWSE_MODE;
|
||||
$this->iDefaultListLength = static::DEFAULT_LIST_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare function to sort actions by their rank attribute
|
||||
*
|
||||
*
|
||||
* @param array $aAction1
|
||||
* @param array $aAction2
|
||||
*
|
||||
@@ -154,13 +154,10 @@ class BrowseBrick extends PortalBrick
|
||||
$bIsAction1RankSet = array_key_exists('rank', $aAction1);
|
||||
$bIsAction2RankSet = array_key_exists('rank', $aAction2);
|
||||
|
||||
if($bIsAction1RankSet && $bIsAction2RankSet)
|
||||
{
|
||||
//If a1 == a2 return 0, if a1 > a2 return 1 else return -1
|
||||
if ($bIsAction1RankSet && $bIsAction2RankSet) {
|
||||
//If a1 == a2 return 0, if a1 > a2 return 1 else return -1
|
||||
return ($aAction1['rank'] === $aAction2['rank'] ? $aAction1['default_rank'] - $aAction2['default_rank'] : $aAction1['rank'] - $aAction2['rank']);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
//If a1 == a2 == null return 0, if a2 is null and not a1 return 1 else return -1
|
||||
return ($bIsAction1RankSet === $bIsAction2RankSet ? $aAction1['default_rank'] - $aAction2['default_rank'] : ($bIsAction1RankSet ? 1 : -1));
|
||||
}
|
||||
@@ -255,7 +252,8 @@ class BrowseBrick extends PortalBrick
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetDefaultListLength($iDefaultListLength) {
|
||||
public function SetDefaultListLength($iDefaultListLength)
|
||||
{
|
||||
$this->iDefaultListLength = $iDefaultListLength;
|
||||
return $this;
|
||||
}
|
||||
@@ -293,8 +291,7 @@ class BrowseBrick extends PortalBrick
|
||||
*/
|
||||
public function RemoveLevels($sLevel)
|
||||
{
|
||||
if (isset($this->aLevels[$sLevel]))
|
||||
{
|
||||
if (isset($this->aLevels[$sLevel])) {
|
||||
unset($this->aLevels[$sLevel]);
|
||||
}
|
||||
|
||||
@@ -309,7 +306,7 @@ class BrowseBrick extends PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*/
|
||||
public function AddAvailableBrowseMode($sModeId, $aData = array())
|
||||
public function AddAvailableBrowseMode($sModeId, $aData = [])
|
||||
{
|
||||
$this->aAvailablesBrowseModes[$sModeId] = $aData;
|
||||
|
||||
@@ -325,8 +322,7 @@ class BrowseBrick extends PortalBrick
|
||||
*/
|
||||
public function RemoveAvailableBrowseMode($sModeId)
|
||||
{
|
||||
if (isset($this->aAvailablesBrowseModes[$sModeId]))
|
||||
{
|
||||
if (isset($this->aAvailablesBrowseModes[$sModeId])) {
|
||||
unset($this->aAvailablesBrowseModes[$sModeId]);
|
||||
}
|
||||
|
||||
@@ -349,43 +345,38 @@ class BrowseBrick extends PortalBrick
|
||||
|
||||
// Checking specific elements
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
|
||||
{
|
||||
switch ($oBrickSubNode->nodeName)
|
||||
{
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode) {
|
||||
switch ($oBrickSubNode->nodeName) {
|
||||
case 'levels':
|
||||
/** @var \Combodo\iTop\DesignElement $oLevelNode */
|
||||
foreach ($oBrickSubNode->GetNodes('*') as $oLevelNode)
|
||||
{
|
||||
if ($oLevelNode->nodeName === 'level')
|
||||
{
|
||||
foreach ($oBrickSubNode->GetNodes('*') as $oLevelNode) {
|
||||
if ($oLevelNode->nodeName === 'level') {
|
||||
$this->AddLevel($this->LoadLevelFromXml($oLevelNode));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'browse_modes':
|
||||
/** @var \Combodo\iTop\DesignElement $oBrowseModeNode */
|
||||
foreach ($oBrickSubNode->GetNodes('*') as $oBrowseModeNode)
|
||||
{
|
||||
switch ($oBrowseModeNode->nodeName)
|
||||
{
|
||||
foreach ($oBrickSubNode->GetNodes('*') as $oBrowseModeNode) {
|
||||
switch ($oBrowseModeNode->nodeName) {
|
||||
case 'availables':
|
||||
/** @var \Combodo\iTop\DesignElement $oModeNode */
|
||||
foreach ($oBrowseModeNode->GetNodes('*') as $oModeNode)
|
||||
{
|
||||
if (!$oModeNode->hasAttribute('id'))
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick: Browse mode must have a unique ID attribute', 0,
|
||||
null, $oModeNode);
|
||||
foreach ($oBrowseModeNode->GetNodes('*') as $oModeNode) {
|
||||
if (!$oModeNode->hasAttribute('id')) {
|
||||
throw new DOMFormatException(
|
||||
'BrowseBrick: Browse mode must have a unique ID attribute',
|
||||
0,
|
||||
null,
|
||||
$oModeNode
|
||||
);
|
||||
}
|
||||
|
||||
$sModeId = $oModeNode->getAttribute('id');
|
||||
$aModeData = array();
|
||||
$aModeData = [];
|
||||
|
||||
// Checking if the browse mode has a specific template
|
||||
$oTemplateNode = $oModeNode->GetOptionalElement('template');
|
||||
if (($oTemplateNode !== null) && ($oTemplateNode->GetText() !== null))
|
||||
{
|
||||
if (($oTemplateNode !== null) && ($oTemplateNode->GetText() !== null)) {
|
||||
$this->SetTemplatePath('page_'.$sModeId, $oTemplateNode->GetText());
|
||||
}
|
||||
|
||||
@@ -400,12 +391,12 @@ class BrowseBrick extends PortalBrick
|
||||
break;
|
||||
case 'default_list_length':
|
||||
$iNodeDefaultListLength = (int)$oBrickSubNode->GetText(static::DEFAULT_LIST_LENGTH);
|
||||
if(!in_array($iNodeDefaultListLength, array(10, 20, 50, -1),true))
|
||||
{
|
||||
if (!in_array($iNodeDefaultListLength, [10, 20, 50, -1], true)) {
|
||||
throw new DOMFormatException(
|
||||
'BrowseBrick: Default list length must be contained in list length options. Expected -1/10/20/50, '.$iNodeDefaultListLength.' given.',
|
||||
null,
|
||||
null, $oBrickSubNode
|
||||
null,
|
||||
$oBrickSubNode
|
||||
);
|
||||
}
|
||||
$this->SetDefaultListLength($iNodeDefaultListLength);
|
||||
@@ -414,19 +405,18 @@ class BrowseBrick extends PortalBrick
|
||||
}
|
||||
|
||||
// Checking that the brick has at least a browse mode
|
||||
if (count($this->GetAvailablesBrowseModes()) === 0)
|
||||
{
|
||||
if (count($this->GetAvailablesBrowseModes()) === 0) {
|
||||
throw new DOMFormatException('BrowseBrick : Must have at least one browse mode', 0, null, $oMDElement);
|
||||
}
|
||||
// Checking that default browse mode in among the available
|
||||
if (!in_array($this->sDefaultBrowseMode, array_keys($this->aAvailablesBrowseModes)))
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : Default browse mode "'.$this->sDefaultBrowseMode.'" must be one of the available browse modes ('.implode(', ',
|
||||
$this->aAvailablesBrowseModes).')', null, null, $oMDElement);
|
||||
if (!in_array($this->sDefaultBrowseMode, array_keys($this->aAvailablesBrowseModes))) {
|
||||
throw new DOMFormatException('BrowseBrick : Default browse mode "'.$this->sDefaultBrowseMode.'" must be one of the available browse modes ('.implode(
|
||||
', ',
|
||||
$this->aAvailablesBrowseModes
|
||||
).')', null, null, $oMDElement);
|
||||
}
|
||||
// Checking that the brick has at least a level
|
||||
if (count($this->GetLevels()) === 0)
|
||||
{
|
||||
if (count($this->GetLevels()) === 0) {
|
||||
throw new DOMFormatException('BrowseBrick : Must have at least one level', 0, null, $oMDElement);
|
||||
}
|
||||
|
||||
@@ -444,39 +434,41 @@ class BrowseBrick extends PortalBrick
|
||||
*/
|
||||
protected function LoadLevelFromXml(DesignElement $oMDElement)
|
||||
{
|
||||
$aLevel = array(
|
||||
$aLevel = [
|
||||
'parent_att' => null,
|
||||
'tooltip_att' => null,
|
||||
'description_att' => null,
|
||||
'image_att' => null,
|
||||
'title' => null,
|
||||
'name_att' => static::DEFAULT_LEVEL_NAME_ATT,
|
||||
'fields' => array(),
|
||||
'actions' => array('default' => array('type' => static::DEFAULT_ACTION, 'rules' => array())),
|
||||
);
|
||||
'fields' => [],
|
||||
'actions' => ['default' => ['type' => static::DEFAULT_ACTION, 'rules' => []]],
|
||||
];
|
||||
|
||||
// Getting level ID
|
||||
if ($oMDElement->hasAttribute('id') && $oMDElement->getAttribute('id') !== '')
|
||||
{
|
||||
if ($oMDElement->hasAttribute('id') && $oMDElement->getAttribute('id') !== '') {
|
||||
$aLevel['id'] = $oMDElement->getAttribute('id');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : level tag without "id" attribute. It must have one and it must not be empty', null,
|
||||
null, $oMDElement);
|
||||
} else {
|
||||
throw new DOMFormatException(
|
||||
'BrowseBrick : level tag without "id" attribute. It must have one and it must not be empty',
|
||||
null,
|
||||
null,
|
||||
$oMDElement
|
||||
);
|
||||
}
|
||||
// Getting level properties
|
||||
/** @var \Combodo\iTop\DesignElement $oLevelPropertyNode */
|
||||
foreach ($oMDElement->GetNodes('*') as $oLevelPropertyNode)
|
||||
{
|
||||
switch ($oLevelPropertyNode->nodeName)
|
||||
{
|
||||
foreach ($oMDElement->GetNodes('*') as $oLevelPropertyNode) {
|
||||
switch ($oLevelPropertyNode->nodeName) {
|
||||
case 'class':
|
||||
$sClass = $oLevelPropertyNode->GetText();
|
||||
if ($sClass === '')
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : class tag is empty. Must contain Classname', null, null,
|
||||
$oLevelPropertyNode);
|
||||
if ($sClass === '') {
|
||||
throw new DOMFormatException(
|
||||
'BrowseBrick : class tag is empty. Must contain Classname',
|
||||
null,
|
||||
null,
|
||||
$oLevelPropertyNode
|
||||
);
|
||||
}
|
||||
|
||||
$aLevel['oql'] = 'SELECT '.$sClass;
|
||||
@@ -484,10 +476,13 @@ class BrowseBrick extends PortalBrick
|
||||
|
||||
case 'oql':
|
||||
$sOql = $oLevelPropertyNode->GetText();
|
||||
if ($sOql === '')
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : oql tag is empty. Must contain OQL statement', null, null,
|
||||
$oLevelPropertyNode);
|
||||
if ($sOql === '') {
|
||||
throw new DOMFormatException(
|
||||
'BrowseBrick : oql tag is empty. Must contain OQL statement',
|
||||
null,
|
||||
null,
|
||||
$oLevelPropertyNode
|
||||
);
|
||||
}
|
||||
|
||||
$aLevel['oql'] = $sOql;
|
||||
@@ -508,25 +503,23 @@ class BrowseBrick extends PortalBrick
|
||||
case 'fields':
|
||||
$sTagName = $oLevelPropertyNode->nodeName;
|
||||
|
||||
if ($oLevelPropertyNode->hasChildNodes())
|
||||
{
|
||||
$aLevel[$sTagName] = array();
|
||||
if ($oLevelPropertyNode->hasChildNodes()) {
|
||||
$aLevel[$sTagName] = [];
|
||||
/** @var \Combodo\iTop\DesignElement $oFieldNode */
|
||||
foreach ($oLevelPropertyNode->GetNodes('*') as $oFieldNode)
|
||||
{
|
||||
if ($oFieldNode->hasAttribute('id') && $oFieldNode->getAttribute('id') !== '')
|
||||
{
|
||||
$aLevel[$sTagName][$oFieldNode->getAttribute('id')] = array('hidden' => false);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/* tag must have an "id" attribute and it must not be empty',
|
||||
null, null, $oFieldNode);
|
||||
foreach ($oLevelPropertyNode->GetNodes('*') as $oFieldNode) {
|
||||
if ($oFieldNode->hasAttribute('id') && $oFieldNode->getAttribute('id') !== '') {
|
||||
$aLevel[$sTagName][$oFieldNode->getAttribute('id')] = ['hidden' => false];
|
||||
} else {
|
||||
throw new DOMFormatException(
|
||||
'BrowseBrick : '.$sTagName.'/* tag must have an "id" attribute and it must not be empty',
|
||||
null,
|
||||
null,
|
||||
$oFieldNode
|
||||
);
|
||||
}
|
||||
|
||||
$oFieldSubNode = $oFieldNode->GetOptionalElement('hidden');
|
||||
if ($oFieldSubNode !== null)
|
||||
{
|
||||
if ($oFieldSubNode !== null) {
|
||||
$aLevel[$sTagName][$oFieldNode->getAttribute('id')]['hidden'] = ($oFieldSubNode->GetText() === 'true') ? true : false;
|
||||
}
|
||||
}
|
||||
@@ -536,94 +529,84 @@ class BrowseBrick extends PortalBrick
|
||||
case 'actions':
|
||||
$sTagName = $oLevelPropertyNode->nodeName;
|
||||
|
||||
if ($oLevelPropertyNode->hasChildNodes())
|
||||
{
|
||||
$aLevel[$sTagName] = array();
|
||||
if ($oLevelPropertyNode->hasChildNodes()) {
|
||||
$aLevel[$sTagName] = [];
|
||||
$iActionDefaultRank = 0;
|
||||
/** @var \Combodo\iTop\DesignElement $oActionNode */
|
||||
foreach ($oLevelPropertyNode->GetNodes('*') as $oActionNode)
|
||||
{
|
||||
if ($oActionNode->hasAttribute('id') && $oActionNode->getAttribute('id') !== '')
|
||||
{
|
||||
$aTmpAction = array(
|
||||
foreach ($oLevelPropertyNode->GetNodes('*') as $oActionNode) {
|
||||
if ($oActionNode->hasAttribute('id') && $oActionNode->getAttribute('id') !== '') {
|
||||
$aTmpAction = [
|
||||
'type' => null,
|
||||
'rules' => array(),
|
||||
);
|
||||
'rules' => [],
|
||||
];
|
||||
|
||||
// Action type
|
||||
$aTmpAction['type'] = ($oActionNode->hasAttribute('xsi:type') && $oActionNode->getAttribute('xsi:type') !== '') ? $oActionNode->getAttribute('xsi:type') : static::DEFAULT_ACTION;
|
||||
// Action destination class
|
||||
if ($aTmpAction['type'] === static::ENUM_ACTION_CREATE_FROM_THIS)
|
||||
{
|
||||
if ($oActionNode->GetOptionalElement('factory_method') !== null)
|
||||
{
|
||||
$aTmpAction['factory'] = array(
|
||||
if ($aTmpAction['type'] === static::ENUM_ACTION_CREATE_FROM_THIS) {
|
||||
if ($oActionNode->GetOptionalElement('factory_method') !== null) {
|
||||
$aTmpAction['factory'] = [
|
||||
'type' => static::ENUM_FACTORY_TYPE_METHOD,
|
||||
'value' => $oActionNode->GetOptionalElement('factory_method')->GetText(),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aTmpAction['factory'] = array(
|
||||
];
|
||||
} else {
|
||||
$aTmpAction['factory'] = [
|
||||
'type' => static::ENUM_FACTORY_TYPE_CLASS,
|
||||
'value' => $oActionNode->GetUniqueElement('class')->GetText(),
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
// Action title
|
||||
$oActionTitleNode = $oActionNode->GetOptionalElement('title');
|
||||
if ($oActionTitleNode !== null)
|
||||
{
|
||||
if ($oActionTitleNode !== null) {
|
||||
$aTmpAction['title'] = $oActionTitleNode->GetText();
|
||||
}
|
||||
// Action icon class
|
||||
$oActionIconClassNode = $oActionNode->GetOptionalElement('icon_class');
|
||||
if ($oActionIconClassNode !== null)
|
||||
{
|
||||
if ($oActionIconClassNode !== null) {
|
||||
$aTmpAction['icon_class'] = $oActionIconClassNode->GetText();
|
||||
}
|
||||
// Action opening target
|
||||
$oActionOpeningTargetNode = $oActionNode->GetOptionalElement('opening_target');
|
||||
if ($oActionOpeningTargetNode !== null)
|
||||
{
|
||||
if ($oActionOpeningTargetNode !== null) {
|
||||
$aTmpAction['opening_target'] = $oActionOpeningTargetNode->GetText(static::DEFAULT_ACTION_OPENING_TARGET);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$aTmpAction['opening_target'] = static::DEFAULT_ACTION_OPENING_TARGET;
|
||||
}
|
||||
// - Checking that opening target is among authorized modes
|
||||
if (!in_array($aTmpAction['opening_target'], static::$aOpeningTargets))
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/action/opening_target has a wrong value. "'.$aTmpAction['opening_target'].'" given, '.implode('|',
|
||||
static::$aOpeningTargets).' expected.', null, null, $oActionOpeningTargetNode);
|
||||
if (!in_array($aTmpAction['opening_target'], static::$aOpeningTargets)) {
|
||||
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/action/opening_target has a wrong value. "'.$aTmpAction['opening_target'].'" given, '.implode(
|
||||
'|',
|
||||
static::$aOpeningTargets
|
||||
).' expected.', null, null, $oActionOpeningTargetNode);
|
||||
}
|
||||
$oActionRankNode = $oActionNode->GetOptionalElement('rank');
|
||||
if ($oActionRankNode !== null)
|
||||
{
|
||||
if ($oActionRankNode !== null) {
|
||||
$aTmpAction['rank'] = (int)$oActionRankNode->GetText();
|
||||
}
|
||||
// Action rules
|
||||
/** @var \Combodo\iTop\DesignElement $oRuleNode */
|
||||
foreach ($oActionNode->GetNodes('./rules/rule') as $oRuleNode)
|
||||
{
|
||||
if ($oRuleNode->hasAttribute('id') && $oRuleNode->getAttribute('id') !== '')
|
||||
{
|
||||
foreach ($oActionNode->GetNodes('./rules/rule') as $oRuleNode) {
|
||||
if ($oRuleNode->hasAttribute('id') && $oRuleNode->getAttribute('id') !== '') {
|
||||
$aTmpAction['rules'][] = $oRuleNode->getAttribute('id');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/rules/rule tag must have an "id" attribute and it must not be empty',
|
||||
null, null, $oRuleNode);
|
||||
} else {
|
||||
throw new DOMFormatException(
|
||||
'BrowseBrick : '.$sTagName.'/rules/rule tag must have an "id" attribute and it must not be empty',
|
||||
null,
|
||||
null,
|
||||
$oRuleNode
|
||||
);
|
||||
}
|
||||
}
|
||||
$aTmpAction['default_rank'] = $iActionDefaultRank++;
|
||||
$aLevel[$sTagName][$oActionNode->getAttribute('id')] = $aTmpAction;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/* tag must have an "id" attribute and it must not be empty',
|
||||
null, null, $oActionNode);
|
||||
} else {
|
||||
throw new DOMFormatException(
|
||||
'BrowseBrick : '.$sTagName.'/* tag must have an "id" attribute and it must not be empty',
|
||||
null,
|
||||
null,
|
||||
$oActionNode
|
||||
);
|
||||
}
|
||||
}
|
||||
uasort($aLevel[$sTagName], [$this, 'CompareActionsByRank']);
|
||||
@@ -631,10 +614,8 @@ class BrowseBrick extends PortalBrick
|
||||
break;
|
||||
|
||||
case 'levels':
|
||||
foreach ($oLevelPropertyNode->GetNodes('*') as $oSubLevelNode)
|
||||
{
|
||||
if ($oSubLevelNode->nodeName === 'level')
|
||||
{
|
||||
foreach ($oLevelPropertyNode->GetNodes('*') as $oSubLevelNode) {
|
||||
if ($oSubLevelNode->nodeName === 'level') {
|
||||
$aLevel['levels'][] = $this->LoadLevelFromXml($oSubLevelNode);
|
||||
}
|
||||
}
|
||||
@@ -644,8 +625,7 @@ class BrowseBrick extends PortalBrick
|
||||
}
|
||||
|
||||
// Checking if level has an oql
|
||||
if (!isset($aLevel['oql']) || $aLevel['oql'] === '')
|
||||
{
|
||||
if (!isset($aLevel['oql']) || $aLevel['oql'] === '') {
|
||||
throw new DOMFormatException('BrowseBrick : must have a valid <class|oql> tag', null, null, $oMDElement);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,10 +35,10 @@ use DOMFormatException;
|
||||
class CreateBrick extends PortalBrick
|
||||
{
|
||||
// Overloaded constants
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-plus';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-plus fa-2x';
|
||||
public const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-plus';
|
||||
public const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-plus fa-2x';
|
||||
/** @var string DEFAULT_CLASS */
|
||||
const DEFAULT_CLASS = '';
|
||||
public const DEFAULT_CLASS = '';
|
||||
|
||||
// Overloaded variables
|
||||
public static $sRouteName = 'p_create_brick';
|
||||
@@ -48,14 +48,15 @@ class CreateBrick extends PortalBrick
|
||||
/** @var array $aRules */
|
||||
protected $aRules;
|
||||
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/create/modal.html.twig';
|
||||
public const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/create/modal.html.twig';
|
||||
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'create/modal.html.twig')
|
||||
$oTemplatesRegister->RegisterTemplates(
|
||||
self::class,
|
||||
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH.'create/modal.html.twig')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,7 +68,7 @@ class CreateBrick extends PortalBrick
|
||||
parent::__construct();
|
||||
|
||||
$this->sClass = static::DEFAULT_CLASS;
|
||||
$this->aRules = array();
|
||||
$this->aRules = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,26 +135,24 @@ class CreateBrick extends PortalBrick
|
||||
|
||||
// Checking specific elements
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
|
||||
{
|
||||
switch ($oBrickSubNode->nodeName)
|
||||
{
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode) {
|
||||
switch ($oBrickSubNode->nodeName) {
|
||||
case 'class':
|
||||
$this->SetClass($oBrickSubNode->GetText(self::DEFAULT_CLASS));
|
||||
break;
|
||||
|
||||
case 'rules':
|
||||
/** @var \Combodo\iTop\DesignElement $oRuleNode */
|
||||
foreach ($oBrickSubNode->GetNodes('*') as $oRuleNode)
|
||||
{
|
||||
if ($oRuleNode->hasAttribute('id') && $oRuleNode->getAttribute('id') !== '')
|
||||
{
|
||||
foreach ($oBrickSubNode->GetNodes('*') as $oRuleNode) {
|
||||
if ($oRuleNode->hasAttribute('id') && $oRuleNode->getAttribute('id') !== '') {
|
||||
$this->aRules[] = $oRuleNode->getAttribute('id');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('CreateBrick: /rules/rule tag must have an "id" attribute and it must not be empty',
|
||||
null, null, $oRuleNode);
|
||||
} else {
|
||||
throw new DOMFormatException(
|
||||
'CreateBrick: /rules/rule tag must have an "id" attribute and it must not be empty',
|
||||
null,
|
||||
null,
|
||||
$oRuleNode
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -35,21 +35,21 @@ use DOMFormatException;
|
||||
class FilterBrick extends PortalBrick
|
||||
{
|
||||
// Overloaded constants
|
||||
const DEFAULT_VISIBLE_NAVIGATION_MENU = false;
|
||||
/**
|
||||
* @deprecated 3.2.1
|
||||
*/
|
||||
const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/filter/tile.html.twig';
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-search';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-search fa-2x';
|
||||
/** @var string DEFAULT_TARGET_BRICK_CLASS */
|
||||
const DEFAULT_TARGET_BRICK_CLASS = 'Combodo\\iTop\\Portal\\Brick\\BrowseBrick';
|
||||
public const DEFAULT_VISIBLE_NAVIGATION_MENU = false;
|
||||
/**
|
||||
* @deprecated 3.2.1
|
||||
*/
|
||||
public const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/filter/tile.html.twig';
|
||||
public const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-search';
|
||||
public const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-search fa-2x';
|
||||
/** @var string DEFAULT_TARGET_BRICK_CLASS */
|
||||
public const DEFAULT_TARGET_BRICK_CLASS = 'Combodo\\iTop\\Portal\\Brick\\BrowseBrick';
|
||||
/** @var string DEFAULT_SEARCH_PLACEHOLDER_VALUE */
|
||||
const DEFAULT_SEARCH_PLACEHOLDER_VALUE = 'Brick:Portal:Filter:SearchInput:Placeholder';
|
||||
public const DEFAULT_SEARCH_PLACEHOLDER_VALUE = 'Brick:Portal:Filter:SearchInput:Placeholder';
|
||||
/** @var string DEFAULT_SEARCH_SUBMIT_LABEL */
|
||||
const DEFAULT_SEARCH_SUBMIT_LABEL = 'Brick:Portal:Filter:SearchInput:Submit';
|
||||
public const DEFAULT_SEARCH_SUBMIT_LABEL = 'Brick:Portal:Filter:SearchInput:Submit';
|
||||
/** @var string DEFAULT_SEARCH_SUBMIT_CLASS */
|
||||
const DEFAULT_SEARCH_SUBMIT_CLASS = '';
|
||||
public const DEFAULT_SEARCH_SUBMIT_CLASS = '';
|
||||
|
||||
/** @var string $sTargetBrickId */
|
||||
protected $sTargetBrickId;
|
||||
@@ -68,8 +68,9 @@ class FilterBrick extends PortalBrick
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('tile', static::TEMPLATES_BASE_PATH . 'filter/tile.html.twig')
|
||||
$oTemplatesRegister->RegisterTemplates(
|
||||
self::class,
|
||||
TemplateDefinitionDto::Create('tile', static::TEMPLATES_BASE_PATH.'filter/tile.html.twig')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,9 +99,9 @@ class FilterBrick extends PortalBrick
|
||||
* @return string
|
||||
*/
|
||||
public function GetTargetBrickClass()
|
||||
{
|
||||
return $this->sTargetBrickClass;
|
||||
}
|
||||
{
|
||||
return $this->sTargetBrickClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
@@ -149,9 +150,9 @@ class FilterBrick extends PortalBrick
|
||||
* @param string $sTargetBrickClass
|
||||
*/
|
||||
public function SetTargetBrickClass($sTargetBrickClass)
|
||||
{
|
||||
$this->sTargetBrickClass = $sTargetBrickClass;
|
||||
}
|
||||
{
|
||||
$this->sTargetBrickClass = $sTargetBrickClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTargetBrickTab
|
||||
@@ -197,38 +198,34 @@ class FilterBrick extends PortalBrick
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the brick's data from the xml passed as a ModuleDesignElement.
|
||||
* This is used to set all the brick attributes at once.
|
||||
*
|
||||
* @param \Combodo\iTop\DesignElement $oMDElement
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\FilterBrick
|
||||
*
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
/**
|
||||
* Load the brick's data from the xml passed as a ModuleDesignElement.
|
||||
* This is used to set all the brick attributes at once.
|
||||
*
|
||||
* @param \Combodo\iTop\DesignElement $oMDElement
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\FilterBrick
|
||||
*
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function LoadFromXml(DesignElement $oMDElement)
|
||||
{
|
||||
parent::LoadFromXml($oMDElement);
|
||||
|
||||
// Checking specific elements
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
|
||||
{
|
||||
switch ($oBrickSubNode->nodeName)
|
||||
{
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode) {
|
||||
switch ($oBrickSubNode->nodeName) {
|
||||
case 'target_brick':
|
||||
/** @var \Combodo\iTop\DesignElement $oTargetBrickNode */
|
||||
foreach ($oBrickSubNode->GetNodes('*') as $oTargetBrickNode)
|
||||
{
|
||||
switch ($oTargetBrickNode->nodeName)
|
||||
{
|
||||
case 'id':
|
||||
$this->SetTargetBrickId($oTargetBrickNode->GetText());
|
||||
break;
|
||||
case 'type':
|
||||
$this->SetTargetBrickClass($oTargetBrickNode->GetText());
|
||||
break;
|
||||
foreach ($oBrickSubNode->GetNodes('*') as $oTargetBrickNode) {
|
||||
switch ($oTargetBrickNode->nodeName) {
|
||||
case 'id':
|
||||
$this->SetTargetBrickId($oTargetBrickNode->GetText());
|
||||
break;
|
||||
case 'type':
|
||||
$this->SetTargetBrickClass($oTargetBrickNode->GetText());
|
||||
break;
|
||||
case 'tab':
|
||||
$this->SetTargetBrickTab($oTargetBrickNode->GetText());
|
||||
break;
|
||||
@@ -236,12 +233,12 @@ class FilterBrick extends PortalBrick
|
||||
}
|
||||
break;
|
||||
case 'search_placeholder_value':
|
||||
// Note: We don't put the default value constant if the node is empty because we might actually want this to be empty
|
||||
// Note: We don't put the default value constant if the node is empty because we might actually want this to be empty
|
||||
$this->SetSearchPlaceholderValue($oBrickSubNode->GetText(''));
|
||||
break;
|
||||
case 'search_submit_label':
|
||||
// Note: We don't put the default value constant if the node is empty because we might actually want this to be empty
|
||||
$this->SetSearchSubmitLabel($oBrickSubNode->GetText(''));
|
||||
// Note: We don't put the default value constant if the node is empty because we might actually want this to be empty
|
||||
$this->SetSearchSubmitLabel($oBrickSubNode->GetText(''));
|
||||
break;
|
||||
case 'search_submit_class':
|
||||
$this->SetSearchSubmitClass($oBrickSubNode->GetText(static::DEFAULT_SEARCH_SUBMIT_CLASS));
|
||||
@@ -250,8 +247,7 @@ class FilterBrick extends PortalBrick
|
||||
}
|
||||
|
||||
// Checking that the brick has at least a target brick id
|
||||
if (($this->GetTargetBrickId() === null) || ($this->GetTargetBrickId() === ''))
|
||||
{
|
||||
if (($this->GetTargetBrickId() === null) || ($this->GetTargetBrickId() === '')) {
|
||||
throw new DOMFormatException('FilterBrick : Must have a target brick id', 0, null, $oMDElement);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,5 +31,4 @@ use Exception;
|
||||
*/
|
||||
class PropertyNotFoundException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use UserRights;
|
||||
|
||||
|
||||
/**
|
||||
* Class AggregatePageBrickController
|
||||
*
|
||||
@@ -41,7 +40,6 @@ use UserRights;
|
||||
*/
|
||||
class AggregatePageBrickController extends BrickController
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -51,8 +49,7 @@ class AggregatePageBrickController extends BrickController
|
||||
*/
|
||||
public function __construct(
|
||||
protected BrickCollection $oBrickCollection
|
||||
)
|
||||
{
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
@@ -76,11 +73,11 @@ class AggregatePageBrickController extends BrickController
|
||||
$aTilesRendering = $this->GetBricksTileRendering($oRequest, $aAggregatePageBricks);
|
||||
|
||||
$sLayoutTemplate = $oBrick->GetTemplatePath('page');
|
||||
$aData = array(
|
||||
$aData = [
|
||||
'oBrick' => $oBrick,
|
||||
'aggregatepage_bricks' => $aAggregatePageBricks,
|
||||
'aTilesRendering' => $aTilesRendering,
|
||||
);
|
||||
];
|
||||
$oResponse = $this->render($sLayoutTemplate, $aData);
|
||||
|
||||
return $oResponse;
|
||||
@@ -94,15 +91,11 @@ class AggregatePageBrickController extends BrickController
|
||||
*/
|
||||
private function GetOrderedAggregatePageBricksObjectsById($aAggregatePageBricksConf)
|
||||
{
|
||||
$aAggregatePageBricks = array();
|
||||
foreach ($aAggregatePageBricksConf as $sBrickId => $iBrickRank)
|
||||
{
|
||||
try
|
||||
{
|
||||
$aAggregatePageBricks = [];
|
||||
foreach ($aAggregatePageBricksConf as $sBrickId => $iBrickRank) {
|
||||
try {
|
||||
$oPortalBrick = $this->oBrickCollection->GetBrickById($sBrickId);
|
||||
}
|
||||
catch (BrickNotFoundException $oException)
|
||||
{
|
||||
} catch (BrickNotFoundException $oException) {
|
||||
IssueLog::Debug('AggregatePageBrick: Could not display brick, either wrong id or user profile not allowed', LogChannels::PORTAL, [
|
||||
'brick_id' => $sBrickId,
|
||||
'user_profiles' => UserRights::ListProfiles(),
|
||||
@@ -124,21 +117,17 @@ class AggregatePageBrickController extends BrickController
|
||||
*/
|
||||
private function GetBricksTileRendering(Request $oRequest, $aBricks)
|
||||
{
|
||||
$aTilesRendering = array();
|
||||
foreach ($aBricks as $oBrick)
|
||||
{
|
||||
if ($oBrick->GetTileControllerAction() !== null)
|
||||
{
|
||||
$aTilesRendering = [];
|
||||
foreach ($aBricks as $oBrick) {
|
||||
if ($oBrick->GetTileControllerAction() !== null) {
|
||||
$aControllerActionParts = explode('::', $oBrick->GetTileControllerAction());
|
||||
if (count($aControllerActionParts) !== 2)
|
||||
{
|
||||
if (count($aControllerActionParts) !== 2) {
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Tile controller action must be of form "\Namespace\ControllerClass::FunctionName" for brick "'.$oBrick->GetId().'"');
|
||||
}
|
||||
|
||||
$aRouteParams = array();
|
||||
$aRouteParams = [];
|
||||
// Add sBrickId in the route params as it is necessary for each brick actions
|
||||
if (is_a($aControllerActionParts[0], BrickController::class, true))
|
||||
{
|
||||
if (is_a($aControllerActionParts[0], BrickController::class, true)) {
|
||||
$aRouteParams['sBrickId'] = $oBrick->GetId();
|
||||
}
|
||||
|
||||
@@ -150,4 +139,4 @@ class AggregatePageBrickController extends BrickController
|
||||
|
||||
return $aTilesRendering;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,5 +29,4 @@ namespace Combodo\iTop\Portal\Controller;
|
||||
*/
|
||||
abstract class BrickController extends AbstractController
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ use VariableExpression;
|
||||
*/
|
||||
class BrowseBrickController extends BrickController
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -67,12 +66,10 @@ class BrowseBrickController extends BrickController
|
||||
protected RequestManipulatorHelper $oRequestManipulatorHelper,
|
||||
protected BrickControllerHelper $oBrickControllerHelper,
|
||||
protected BrickCollection $oBrickCollection
|
||||
)
|
||||
{
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \Symfony\Component\HttpFoundation\Request $oRequest
|
||||
* @param string $sBrickId
|
||||
@@ -103,85 +100,92 @@ class BrowseBrickController extends BrickController
|
||||
// Getting current browse mode (First from router parameter, then default brick value)
|
||||
$sBrowseMode = (!empty($sBrowseMode)) ? $sBrowseMode : $oBrick->GetDefaultBrowseMode();
|
||||
// Getting current dataloading mode (First from router parameter, then query parameter, then default brick value)
|
||||
$sDataLoading = ($sDataLoading !== null) ? $sDataLoading : $this->oRequestManipulatorHelper->ReadParam('sDataLoading',
|
||||
$oBrick->GetDataLoading());
|
||||
$sDataLoading = ($sDataLoading !== null) ? $sDataLoading : $this->oRequestManipulatorHelper->ReadParam(
|
||||
'sDataLoading',
|
||||
$oBrick->GetDataLoading()
|
||||
);
|
||||
// Getting search value
|
||||
$sRawSearchValue = $this->oRequestManipulatorHelper->ReadParam('sSearchValue', '');
|
||||
$sSearchValue = html_entity_decode($sRawSearchValue);
|
||||
if (strlen($sSearchValue) > 0)
|
||||
{
|
||||
if (strlen($sSearchValue) > 0) {
|
||||
$sDataLoading = AbstractBrick::ENUM_DATA_LOADING_LAZY;
|
||||
}
|
||||
|
||||
$aData = array();
|
||||
$aLevelsProperties = array();
|
||||
$aLevelsClasses = array();
|
||||
$aData = [];
|
||||
$aLevelsProperties = [];
|
||||
$aLevelsClasses = [];
|
||||
$this->oBrowseBrickHelper->TreeToFlatLevelsProperties($oBrick->GetLevels(), $aLevelsProperties);
|
||||
|
||||
// Consistency checks
|
||||
if (!in_array($sBrowseMode, array_keys($aBrowseModes)))
|
||||
{
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'Browse brick "'.$sBrickId.'" : Unknown browse mode "'.$sBrowseMode.'", availables are '.implode(' / ',
|
||||
array_keys($aBrowseModes)));
|
||||
if (!in_array($sBrowseMode, array_keys($aBrowseModes))) {
|
||||
throw new HttpException(
|
||||
Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'Browse brick "'.$sBrickId.'" : Unknown browse mode "'.$sBrowseMode.'", availables are '.implode(
|
||||
' / ',
|
||||
array_keys($aBrowseModes)
|
||||
)
|
||||
);
|
||||
}
|
||||
if (empty($aLevelsProperties))
|
||||
{
|
||||
if (empty($aLevelsProperties)) {
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Browse brick "'.$sBrickId.'" : No levels to display.');
|
||||
}
|
||||
|
||||
// Building DBObjectSearch
|
||||
$oQuery = null;
|
||||
// ... In this case only we have to build a specific query for the current level only
|
||||
if (in_array($sBrowseMode, array(
|
||||
if (in_array($sBrowseMode, [
|
||||
BrowseBrick::ENUM_BROWSE_MODE_TREE,
|
||||
BrowseBrick::ENUM_BROWSE_MODE_MOSAIC,
|
||||
)) && ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY))
|
||||
{
|
||||
]) && ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY)) {
|
||||
// Will be handled later in the pagination part
|
||||
}
|
||||
// .. Otherwise
|
||||
else
|
||||
{
|
||||
else {
|
||||
// We iterate (in reverse mode /!\) over the levels to build the whole query, starting from the bottom
|
||||
$aLevelsPropertiesKeys = array_keys($aLevelsProperties);
|
||||
$iLoopMax = count($aLevelsPropertiesKeys) - 1;
|
||||
$oFullBinExpr = null;
|
||||
for ($i = $iLoopMax; $i >= 0; $i--)
|
||||
{
|
||||
for ($i = $iLoopMax; $i >= 0; $i--) {
|
||||
// Retrieving class alias for all depth
|
||||
array_unshift($aLevelsClasses, $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->GetClassAlias());
|
||||
|
||||
// Joining queries from bottom-up
|
||||
if ($i < $iLoopMax)
|
||||
{
|
||||
$aRealiasingMap = array();
|
||||
if ($i < $iLoopMax) {
|
||||
$aRealiasingMap = [];
|
||||
$oParentAtt = MetaModel::GetAttributeDef($aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['search']->GetClass(), $aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['parent_att']);
|
||||
// If we work on a n:n link
|
||||
if($oParentAtt instanceof AttributeLinkedSetIndirect)
|
||||
{
|
||||
if ($oParentAtt instanceof AttributeLinkedSetIndirect) {
|
||||
// Create a DBSearch from Link class
|
||||
$oSubSearch = new DBObjectSearch($oParentAtt->GetLinkedClass());
|
||||
// Join it to the bottom query
|
||||
$oSubSearch = $oSubSearch->Join($aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['search'],
|
||||
DBSearch::JOIN_POINTING_TO, $oParentAtt->GetExtKeyToMe(), TREE_OPERATOR_EQUALS, $aRealiasingMap);
|
||||
$oSubSearch = $oSubSearch->Join(
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['search'],
|
||||
DBSearch::JOIN_POINTING_TO,
|
||||
$oParentAtt->GetExtKeyToMe(),
|
||||
TREE_OPERATOR_EQUALS,
|
||||
$aRealiasingMap
|
||||
);
|
||||
// Join our Link class + bottom query to the up query
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] ->Join($oSubSearch, DBSearch::JOIN_REFERENCED_BY,
|
||||
$oParentAtt->GetExtKeyToRemote(), TREE_OPERATOR_EQUALS, $aRealiasingMap);
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] ->Join(
|
||||
$oSubSearch,
|
||||
DBSearch::JOIN_REFERENCED_BY,
|
||||
$oParentAtt->GetExtKeyToRemote(),
|
||||
TREE_OPERATOR_EQUALS,
|
||||
$aRealiasingMap
|
||||
);
|
||||
} else {
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->Join(
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['search'],
|
||||
DBSearch::JOIN_REFERENCED_BY,
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['parent_att'],
|
||||
TREE_OPERATOR_EQUALS,
|
||||
$aRealiasingMap
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->Join($aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['search'],
|
||||
DBSearch::JOIN_REFERENCED_BY, $aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['parent_att'],
|
||||
TREE_OPERATOR_EQUALS, $aRealiasingMap);
|
||||
}
|
||||
foreach ($aLevelsPropertiesKeys as $sLevelAlias)
|
||||
{
|
||||
if (array_key_exists($sLevelAlias, $aRealiasingMap))
|
||||
{
|
||||
foreach ($aLevelsPropertiesKeys as $sLevelAlias) {
|
||||
if (array_key_exists($sLevelAlias, $aRealiasingMap)) {
|
||||
/** @since 2.7.2 */
|
||||
foreach ($aRealiasingMap[$sLevelAlias] as $sAliasToChange)
|
||||
{
|
||||
foreach ($aRealiasingMap[$sLevelAlias] as $sAliasToChange) {
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->RenameAlias($sAliasToChange, $sLevelAlias);
|
||||
}
|
||||
}
|
||||
@@ -190,8 +194,7 @@ class BrowseBrickController extends BrickController
|
||||
|
||||
// Adding search clause
|
||||
// Note : For know the search is naive and looks only for the exact match. It doesn't search for words separately
|
||||
if (strlen($sSearchValue) > 0)
|
||||
{
|
||||
if (strlen($sSearchValue) > 0) {
|
||||
// - Cleaning the search value by exploding and trimming spaces
|
||||
$aExplodedSearchValues = explode(' ', $sSearchValue);
|
||||
$aSearchValues = [];
|
||||
@@ -202,25 +205,21 @@ class BrowseBrickController extends BrickController
|
||||
}
|
||||
|
||||
// - Retrieving fields to search
|
||||
$aSearchFields = array($aLevelsProperties[$aLevelsPropertiesKeys[$i]]['name_att']);
|
||||
if (!empty($aLevelsProperties[$aLevelsPropertiesKeys[$i]]['fields']))
|
||||
{
|
||||
$aSearchFields = [$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['name_att']];
|
||||
if (!empty($aLevelsProperties[$aLevelsPropertiesKeys[$i]]['fields'])) {
|
||||
$sTmpFieldClass = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->GetClass();
|
||||
foreach ($aLevelsProperties[$aLevelsPropertiesKeys[$i]]['fields'] as $aTmpField)
|
||||
{
|
||||
foreach ($aLevelsProperties[$aLevelsPropertiesKeys[$i]]['fields'] as $aTmpField) {
|
||||
$sTmpFieldAttCode = $aTmpField['code'];
|
||||
|
||||
// Skip invalid attcodes
|
||||
if(!MetaModel::IsValidAttCode($sTmpFieldClass, $sTmpFieldAttCode))
|
||||
{
|
||||
if (!MetaModel::IsValidAttCode($sTmpFieldClass, $sTmpFieldAttCode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// For external key, force search on the friendlyname instead of the ID.
|
||||
// This should be addressed more globally with the bigger issue, see N°1970
|
||||
$oTmpFieldAttDef = MetaModel::GetAttributeDef($sTmpFieldClass, $sTmpFieldAttCode);
|
||||
if($oTmpFieldAttDef instanceof AttributeExternalKey)
|
||||
{
|
||||
if ($oTmpFieldAttDef instanceof AttributeExternalKey) {
|
||||
$sTmpFieldAttCode .= '_friendlyname';
|
||||
}
|
||||
|
||||
@@ -231,60 +230,49 @@ class BrowseBrickController extends BrickController
|
||||
$oLevelBinExpr = null;
|
||||
$iFieldLoopMax = count($aSearchFields) - 1;
|
||||
$iSearchLoopMax = count($aSearchValues) - 1;
|
||||
for ($j = 0; $j <= $iFieldLoopMax; $j++)
|
||||
{
|
||||
for ($j = 0; $j <= $iFieldLoopMax; $j++) {
|
||||
$sTmpFieldAttCode = $aSearchFields[$j];
|
||||
$oFieldBinExpr = null;
|
||||
//$oFieldBinExpr = new BinaryExpression(new FieldExpression($aSearchFields[$j], $aLevelsPropertiesKeys[$i]), )
|
||||
|
||||
for ($k = 0; $k <= $iSearchLoopMax; $k++)
|
||||
{
|
||||
$oSearchBinExpr = new BinaryExpression(new FieldExpression($sTmpFieldAttCode, $aLevelsPropertiesKeys[$i]),
|
||||
'LIKE', new VariableExpression('search_value_'.$k));
|
||||
if ($k === 0)
|
||||
{
|
||||
for ($k = 0; $k <= $iSearchLoopMax; $k++) {
|
||||
$oSearchBinExpr = new BinaryExpression(
|
||||
new FieldExpression($sTmpFieldAttCode, $aLevelsPropertiesKeys[$i]),
|
||||
'LIKE',
|
||||
new VariableExpression('search_value_'.$k)
|
||||
);
|
||||
if ($k === 0) {
|
||||
$oFieldBinExpr = $oSearchBinExpr;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oFieldBinExpr = new BinaryExpression($oFieldBinExpr, 'AND', $oSearchBinExpr);
|
||||
}
|
||||
}
|
||||
|
||||
if ($j === 0)
|
||||
{
|
||||
if ($j === 0) {
|
||||
$oLevelBinExpr = $oFieldBinExpr;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oLevelBinExpr = new BinaryExpression($oLevelBinExpr, 'OR', $oFieldBinExpr);
|
||||
}
|
||||
}
|
||||
|
||||
// - Building query for the level
|
||||
if ($i === $iLoopMax)
|
||||
{
|
||||
if ($i === $iLoopMax) {
|
||||
$oFullBinExpr = $oLevelBinExpr;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oFullBinExpr = new BinaryExpression($oFullBinExpr, 'OR', $oLevelBinExpr);
|
||||
}
|
||||
|
||||
// - Adding it to the query when complete
|
||||
if ($i === 0)
|
||||
{
|
||||
if ($i === 0) {
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->AddConditionExpression($oFullBinExpr);
|
||||
}
|
||||
}
|
||||
|
||||
// Setting selected classes and binding parameters
|
||||
if ($i === 0)
|
||||
{
|
||||
if ($i === 0) {
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->SetSelectedClasses($aLevelsClasses);
|
||||
|
||||
if (strlen($sSearchValue) > 0)
|
||||
{
|
||||
if (strlen($sSearchValue) > 0) {
|
||||
// Note : This could be way more simpler if we had a SetInternalParam($sParam, $value) verb
|
||||
$aQueryParams = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->GetInternalParams();
|
||||
// Note : $iSearchloopMax was initialized on the previous loop
|
||||
@@ -302,23 +290,26 @@ class BrowseBrickController extends BrickController
|
||||
// - Check how many records there is.
|
||||
// - Update $sDataLoading with its new value regarding the number of record and the threshold
|
||||
$oCountSet = new DBObjectSet($oQuery);
|
||||
$fThreshold = (float)MetaModel::GetModuleSetting($sPortalId,
|
||||
'lazy_loading_threshold');
|
||||
$fThreshold = (float)MetaModel::GetModuleSetting(
|
||||
$sPortalId,
|
||||
'lazy_loading_threshold'
|
||||
);
|
||||
$sDataLoading = ($oCountSet->Count() > $fThreshold) ? AbstractBrick::ENUM_DATA_LOADING_LAZY : AbstractBrick::ENUM_DATA_LOADING_FULL;
|
||||
unset($oCountSet);
|
||||
}
|
||||
}
|
||||
|
||||
// Setting query pagination if needed
|
||||
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY)
|
||||
{
|
||||
switch ($sBrowseMode)
|
||||
{
|
||||
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY) {
|
||||
switch ($sBrowseMode) {
|
||||
case BrowseBrick::ENUM_BROWSE_MODE_LIST:
|
||||
// Retrieving parameters
|
||||
$iPageNumber = (int)$this->oRequestManipulatorHelper->ReadParam('iPageNumber', 1, FILTER_SANITIZE_NUMBER_INT);
|
||||
$iListLength = (int)$this->oRequestManipulatorHelper->ReadParam('iListLength', BrowseBrick::DEFAULT_LIST_LENGTH,
|
||||
FILTER_SANITIZE_NUMBER_INT);
|
||||
$iListLength = (int)$this->oRequestManipulatorHelper->ReadParam(
|
||||
'iListLength',
|
||||
BrowseBrick::DEFAULT_LIST_LENGTH,
|
||||
FILTER_SANITIZE_NUMBER_INT
|
||||
);
|
||||
|
||||
// Getting total records number
|
||||
$oCountSet = new DBObjectSet($oQuery);
|
||||
@@ -337,36 +328,26 @@ class BrowseBrickController extends BrickController
|
||||
$sNodeId = $this->oRequestManipulatorHelper->ReadParam('sNodeId', '');
|
||||
|
||||
// If no values for those parameters, we might be loading page in lazy mode for the first time, therefore the URL doesn't have those information.
|
||||
if (empty($sLevelAlias))
|
||||
{
|
||||
if (empty($sLevelAlias)) {
|
||||
reset($aLevelsProperties);
|
||||
$oQuery = $aLevelsProperties[key($aLevelsProperties)]['search'];
|
||||
if (!empty($sNodeId))
|
||||
{
|
||||
if (!empty($sNodeId)) {
|
||||
$oQuery->AddCondition('id', $sNodeId);
|
||||
}
|
||||
}
|
||||
// Else we need to find the OQL for that particular level
|
||||
else
|
||||
{
|
||||
else {
|
||||
$bFoundLevel = false;
|
||||
foreach ($aLevelsProperties as $aLevelProperties)
|
||||
{
|
||||
if ($aLevelProperties['alias'] === $sLevelAlias)
|
||||
{
|
||||
if (isset($aLevelProperties['levels']) && !empty($aLevelProperties['levels']) && isset($aLevelsProperties[$aLevelProperties['levels'][0]]))
|
||||
{
|
||||
foreach ($aLevelsProperties as $aLevelProperties) {
|
||||
if ($aLevelProperties['alias'] === $sLevelAlias) {
|
||||
if (isset($aLevelProperties['levels']) && !empty($aLevelProperties['levels']) && isset($aLevelsProperties[$aLevelProperties['levels'][0]])) {
|
||||
$oQuery = $aLevelsProperties[$aLevelProperties['levels'][0]]['search'];
|
||||
if (!empty($sNodeId))
|
||||
{
|
||||
if (!empty($sNodeId)) {
|
||||
$sParentAttCode = $aLevelsProperties[$aLevelProperties['levels'][0]]['parent_att'];
|
||||
$oParentAtt = MetaModel::GetAttributeDef($oQuery->GetClass(), $sParentAttCode);
|
||||
if($oParentAtt instanceof AttributeLinkedSetIndirect)
|
||||
{
|
||||
if ($oParentAtt instanceof AttributeLinkedSetIndirect) {
|
||||
$oQuery->AddConditionAdvanced($sParentAttCode.'->'.$oParentAtt->GetExtKeyToRemote(), $sNodeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oQuery->AddCondition($sParentAttCode, $sNodeId);
|
||||
}
|
||||
}
|
||||
@@ -376,10 +357,11 @@ class BrowseBrickController extends BrickController
|
||||
}
|
||||
}
|
||||
|
||||
if (!$bFoundLevel)
|
||||
{
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'Browse brick "'.$sBrickId.'" : Level alias "'.$sLevelAlias.'" is not defined for that brick.');
|
||||
if (!$bFoundLevel) {
|
||||
throw new HttpException(
|
||||
Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'Browse brick "'.$sBrickId.'" : Level alias "'.$sLevelAlias.'" is not defined for that brick.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,34 +376,26 @@ class BrowseBrickController extends BrickController
|
||||
$oSet = new DBObjectSet($oQuery);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oSet = new DBObjectSet($oQuery);
|
||||
}
|
||||
|
||||
// Optimizing the ObjectSet to retrieve only necessary columns
|
||||
$aColumnAttrs = array();
|
||||
foreach ($oSet->GetFilter()->GetSelectedClasses() as $sTmpClassAlias => $sTmpClassName)
|
||||
{
|
||||
if (isset($aLevelsProperties[$sTmpClassAlias]))
|
||||
{
|
||||
$aColumnAttrs = [];
|
||||
foreach ($oSet->GetFilter()->GetSelectedClasses() as $sTmpClassAlias => $sTmpClassName) {
|
||||
if (isset($aLevelsProperties[$sTmpClassAlias])) {
|
||||
$aTmpLevelProperties = $aLevelsProperties[$sTmpClassAlias];
|
||||
// Mandatory main attribute
|
||||
$aTmpColumnAttrs = array($aTmpLevelProperties['name_att']);
|
||||
$aTmpColumnAttrs = [$aTmpLevelProperties['name_att']];
|
||||
// Optional attributes, only if in list mode
|
||||
if ($sBrowseMode === BrowseBrick::ENUM_BROWSE_MODE_LIST)
|
||||
{
|
||||
foreach ($aTmpLevelProperties['fields'] as $aTmpField)
|
||||
{
|
||||
if ($sBrowseMode === BrowseBrick::ENUM_BROWSE_MODE_LIST) {
|
||||
foreach ($aTmpLevelProperties['fields'] as $aTmpField) {
|
||||
$aTmpColumnAttrs[] = $aTmpField['code'];
|
||||
}
|
||||
}
|
||||
// Optional attributes
|
||||
foreach (BrowseBrickHelper::OPTIONAL_ATTRIBUTES as $sOptionalAttribute)
|
||||
{
|
||||
if ($aTmpLevelProperties[$sOptionalAttribute] !== null)
|
||||
{
|
||||
foreach (BrowseBrickHelper::OPTIONAL_ATTRIBUTES as $sOptionalAttribute) {
|
||||
if ($aTmpLevelProperties[$sOptionalAttribute] !== null) {
|
||||
$aTmpColumnAttrs[] = $aTmpLevelProperties[$sOptionalAttribute];
|
||||
}
|
||||
}
|
||||
@@ -434,20 +408,15 @@ class BrowseBrickController extends BrickController
|
||||
|
||||
// Setting specified column sort, setting default datamodel one otherwise
|
||||
$aSortedParams = $this->oBrickControllerHelper->ExtractSortParams();
|
||||
if (!empty($aSortedParams))
|
||||
{
|
||||
if (!empty($aSortedParams)) {
|
||||
$oSet->SetOrderBy($aSortedParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oSet->SetOrderByClasses();
|
||||
}
|
||||
// Retrieving results and organizing them for templating
|
||||
$aItems = array();
|
||||
while ($aCurrentRow = $oSet->FetchAssoc())
|
||||
{
|
||||
switch ($sBrowseMode)
|
||||
{
|
||||
$aItems = [];
|
||||
while ($aCurrentRow = $oSet->FetchAssoc()) {
|
||||
switch ($sBrowseMode) {
|
||||
case BrowseBrick::ENUM_BROWSE_MODE_TREE:
|
||||
case BrowseBrick::ENUM_BROWSE_MODE_MOSAIC:
|
||||
$this->oBrowseBrickHelper->AddToTreeItems($aItems, $aCurrentRow, $aLevelsProperties, null);
|
||||
@@ -460,22 +429,21 @@ class BrowseBrickController extends BrickController
|
||||
}
|
||||
}
|
||||
|
||||
IssueLog::Debug('Portal BrowseBrick query', LogChannels::PORTAL, array(
|
||||
IssueLog::Debug('Portal BrowseBrick query', LogChannels::PORTAL, [
|
||||
'sPortalId' => $sPortalId,
|
||||
'sBrickId' => $sBrickId,
|
||||
'oql' => $oSet->GetFilter()->ToOQL(),
|
||||
));
|
||||
|
||||
]);
|
||||
|
||||
// Preparing response
|
||||
if ($oRequest->isXmlHttpRequest()) {
|
||||
$aData = $aData + array(
|
||||
$aData = $aData + [
|
||||
'data' => $aItems,
|
||||
'levelsProperties' => $aLevelsProperties,
|
||||
);
|
||||
];
|
||||
$oResponse = new JsonResponse($aData);
|
||||
} else {
|
||||
$aData = $aData + array(
|
||||
$aData = $aData + [
|
||||
'oBrick' => $oBrick,
|
||||
'sBrickId' => $sBrickId,
|
||||
'sBrowseMode' => $sBrowseMode,
|
||||
@@ -486,7 +454,7 @@ class BrowseBrickController extends BrickController
|
||||
'iItemsCount' => count($aItems),
|
||||
'aLevelsProperties' => json_encode($aLevelsProperties),
|
||||
'iDefaultLengthList' => $oBrick->GetDefaultListLength(),
|
||||
);
|
||||
];
|
||||
|
||||
// Note : To extend this brick's template, depending on what you want to do :
|
||||
// a) Modify the whole template :
|
||||
@@ -495,13 +463,10 @@ class BrowseBrickController extends BrickController
|
||||
// - Create a template for that browse mode,
|
||||
// - Add the mode to those available in the brick configuration,
|
||||
// - Create a router and add a route for the new browse mode
|
||||
if ($oBrick->HasInstanceOverriddenTemplate('page'))
|
||||
{
|
||||
if ($oBrick->HasInstanceOverriddenTemplate('page')) {
|
||||
$sTemplatePath = $oBrick->GetTemplatePath('page');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sTemplatePath = $oBrick->GetTemplatePath('page_' .$sBrowseMode);
|
||||
} else {
|
||||
$sTemplatePath = $oBrick->GetTemplatePath('page_'.$sBrowseMode);
|
||||
}
|
||||
$oResponse = $this->render($sTemplatePath, $aData);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
*/
|
||||
class CreateBrickController extends BrickController
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -43,8 +42,7 @@ class CreateBrickController extends BrickController
|
||||
*/
|
||||
public function __construct(
|
||||
protected BrickCollection $oBrickCollection
|
||||
)
|
||||
{
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,16 +58,15 @@ class CreateBrickController extends BrickController
|
||||
/** @var \Combodo\iTop\Portal\Brick\CreateBrick $oBrick */
|
||||
$oBrick = $this->oBrickCollection->GetBrickById($sBrickId);
|
||||
|
||||
$aRouteParams = array(
|
||||
$aRouteParams = [
|
||||
'sBrickId' => $sBrickId,
|
||||
'sObjectClass' => $oBrick->GetClass(),
|
||||
'ar_token' => null,
|
||||
);
|
||||
];
|
||||
|
||||
// Checking for actions rules
|
||||
$aRules = $oBrick->GetRules();
|
||||
if (!empty($aRules))
|
||||
{
|
||||
if (!empty($aRules)) {
|
||||
$aRouteParams['ar_token'] = ContextManipulatorHelper::PrepareAndEncodeRulesToken($aRules);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,9 @@ class DefaultController extends AbstractController
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('home', static::TEMPLATES_BASE_PATH . 'home/layout.html.twig'),
|
||||
$oTemplatesRegister->RegisterTemplates(
|
||||
self::class,
|
||||
TemplateDefinitionDto::Create('home', static::TEMPLATES_BASE_PATH.'home/layout.html.twig'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -53,26 +54,24 @@ class DefaultController extends AbstractController
|
||||
*/
|
||||
public function HomeAction(Request $oRequest, BrickCollection $oBricksCollection)
|
||||
{
|
||||
$aData = array();
|
||||
$aData = [];
|
||||
|
||||
// Rendering tiles
|
||||
$aData['aTilesRendering'] = array();
|
||||
foreach ($oBricksCollection->GetBricks() as $oBrick)
|
||||
{
|
||||
$aData['aTilesRendering'] = [];
|
||||
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))
|
||||
{
|
||||
if (($oBrick->GetVisibleHome() === true) && ($oBrick->GetTileControllerAction() !== null)) {
|
||||
$aControllerActionParts = explode('::', $oBrick->GetTileControllerAction());
|
||||
if (count($aControllerActionParts) !== 2)
|
||||
{
|
||||
return new Response('Tile controller action must be of form "\Namespace\ControllerClass::FunctionName" for brick "'.$oBrick->GetId().'"',
|
||||
500);
|
||||
if (count($aControllerActionParts) !== 2) {
|
||||
return new Response(
|
||||
'Tile controller action must be of form "\Namespace\ControllerClass::FunctionName" for brick "'.$oBrick->GetId().'"',
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
$aRouteParams = array();
|
||||
$aRouteParams = [];
|
||||
// Add sBrickId in the route params as it is necessary for each brick actions
|
||||
if (is_a($aControllerActionParts[0], BrickController::class, true))
|
||||
{
|
||||
if (is_a($aControllerActionParts[0], BrickController::class, true)) {
|
||||
$aRouteParams['sBrickId'] = $oBrick->GetId();
|
||||
}
|
||||
|
||||
|
||||
@@ -72,18 +72,19 @@ use utils;
|
||||
*/
|
||||
class ManageBrickController extends BrickController
|
||||
{
|
||||
/**
|
||||
* @var string EXCEL_EXPORT_TEMPLATE_PATH
|
||||
/**
|
||||
* @var string EXCEL_EXPORT_TEMPLATE_PATH
|
||||
* @deprecated since 3.2.1
|
||||
*/
|
||||
const EXCEL_EXPORT_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig';
|
||||
|
||||
public const EXCEL_EXPORT_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig';
|
||||
|
||||
/** @inheritdoc */
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
|
||||
{
|
||||
parent::RegisterTemplates($oTemplatesRegister);
|
||||
$oTemplatesRegister->RegisterTemplates(self::class,
|
||||
TemplateDefinitionDto::Create('modal_export_excel', static::TEMPLATES_BASE_PATH . 'bricks/manage/popup-export-excel.html.twig'),
|
||||
$oTemplatesRegister->RegisterTemplates(
|
||||
self::class,
|
||||
TemplateDefinitionDto::Create('modal_export_excel', static::TEMPLATES_BASE_PATH.'bricks/manage/popup-export-excel.html.twig'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -104,8 +105,7 @@ class ManageBrickController extends BrickController
|
||||
protected RequestManipulatorHelper $oRequestManipulatorHelper,
|
||||
protected SecurityHelper $oSecurityHelper,
|
||||
protected BrickControllerHelper $oBrickControllerHelper
|
||||
)
|
||||
{
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
@@ -138,17 +138,15 @@ class ManageBrickController extends BrickController
|
||||
$aData = $this->GetData($oRequest, $sBrickId, $sGroupingTab, $oBrick->IsDetailsNeeded($sDisplayMode));
|
||||
|
||||
$aExportFields = $oBrick->GetExportFields();
|
||||
$aData = $aData + array(
|
||||
$aData = $aData + [
|
||||
'sDisplayMode' => $sDisplayMode,
|
||||
'bCanExport' => !empty($aExportFields),
|
||||
'iDefaultListLength' => $oBrick->GetDefaultListLength(),
|
||||
);
|
||||
];
|
||||
// Preparing response
|
||||
if ($oRequest->isXmlHttpRequest()) {
|
||||
$oResponse = new JsonResponse($aData);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$sLayoutTemplate = $oBrick->GetPageTemplate($sDisplayMode);
|
||||
$oResponse = $this->render($sLayoutTemplate, $aData);
|
||||
}
|
||||
@@ -171,14 +169,11 @@ class ManageBrickController extends BrickController
|
||||
/** @var \Combodo\iTop\Portal\Brick\ManageBrick $oBrick */
|
||||
$oBrick = $this->oBrickCollection->GetBrickById($sBrickId);
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
$aData = $this->GetData($oRequest, $sBrickId, null);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
// TODO Default values
|
||||
$aData = array();
|
||||
$aData = [];
|
||||
}
|
||||
|
||||
return $this->render($oBrick->GetTileTemplate(), $aData);
|
||||
@@ -210,37 +205,28 @@ class ManageBrickController extends BrickController
|
||||
$sClass = $oQuery->GetClass();
|
||||
$aData = $this->GetData($oRequest, $sBrickId, $sGroupingTab, true);
|
||||
|
||||
if (isset($aData['aQueries']) && count($aData['aQueries']) === 1)
|
||||
{
|
||||
if (isset($aData['aQueries']) && count($aData['aQueries']) === 1) {
|
||||
$aQueries = $aData['aQueries'];
|
||||
reset($aQueries);
|
||||
$sKey = key($aQueries);
|
||||
$oSearch = $aData['aQueries'][$sKey];
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$this->oScopeValidatorHelper->AddScopeToQuery($oQuery, $sClass);
|
||||
$aData = array();
|
||||
$aData = [];
|
||||
$this->ManageSearchValue($aData, $oQuery, $sClass);
|
||||
|
||||
// Grouping tab
|
||||
if ($oBrick->HasGroupingTabs())
|
||||
{
|
||||
if ($oBrick->HasGroupingTabs()) {
|
||||
$aGroupingTabs = $oBrick->GetGroupingTabs();
|
||||
|
||||
// If tabs are made of the distinct values of an attribute, we have a find them via a query
|
||||
if ($oBrick->IsGroupingTabsByDistinctValues())
|
||||
{
|
||||
if ($oBrick->IsGroupingTabsByDistinctValues()) {
|
||||
$sGroupingTabAttCode = $aGroupingTabs['attribute'];
|
||||
$aGroupingTabsValues = $this->GroupByAttribute($oQuery, $sGroupingTabAttCode, $oBrick);
|
||||
$oQuery = $oQuery->Intersect($aGroupingTabsValues[$sGroupingTab]['condition']);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($aGroupingTabs['groups'] as $aGroup)
|
||||
{
|
||||
if ($aGroup['id'] === $sGroupingTab)
|
||||
{
|
||||
} else {
|
||||
foreach ($aGroupingTabs['groups'] as $aGroup) {
|
||||
if ($aGroup['id'] === $sGroupingTab) {
|
||||
$oConditionQuery = $oQuery->Intersect(DBSearch::FromOQL($aGroup['condition']));
|
||||
$oQuery = $oQuery->Intersect($oConditionQuery);
|
||||
break;
|
||||
@@ -251,29 +237,27 @@ class ManageBrickController extends BrickController
|
||||
|
||||
// Finalclass
|
||||
$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GARE');
|
||||
$oExpression = new BinaryExpression(new FieldExpression('finalclass', 'GARE'), '=',
|
||||
new UnaryExpression($sGroupingArea));
|
||||
$oExpression = new BinaryExpression(
|
||||
new FieldExpression('finalclass', 'GARE'),
|
||||
'=',
|
||||
new UnaryExpression($sGroupingArea)
|
||||
);
|
||||
$oConditionQuery->AddConditionExpression($oExpression);
|
||||
/** @var DBSearch $oSearch */
|
||||
$oSearch = $oQuery->Intersect($oConditionQuery);
|
||||
}
|
||||
|
||||
$aColumnsAttrs = $oBrick->GetExportFields();
|
||||
$aFields = array();
|
||||
$aFields = [];
|
||||
$sTitleAttrCode = 'friendlyname';
|
||||
if (!in_array($sTitleAttrCode, $aColumnsAttrs))
|
||||
{
|
||||
if (!in_array($sTitleAttrCode, $aColumnsAttrs)) {
|
||||
$aFields[] = $sTitleAttrCode;
|
||||
}
|
||||
foreach ($aColumnsAttrs as $sAttCode)
|
||||
{
|
||||
foreach ($aColumnsAttrs as $sAttCode) {
|
||||
$oAttributeDef = MetaModel::GetAttributeDef($sGroupingArea, $sAttCode);
|
||||
if ($oAttributeDef->IsExternalKey(EXTKEY_ABSOLUTE))
|
||||
{
|
||||
if ($oAttributeDef->IsExternalKey(EXTKEY_ABSOLUTE)) {
|
||||
$aFields[] = $sAttCode.'_friendlyname';
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$aFields[] = $sAttCode;
|
||||
}
|
||||
}
|
||||
@@ -288,12 +272,12 @@ class ManageBrickController extends BrickController
|
||||
$oExporter->SetLocalizeOutput(true);
|
||||
$oExporter->SetFields($sFields);
|
||||
|
||||
$aData = array(
|
||||
$aData = [
|
||||
'oBrick' => $oBrick,
|
||||
'sBrickId' => $sBrickId,
|
||||
'sToken' => $oExporter->SaveState(),
|
||||
'sWikiUrl' => 'https://www.itophub.io/wiki/page?id='.utils::GetItopVersionWikiSyntax().'%3Auser%3Alists#excel_export',
|
||||
);
|
||||
'sWikiUrl' => 'https://www.itophub.io/wiki/page?id='.utils::GetItopVersionWikiSyntax().'%3Auser%3Alists#excel_export',
|
||||
];
|
||||
|
||||
return $this->render($this->GetTemplatePath('modal_export_excel'), $aData);
|
||||
}
|
||||
@@ -323,10 +307,10 @@ class ManageBrickController extends BrickController
|
||||
/** @var \Combodo\iTop\Portal\Brick\ManageBrick $oBrick */
|
||||
$oBrick = $this->oBrickCollection->GetBrickById($sBrickId);
|
||||
|
||||
$aData = array();
|
||||
$aGroupingTabsValues = array();
|
||||
$aGroupingAreasValues = array();
|
||||
$aQueries = array();
|
||||
$aData = [];
|
||||
$aGroupingTabsValues = [];
|
||||
$aGroupingAreasValues = [];
|
||||
$aQueries = [];
|
||||
$bHasScope = true;
|
||||
|
||||
// Getting current data loading mode (First from router parameter, then query parameter, then default brick value)
|
||||
@@ -334,8 +318,7 @@ class ManageBrickController extends BrickController
|
||||
|
||||
// - Retrieving the grouping areas to display
|
||||
$sGroupingArea = $this->oRequestManipulatorHelper->ReadParam('sGroupingArea', '');
|
||||
if (!empty($sGroupingArea))
|
||||
{
|
||||
if (!empty($sGroupingArea)) {
|
||||
$bNeedDetails = true;
|
||||
}
|
||||
|
||||
@@ -343,9 +326,8 @@ class ManageBrickController extends BrickController
|
||||
$aColumnsAttrs = $oBrick->GetFields();
|
||||
// Adding friendlyname attribute to the list if not already in it
|
||||
$sTitleAttrCode = 'friendlyname';
|
||||
if (($sTitleAttrCode !== null) && !in_array($sTitleAttrCode, $aColumnsAttrs))
|
||||
{
|
||||
$aColumnsAttrs = array_merge(array($sTitleAttrCode), $aColumnsAttrs);
|
||||
if (($sTitleAttrCode !== null) && !in_array($sTitleAttrCode, $aColumnsAttrs)) {
|
||||
$aColumnsAttrs = array_merge([$sTitleAttrCode], $aColumnsAttrs);
|
||||
}
|
||||
|
||||
// Starting to build query
|
||||
@@ -356,100 +338,78 @@ class ManageBrickController extends BrickController
|
||||
// Preparing tabs
|
||||
// - We need to retrieve distinct values for the grouping attribute
|
||||
$iCount = 0;
|
||||
if ($oBrick->HasGroupingTabs())
|
||||
{
|
||||
if ($oBrick->HasGroupingTabs()) {
|
||||
$aGroupingTabs = $oBrick->GetGroupingTabs();
|
||||
|
||||
// If tabs are made of the distinct values of an attribute, we have a find them via a query
|
||||
if ($oBrick->IsGroupingTabsByDistinctValues())
|
||||
{
|
||||
if ($oBrick->IsGroupingTabsByDistinctValues()) {
|
||||
$sGroupingTabAttCode = $aGroupingTabs['attribute'];
|
||||
$aGroupingTabsValues = $this->GroupByAttribute($oQuery, $sGroupingTabAttCode, $oBrick);
|
||||
foreach ($aGroupingTabsValues as $aResult)
|
||||
{
|
||||
foreach ($aGroupingTabsValues as $aResult) {
|
||||
$iCount += $aResult['count'];
|
||||
}
|
||||
}
|
||||
// Otherwise we create the tabs from the SQL expressions
|
||||
else
|
||||
{
|
||||
$aConditionQueryGrouping = array();
|
||||
foreach ($aGroupingTabs['groups'] as $aGroup)
|
||||
{
|
||||
else {
|
||||
$aConditionQueryGrouping = [];
|
||||
foreach ($aGroupingTabs['groups'] as $aGroup) {
|
||||
$oDBSearch = DBSearch::FromOQL($aGroup['condition']);
|
||||
$oConditionQuery = $oQuery->Intersect($oDBSearch);
|
||||
// - Restricting query to scope
|
||||
array_push($aConditionQueryGrouping,$oDBSearch);
|
||||
array_push($aConditionQueryGrouping, $oDBSearch);
|
||||
$bHasScope = $this->oScopeValidatorHelper->AddScopeToQuery($oConditionQuery, $oConditionQuery->GetClass());
|
||||
if ($bHasScope)
|
||||
{
|
||||
if ($bHasScope) {
|
||||
// - Building ObjectSet
|
||||
$oConditionSet = new DBObjectSet($oConditionQuery);
|
||||
$iGroupCount = $oConditionSet->Count();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oConditionSet = null;
|
||||
$iGroupCount = 0;
|
||||
}
|
||||
$aGroupingTabsValues[$aGroup['id']] = array(
|
||||
$aGroupingTabsValues[$aGroup['id']] = [
|
||||
'value' => $aGroup['id'],
|
||||
'label' => Dict::S($aGroup['title']),
|
||||
'label_html' => Dict::S($aGroup['title']),
|
||||
'description' => array_key_exists('description',$aGroup) ? Dict::S($aGroup['description']) : null,
|
||||
'description' => array_key_exists('description', $aGroup) ? Dict::S($aGroup['description']) : null,
|
||||
'condition' => $oConditionQuery,
|
||||
'count' => $iGroupCount,
|
||||
);
|
||||
];
|
||||
}
|
||||
try
|
||||
{
|
||||
try {
|
||||
$oConditionQuery = $oQuery->Intersect(new DBUnionSearch($aConditionQueryGrouping));
|
||||
$bHasScope = $this->oScopeValidatorHelper->AddScopeToQuery($oConditionQuery, $oConditionQuery->GetClass());
|
||||
if ($bHasScope)
|
||||
{
|
||||
if ($bHasScope) {
|
||||
// - Building ObjectSet
|
||||
$oConditionSet = new DBObjectSet($oConditionQuery);
|
||||
$iCount = $oConditionSet->Count();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oConditionSet = null;
|
||||
$iCount = 0;
|
||||
}
|
||||
}
|
||||
catch (Exception $e){
|
||||
} catch (Exception $e) {
|
||||
$oConditionSet = null;
|
||||
$iCount = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oConditionQuery = $this->GetScopedQuery($oBrick, $sClass);
|
||||
if (!is_null($oConditionQuery))
|
||||
{
|
||||
if (!is_null($oConditionQuery)) {
|
||||
$oSet = new DBObjectSet($oConditionQuery);
|
||||
$iCount = $oSet->Count();
|
||||
}
|
||||
}
|
||||
|
||||
// - Retrieving the current grouping tab to display if necessary and altering the query to do so
|
||||
if (empty($sGroupingTab))
|
||||
{
|
||||
if ($oBrick->HasGroupingTabs())
|
||||
{
|
||||
if (empty($sGroupingTab)) {
|
||||
if ($oBrick->HasGroupingTabs()) {
|
||||
reset($aGroupingTabsValues);
|
||||
$sGroupingTab = key($aGroupingTabsValues);
|
||||
if ($aGroupingTabsValues[$sGroupingTab]['condition'] !== null)
|
||||
{
|
||||
if ($aGroupingTabsValues[$sGroupingTab]['condition'] !== null) {
|
||||
$oQuery = $aGroupingTabsValues[$sGroupingTab]['condition']->DeepClone();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($aGroupingTabsValues[$sGroupingTab]['condition'] !== null)
|
||||
{
|
||||
} else {
|
||||
if ($aGroupingTabsValues[$sGroupingTab]['condition'] !== null) {
|
||||
$oQuery = $aGroupingTabsValues[$sGroupingTab]['condition']->DeepClone();
|
||||
}
|
||||
}
|
||||
@@ -464,60 +424,56 @@ class ManageBrickController extends BrickController
|
||||
// - We need to retrieve distinct values for the grouping attribute
|
||||
// Note : Will have to be changed when we consider grouping on something else than the finalclass
|
||||
$sParentAlias = $oQuery->GetClassAlias();
|
||||
if ($bNeedDetails)
|
||||
{
|
||||
if ($bNeedDetails) {
|
||||
$sGroupingAreaAttCode = 'finalclass';
|
||||
|
||||
// For root classes
|
||||
if (MetaModel::IsValidAttCode($sClass, $sGroupingAreaAttCode))
|
||||
{
|
||||
if (MetaModel::IsValidAttCode($sClass, $sGroupingAreaAttCode)) {
|
||||
$oDistinctQuery = $this->GetScopedQuery($oBrick, $sClass);
|
||||
// Adding grouping conditions
|
||||
$oFieldExp = new FieldExpression($sGroupingAreaAttCode, $oDistinctQuery->GetClassAlias());
|
||||
$sDistinctSql = $oDistinctQuery->MakeGroupByQuery(array(), array('grouped_by_1' => $oFieldExp), true);
|
||||
$sDistinctSql = $oDistinctQuery->MakeGroupByQuery([], ['grouped_by_1' => $oFieldExp], true);
|
||||
$aDistinctResults = CMDBSource::QueryToArray($sDistinctSql);
|
||||
|
||||
foreach ($aDistinctResults as $aDistinctResult)
|
||||
{
|
||||
foreach ($aDistinctResults as $aDistinctResult) {
|
||||
$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GARE');
|
||||
$oExpression = new BinaryExpression(new FieldExpression($sGroupingAreaAttCode, 'GARE'), '=',
|
||||
new UnaryExpression($aDistinctResult['grouped_by_1']));
|
||||
$oExpression = new BinaryExpression(
|
||||
new FieldExpression($sGroupingAreaAttCode, 'GARE'),
|
||||
'=',
|
||||
new UnaryExpression($aDistinctResult['grouped_by_1'])
|
||||
);
|
||||
$oConditionQuery->AddConditionExpression($oExpression);
|
||||
|
||||
$aGroupingAreasValues[$aDistinctResult['grouped_by_1']] = array(
|
||||
$aGroupingAreasValues[$aDistinctResult['grouped_by_1']] = [
|
||||
'value' => $aDistinctResult['grouped_by_1'],
|
||||
'label' => MetaModel::GetName($aDistinctResult['grouped_by_1']),
|
||||
// Caution : This works only because we froze the grouping areas on the finalclass attribute.
|
||||
'condition' => $oConditionQuery,
|
||||
'count' => $aDistinctResult['_itop_count_'],
|
||||
);
|
||||
];
|
||||
unset($oConditionQuery);
|
||||
}
|
||||
unset($aDistinctResults);
|
||||
}
|
||||
// For leaf classes
|
||||
else
|
||||
{
|
||||
$aGroupingAreasValues[$sClass] = array(
|
||||
else {
|
||||
$aGroupingAreasValues[$sClass] = [
|
||||
'value' => $sClass,
|
||||
'label' => MetaModel::GetName($sClass),
|
||||
// Caution : This works only because we froze the grouping areas on the finalclass attribute.
|
||||
'condition' => null,
|
||||
'count' => 0,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
// - If specified or lazy loading, we truncate the $aGroupingAreasValues to keep only this one
|
||||
if (!empty($sGroupingArea))
|
||||
{
|
||||
$aGroupingAreasValues = array($sGroupingArea => $aGroupingAreasValues[$sGroupingArea]);
|
||||
if (!empty($sGroupingArea)) {
|
||||
$aGroupingAreasValues = [$sGroupingArea => $aGroupingAreasValues[$sGroupingArea]];
|
||||
}
|
||||
// - Preparing the queries
|
||||
foreach ($aGroupingAreasValues as $sKey => $aGroupingAreasValue)
|
||||
{
|
||||
foreach ($aGroupingAreasValues as $sKey => $aGroupingAreasValue) {
|
||||
$oAreaQuery = DBSearch::CloneWithAlias($oQuery, $sParentAlias);
|
||||
if ($aGroupingAreasValue['condition'] !== null)
|
||||
{
|
||||
if ($aGroupingAreasValue['condition'] !== null) {
|
||||
$oAreaQuery = $aGroupingAreasValue['condition']->DeepClone();
|
||||
}
|
||||
|
||||
@@ -525,8 +481,7 @@ class ManageBrickController extends BrickController
|
||||
// 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
|
||||
$bHasScope = $this->oScopeValidatorHelper->AddScopeToQuery($oAreaQuery, $aGroupingAreasValue['value']);
|
||||
if (!$bHasScope)
|
||||
{
|
||||
if (!$bHasScope) {
|
||||
// if no scope apply does not allow any data
|
||||
$oAreaQuery = null;
|
||||
}
|
||||
@@ -538,71 +493,64 @@ class ManageBrickController extends BrickController
|
||||
|
||||
// Testing appropriate data loading mode if we are in auto
|
||||
// - For all (html) tables, this doesn't care for the grouping ares (finalclass)
|
||||
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_AUTO)
|
||||
{
|
||||
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_AUTO) {
|
||||
// - Check how many records there is.
|
||||
// - Update $sDataLoading with its new value regarding the number of record and the threshold
|
||||
$oCountSet = new DBObjectSet($oQuery);
|
||||
$oCountSet->OptimizeColumnLoad(array($oQuery->GetClassAlias() => array()));
|
||||
$fThreshold = (float)MetaModel::GetModuleSetting($sPortalId,
|
||||
'lazy_loading_threshold');
|
||||
$oCountSet->OptimizeColumnLoad([$oQuery->GetClassAlias() => []]);
|
||||
$fThreshold = (float)MetaModel::GetModuleSetting(
|
||||
$sPortalId,
|
||||
'lazy_loading_threshold'
|
||||
);
|
||||
$sDataLoading = ($oCountSet->Count() > $fThreshold) ? AbstractBrick::ENUM_DATA_LOADING_LAZY : AbstractBrick::ENUM_DATA_LOADING_FULL;
|
||||
unset($oCountSet);
|
||||
}
|
||||
|
||||
// Preparing data sets
|
||||
$aSets = array();
|
||||
$aSets = [];
|
||||
/** @var DBSearch $oQuery */
|
||||
foreach ($aQueries as $sKey => $oQuery)
|
||||
{
|
||||
foreach ($aQueries as $sKey => $oQuery) {
|
||||
// Checking if we have a valid query
|
||||
if ($oQuery !== null)
|
||||
{
|
||||
if ($oQuery !== null) {
|
||||
// - Adding search clause if necessary
|
||||
$this->ManageSearchValue($aData, $oQuery, $sKey, $aColumnsAttrs);
|
||||
|
||||
|
||||
// Setting query pagination if needed
|
||||
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY)
|
||||
{
|
||||
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY) {
|
||||
// Retrieving parameters
|
||||
$iPageNumber = (int)$this->oRequestManipulatorHelper->ReadParam('iPageNumber', 1, FILTER_SANITIZE_NUMBER_INT);
|
||||
$iListLength = (int)$this->oRequestManipulatorHelper->ReadParam('iListLength', ManageBrick::DEFAULT_LIST_LENGTH,
|
||||
FILTER_SANITIZE_NUMBER_INT);
|
||||
$iListLength = (int)$this->oRequestManipulatorHelper->ReadParam(
|
||||
'iListLength',
|
||||
ManageBrick::DEFAULT_LIST_LENGTH,
|
||||
FILTER_SANITIZE_NUMBER_INT
|
||||
);
|
||||
|
||||
// Getting total records number
|
||||
$oCountSet = new DBObjectSet($oQuery);
|
||||
$oCountSet->OptimizeColumnLoad(array($oQuery->GetClassAlias() => $aColumnsAttrs));
|
||||
$oCountSet->OptimizeColumnLoad([$oQuery->GetClassAlias() => $aColumnsAttrs]);
|
||||
$aData['recordsTotal'] = $oCountSet->Count();
|
||||
$aData['recordsFiltered'] = $oCountSet->Count();
|
||||
unset($oCountSet);
|
||||
|
||||
$oSet = new DBObjectSet($oQuery);
|
||||
$oSet->SetLimit($iListLength, $iListLength * ($iPageNumber - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oSet = new DBObjectSet($oQuery);
|
||||
}
|
||||
|
||||
// Setting specified column sort, setting default datamodel one otherwise
|
||||
if (!empty($aSortedParams))
|
||||
{
|
||||
if (!empty($aSortedParams)) {
|
||||
$oSet->SetOrderBy($aSortedParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oSet->SetOrderByClasses();
|
||||
}
|
||||
|
||||
// Adding always_in_tables attributes
|
||||
$aColumnsToLoad = array($oQuery->GetClassAlias() => $aColumnsAttrs);
|
||||
foreach ($oQuery->GetSelectedClasses() as $sAlias => $sClassSelected)
|
||||
{
|
||||
$aColumnsToLoad = [$oQuery->GetClassAlias() => $aColumnsAttrs];
|
||||
foreach ($oQuery->GetSelectedClasses() as $sAlias => $sClassSelected) {
|
||||
/** @var AttributeDefinition $oAttDef */
|
||||
foreach (MetaModel::ListAttributeDefs($sClassSelected) as $sAttCode => $oAttDef)
|
||||
{
|
||||
if ($oAttDef->AlwaysLoadInTables())
|
||||
{
|
||||
foreach (MetaModel::ListAttributeDefs($sClassSelected) as $sAttCode => $oAttDef) {
|
||||
if ($oAttDef->AlwaysLoadInTables()) {
|
||||
$aColumnsToLoad[$sAlias][] = $sAttCode;
|
||||
}
|
||||
}
|
||||
@@ -610,17 +558,18 @@ class ManageBrickController extends BrickController
|
||||
// Note: $aColumnToLoad already contains array of aliases => attcodes
|
||||
$oSet->OptimizeColumnLoad($aColumnsToLoad);
|
||||
|
||||
$this->oSecurityHelper->PreloadForCache($oSet->GetFilter(),
|
||||
$aColumnsToLoad[$oQuery->GetClassAlias()] /* preloading only extkeys from the main class */);
|
||||
$this->oSecurityHelper->PreloadForCache(
|
||||
$oSet->GetFilter(),
|
||||
$aColumnsToLoad[$oQuery->GetClassAlias()] /* preloading only extkeys from the main class */
|
||||
);
|
||||
$aSets[$sKey] = $oSet;
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieving and preparing data for rendering
|
||||
$aGroupingAreasData = array();
|
||||
$aGroupingAreasData = [];
|
||||
$bHasObjectListItemExtension = false;
|
||||
foreach ($aSets as $sKey => $oSet)
|
||||
{
|
||||
foreach ($aSets as $sKey => $oSet) {
|
||||
// Set properties
|
||||
$sCurrentClass = $sKey;
|
||||
|
||||
@@ -628,94 +577,88 @@ class ManageBrickController extends BrickController
|
||||
$sMainActionAttrCode = $aColumnsAttrs[0];
|
||||
|
||||
// Loading columns definition
|
||||
$aColumnsDefinition = array();
|
||||
foreach ($aColumnsAttrs as $sColumnAttr)
|
||||
{
|
||||
$aColumnsDefinition = [];
|
||||
foreach ($aColumnsAttrs as $sColumnAttr) {
|
||||
$oAttDef = MetaModel::GetAttributeDef($sKey, $sColumnAttr);
|
||||
$aColumnsDefinition[$sColumnAttr] = array(
|
||||
$aColumnsDefinition[$sColumnAttr] = [
|
||||
'title' => $oAttDef->GetLabel(),
|
||||
'type' => ($oAttDef instanceof AttributeDateTime) ? 'moment-'.$oAttDef->GetFormat()->ToMomentJS() : 'html',
|
||||
// Special sorting for Date & Time
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
// Getting items
|
||||
$aItems = array();
|
||||
$aItems = [];
|
||||
// ... For each item
|
||||
/** @var DBObject $oCurrentRow */
|
||||
while ($oCurrentRow = $oSet->Fetch())
|
||||
{
|
||||
while ($oCurrentRow = $oSet->Fetch()) {
|
||||
$sCurrentObjectClass = get_class($oCurrentRow);
|
||||
$sCurrentObjectId = $oCurrentRow->GetKey();
|
||||
|
||||
// ... Retrieving item's attributes values
|
||||
$aItemAttrs = array();
|
||||
foreach ($aColumnsAttrs as $sItemAttr)
|
||||
{
|
||||
$aActions = array();
|
||||
$aItemAttrs = [];
|
||||
foreach ($aColumnsAttrs as $sItemAttr) {
|
||||
$aActions = [];
|
||||
// Set the edit action to the main (first) attribute only
|
||||
//if ($sItemAttr === $sTitleAttrCode)
|
||||
if ($sItemAttr === $sMainActionAttrCode)
|
||||
{
|
||||
if ($sItemAttr === $sMainActionAttrCode) {
|
||||
// Checking if we can edit the object
|
||||
if (($oBrick->GetOpeningMode() === ManageBrick::ENUM_ACTION_EDIT) && $this->oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY,
|
||||
$sCurrentClass, $oCurrentRow->GetKey()))
|
||||
{
|
||||
if (($oBrick->GetOpeningMode() === ManageBrick::ENUM_ACTION_EDIT) && $this->oSecurityHelper->IsActionAllowed(
|
||||
UR_ACTION_MODIFY,
|
||||
$sCurrentClass,
|
||||
$oCurrentRow->GetKey()
|
||||
)) {
|
||||
$sActionType = ManageBrick::ENUM_ACTION_EDIT;
|
||||
}
|
||||
// - Otherwise, check if view is allowed
|
||||
elseif ($this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sCurrentClass,
|
||||
$oCurrentRow->GetKey()))
|
||||
{
|
||||
elseif ($this->oSecurityHelper->IsActionAllowed(
|
||||
UR_ACTION_READ,
|
||||
$sCurrentClass,
|
||||
$oCurrentRow->GetKey()
|
||||
)) {
|
||||
$sActionType = ManageBrick::ENUM_ACTION_VIEW;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$sActionType = null;
|
||||
}
|
||||
// - Then set allowed action
|
||||
if ($sActionType !== null)
|
||||
{
|
||||
$aActions[] = array(
|
||||
if ($sActionType !== null) {
|
||||
$aActions[] = [
|
||||
'type' => $sActionType,
|
||||
'class' => $sCurrentClass,
|
||||
'id' => $oCurrentRow->GetKey(),
|
||||
'opening_target' => $oBrick->GetOpeningTarget(),
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/** @var \AttributeDefinition $oAttDef */
|
||||
$oAttDef = MetaModel::GetAttributeDef($sCurrentClass, $sItemAttr);
|
||||
$sAttDefClass = get_class($oAttDef);
|
||||
if ($oAttDef->IsExternalKey())
|
||||
{
|
||||
if ($oAttDef->IsExternalKey()) {
|
||||
/** @var \AttributeExternalKey $oAttDef */
|
||||
$sValue = $oCurrentRow->GetAsHTML($sItemAttr.'_friendlyname');
|
||||
$sSortValue = $oCurrentRow->Get($sItemAttr.'_friendlyname');
|
||||
|
||||
// Adding a view action on the external keys
|
||||
if ($oCurrentRow->Get($sItemAttr) !== $oAttDef->GetNullValue())
|
||||
{
|
||||
if ($oCurrentRow->Get($sItemAttr) !== $oAttDef->GetNullValue()) {
|
||||
// Checking if we can view the object
|
||||
if (($this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $oAttDef->GetTargetClass(),
|
||||
$oCurrentRow->Get($sItemAttr))))
|
||||
{
|
||||
$aActions[] = array(
|
||||
if (($this->oSecurityHelper->IsActionAllowed(
|
||||
UR_ACTION_READ,
|
||||
$oAttDef->GetTargetClass(),
|
||||
$oCurrentRow->Get($sItemAttr)
|
||||
))) {
|
||||
$aActions[] = [
|
||||
'type' => ManageBrick::ENUM_ACTION_VIEW,
|
||||
'class' => $oAttDef->GetTargetClass(),
|
||||
'id' => $oCurrentRow->Get($sItemAttr),
|
||||
'opening_target' => $oBrick->GetOpeningTarget(),
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($oAttDef instanceof AttributeImage)
|
||||
{
|
||||
} elseif ($oAttDef instanceof AttributeImage) {
|
||||
/** @var \ormDocument $oOrmDoc */
|
||||
$oOrmDoc = $oCurrentRow->Get($sItemAttr);
|
||||
if (is_object($oOrmDoc) && !$oOrmDoc->IsEmpty())
|
||||
{
|
||||
if (is_object($oOrmDoc) && !$oOrmDoc->IsEmpty()) {
|
||||
$sUrl = $this->oUrlGenerator->generate('p_object_document_display', [
|
||||
'sObjectClass' => get_class($oCurrentRow),
|
||||
'sObjectId' => $oCurrentRow->GetKey(),
|
||||
@@ -723,16 +666,12 @@ class ManageBrickController extends BrickController
|
||||
'cache' => 86400,
|
||||
's' => $oOrmDoc->GetSignature(),
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$sUrl = $oAttDef->Get('default_image');
|
||||
}
|
||||
$sValue = '<img src="'.$sUrl.'" />';
|
||||
$sSortValue = null;
|
||||
}
|
||||
elseif ($oAttDef instanceof AttributeTagSet)
|
||||
{
|
||||
} elseif ($oAttDef instanceof AttributeTagSet) {
|
||||
/** @var \ormTagSet $oSetValues */
|
||||
$oSetValues = $oCurrentRow->Get($sItemAttr);
|
||||
$aCodes = $oSetValues->GetTags();
|
||||
@@ -754,17 +693,15 @@ class ManageBrickController extends BrickController
|
||||
|
||||
// For simple fields, we get the raw (stored) value as well
|
||||
$bExcludeRawValue = false;
|
||||
foreach (ApplicationHelper::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude)
|
||||
{
|
||||
if (is_a($sAttDefClass, $sAttDefClassToExclude, true))
|
||||
{
|
||||
foreach (ApplicationHelper::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude) {
|
||||
if (is_a($sAttDefClass, $sAttDefClassToExclude, true)) {
|
||||
$bExcludeRawValue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$attValueRaw = ($bExcludeRawValue === false) ? $oCurrentRow->Get($sItemAttr) : null;
|
||||
|
||||
$aItemAttrs[$sItemAttr] = array(
|
||||
$aItemAttrs[$sItemAttr] = [
|
||||
'object_class' => $sCurrentObjectClass,
|
||||
'object_id' => $sCurrentObjectId,
|
||||
'attribute_code' => $sItemAttr,
|
||||
@@ -773,114 +710,105 @@ class ManageBrickController extends BrickController
|
||||
'value_html' => $sValue,
|
||||
'sort_value' => $sSortValue,
|
||||
'actions' => $aActions,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
// ... Checking menu extensions
|
||||
$aItemButtons = array();
|
||||
$aItemButtons = [];
|
||||
/** @var iPopupMenuExtension $oExtensionInstance */
|
||||
foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance)
|
||||
{
|
||||
foreach ($oExtensionInstance->EnumItems(iPopupMenuExtension::PORTAL_OBJLISTITEM_ACTIONS, array(
|
||||
foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance) {
|
||||
foreach ($oExtensionInstance->EnumItems(iPopupMenuExtension::PORTAL_OBJLISTITEM_ACTIONS, [
|
||||
'portal_id' => $sPortalId,
|
||||
'object' => $oCurrentRow,
|
||||
)) as $oMenuItem)
|
||||
{
|
||||
if (is_object($oMenuItem))
|
||||
{
|
||||
if ($oMenuItem instanceof JSButtonItem)
|
||||
{
|
||||
$aItemButtons[] = $oMenuItem->GetMenuItem() + array(
|
||||
]) as $oMenuItem) {
|
||||
if (is_object($oMenuItem)) {
|
||||
if ($oMenuItem instanceof JSButtonItem) {
|
||||
$aItemButtons[] = $oMenuItem->GetMenuItem() + [
|
||||
'js_files' => $oMenuItem->GetLinkedScripts(),
|
||||
'type' => 'button',
|
||||
);
|
||||
}
|
||||
elseif ($oMenuItem instanceof URLButtonItem)
|
||||
{
|
||||
$aItemButtons[] = $oMenuItem->GetMenuItem() + array('type' => 'link');
|
||||
];
|
||||
} elseif ($oMenuItem instanceof URLButtonItem) {
|
||||
$aItemButtons[] = $oMenuItem->GetMenuItem() + ['type' => 'link'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ... And item's properties
|
||||
$aItems[] = array(
|
||||
$aItems[] = [
|
||||
'id' => $oCurrentRow->GetKey(),
|
||||
'class' => $sCurrentClass,
|
||||
'attributes' => $aItemAttrs,
|
||||
'highlight_class' => $oCurrentRow->GetHilightClass(),
|
||||
'actions' => $aItemButtons,
|
||||
);
|
||||
];
|
||||
|
||||
if (!empty($aItemButtons))
|
||||
{
|
||||
if (!empty($aItemButtons)) {
|
||||
$bHasObjectListItemExtension = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Adding an extra column for object list item extensions
|
||||
if ($bHasObjectListItemExtension === true)
|
||||
{
|
||||
$aColumnsDefinition['_ui_extensions'] = array(
|
||||
if ($bHasObjectListItemExtension === true) {
|
||||
$aColumnsDefinition['_ui_extensions'] = [
|
||||
'title' => Dict::S('Brick:Portal:Manage:Table:ItemActions'),
|
||||
'type' => 'html',
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
$aGroupingAreasData[$sKey] = array(
|
||||
$aGroupingAreasData[$sKey] = [
|
||||
'sId' => $sKey,
|
||||
'sTitle' => $aGroupingAreasValues[$sKey]['label'],
|
||||
'aItems' => $aItems,
|
||||
'iItemsCount' => $oSet->Count(),
|
||||
'aColumnsDefinition' => $aColumnsDefinition,
|
||||
);
|
||||
];
|
||||
|
||||
IssueLog::Debug('Portal ManageBrick query', LogChannels::PORTAL, array(
|
||||
IssueLog::Debug('Portal ManageBrick query', LogChannels::PORTAL, [
|
||||
'sPortalId' => $sPortalId,
|
||||
'sBrickId' => $sBrickId,
|
||||
'sGroupingTab' => $sGroupingTab,
|
||||
'oql' => $oSet->GetFilter()->ToOQL(),
|
||||
'aGroupingTabs' => $aGroupingTabs,
|
||||
));
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
$aGroupingAreasData = array();
|
||||
$aGroupingAreasData = [];
|
||||
$sGroupingArea = null;
|
||||
}
|
||||
|
||||
// Preparing response
|
||||
if ($oRequest->isXmlHttpRequest()) {
|
||||
$aData = $aData + array(
|
||||
$aData = $aData + [
|
||||
'data' => $aGroupingAreasData[$sGroupingArea]['aItems'],
|
||||
);
|
||||
];
|
||||
} else {
|
||||
$aDisplayValues = array();
|
||||
$aUrls = array();
|
||||
$aColumns = array();
|
||||
$aNames = array();
|
||||
$aDisplayValues = [];
|
||||
$aUrls = [];
|
||||
$aColumns = [];
|
||||
$aNames = [];
|
||||
if ($bHasScope) {
|
||||
foreach ($aGroupingTabsValues as $aValues) {
|
||||
$aDisplayValues[] = array(
|
||||
$aDisplayValues[] = [
|
||||
'value' => $aValues['count'],
|
||||
'label' => $aValues['label'],
|
||||
'label_html' => $aValues['label_html'],
|
||||
);
|
||||
$aUrls[] = $this->oUrlGenerator->generate('p_manage_brick_display_as', array(
|
||||
];
|
||||
$aUrls[] = $this->oUrlGenerator->generate('p_manage_brick_display_as', [
|
||||
'sBrickId' => $sBrickId,
|
||||
'sDisplayMode' => 'list',
|
||||
'sGroupingTab' => $aValues['value'],
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($aDisplayValues as $idx => $aValue)
|
||||
{
|
||||
$aColumns[] = array('series_'.$idx, (int)$aValue['value']);
|
||||
foreach ($aDisplayValues as $idx => $aValue) {
|
||||
$aColumns[] = ['series_'.$idx, (int)$aValue['value']];
|
||||
$aNames['series_'.$idx] = $aValue['label'];
|
||||
}
|
||||
}
|
||||
|
||||
// Preparing data to pass to the templating service
|
||||
$aData = $aData + array(
|
||||
$aData = $aData + [
|
||||
'sFct' => 'count',
|
||||
'sIconURL' => $sIconURL,
|
||||
'aColumns' => $aColumns,
|
||||
@@ -896,7 +824,7 @@ class ManageBrickController extends BrickController
|
||||
'sDateFormat' => AttributeDate::GetFormat()->ToMomentJS(),
|
||||
'sDateTimeFormat' => AttributeDateTime::GetFormat()->ToMomentJS(),
|
||||
'iCount' => $iCount,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
return $aData;
|
||||
@@ -911,7 +839,7 @@ class ManageBrickController extends BrickController
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function ManageSearchValue(&$aData, DBSearch &$oQuery, $sClass, $aColumnsAttrs = array())
|
||||
protected function ManageSearchValue(&$aData, DBSearch &$oQuery, $sClass, $aColumnsAttrs = [])
|
||||
{
|
||||
// Getting search value
|
||||
$sRawSearchValue = trim($this->oRequestManipulatorHelper->ReadParam('sSearchValue', ''));
|
||||
@@ -975,24 +903,22 @@ class ManageBrickController extends BrickController
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function GroupByAttribute(DBSearch $oQuery, $sGroupingTabAttCode, ManageBrick $oBrick) {
|
||||
protected function GroupByAttribute(DBSearch $oQuery, $sGroupingTabAttCode, ManageBrick $oBrick)
|
||||
{
|
||||
|
||||
$aGroupingTabsValues = array();
|
||||
$aDistinctResults = array();
|
||||
$aGroupingTabsValues = [];
|
||||
$aDistinctResults = [];
|
||||
$oDistinctQuery = DBSearch::FromOQL($oBrick->GetOql());
|
||||
$bHasScope = $this->oScopeValidatorHelper->AddScopeToQuery($oDistinctQuery, $oDistinctQuery->GetClass());
|
||||
if ($bHasScope)
|
||||
{
|
||||
if ($bHasScope) {
|
||||
// - Adding field condition
|
||||
$oFieldExp = new FieldExpression($sGroupingTabAttCode, $oDistinctQuery->GetClassAlias());
|
||||
$sDistinctSql = $oDistinctQuery->MakeGroupByQuery(array(), array('grouped_by_1' => $oFieldExp), true);
|
||||
$sDistinctSql = $oDistinctQuery->MakeGroupByQuery([], ['grouped_by_1' => $oFieldExp], true);
|
||||
$aDistinctResults = CMDBSource::QueryToArray($sDistinctSql);
|
||||
if (!empty($aDistinctResults))
|
||||
{
|
||||
if (!empty($aDistinctResults)) {
|
||||
$iLimit = $oBrick->GetGroupLimit();
|
||||
$aOthers = array();
|
||||
if ($iLimit > 0)
|
||||
{
|
||||
$aOthers = [];
|
||||
if ($iLimit > 0) {
|
||||
uasort($aDistinctResults, function ($a, $b) {
|
||||
$v1 = $a['_itop_count_'];
|
||||
$v2 = $b['_itop_count_'];
|
||||
@@ -1000,77 +926,72 @@ class ManageBrickController extends BrickController
|
||||
return ($v1 == $v2) ? 0 : (($v1 > $v2) ? -1 : 1);
|
||||
});
|
||||
|
||||
if (count($aDistinctResults) > $iLimit)
|
||||
{
|
||||
if ($oBrick->ShowGroupOthers())
|
||||
{
|
||||
if (count($aDistinctResults) > $iLimit) {
|
||||
if ($oBrick->ShowGroupOthers()) {
|
||||
$aOthers = array_slice($aDistinctResults, $iLimit);
|
||||
}
|
||||
$aDistinctResults = array_slice($aDistinctResults, 0, $iLimit);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($aDistinctResults as $aDistinctResult)
|
||||
{
|
||||
foreach ($aDistinctResults as $aDistinctResult) {
|
||||
$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GTAB');
|
||||
$oExpression = new BinaryExpression(new FieldExpression($sGroupingTabAttCode,
|
||||
$oConditionQuery->GetClassAlias()), '=', new UnaryExpression($aDistinctResult['grouped_by_1']));
|
||||
$oExpression = new BinaryExpression(new FieldExpression(
|
||||
$sGroupingTabAttCode,
|
||||
$oConditionQuery->GetClassAlias()
|
||||
), '=', new UnaryExpression($aDistinctResult['grouped_by_1']));
|
||||
$oConditionQuery->AddConditionExpression($oExpression);
|
||||
|
||||
$sHtmlLabel = $oFieldExp->MakeValueLabel($oDistinctQuery, $aDistinctResult['grouped_by_1'], '');
|
||||
$aGroupingTabsValues[$aDistinctResult['grouped_by_1']] = array(
|
||||
$aGroupingTabsValues[$aDistinctResult['grouped_by_1']] = [
|
||||
'value' => $aDistinctResult['grouped_by_1'],
|
||||
'label_html' => $sHtmlLabel,
|
||||
'label' => strip_tags(html_entity_decode($sHtmlLabel, ENT_QUOTES, 'UTF-8')),
|
||||
'condition' => $oConditionQuery,
|
||||
'count' => $aDistinctResult['_itop_count_'],
|
||||
);
|
||||
];
|
||||
unset($oConditionQuery);
|
||||
}
|
||||
if (!empty($aOthers))
|
||||
{
|
||||
if (!empty($aOthers)) {
|
||||
// Aggregate others
|
||||
$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GTAB');
|
||||
$oExpression = null;
|
||||
$iOtherCount = 0;
|
||||
foreach ($aOthers as $aResult)
|
||||
{
|
||||
foreach ($aOthers as $aResult) {
|
||||
$iOtherCount += $aResult['_itop_count_'];
|
||||
$oExpr = new BinaryExpression(new FieldExpression($sGroupingTabAttCode,
|
||||
$oConditionQuery->GetClassAlias()), '=', new UnaryExpression($aResult['grouped_by_1']));
|
||||
if (is_null($oExpression))
|
||||
{
|
||||
$oExpr = new BinaryExpression(new FieldExpression(
|
||||
$sGroupingTabAttCode,
|
||||
$oConditionQuery->GetClassAlias()
|
||||
), '=', new UnaryExpression($aResult['grouped_by_1']));
|
||||
if (is_null($oExpression)) {
|
||||
$oExpression = $oExpr;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oExpression = new BinaryExpression($oExpression, 'OR', $oExpr);
|
||||
}
|
||||
}
|
||||
$oConditionQuery->AddConditionExpression($oExpression);
|
||||
|
||||
$sLabel = Dict::S('Brick:Portal:Manage:Others');
|
||||
$aGroupingTabsValues['Others'] = array(
|
||||
$aGroupingTabsValues['Others'] = [
|
||||
'value' => 'Others',
|
||||
'label_html' => $sLabel,
|
||||
'label' => $sLabel,
|
||||
'condition' => $oConditionQuery,
|
||||
'count' => $iOtherCount,
|
||||
);
|
||||
];
|
||||
unset($oConditionQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (empty($aDistinctResults))
|
||||
{
|
||||
if (empty($aDistinctResults)) {
|
||||
$sLabel = Dict::S('Brick:Portal:Manage:All');
|
||||
$aGroupingTabsValues['undefined'] = array(
|
||||
$aGroupingTabsValues['undefined'] = [
|
||||
'value' => 'All',
|
||||
'label_html' => $sLabel,
|
||||
'label' => $sLabel,
|
||||
'condition' => null,
|
||||
'count' => 0,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
return $aGroupingTabsValues;
|
||||
|
||||
@@ -36,7 +36,6 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
*/
|
||||
class SessionMessageController extends AbstractController
|
||||
{
|
||||
|
||||
/**
|
||||
* @param \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulatorHelper
|
||||
* @param \Combodo\iTop\Portal\Helper\SessionMessageHelper $oSessionMessageHelper
|
||||
@@ -46,8 +45,7 @@ class SessionMessageController extends AbstractController
|
||||
public function __construct(
|
||||
protected RequestManipulatorHelper $oRequestManipulatorHelper,
|
||||
protected SessionMessageHelper $oSessionMessageHelper
|
||||
)
|
||||
{
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,15 +55,14 @@ class SessionMessageController extends AbstractController
|
||||
*/
|
||||
public function AddMessageAction(Request $oRequest)
|
||||
{
|
||||
$aData = array();
|
||||
$aData = [];
|
||||
|
||||
// Retrieve parameters
|
||||
$sMessageSeverity = $this->oRequestManipulatorHelper->ReadParam('sSeverity');
|
||||
$sMessageContent = $this->oRequestManipulatorHelper->ReadParam('sContent');
|
||||
|
||||
// Check parameters consistency
|
||||
if (empty($sMessageSeverity) || empty($sMessageContent))
|
||||
{
|
||||
if (empty($sMessageSeverity) || empty($sMessageContent)) {
|
||||
throw new HttpException(Response::HTTP_BAD_REQUEST, 'Message must have a severity and a content, make sure both sSeverity & sContent parameters are sent.');
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ use Throwable;
|
||||
*/
|
||||
class PortalCollector extends AbstractDataCollector
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -100,13 +99,13 @@ class PortalCollector extends AbstractDataCollector
|
||||
$iOverridesCount = 0;
|
||||
$aExtensions = [];
|
||||
|
||||
foreach($aTemplatesDefinitions as $templates){
|
||||
foreach ($aTemplatesDefinitions as $templates) {
|
||||
foreach ($templates as $template) {
|
||||
|
||||
$aMatches = [];
|
||||
preg_match('#([\w-]+)/#', $template->GetPath(), $aMatches);
|
||||
|
||||
if(!in_array($aMatches[1], $aExtensions)){
|
||||
if (!in_array($aMatches[1], $aExtensions)) {
|
||||
$aExtensions[] = $aMatches[1];
|
||||
}
|
||||
|
||||
@@ -134,4 +133,4 @@ class PortalCollector extends AbstractDataCollector
|
||||
return 'portal';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,4 +52,4 @@ class AbstractConfiguration
|
||||
return $this->oModuleDesign;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -42,23 +43,19 @@ class Forms extends AbstractConfiguration
|
||||
*/
|
||||
public function Process(Container $oContainer)
|
||||
{
|
||||
$aForms = array();
|
||||
$aForms = [];
|
||||
|
||||
/** @var \MFElement $oFormNode */
|
||||
foreach ($this->GetModuleDesign()->GetNodes('/module_design/forms/form') as $oFormNode)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach ($this->GetModuleDesign()->GetNodes('/module_design/forms/form') as $oFormNode) {
|
||||
try {
|
||||
// Parsing form id
|
||||
$sFormId = $oFormNode->getAttribute('id');
|
||||
if ($oFormNode->getAttribute('id') === '')
|
||||
{
|
||||
if ($oFormNode->getAttribute('id') === '') {
|
||||
throw new DOMFormatException('form tag must have an id attribute', 0, null, $oFormNode);
|
||||
}
|
||||
|
||||
// Parsing form object class
|
||||
if ($oFormNode->GetUniqueElement('class')->GetText() === null)
|
||||
{
|
||||
if ($oFormNode->GetUniqueElement('class')->GetText() === null) {
|
||||
throw new DOMFormatException('Class tag must be defined', 0, null, $oFormNode);
|
||||
}
|
||||
|
||||
@@ -66,29 +63,26 @@ class Forms extends AbstractConfiguration
|
||||
$sFormClass = $oFormNode->GetUniqueElement('class')->GetText();
|
||||
|
||||
// Parsing properties
|
||||
$aFormProperties = array(
|
||||
$aFormProperties = [
|
||||
'display_mode' => ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE,
|
||||
'always_show_submit' => ApplicationHelper::FORM_DEFAULT_ALWAYS_SHOW_SUBMIT,
|
||||
'navigation_rules' => array(
|
||||
'submit' => array(
|
||||
'navigation_rules' => [
|
||||
'submit' => [
|
||||
NavigationRuleHelper::ENUM_ORIGIN_PAGE => null,
|
||||
NavigationRuleHelper::ENUM_ORIGIN_MODAL => null,
|
||||
),
|
||||
'cancel' => array(
|
||||
],
|
||||
'cancel' => [
|
||||
NavigationRuleHelper::ENUM_ORIGIN_PAGE => null,
|
||||
NavigationRuleHelper::ENUM_ORIGIN_MODAL => null,
|
||||
),
|
||||
),
|
||||
);
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$aAllowedNavRulesButtonCodes = array_keys($aFormProperties['navigation_rules']);
|
||||
if ($oFormNode->GetOptionalElement('properties') !== null)
|
||||
{
|
||||
if ($oFormNode->GetOptionalElement('properties') !== null) {
|
||||
/** @var \MFElement $oPropertyNode */
|
||||
foreach ($oFormNode->GetOptionalElement('properties')->GetNodes('*') as $oPropertyNode)
|
||||
{
|
||||
switch ($oPropertyNode->nodeName)
|
||||
{
|
||||
foreach ($oFormNode->GetOptionalElement('properties')->GetNodes('*') as $oPropertyNode) {
|
||||
switch ($oPropertyNode->nodeName) {
|
||||
case 'display_mode':
|
||||
$aFormProperties['display_mode'] = $oPropertyNode->GetText(ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE);
|
||||
break;
|
||||
@@ -99,28 +93,23 @@ class Forms extends AbstractConfiguration
|
||||
|
||||
case 'navigation_rules':
|
||||
/** @var \MFElement $oNavRuleButtonNode */
|
||||
foreach($oPropertyNode->GetNodes('*') as $oNavRuleButtonNode)
|
||||
{
|
||||
foreach ($oPropertyNode->GetNodes('*') as $oNavRuleButtonNode) {
|
||||
$sNavRuleButtonCode = $oNavRuleButtonNode->nodeName;
|
||||
if(!in_array($sNavRuleButtonCode, $aAllowedNavRulesButtonCodes))
|
||||
{
|
||||
if (!in_array($sNavRuleButtonCode, $aAllowedNavRulesButtonCodes)) {
|
||||
throw new DOMFormatException('navigation_rules tag must only contain '.implode('|', $aAllowedNavRulesButtonCodes).' tags, "'.$sNavRuleButtonCode.'" given.', null, null, $oPropertyNode);
|
||||
}
|
||||
|
||||
/** @var \MFElement $oNavRuleOriginNode */
|
||||
foreach($oNavRuleButtonNode->GetNodes('*') as $oNavRuleOriginNode)
|
||||
{
|
||||
foreach ($oNavRuleButtonNode->GetNodes('*') as $oNavRuleOriginNode) {
|
||||
$sNavRuleOrigin = $oNavRuleOriginNode->nodeName;
|
||||
if(!in_array($sNavRuleOrigin, NavigationRuleHelper::GetAllowedOrigins()))
|
||||
{
|
||||
throw new DOMFormatException($sNavRuleButtonCode. ' tag must only contain '.implode('|', NavigationRuleHelper::GetAllowedOrigins()).' tags, "'.$sNavRuleOrigin.'" given.', null, null, $oPropertyNode);
|
||||
if (!in_array($sNavRuleOrigin, NavigationRuleHelper::GetAllowedOrigins())) {
|
||||
throw new DOMFormatException($sNavRuleButtonCode.' tag must only contain '.implode('|', NavigationRuleHelper::GetAllowedOrigins()).' tags, "'.$sNavRuleOrigin.'" given.', null, null, $oPropertyNode);
|
||||
}
|
||||
|
||||
$sNavRuleId = $oNavRuleOriginNode->GetText();
|
||||
// Note: We don't check is rule exists as it would introduce a dependency to the NavigationRuleHelper service.
|
||||
// Maybe we will consider it later.
|
||||
if(empty($sNavRuleId))
|
||||
{
|
||||
if (empty($sNavRuleId)) {
|
||||
throw new DOMFormatException($sNavRuleButtonCode.' tag cannot be empty.', null, null, $oPropertyNode);
|
||||
}
|
||||
|
||||
@@ -129,8 +118,7 @@ class Forms extends AbstractConfiguration
|
||||
|
||||
// Set modal rule as the same as default is not present.
|
||||
// We preset it so we don't have to make checks elsewhere in the code when using it.
|
||||
if(empty($aFormProperties['navigation_rules'][$sNavRuleButtonCode][NavigationRuleHelper::ENUM_ORIGIN_MODAL]))
|
||||
{
|
||||
if (empty($aFormProperties['navigation_rules'][$sNavRuleButtonCode][NavigationRuleHelper::ENUM_ORIGIN_MODAL])) {
|
||||
$aFormProperties['navigation_rules'][$sNavRuleButtonCode][NavigationRuleHelper::ENUM_ORIGIN_MODAL] = $aFormProperties['navigation_rules'][$sNavRuleButtonCode][NavigationRuleHelper::ENUM_ORIGIN_PAGE];
|
||||
}
|
||||
}
|
||||
@@ -139,36 +127,33 @@ class Forms extends AbstractConfiguration
|
||||
}
|
||||
|
||||
// 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();
|
||||
$aFormStimuli = [];
|
||||
if (($oFormNode->GetOptionalElement('modes') !== null) && ($oFormNode->GetOptionalElement('modes')->GetNodes('mode')->length > 0)) {
|
||||
$aModes = [];
|
||||
/** @var \MFElement $oModeNode */
|
||||
foreach ($oFormNode->GetOptionalElement('modes')->GetNodes('mode') as $oModeNode)
|
||||
{
|
||||
foreach ($oFormNode->GetOptionalElement('modes')->GetNodes('mode') as $oModeNode) {
|
||||
$sModeId = $oModeNode->getAttribute('id');
|
||||
if ($sModeId === '')
|
||||
{
|
||||
throw new DOMFormatException('mode tag must have an id attribute', 0, null,
|
||||
$oFormNode);
|
||||
if ($sModeId === '') {
|
||||
throw new DOMFormatException(
|
||||
'mode tag must have an id attribute',
|
||||
0,
|
||||
null,
|
||||
$oFormNode
|
||||
);
|
||||
}
|
||||
$aModes[] = $sModeId;
|
||||
|
||||
// If apply_stimulus mode, checking if stimuli are defined
|
||||
if ($sModeId === 'apply_stimulus')
|
||||
{
|
||||
if ($sModeId === 'apply_stimulus') {
|
||||
$oStimuliNode = $oModeNode->GetOptionalElement('stimuli');
|
||||
// If stimuli are defined, we overwrite the form that could have been set by the generic form
|
||||
if ($oStimuliNode !== null)
|
||||
{
|
||||
if ($oStimuliNode !== null) {
|
||||
/** @var \MFElement $oStimulusNode */
|
||||
foreach ($oStimuliNode->GetNodes('stimulus') as $oStimulusNode)
|
||||
{
|
||||
foreach ($oStimuliNode->GetNodes('stimulus') as $oStimulusNode) {
|
||||
$sStimulusCode = $oStimulusNode->getAttribute('id');
|
||||
|
||||
// Removing default form if present (in case the default forms were parsed before the current one (from current or parent class))
|
||||
if (isset($aForms[$sFormClass]['apply_stimulus'][$sStimulusCode]))
|
||||
{
|
||||
if (isset($aForms[$sFormClass]['apply_stimulus'][$sStimulusCode])) {
|
||||
unset($aForms[$sFormClass]['apply_stimulus'][$sStimulusCode]);
|
||||
}
|
||||
|
||||
@@ -177,111 +162,95 @@ class Forms extends AbstractConfiguration
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// If no mode was specified, we set it all but stimuli as it would have no sense that every transition forms
|
||||
// have as many fields displayed as a regular edit form for example.
|
||||
$aModes = array('view', 'edit', 'create');
|
||||
$aModes = ['view', 'edit', 'create'];
|
||||
}
|
||||
|
||||
// Parsing fields
|
||||
$aFields = array(
|
||||
$aFields = [
|
||||
'_brought_by' => $sFormClass,
|
||||
'id' => $sFormId,
|
||||
'type' => null,
|
||||
'properties' => $aFormProperties,
|
||||
'fields' => null,
|
||||
'layout' => null,
|
||||
);
|
||||
];
|
||||
// ... either enumerated fields ...
|
||||
if ($oFormNode->GetOptionalElement('fields') !== null)
|
||||
{
|
||||
if ($oFormNode->GetOptionalElement('fields') !== null) {
|
||||
$aFields['type'] = 'custom_list';
|
||||
$aFields['fields'] = array();
|
||||
$aFields['fields'] = [];
|
||||
|
||||
/** @var \MFElement $oFieldNode */
|
||||
foreach ($oFormNode->GetOptionalElement('fields')->GetNodes('field') as $oFieldNode)
|
||||
{
|
||||
foreach ($oFormNode->GetOptionalElement('fields')->GetNodes('field') as $oFieldNode) {
|
||||
$sFieldId = $oFieldNode->getAttribute('id');
|
||||
if ($sFieldId !== '')
|
||||
{
|
||||
$aField = array();
|
||||
if ($sFieldId !== '') {
|
||||
$aField = [];
|
||||
// Parsing field options like read_only, hidden and mandatory
|
||||
if ($oFieldNode->GetOptionalElement('read_only'))
|
||||
{
|
||||
if ($oFieldNode->GetOptionalElement('read_only')) {
|
||||
$aField['readonly'] = ($oFieldNode->GetOptionalElement('read_only')->GetText('true') === 'true') ? true : false;
|
||||
}
|
||||
if ($oFieldNode->GetOptionalElement('mandatory'))
|
||||
{
|
||||
if ($oFieldNode->GetOptionalElement('mandatory')) {
|
||||
$aField['mandatory'] = ($oFieldNode->GetOptionalElement('mandatory')->GetText('true') === 'true') ? true : false;
|
||||
}
|
||||
if ($oFieldNode->GetOptionalElement('hidden'))
|
||||
{
|
||||
if ($oFieldNode->GetOptionalElement('hidden')) {
|
||||
$aField['hidden'] = ($oFieldNode->GetOptionalElement('hidden')->GetText('true') === 'true') ? true : false;
|
||||
}
|
||||
|
||||
$aFields['fields'][$sFieldId] = $aField;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('Field tag must have an id attribute', 0, null,
|
||||
$oFormNode);
|
||||
} else {
|
||||
throw new DOMFormatException(
|
||||
'Field tag must have an id attribute',
|
||||
0,
|
||||
null,
|
||||
$oFormNode
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ... or the default zlist
|
||||
else
|
||||
{
|
||||
else {
|
||||
$aFields['type'] = 'zlist';
|
||||
$aFields['fields'] = 'details';
|
||||
}
|
||||
|
||||
// Parsing presentation
|
||||
if ($oFormNode->GetOptionalElement('twig') !== null)
|
||||
{
|
||||
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 = preg_replace('/^.+\n/', '', $sXml);
|
||||
$sXml = preg_replace('/\n.+$/', '', $sXml);
|
||||
|
||||
$aFields['layout'] = array(
|
||||
$aFields['layout'] = [
|
||||
'type' => (preg_match('/{{|{#|{%/', $sXml) === 1) ? 'twig' : 'xhtml',
|
||||
'content' => $sXml,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
// Adding form for each class / mode
|
||||
foreach ($aModes as $sMode)
|
||||
{
|
||||
foreach ($aModes as $sMode) {
|
||||
// Initializing current class if necessary
|
||||
if (!isset($aForms[$sFormClass]))
|
||||
{
|
||||
$aForms[$sFormClass] = array();
|
||||
if (!isset($aForms[$sFormClass])) {
|
||||
$aForms[$sFormClass] = [];
|
||||
}
|
||||
|
||||
// For stimuli we need to fill the matrix as only some stimuli might have been given
|
||||
if ($sMode === 'apply_stimulus')
|
||||
{
|
||||
if ($sMode === 'apply_stimulus') {
|
||||
// Iterating over current class and child classes
|
||||
foreach (MetaModel::EnumChildClasses($sFormClass, ENUM_CHILD_CLASSES_ALL) as $sChildClass)
|
||||
{
|
||||
foreach (MetaModel::EnumChildClasses($sFormClass, ENUM_CHILD_CLASSES_ALL) as $sChildClass) {
|
||||
// Initializing child class if necessary
|
||||
if (!isset($aForms[$sChildClass][$sMode]))
|
||||
{
|
||||
$aForms[$sChildClass][$sMode] = array();
|
||||
if (!isset($aForms[$sChildClass][$sMode])) {
|
||||
$aForms[$sChildClass][$sMode] = [];
|
||||
}
|
||||
|
||||
// If no explicit stimulus defined in this form, than it's the generic stimulus form
|
||||
// we need to find which stimulus are missing
|
||||
if(empty($aFormStimuli))
|
||||
{
|
||||
$aExistingStimuli = array();
|
||||
if (empty($aFormStimuli)) {
|
||||
$aExistingStimuli = [];
|
||||
// Keep only stimuli brought by the class itself
|
||||
foreach($aForms[$sChildClass][$sMode] as $sExistingStimulus => $aExistingForm)
|
||||
{
|
||||
if(!in_array($aExistingForm['_brought_by'], MetaModel::EnumParentClasses($sFormClass, ENUM_PARENT_CLASSES_EXCLUDELEAF)))
|
||||
{
|
||||
foreach ($aForms[$sChildClass][$sMode] as $sExistingStimulus => $aExistingForm) {
|
||||
if (!in_array($aExistingForm['_brought_by'], MetaModel::EnumParentClasses($sFormClass, ENUM_PARENT_CLASSES_EXCLUDELEAF))) {
|
||||
//continue;
|
||||
$aExistingStimuli[] = $sExistingStimulus;
|
||||
}
|
||||
@@ -290,51 +259,43 @@ class Forms extends AbstractConfiguration
|
||||
$aMissingStimulusForms = array_diff($aDatamodelStimuli, $aExistingStimuli);
|
||||
}
|
||||
// Otherwise, we process only the ones for this form
|
||||
else
|
||||
{
|
||||
else {
|
||||
$aMissingStimulusForms = $aFormStimuli;
|
||||
}
|
||||
|
||||
// Retrieve missing stimuli of the child class to fill the matrix
|
||||
foreach ($aMissingStimulusForms as $sDatamodelStimulus)
|
||||
{
|
||||
foreach ($aMissingStimulusForms as $sDatamodelStimulus) {
|
||||
// Check some facts about the target form
|
||||
$bFormExists = isset($aForms[$sChildClass][$sMode][$sDatamodelStimulus]);
|
||||
$bWasFormBroughtByParent = $bFormExists && in_array($aForms[$sChildClass][$sMode][$sDatamodelStimulus]['_brought_by'], MetaModel::EnumParentClasses($sFormClass, ENUM_PARENT_CLASSES_EXCLUDELEAF));
|
||||
|
||||
// Check if we need to overwrite (form created by parent)
|
||||
$bOverwriteNecessary = false;
|
||||
if($bWasFormBroughtByParent || in_array($sDatamodelStimulus, $aFormStimuli))
|
||||
{
|
||||
if ($bWasFormBroughtByParent || in_array($sDatamodelStimulus, $aFormStimuli)) {
|
||||
$bOverwriteNecessary = true;
|
||||
}
|
||||
|
||||
// Setting form if not defined OR if it was defined by a parent (abstract) class
|
||||
if (!$bFormExists || $bOverwriteNecessary)
|
||||
{
|
||||
if (!$bFormExists || $bOverwriteNecessary) {
|
||||
$aForms[$sChildClass][$sMode][$sDatamodelStimulus] = $aFields;
|
||||
$aForms[$sChildClass][$sMode][$sDatamodelStimulus]['id'] = 'apply_stimulus-'.$sChildClass.'-'.$sDatamodelStimulus;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (!isset($aForms[$sFormClass][$sMode]))
|
||||
{
|
||||
} elseif (!isset($aForms[$sFormClass][$sMode])) {
|
||||
$aForms[$sFormClass][$sMode] = $aFields;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('There is already a form for the class "'.$sFormClass.'" in "'.$sMode.'"',
|
||||
null, null, $oFormNode);
|
||||
} else {
|
||||
throw new DOMFormatException(
|
||||
'There is already a form for the class "'.$sFormClass.'" in "'.$sMode.'"',
|
||||
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());
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
throw new Exception('Could not create from from XML : '.$oFormNode->Dump().' '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
@@ -343,4 +304,4 @@ class Forms extends AbstractConfiguration
|
||||
$aPortalConf['forms'] = $aForms;
|
||||
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -39,51 +40,52 @@ class Lists extends AbstractConfiguration
|
||||
public function Process(Container $oContainer)
|
||||
{
|
||||
$iDefaultItemRank = 0;
|
||||
$aClassesLists = array();
|
||||
$aClassesLists = [];
|
||||
|
||||
// Parsing XML file
|
||||
// - Each classes
|
||||
/** @var \MFElement $oClassNode */
|
||||
foreach ($this->GetModuleDesign()->GetNodes('/module_design/classes/class') as $oClassNode)
|
||||
{
|
||||
$aClassLists = array();
|
||||
foreach ($this->GetModuleDesign()->GetNodes('/module_design/classes/class') as $oClassNode) {
|
||||
$aClassLists = [];
|
||||
$sClassId = $oClassNode->getAttribute('id');
|
||||
if ($sClassId === null)
|
||||
{
|
||||
if ($sClassId === null) {
|
||||
throw new DOMFormatException('Class tag must have an id attribute', 0, null, $oClassNode);
|
||||
}
|
||||
|
||||
// - Each lists
|
||||
/** @var \MFElement $oListNode */
|
||||
foreach ($oClassNode->GetNodes('./lists/list') as $oListNode)
|
||||
{
|
||||
$aListItems = array();
|
||||
foreach ($oClassNode->GetNodes('./lists/list') as $oListNode) {
|
||||
$aListItems = [];
|
||||
$sListId = $oListNode->getAttribute('id');
|
||||
if ($sListId === null)
|
||||
{
|
||||
throw new DOMFormatException('List tag of "'.$sClassId.'" class must have an id attribute', null,
|
||||
null, $oListNode);
|
||||
if ($sListId === null) {
|
||||
throw new DOMFormatException(
|
||||
'List tag of "'.$sClassId.'" class must have an id attribute',
|
||||
null,
|
||||
null,
|
||||
$oListNode
|
||||
);
|
||||
}
|
||||
|
||||
// - Each items
|
||||
/** @var \MFElement $oItemNode */
|
||||
foreach ($oListNode->GetNodes('./items/item') as $oItemNode)
|
||||
{
|
||||
foreach ($oListNode->GetNodes('./items/item') as $oItemNode) {
|
||||
$sItemId = $oItemNode->getAttribute('id');
|
||||
if ($sItemId === null)
|
||||
{
|
||||
throw new DOMFormatException('Item tag of "'.$sItemId.'" list must have an id attribute', null,
|
||||
null, $oItemNode);
|
||||
if ($sItemId === null) {
|
||||
throw new DOMFormatException(
|
||||
'Item tag of "'.$sItemId.'" list must have an id attribute',
|
||||
null,
|
||||
null,
|
||||
$oItemNode
|
||||
);
|
||||
}
|
||||
|
||||
$aItem = array(
|
||||
$aItem = [
|
||||
'att_code' => $sItemId,
|
||||
'rank' => $iDefaultItemRank,
|
||||
);
|
||||
];
|
||||
|
||||
$oRankNode = $oItemNode->GetOptionalElement('rank');
|
||||
if ($oRankNode !== null)
|
||||
{
|
||||
if ($oRankNode !== null) {
|
||||
$aItem['rank'] = $oRankNode->GetText($iDefaultItemRank);
|
||||
}
|
||||
|
||||
@@ -100,8 +102,7 @@ class Lists extends AbstractConfiguration
|
||||
}
|
||||
|
||||
// - Adding class only if it has at least one list
|
||||
if (!empty($aClassLists))
|
||||
{
|
||||
if (!empty($aClassLists)) {
|
||||
$aClassesLists[$sClassId] = $aClassLists;
|
||||
}
|
||||
}
|
||||
@@ -110,4 +111,4 @@ class Lists extends AbstractConfiguration
|
||||
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -46,4 +47,4 @@ class ApplicationContextSetPluginPropertyClass
|
||||
ApplicationContext::SetPluginProperty('QueryLocalizerPlugin', 'language_code', UserRights::GetUserLanguage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -31,16 +32,16 @@ use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
*/
|
||||
class ApplicationContextSetUrlMakerClass
|
||||
{
|
||||
/** @var array $aCombodoPortalInstanceConf */
|
||||
private $aCombodoPortalInstanceConf;
|
||||
/** @var array $aCombodoPortalInstanceConf */
|
||||
private $aCombodoPortalInstanceConf;
|
||||
|
||||
/**
|
||||
* @param array $aCombodoPortalInstanceConf
|
||||
*/
|
||||
public function __construct($aCombodoPortalInstanceConf)
|
||||
{
|
||||
$this->aCombodoPortalInstanceConf = $aCombodoPortalInstanceConf;
|
||||
}
|
||||
/**
|
||||
* @param array $aCombodoPortalInstanceConf
|
||||
*/
|
||||
public function __construct($aCombodoPortalInstanceConf)
|
||||
{
|
||||
$this->aCombodoPortalInstanceConf = $aCombodoPortalInstanceConf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RequestEvent $oRequestEvent
|
||||
@@ -51,4 +52,4 @@ class ApplicationContextSetUrlMakerClass
|
||||
ApplicationContext::SetUrlMakerClass($this->aCombodoPortalInstanceConf['properties']['urlmaker_class']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -56,19 +57,15 @@ class CssFromSassCompiler
|
||||
return;
|
||||
}
|
||||
|
||||
$aImportPaths = array($_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'].'css/');
|
||||
$aImportPaths = [$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'].'css/'];
|
||||
foreach ($this->aCombodoPortalInstanceConf['properties']['themes'] as $sKey => $value) {
|
||||
if (!is_array($value))
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$value, $aImportPaths);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($value as $sSubValue)
|
||||
{
|
||||
} else {
|
||||
foreach ($value as $sSubValue) {
|
||||
utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$sSubValue, $aImportPaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,8 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Portal\EventListener;
|
||||
|
||||
|
||||
use Dict;
|
||||
use ExceptionLog;
|
||||
use Symfony\Component\ErrorHandler\Exception\FlattenException;
|
||||
@@ -40,7 +38,6 @@ use Twig\Environment;
|
||||
*/
|
||||
class ExceptionListener
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -48,8 +45,7 @@ class ExceptionListener
|
||||
*/
|
||||
public function __construct(
|
||||
protected Environment $oTwig
|
||||
)
|
||||
{
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,7 +55,7 @@ class ExceptionListener
|
||||
* @throws \Twig\Error\RuntimeError
|
||||
* @throws \Twig\Error\SyntaxError
|
||||
*/
|
||||
public function onKernelException(ExceptionEvent $oEvent) : void
|
||||
public function onKernelException(ExceptionEvent $oEvent): void
|
||||
{
|
||||
// Get the exception object from the received event
|
||||
$oException = $oEvent->getThrowable();
|
||||
@@ -87,13 +83,11 @@ class ExceptionListener
|
||||
// Prepare flatten exception
|
||||
$oFlattenException = ($_SERVER['APP_DEBUG'] == 1) ? FlattenException::createFromThrowable($oException) : null;
|
||||
// Remove APPROOT from file paths if in production (SF context)
|
||||
if (!is_null($oFlattenException) && ($_SERVER['APP_ENV'] === 'prod'))
|
||||
{
|
||||
if (!is_null($oFlattenException) && ($_SERVER['APP_ENV'] === 'prod')) {
|
||||
$oFlattenException->setFile($this->removeAppRootFromPath($oFlattenException->getFile()));
|
||||
|
||||
$aTrace = $oFlattenException->getTrace();
|
||||
foreach ($aTrace as $iIdx => $aEntry)
|
||||
{
|
||||
foreach ($aTrace as $iIdx => $aEntry) {
|
||||
$aTrace[$iIdx]['file'] = $this->removeAppRootFromPath($aEntry['file']);
|
||||
}
|
||||
$oFlattenException->setTrace($aTrace, $oFlattenException->getFile(), $oFlattenException->getLine());
|
||||
@@ -105,20 +99,17 @@ class ExceptionListener
|
||||
]);
|
||||
|
||||
// Prepare data for template
|
||||
$aData = array(
|
||||
$aData = [
|
||||
'exception' => $oFlattenException,
|
||||
'code' => $iStatusCode,
|
||||
'error_title' => $sErrorTitle,
|
||||
'error_message' => $sErrorMessage,
|
||||
);
|
||||
];
|
||||
|
||||
// Generate the response
|
||||
if ($oEvent->getRequest()->isXmlHttpRequest())
|
||||
{
|
||||
if ($oEvent->getRequest()->isXmlHttpRequest()) {
|
||||
$oResponse = new JsonResponse($aData);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oResponse = new Response();
|
||||
$oResponse->setContent($this->oTwig->render('itop-portal-base/portal/templates/errors/layout.html.twig', $aData));
|
||||
}
|
||||
@@ -164,5 +155,4 @@ class ExceptionListener
|
||||
return str_replace($sNormalizedAppRoot, '', $sNormalizedInputPath);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -78,7 +79,7 @@ class UserProvider
|
||||
// - Checking user rights and prompt if needed (401 HTTP code returned if XHR request)
|
||||
$iExitMethod = ($oRequestEvent->getRequest()->isXmlHttpRequest()) ? LoginWebPage::EXIT_RETURN : LoginWebPage::EXIT_PROMPT;
|
||||
$iLogonRes = LoginWebPage::DoLoginEx($this->sPortalId, false, $iExitMethod);
|
||||
if( ($iExitMethod === LoginWebPage::EXIT_RETURN) && ($iLogonRes != 0) ) {
|
||||
if (($iExitMethod === LoginWebPage::EXIT_RETURN) && ($iLogonRes != 0)) {
|
||||
die(Dict::S('Portal:ErrorUserLoggedOut'));
|
||||
}
|
||||
// - User must be associated with a Contact
|
||||
@@ -92,8 +93,8 @@ class UserProvider
|
||||
throw new Exception('Could not load connected user.');
|
||||
}
|
||||
|
||||
// User allowed to log off or not
|
||||
$this->bUserCanLogOff = utils::CanLogOff();
|
||||
// User allowed to log off or not
|
||||
$this->bUserCanLogOff = utils::CanLogOff();
|
||||
|
||||
// Allowed portals
|
||||
$aAllowedPortals = UserRights::GetAllowedPortals();
|
||||
@@ -146,5 +147,4 @@ class UserProvider
|
||||
return $this->aAllowedPortals;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use UserRights;
|
||||
use utils;
|
||||
|
||||
use const UR_ACTION_READ;
|
||||
|
||||
/**
|
||||
@@ -62,13 +63,13 @@ use const UR_ACTION_READ;
|
||||
class ObjectFormManager extends FormManager
|
||||
{
|
||||
/** @var string ENUM_MODE_VIEW */
|
||||
const ENUM_MODE_VIEW = 'view';
|
||||
public const ENUM_MODE_VIEW = 'view';
|
||||
/** @var string ENUM_MODE_EDIT */
|
||||
const ENUM_MODE_EDIT = 'edit';
|
||||
public const ENUM_MODE_EDIT = 'edit';
|
||||
/** @var string ENUM_MODE_CREATE */
|
||||
const ENUM_MODE_CREATE = 'create';
|
||||
public const ENUM_MODE_CREATE = 'create';
|
||||
/** @var string ENUM_MODE_APPLY_STIMULUS */
|
||||
const ENUM_MODE_APPLY_STIMULUS = 'apply_stimulus';
|
||||
public const ENUM_MODE_APPLY_STIMULUS = 'apply_stimulus';
|
||||
|
||||
/** @var \cmdbAbstractObject $oObject */
|
||||
protected $oObject;
|
||||
@@ -79,14 +80,14 @@ class ObjectFormManager extends FormManager
|
||||
/** @var array $aFormProperties */
|
||||
protected $aFormProperties;
|
||||
/** @var array $aCallbackUrls */
|
||||
protected $aCallbackUrls = array();
|
||||
protected $aCallbackUrls = [];
|
||||
/**
|
||||
* List of hidden fields, used for form update (eg. remove them from the form regarding they dependencies)
|
||||
*
|
||||
* @var array $aHiddenFieldsId
|
||||
* @since 2.7.5
|
||||
*/
|
||||
protected $aHiddenFieldsId = array();
|
||||
protected $aHiddenFieldsId = [];
|
||||
|
||||
/**
|
||||
* @var ObjectFormHandlerHelper $oFormHandlerHelper
|
||||
@@ -95,7 +96,7 @@ class ObjectFormManager extends FormManager
|
||||
private $oFormHandlerHelper;
|
||||
|
||||
/** @var array $aPlugins plugins data */
|
||||
private array $aPlugins = array();
|
||||
private array $aPlugins = [];
|
||||
private array $aFieldsAtts = [];
|
||||
private array $aExtraData = [];
|
||||
private DOMDocument $oHtmlDocument;
|
||||
@@ -143,27 +144,22 @@ class ObjectFormManager extends FormManager
|
||||
}
|
||||
$sObjectClass = $aJson['formobject_class'];
|
||||
|
||||
if (!isset($aJson['formobject_id']))
|
||||
{
|
||||
if (!isset($aJson['formobject_id'])) {
|
||||
$oObject = MetaModel::NewObject($sObjectClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Note : AllowAllData set to true here instead of checking scope's flag because we are displaying a value that has been set and validated
|
||||
$oObject = MetaModel::GetObject($sObjectClass, $aJson['formobject_id'], true, true);
|
||||
}
|
||||
$oFormManager->SetObject($oObject);
|
||||
|
||||
// Retrieving form mode
|
||||
if (!isset($aJson['formmode']))
|
||||
{
|
||||
if (!isset($aJson['formmode'])) {
|
||||
throw new Exception('Form mode must be defined in order to generate the form');
|
||||
}
|
||||
$oFormManager->SetMode($aJson['formmode']);
|
||||
|
||||
// Retrieving actions rules
|
||||
if (isset($aJson['formactionrulestoken']))
|
||||
{
|
||||
if (isset($aJson['formactionrulestoken'])) {
|
||||
$oFormManager->SetActionRulesToken($aJson['formactionrulestoken']);
|
||||
}
|
||||
|
||||
@@ -316,8 +312,7 @@ class ObjectFormManager extends FormManager
|
||||
{
|
||||
$aJson = parent::ToJSON();
|
||||
$aJson['formobject_class'] = get_class($this->oObject);
|
||||
if ($this->oObject->GetKey() > 0)
|
||||
{
|
||||
if ($this->oObject->GetKey() > 0) {
|
||||
$aJson['formobject_id'] = $this->oObject->GetKey();
|
||||
}
|
||||
$aJson['formmode'] = $this->sMode;
|
||||
@@ -338,11 +333,9 @@ class ObjectFormManager extends FormManager
|
||||
|
||||
// Building form from its properties
|
||||
// - Consistency checks for stimulus form
|
||||
if (isset($this->aFormProperties['stimulus_code']))
|
||||
{
|
||||
if (isset($this->aFormProperties['stimulus_code'])) {
|
||||
$aTransitions = MetaModel::EnumTransitions($sObjectClass, $this->oObject->GetState());
|
||||
if (!isset($aTransitions[$this->aFormProperties['stimulus_code']]))
|
||||
{
|
||||
if (!isset($aTransitions[$this->aFormProperties['stimulus_code']])) {
|
||||
$aStimuli = Metamodel::EnumStimuli($sObjectClass);
|
||||
$sStimulusLabel = $aStimuli[$this->aFormProperties['stimulus_code']]->GetLabel();
|
||||
|
||||
@@ -351,24 +344,22 @@ class ObjectFormManager extends FormManager
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Adding rendered template to the form renderer as the base layout
|
||||
$this->oRenderer->SetBaseLayout($this->oHtmlDocument->saveHTML());
|
||||
|
||||
// Building the form
|
||||
foreach ($this->aFieldsAtts as $sAttCode => $iFieldFlags)
|
||||
{
|
||||
foreach ($this->aFieldsAtts as $sAttCode => $iFieldFlags) {
|
||||
// handle plugins fields
|
||||
if($this->sMode !== 'apply_stimulus'
|
||||
if ($this->sMode !== 'apply_stimulus'
|
||||
&& array_key_exists($sAttCode, $this->aExtraData)
|
||||
&& array_key_exists('plugin', $this->aExtraData[$sAttCode])){
|
||||
&& array_key_exists('plugin', $this->aExtraData[$sAttCode])) {
|
||||
$sPluginName = $this->aExtraData[$sAttCode]['plugin'];
|
||||
switch($sPluginName){
|
||||
switch ($sPluginName) {
|
||||
case AttachmentPlugIn::class:
|
||||
$this->AddAttachmentField($this->oForm, $sAttCode, $this->aExtraData);
|
||||
break;
|
||||
default:
|
||||
throw new Exception('Unknown plugin ' . $sPluginName);
|
||||
throw new Exception('Unknown plugin '.$sPluginName);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -377,57 +368,44 @@ class ObjectFormManager extends FormManager
|
||||
|
||||
/** @var Field $oField */
|
||||
$oField = null;
|
||||
if (is_callable([$oAttDef, 'MakeFormField']))
|
||||
{
|
||||
if (is_callable([$oAttDef, 'MakeFormField'])) {
|
||||
$oField = $oAttDef->MakeFormField($this->oObject);
|
||||
}
|
||||
|
||||
// Failsafe for AttributeType that would not have MakeFormField and therefore could not be used in a form
|
||||
if ($oField !== null)
|
||||
{
|
||||
if ($this->sMode !== static::ENUM_MODE_VIEW)
|
||||
{
|
||||
if ($oField !== null) {
|
||||
if ($this->sMode !== static::ENUM_MODE_VIEW) {
|
||||
// Field dependencies
|
||||
$aFieldDependencies = $oAttDef->GetPrerequisiteAttributes();
|
||||
if (!empty($aFieldDependencies))
|
||||
{
|
||||
if (!empty($aFieldDependencies)) {
|
||||
$this->oForm->AddFieldDependencies($oField->GetId(), $aFieldDependencies);
|
||||
}
|
||||
|
||||
// Setting the field flags
|
||||
// - If it's locked because slave, we force it as read only
|
||||
if (($iFieldFlags & OPT_ATT_SLAVE) === OPT_ATT_SLAVE)
|
||||
{
|
||||
if (($iFieldFlags & OPT_ATT_SLAVE) === OPT_ATT_SLAVE) {
|
||||
$oField->SetReadOnly(true);
|
||||
}
|
||||
// - Else if it's must change (transition), we force it as mustchange, not readonly and not hidden
|
||||
elseif (($iFieldFlags & OPT_ATT_MUSTCHANGE) === OPT_ATT_MUSTCHANGE && $this->IsTransitionForm())
|
||||
{
|
||||
elseif (($iFieldFlags & OPT_ATT_MUSTCHANGE) === OPT_ATT_MUSTCHANGE && $this->IsTransitionForm()) {
|
||||
$oField->SetMustChange(true);
|
||||
$oField->SetReadOnly(false);
|
||||
$oField->SetHidden(false);
|
||||
}
|
||||
// - Else if it's must prompt (transition), we force it as not readonly and not hidden
|
||||
elseif (($iFieldFlags & OPT_ATT_MUSTPROMPT) === OPT_ATT_MUSTPROMPT && $this->IsTransitionForm())
|
||||
{
|
||||
elseif (($iFieldFlags & OPT_ATT_MUSTPROMPT) === OPT_ATT_MUSTPROMPT && $this->IsTransitionForm()) {
|
||||
$oField->SetReadOnly(false);
|
||||
$oField->SetHidden(false);
|
||||
}
|
||||
// - Else if it wasn't mandatory or already had a value, and it's hidden, we force it as hidden
|
||||
elseif (($iFieldFlags & OPT_ATT_HIDDEN) === OPT_ATT_HIDDEN)
|
||||
{
|
||||
elseif (($iFieldFlags & OPT_ATT_HIDDEN) === OPT_ATT_HIDDEN) {
|
||||
$oField->SetHidden(true);
|
||||
}
|
||||
elseif (($iFieldFlags & OPT_ATT_READONLY) === OPT_ATT_READONLY)
|
||||
{
|
||||
} elseif (($iFieldFlags & OPT_ATT_READONLY) === OPT_ATT_READONLY) {
|
||||
$oField->SetReadOnly(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Normal field, use "flags" set by AttDef::MakeFormField()
|
||||
// Except if we are in a transition be cause $oAttDef doesn't know if the form is for a transition
|
||||
if ($this->IsTransitionForm())
|
||||
{
|
||||
if ($this->IsTransitionForm()) {
|
||||
$oField->SetReadOnly(false);
|
||||
$oField->SetHidden(false);
|
||||
$oField->SetMandatory(false);
|
||||
@@ -435,114 +413,110 @@ class ObjectFormManager extends FormManager
|
||||
}
|
||||
|
||||
// Finally, if it's mandatory ...
|
||||
if (($iFieldFlags & OPT_ATT_MANDATORY) === OPT_ATT_MANDATORY)
|
||||
{
|
||||
if (($iFieldFlags & OPT_ATT_MANDATORY) === OPT_ATT_MANDATORY) {
|
||||
// ... and when in a transition, we force it as mandatory
|
||||
if ($this->IsTransitionForm() && $oAttDef->IsNull($this->oObject->Get($sAttCode)))
|
||||
{
|
||||
if ($this->IsTransitionForm() && $oAttDef->IsNull($this->oObject->Get($sAttCode))) {
|
||||
$oField->SetMandatory(true);
|
||||
}
|
||||
// .. and has no value, we force it as mandatory
|
||||
elseif ($oAttDef->IsNull($this->oObject->Get($sAttCode)))
|
||||
{
|
||||
elseif ($oAttDef->IsNull($this->oObject->Get($sAttCode))) {
|
||||
$oField->SetMandatory(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Specific operation on field
|
||||
// - Field that require a transaction id
|
||||
if (in_array(get_class($oField),
|
||||
array('Combodo\\iTop\\Form\\Field\\TextAreaField', 'Combodo\\iTop\\Form\\Field\\CaseLogField')))
|
||||
{
|
||||
if (in_array(
|
||||
get_class($oField),
|
||||
['Combodo\\iTop\\Form\\Field\\TextAreaField', 'Combodo\\iTop\\Form\\Field\\CaseLogField']
|
||||
)) {
|
||||
/** @var \Combodo\iTop\Form\Field\TextAreaField|\Combodo\iTop\Form\Field\CaseLogField $oField */
|
||||
$oField->SetTransactionId($this->oForm->GetTransactionId());
|
||||
}
|
||||
// - Field that require a search endpoint
|
||||
if (in_array(get_class($oField),
|
||||
array('Combodo\\iTop\\Form\\Field\\SelectObjectField', 'Combodo\\iTop\\Form\\Field\\LinkedSetField'))) {
|
||||
if (in_array(
|
||||
get_class($oField),
|
||||
['Combodo\\iTop\\Form\\Field\\SelectObjectField', 'Combodo\\iTop\\Form\\Field\\LinkedSetField']
|
||||
)) {
|
||||
/** @var \Combodo\iTop\Form\Field\SelectObjectField|\Combodo\iTop\Form\Field\LinkedSetField $oField */
|
||||
if ($this->oFormHandlerHelper !== null) {
|
||||
$sSearchEndpoint = $this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_search_generic', array(
|
||||
$sSearchEndpoint = $this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_search_generic', [
|
||||
'sTargetAttCode' => $oAttDef->GetCode(),
|
||||
'sHostObjectClass' => get_class($this->oObject),
|
||||
'sHostObjectId' => ($this->oObject->IsNew()) ? null : $this->oObject->GetKey(),
|
||||
'ar_token' => $this->GetActionRulesToken(),
|
||||
));
|
||||
]);
|
||||
$oField->SetSearchEndpoint($sSearchEndpoint);
|
||||
}
|
||||
}
|
||||
// - Field that require an information endpoint
|
||||
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\LinkedSetField'))) {
|
||||
if (in_array(get_class($oField), ['Combodo\\iTop\\Form\\Field\\LinkedSetField'])) {
|
||||
/** @var \Combodo\iTop\Form\Field\LinkedSetField $oField */
|
||||
if ($this->oFormHandlerHelper !== null) {
|
||||
$oField->SetInformationEndpoint($this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_get_information_for_linked_set_json'));
|
||||
}
|
||||
}
|
||||
// - Field that require to apply scope on its DM OQL
|
||||
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\SelectObjectField')))
|
||||
{
|
||||
if (in_array(get_class($oField), ['Combodo\\iTop\\Form\\Field\\SelectObjectField'])) {
|
||||
/** @var \Combodo\iTop\Form\Field\SelectObjectField $oField */
|
||||
if ($this->oFormHandlerHelper !== null) {
|
||||
$oScopeOriginal = ($oField->GetSearch() !== null) ? $oField->GetSearch() : DBSearch::FromOQL($oAttDef->GetValuesDef()->GetFilterExpression());
|
||||
|
||||
/** @var \DBSearch $oScopeSearch */
|
||||
$oScopeSearch = $this->oFormHandlerHelper->GetScopeValidator()->GetScopeFilterForProfiles(UserRights::ListProfiles(),
|
||||
$oScopeOriginal->GetClass(), UR_ACTION_READ);
|
||||
$oScopeSearch = $this->oFormHandlerHelper->GetScopeValidator()->GetScopeFilterForProfiles(
|
||||
UserRights::ListProfiles(),
|
||||
$oScopeOriginal->GetClass(),
|
||||
UR_ACTION_READ
|
||||
);
|
||||
if ($oScopeSearch === null) {
|
||||
IssueLog::Info(__METHOD__.' at line '.__LINE__.' : User #'.UserRights::GetUserId().' has no scope query for '.$oScopeOriginal->GetClass().' class.');
|
||||
throw new HttpException(Response::HTTP_NOT_FOUND, Dict::S('UI:ObjectDoesNotExist'));
|
||||
}
|
||||
$oScopeOriginal = $oScopeOriginal->Intersect($oScopeSearch);
|
||||
// Note : This is to skip the silo restriction on the final query
|
||||
if ($oScopeSearch->IsAllDataAllowed())
|
||||
{
|
||||
if ($oScopeSearch->IsAllDataAllowed()) {
|
||||
$oScopeOriginal->AllowAllData();
|
||||
}
|
||||
$oScopeOriginal->SetInternalParams(array('this' => $this->oObject));
|
||||
$oScopeOriginal->SetInternalParams(['this' => $this->oObject]);
|
||||
$oField->SetSearch($oScopeOriginal);
|
||||
}
|
||||
}
|
||||
// - Field that require to check if the current value is among allowed ones
|
||||
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\SelectObjectField')))
|
||||
{
|
||||
if (in_array(get_class($oField), ['Combodo\\iTop\\Form\\Field\\SelectObjectField'])) {
|
||||
// Note: We can't do this in AttributeExternalKey::MakeFormField() in the Field::SetOnFinalizeCallback() because at this point we have no information about the portal scope and ignore_silos flag, hence it always applies silos.
|
||||
// As a workaround we have to manually check if the field's current value is among the scope
|
||||
$oField->ResetCurrentValueIfNotAmongAllowedValues();
|
||||
}
|
||||
// - Field that require processing on their subfields
|
||||
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\SubFormField')))
|
||||
{
|
||||
if (in_array(get_class($oField), ['Combodo\\iTop\\Form\\Field\\SubFormField'])) {
|
||||
/** @var \Combodo\iTop\Form\Field\SubFormField $oField */
|
||||
$oSubForm = $oField->GetForm();
|
||||
if ($oAttDef->GetEditClass() === 'CustomFields')
|
||||
{
|
||||
if ($oAttDef->GetEditClass() === 'CustomFields') {
|
||||
// Retrieving only user data fields (not the metadata fields of the template)
|
||||
if ($oSubForm->HasField('user_data'))
|
||||
{
|
||||
if ($oSubForm->HasField('user_data')) {
|
||||
/** @var \Combodo\iTop\Form\Field\SubFormField $oUserDataField */
|
||||
$oUserDataField = $oSubForm->GetField('user_data');
|
||||
$oUserDataForm = $oUserDataField->GetForm();
|
||||
foreach ($oUserDataForm->GetFields() as $oCustomField)
|
||||
{
|
||||
foreach ($oUserDataForm->GetFields() as $oCustomField) {
|
||||
// - Field that require a search endpoint (OQL based dropdown list fields)
|
||||
if (in_array(get_class($oCustomField), array('Combodo\\iTop\\Form\\Field\\SelectObjectField')))
|
||||
{
|
||||
if (in_array(get_class($oCustomField), ['Combodo\\iTop\\Form\\Field\\SelectObjectField'])) {
|
||||
/** @var \Combodo\iTop\Form\Field\SelectObjectField $oCustomField */
|
||||
if ($this->oFormHandlerHelper->GetUrlGenerator() !== null) {
|
||||
|
||||
$sSearchEndpoint = $this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_search_generic',
|
||||
array(
|
||||
$sSearchEndpoint = $this->oFormHandlerHelper->GetUrlGenerator()->generate(
|
||||
'p_object_search_generic',
|
||||
[
|
||||
'sTargetAttCode' => $oAttDef->GetCode(),
|
||||
'sHostObjectClass' => get_class($this->oObject),
|
||||
'sHostObjectId' => ($this->oObject->IsNew()) ? null : $this->oObject->GetKey(),
|
||||
'ar_token' => $this->GetActionRulesToken(),
|
||||
));
|
||||
]
|
||||
);
|
||||
$oCustomField->SetSearchEndpoint($sSearchEndpoint);
|
||||
}
|
||||
}
|
||||
// - Field that require to check if the current value is among allowed ones
|
||||
if (in_array(get_class($oCustomField), array('Combodo\\iTop\\Form\\Field\\SelectObjectField')))
|
||||
{
|
||||
if (in_array(get_class($oCustomField), ['Combodo\\iTop\\Form\\Field\\SelectObjectField'])) {
|
||||
/** @var \Combodo\iTop\Form\Field\SelectObjectField $oCustomField */
|
||||
$oCustomField->ResetCurrentValueIfNotAmongAllowedValues();
|
||||
}
|
||||
@@ -550,37 +524,34 @@ class ObjectFormManager extends FormManager
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (($iFieldFlags & OPT_ATT_HIDDEN) === OPT_ATT_HIDDEN)
|
||||
{
|
||||
} else {
|
||||
if (($iFieldFlags & OPT_ATT_HIDDEN) === OPT_ATT_HIDDEN) {
|
||||
$oField->SetHidden(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oField->SetReadOnly(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Specific operation on field
|
||||
// - LinkedSet
|
||||
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\LinkedSetField')))
|
||||
{
|
||||
if (in_array(get_class($oField), ['Combodo\\iTop\\Form\\Field\\LinkedSetField'])) {
|
||||
/** @var \Combodo\iTop\Form\Field\LinkedSetField $oField */
|
||||
/** @var \AttributeLinkedSetIndirect $oAttDef */
|
||||
// - Overriding attributes to display
|
||||
if ($this->oFormHandlerHelper !== null) {
|
||||
// Note : This snippet is inspired from AttributeLinkedSet::MakeFormField()
|
||||
$aAttCodesToDisplay = ApplicationHelper::GetLoadedListFromClass($this->oFormHandlerHelper->getCombodoPortalConf()['lists'],
|
||||
$oField->GetTargetClass(), 'list');
|
||||
$aAttCodesToDisplay = ApplicationHelper::GetLoadedListFromClass(
|
||||
$this->oFormHandlerHelper->getCombodoPortalConf()['lists'],
|
||||
$oField->GetTargetClass(),
|
||||
'list'
|
||||
);
|
||||
// - Adding friendlyname attribute to the list is not already in it
|
||||
$sTitleAttCode = 'friendlyname';
|
||||
if (($sTitleAttCode !== null) && !in_array($sTitleAttCode, $aAttCodesToDisplay)) {
|
||||
$aAttCodesToDisplay = array_merge(array($sTitleAttCode), $aAttCodesToDisplay);
|
||||
$aAttCodesToDisplay = array_merge([$sTitleAttCode], $aAttCodesToDisplay);
|
||||
}
|
||||
// - Adding attribute labels
|
||||
$aAttributesToDisplay = array();
|
||||
$aAttributesToDisplay = [];
|
||||
foreach ($aAttCodesToDisplay as $sAttCodeToDisplay) {
|
||||
$oAttDefToDisplay = MetaModel::GetAttributeDef($oField->GetTargetClass(), $sAttCodeToDisplay);
|
||||
$aAttributesToDisplay[$sAttCodeToDisplay] = [
|
||||
@@ -598,7 +569,7 @@ class ObjectFormManager extends FormManager
|
||||
}
|
||||
// - Filtering links regarding scopes
|
||||
if ($this->oFormHandlerHelper !== null) {
|
||||
$aLimitedAccessItemIDs = array();
|
||||
$aLimitedAccessItemIDs = [];
|
||||
|
||||
/** @var \ormLinkSet $oFieldOriginalSet */
|
||||
$oFieldOriginalSet = $oField->GetCurrentValue();
|
||||
@@ -617,19 +588,16 @@ class ObjectFormManager extends FormManager
|
||||
$oField->SetLimitedAccessItemIDs($aLimitedAccessItemIDs);
|
||||
}
|
||||
// - Displaying as opened
|
||||
if (array_key_exists($sAttCode, $this->aExtraData) && array_key_exists('opened', $this->aExtraData[$sAttCode]))
|
||||
{
|
||||
if (array_key_exists($sAttCode, $this->aExtraData) && array_key_exists('opened', $this->aExtraData[$sAttCode])) {
|
||||
$oField->SetDisplayOpened(true);
|
||||
}
|
||||
// - Displaying out of scopes items
|
||||
if (array_key_exists($sAttCode, $this->aExtraData) && array_key_exists('ignore_scopes', $this->aExtraData[$sAttCode]))
|
||||
{
|
||||
if (array_key_exists($sAttCode, $this->aExtraData) && array_key_exists('ignore_scopes', $this->aExtraData[$sAttCode])) {
|
||||
$oField->SetDisplayLimitedAccessItems(true);
|
||||
}
|
||||
}
|
||||
// - BlobField
|
||||
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\BlobField', 'Combodo\\iTop\\Form\\Field\\ImageField')))
|
||||
{
|
||||
if (in_array(get_class($oField), ['Combodo\\iTop\\Form\\Field\\BlobField', 'Combodo\\iTop\\Form\\Field\\ImageField'])) {
|
||||
// - Overriding attributes to display
|
||||
if ($this->oFormHandlerHelper !== null) {
|
||||
// Override hardcoded URLs in ormDocument pointing to back office console
|
||||
@@ -654,9 +622,7 @@ class ObjectFormManager extends FormManager
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oField = new LabelField($sAttCode);
|
||||
$oField->SetReadOnly(true)
|
||||
->SetHidden(false)
|
||||
@@ -665,8 +631,7 @@ class ObjectFormManager extends FormManager
|
||||
}
|
||||
|
||||
// Setting field display mode
|
||||
if (array_key_exists($sAttCode, $this->aExtraData) && array_key_exists('display_mode', $this->aExtraData[$sAttCode]))
|
||||
{
|
||||
if (array_key_exists($sAttCode, $this->aExtraData) && array_key_exists('display_mode', $this->aExtraData[$sAttCode])) {
|
||||
$oField->SetDisplayMode($this->aExtraData[$sAttCode]['display_mode']);
|
||||
}
|
||||
|
||||
@@ -678,32 +643,25 @@ class ObjectFormManager extends FormManager
|
||||
|
||||
// Do not add hidden fields as they are of no use, if one is necessary because another depends on it, it will be automatically added.
|
||||
// Note: We do this at the end because during the process an hidden field could have become writable if mandatory and empty for example.
|
||||
if($oField->GetHidden() === false)
|
||||
{
|
||||
if ($oField->GetHidden() === false) {
|
||||
$this->oForm->AddField($oField);
|
||||
} else {
|
||||
$this->aHiddenFieldsId[]=$oField->GetId();
|
||||
$this->aHiddenFieldsId[] = $oField->GetId();
|
||||
}
|
||||
}
|
||||
|
||||
// Checking dependencies to ensure that all needed fields are in the form
|
||||
// (This is kind of a garbage collector for dependencies)
|
||||
foreach ($this->oForm->GetDependencies() as $sImpactedFieldId => $aDependencies)
|
||||
{
|
||||
foreach ($aDependencies as $sDependencyFieldId)
|
||||
{
|
||||
if (!$this->oForm->HasField($sDependencyFieldId))
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach ($this->oForm->GetDependencies() as $sImpactedFieldId => $aDependencies) {
|
||||
foreach ($aDependencies as $sDependencyFieldId) {
|
||||
if (!$this->oForm->HasField($sDependencyFieldId)) {
|
||||
try {
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this->oObject), $sDependencyFieldId);
|
||||
$oField = $oAttDef->MakeFormField($this->oObject);
|
||||
$oField->SetHidden(true);
|
||||
|
||||
$this->oForm->AddField($oField);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
// Avoid blocking a form if a RequestTemplate reference a bad attribute (e.g. :this->id)
|
||||
IssueLog::Error('May be a bad OQL (referencing :this->id) in a RequestTemplate causes the following error');
|
||||
IssueLog::Error($e);
|
||||
@@ -717,7 +675,7 @@ class ObjectFormManager extends FormManager
|
||||
if ($this->sMode !== 'apply_stimulus'
|
||||
&& class_exists('Attachment') && class_exists('AttachmentPlugIn')
|
||||
&& !$this->IsPluginInitialized(AttachmentPlugIn::class)
|
||||
&& AttachmentPlugIn::IsAttachmentAllowedForObject($this->oObject)){
|
||||
&& AttachmentPlugIn::IsAttachmentAllowedForObject($this->oObject)) {
|
||||
$this->AddAttachmentField($this->oForm, 'attachments_plugin', $this->aExtraData);
|
||||
}
|
||||
|
||||
@@ -732,7 +690,7 @@ class ObjectFormManager extends FormManager
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function IsPluginInitialized(string $sPluginName) : bool
|
||||
private function IsPluginInitialized(string $sPluginName): bool
|
||||
{
|
||||
return array_key_exists($sPluginName, $this->aPlugins);
|
||||
}
|
||||
@@ -746,48 +704,54 @@ class ObjectFormManager extends FormManager
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function AddAttachmentField($oForm, $sId, $aFieldsExtraData) : void
|
||||
private function AddAttachmentField($oForm, $sId, $aFieldsExtraData): void
|
||||
{
|
||||
// only one instance allowed
|
||||
if($this->IsPluginInitialized(AttachmentPlugIn::class)){
|
||||
throw new Exception("Unable to process field `$sId`, AttachmentPlugIn has already been initialized with field `" . $this->aPlugins[AttachmentPlugIn::class]['field']->GetId() . '`');
|
||||
if ($this->IsPluginInitialized(AttachmentPlugIn::class)) {
|
||||
throw new Exception("Unable to process field `$sId`, AttachmentPlugIn has already been initialized with field `".$this->aPlugins[AttachmentPlugIn::class]['field']->GetId().'`');
|
||||
}
|
||||
|
||||
// not allowed for object class
|
||||
if(!AttachmentPlugIn::IsAttachmentAllowedForObject($this->oObject)){
|
||||
throw new Exception("Unable to process field `$sId`, AttachmentPlugIn is not allowed for class `" . $this->oObject::class . '`');
|
||||
if (!AttachmentPlugIn::IsAttachmentAllowedForObject($this->oObject)) {
|
||||
throw new Exception("Unable to process field `$sId`, AttachmentPlugIn is not allowed for class `".$this->oObject::class.'`');
|
||||
}
|
||||
|
||||
// set id to a unique key - avoid collisions with another attribute that could exist with the name 'attachments'
|
||||
$oField = new FileUploadField($sId);
|
||||
$oField->SetLabel(Dict::S('Portal:Attachments'))
|
||||
->SetUploadEndpoint($this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_attachment_add'))
|
||||
->SetDownloadEndpoint($this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_attachment_download',
|
||||
array('sAttachmentId' => '-sAttachmentId-')))
|
||||
->SetDisplayEndpoint($this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_attachment_display',
|
||||
array('sAttachmentId' => '-sAttachmentId-')))
|
||||
->SetDownloadEndpoint($this->oFormHandlerHelper->GetUrlGenerator()->generate(
|
||||
'p_object_attachment_download',
|
||||
['sAttachmentId' => '-sAttachmentId-']
|
||||
))
|
||||
->SetDisplayEndpoint($this->oFormHandlerHelper->GetUrlGenerator()->generate(
|
||||
'p_object_attachment_display',
|
||||
['sAttachmentId' => '-sAttachmentId-']
|
||||
))
|
||||
->SetTransactionId($oForm->GetTransactionId())
|
||||
->SetAllowDelete($this->oFormHandlerHelper->getCombodoPortalConf()['properties']['attachments']['allow_delete'])
|
||||
->SetObject($this->oObject);
|
||||
|
||||
// Checking if we can edit attachments in the current state
|
||||
$oObjectFormManager = $this;
|
||||
$oField->SetOnFinalizeCallback(function() use ($oObjectFormManager, $oForm, $oField){
|
||||
$oField->SetOnFinalizeCallback(function () use ($oObjectFormManager, $oForm, $oField) {
|
||||
if (($oObjectFormManager->sMode === static::ENUM_MODE_VIEW)
|
||||
|| AttachmentPlugIn::IsReadonlyState($oObjectFormManager->oObject, $oObjectFormManager->oObject->GetState(),
|
||||
AttachmentPlugIn::ENUM_GUI_PORTALS) === true
|
||||
|| $oForm->GetEditableFieldCount(true) === 0)
|
||||
{
|
||||
|| AttachmentPlugIn::IsReadonlyState(
|
||||
$oObjectFormManager->oObject,
|
||||
$oObjectFormManager->oObject->GetState(),
|
||||
AttachmentPlugIn::ENUM_GUI_PORTALS
|
||||
) === true
|
||||
|| $oForm->GetEditableFieldCount(true) === 0) {
|
||||
$oField->SetReadOnly(true);
|
||||
}
|
||||
});
|
||||
|
||||
if (array_key_exists($sId, $aFieldsExtraData) && array_key_exists('opened', $aFieldsExtraData[$sId])){
|
||||
if (array_key_exists($sId, $aFieldsExtraData) && array_key_exists('opened', $aFieldsExtraData[$sId])) {
|
||||
$oField->SetDisplayOpened(true);
|
||||
}
|
||||
|
||||
// Adding attachments field in transition only if it is editable
|
||||
if (!$this->IsTransitionForm() || !$oField->GetReadOnly()){
|
||||
if (!$this->IsTransitionForm() || !$oField->GetReadOnly()) {
|
||||
$oForm->AddField($oField);
|
||||
}
|
||||
|
||||
@@ -810,8 +774,7 @@ class ObjectFormManager extends FormManager
|
||||
{
|
||||
// Ask to each field to clean itself
|
||||
/** @var \Combodo\iTop\Form\Field\Field $oField */
|
||||
foreach ($this->oForm->GetFields() as $oField)
|
||||
{
|
||||
foreach ($this->oForm->GetFields() as $oField) {
|
||||
$oField->OnCancel();
|
||||
}
|
||||
// Then clean inline images from rich text editor such as TextareaField
|
||||
@@ -837,7 +800,7 @@ class ObjectFormManager extends FormManager
|
||||
}
|
||||
|
||||
$aData['messages']['error'] += [
|
||||
'_main' => [$sError]
|
||||
'_main' => [$sError],
|
||||
];
|
||||
$aData['valid'] = false;
|
||||
}
|
||||
@@ -875,8 +838,7 @@ class ObjectFormManager extends FormManager
|
||||
$this->OnUpdate($aArgs);
|
||||
|
||||
// Check if form valid
|
||||
if (! $this->oForm->Validate())
|
||||
{
|
||||
if (! $this->oForm->Validate()) {
|
||||
// Handle errors
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += $this->oForm->GetErrorMessages();
|
||||
@@ -901,8 +863,7 @@ class ObjectFormManager extends FormManager
|
||||
}
|
||||
|
||||
// Writing object to DB
|
||||
try
|
||||
{
|
||||
try {
|
||||
$this->oObject->DBWrite();
|
||||
} catch (CoreCannotSaveObjectException $e) {
|
||||
throw new Exception($e->getTextMessage());
|
||||
@@ -929,34 +890,29 @@ class ObjectFormManager extends FormManager
|
||||
InlineImage::FinalizeInlineImages($this->oObject);
|
||||
// Finalizing attachments link to object
|
||||
// TODO : This has to be refactored when the function from itop-attachments has been migrated into the core
|
||||
if (isset($aArgs['attachmentIds']))
|
||||
{
|
||||
if (isset($aArgs['attachmentIds'])) {
|
||||
$this->FinalizeAttachments($aArgs['attachmentIds']);
|
||||
}
|
||||
|
||||
// Checking if we have to apply a stimulus
|
||||
if (isset($aArgs['applyStimulus']))
|
||||
{
|
||||
if (isset($aArgs['applyStimulus'])) {
|
||||
$this->oObject->ApplyStimulus($aArgs['applyStimulus']['code']);
|
||||
}
|
||||
// Activating triggers only on update
|
||||
if ($bActivateTriggers)
|
||||
{
|
||||
if ($bActivateTriggers) {
|
||||
$sTriggersQuery = $this->oFormHandlerHelper->getCombodoPortalConf()['properties']['triggers_query'];
|
||||
if ($sTriggersQuery !== null)
|
||||
{
|
||||
if ($sTriggersQuery !== null) {
|
||||
$aParentClasses = MetaModel::EnumParentClasses($sObjectClass, ENUM_PARENT_CLASSES_ALL);
|
||||
$oTriggerSet = new DBObjectSet(DBObjectSearch::FromOQL($sTriggersQuery), array(),
|
||||
array('parent_classes' => $aParentClasses));
|
||||
$oTriggerSet = new DBObjectSet(
|
||||
DBObjectSearch::FromOQL($sTriggersQuery),
|
||||
[],
|
||||
['parent_classes' => $aParentClasses]
|
||||
);
|
||||
/** @var \Trigger $oTrigger */
|
||||
while ($oTrigger = $oTriggerSet->Fetch())
|
||||
{
|
||||
try
|
||||
{
|
||||
while ($oTrigger = $oTriggerSet->Fetch()) {
|
||||
try {
|
||||
$oTrigger->DoActivate($this->oObject->ToArgs('this'));
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
utils::EnrichRaisedException($oTrigger, $e);
|
||||
}
|
||||
}
|
||||
@@ -966,30 +922,24 @@ class ObjectFormManager extends FormManager
|
||||
// Resetting caselog fields value, otherwise the value will stay in it after submit.
|
||||
$this->oForm->ResetCaseLogFields();
|
||||
|
||||
if ($bWasModified)
|
||||
{
|
||||
if ($bWasModified) {
|
||||
//=if (isNew) because $bActivateTriggers = (!$this->oObject->IsNew() && $this->oObject->IsModified())
|
||||
if(!$bActivateTriggers)
|
||||
{
|
||||
$aData['messages']['success'] += array( '_main' => array(Dict::Format('UI:Title:Object_Of_Class_Created', $this->oObject->GetName(),MetaModel::GetName(get_class($this->oObject)))));
|
||||
}
|
||||
else
|
||||
{
|
||||
$aData['messages']['success'] += array('_main' => array(Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($this->oObject)), $this->oObject->GetName())));
|
||||
if (!$bActivateTriggers) {
|
||||
$aData['messages']['success'] += [ '_main' => [Dict::Format('UI:Title:Object_Of_Class_Created', $this->oObject->GetName(), MetaModel::GetName(get_class($this->oObject)))]];
|
||||
} else {
|
||||
$aData['messages']['success'] += ['_main' => [Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($this->oObject)), $this->oObject->GetName())]];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (CoreCannotSaveObjectException $e) {
|
||||
} catch (CoreCannotSaveObjectException $e) {
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += array('_main' => array($e->getTextMessage()));
|
||||
$aData['messages']['error'] += ['_main' => [$e->getTextMessage()]];
|
||||
if (false === $bExceptionLogged) {
|
||||
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += [
|
||||
'_main' => [ ($e instanceof CoreCannotSaveObjectException) ? $e->getTextMessage() : $e->getMessage()]
|
||||
'_main' => [ ($e instanceof CoreCannotSaveObjectException) ? $e->getTextMessage() : $e->getMessage()],
|
||||
];
|
||||
if (false === $bExceptionLogged) {
|
||||
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : '.$e->getMessage());
|
||||
@@ -1016,11 +966,9 @@ class ObjectFormManager extends FormManager
|
||||
{
|
||||
$aFormProperties = [];
|
||||
|
||||
if (is_array($aArgs))
|
||||
{
|
||||
if (is_array($aArgs)) {
|
||||
// Then we retrieve properties of the form to build
|
||||
if (isset($aArgs['formProperties']))
|
||||
{
|
||||
if (isset($aArgs['formProperties'])) {
|
||||
$aFormProperties = $aArgs['formProperties'];
|
||||
}
|
||||
}
|
||||
@@ -1054,20 +1002,17 @@ class ObjectFormManager extends FormManager
|
||||
*/
|
||||
protected function FinalizeAttachments($aAttachmentIds)
|
||||
{
|
||||
$aRemovedAttachmentsIds = (isset($aAttachmentIds['removed_attachments_ids'])) ? $aAttachmentIds['removed_attachments_ids'] : array();
|
||||
$aRemovedAttachmentsIds = (isset($aAttachmentIds['removed_attachments_ids'])) ? $aAttachmentIds['removed_attachments_ids'] : [];
|
||||
// Not used for now. //$aActualAttachmentsIds = (isset($aAttachmentIds['actual_attachments_ids'])) ? $aAttachmentIds['actual_attachments_ids'] : array();
|
||||
$aActions = array();
|
||||
$aActions = [];
|
||||
|
||||
// Removing attachments from currents
|
||||
if (!empty($aRemovedAttachmentsIds))
|
||||
{
|
||||
if (!empty($aRemovedAttachmentsIds)) {
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id");
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('class' => get_class($this->oObject), 'item_id' => $this->oObject->GetKey()));
|
||||
while ($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
$oSet = new DBObjectSet($oSearch, [], ['class' => get_class($this->oObject), 'item_id' => $this->oObject->GetKey()]);
|
||||
while ($oAttachment = $oSet->Fetch()) {
|
||||
// Remove attachments that are no longer attached to the current object
|
||||
if (in_array($oAttachment->GetKey(), $aRemovedAttachmentsIds))
|
||||
{
|
||||
if (in_array($oAttachment->GetKey(), $aRemovedAttachmentsIds)) {
|
||||
$aData = ['attachment' => $oAttachment];
|
||||
$this->oObject->FireEvent(EVENT_REMOVE_ATTACHMENT_FROM_OBJECT, $aData);
|
||||
$oAttachment->DBDelete();
|
||||
@@ -1080,16 +1025,12 @@ class ObjectFormManager extends FormManager
|
||||
$sTempId = utils::GetUploadTempId($this->oForm->GetTransactionId());
|
||||
$sOQL = 'SELECT Attachment WHERE temp_id = :temp_id';
|
||||
$oSearch = DBObjectSearch::FromOQL($sOQL);
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('temp_id' => $sTempId));
|
||||
while ($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
$oSet = new DBObjectSet($oSearch, [], ['temp_id' => $sTempId]);
|
||||
while ($oAttachment = $oSet->Fetch()) {
|
||||
// Temp attachment removed
|
||||
if (in_array($oAttachment->GetKey(), $aRemovedAttachmentsIds))
|
||||
{
|
||||
if (in_array($oAttachment->GetKey(), $aRemovedAttachmentsIds)) {
|
||||
$oAttachment->DBDelete();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oAttachment->SetItem($this->oObject);
|
||||
$oAttachment->Set('temp_id', '');
|
||||
$oAttachment->DBUpdate();
|
||||
@@ -1101,8 +1042,7 @@ class ObjectFormManager extends FormManager
|
||||
|
||||
// Save changes to current object history
|
||||
// inspired from itop-attachments/main.attachments.php / RecordHistory
|
||||
foreach ($aActions as $oChangeOp)
|
||||
{
|
||||
foreach ($aActions as $oChangeOp) {
|
||||
$oChangeOp->Set("objclass", get_class($this->oObject));
|
||||
$oChangeOp->Set("objkey", $this->oObject->GetKey());
|
||||
$oChangeOp->DBInsertNoReload();
|
||||
@@ -1125,9 +1065,8 @@ class ObjectFormManager extends FormManager
|
||||
$sTempId = utils::GetUploadTempId($this->oForm->GetTransactionId());
|
||||
$sOQL = 'SELECT Attachment WHERE temp_id = :temp_id';
|
||||
$oSearch = DBObjectSearch::FromOQL($sOQL);
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('temp_id' => $sTempId));
|
||||
while ($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
$oSet = new DBObjectSet($oSearch, [], ['temp_id' => $sTempId]);
|
||||
while ($oAttachment = $oSet->Fetch()) {
|
||||
$oAttachment->DBDelete();
|
||||
}
|
||||
}
|
||||
@@ -1147,14 +1086,11 @@ class ObjectFormManager extends FormManager
|
||||
{
|
||||
$oBlob = $oAttachment->Get('contents');
|
||||
$sFileName = $oBlob->GetFileName();
|
||||
if ($bCreate)
|
||||
{
|
||||
if ($bCreate) {
|
||||
$oChangeOp = new CMDBChangeOpAttachmentAdded();
|
||||
$oChangeOp->Set('attachment_id', $oAttachment->GetKey());
|
||||
$oChangeOp->Set('filename', $sFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oChangeOp = new CMDBChangeOpAttachmentRemoved();
|
||||
$oChangeOp->Set('filename', $sFileName);
|
||||
}
|
||||
@@ -1238,8 +1174,7 @@ class ObjectFormManager extends FormManager
|
||||
{
|
||||
$sObjectClass = get_class($this->oObject);
|
||||
|
||||
foreach ($aCurrentValues as $sAttCode => $value)
|
||||
{
|
||||
foreach ($aCurrentValues as $sAttCode => $value) {
|
||||
if (count($this->aFieldsAtts) !== 0) {
|
||||
if (!array_key_exists($sAttCode, $this->aFieldsAtts)) {
|
||||
continue;
|
||||
@@ -1342,8 +1277,7 @@ class ObjectFormManager extends FormManager
|
||||
}
|
||||
$oOrmSet->ApplyDelta(json_decode($value, true));
|
||||
$this->oObject->Set($sAttCode, $oOrmSet);
|
||||
} elseif ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime
|
||||
{
|
||||
} elseif ($oAttDef instanceof AttributeDateTime) { // AttributeDate is derived from AttributeDateTime
|
||||
if ($value != null) {
|
||||
$value = $oAttDef->GetFormat()->Parse($value);
|
||||
if (is_object($value)) {
|
||||
@@ -1351,11 +1285,9 @@ class ObjectFormManager extends FormManager
|
||||
}
|
||||
}
|
||||
$this->oObject->Set($sAttCode, $value);
|
||||
}
|
||||
elseif ($oAttDef->IsScalar() && is_array($value)) {
|
||||
} elseif ($oAttDef->IsScalar() && is_array($value)) {
|
||||
$this->oObject->Set($sAttCode, current($value));
|
||||
}
|
||||
elseif ($oAttDef->GetEditClass() === 'CustomFields') {
|
||||
} elseif ($oAttDef->GetEditClass() === 'CustomFields') {
|
||||
// We don't update attribute as ormCustomField comparaison is not working as excepted.
|
||||
// When several templates available, "template_id" is not sent by the portal has it is a read-only select input
|
||||
// therefore, the TemplateFieldsHandler::CompareValues() doesn't work.
|
||||
@@ -1377,8 +1309,7 @@ class ObjectFormManager extends FormManager
|
||||
$this->oObject->Set($sAttCode, $value);
|
||||
}
|
||||
// Else don't update! Otherwise we might loose current value
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$this->oObject->Set($sAttCode, $value);
|
||||
}
|
||||
}
|
||||
@@ -1400,9 +1331,9 @@ class ObjectFormManager extends FormManager
|
||||
public function PrepareFields(): void
|
||||
{
|
||||
$sObjectClass = get_class($this->oObject);
|
||||
$this->aFieldsAtts = array();
|
||||
$this->aExtraData = array();
|
||||
$aFieldsDMOnlyAttCodes = array();
|
||||
$this->aFieldsAtts = [];
|
||||
$this->aExtraData = [];
|
||||
$aFieldsDMOnlyAttCodes = [];
|
||||
if (array_key_exists('type', $this->aFormProperties)) {
|
||||
switch ($this->aFormProperties['type']) {
|
||||
case 'custom_list':
|
||||
@@ -1518,8 +1449,7 @@ class ObjectFormManager extends FormManager
|
||||
if (array_key_exists('type', $this->aFormProperties) && $this->aFormProperties['type'] !== 'static') {
|
||||
if ($this->IsTransitionForm()) {
|
||||
$aDatamodelAttCodes = $this->oObject->GetTransitionAttributes($this->aFormProperties['stimulus_code']);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$aDatamodelAttCodes = MetaModel::ListAttributeDefs($sObjectClass);
|
||||
}
|
||||
|
||||
@@ -1536,12 +1466,10 @@ class ObjectFormManager extends FormManager
|
||||
// Retrieving only mandatory flag from DM when on a transition
|
||||
$iFieldFlags = $value & OPT_ATT_MANDATORY;
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this->oObject), $sAttCode);
|
||||
}
|
||||
elseif ($this->oObject->IsNew()) {
|
||||
} elseif ($this->oObject->IsNew()) {
|
||||
$iFieldFlags = $this->oObject->GetInitialStateAttributeFlags($sAttCode);
|
||||
$oAttDef = $value;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$iFieldFlags = $this->oObject->GetAttributeFlags($sAttCode);
|
||||
$oAttDef = $value;
|
||||
}
|
||||
@@ -1581,11 +1509,9 @@ class ObjectFormManager extends FormManager
|
||||
if ($this->IsTransitionForm()) {
|
||||
$aTransitionAtts = $this->oObject->GetTransitionAttributes($this->aFormProperties['stimulus_code']);
|
||||
$iFieldFlags = $aTransitionAtts[$sAttCode];
|
||||
}
|
||||
elseif ($this->oObject->IsNew()) {
|
||||
} elseif ($this->oObject->IsNew()) {
|
||||
$iFieldFlags = $this->oObject->GetInitialStateAttributeFlags($sAttCode);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$iFieldFlags = $this->oObject->GetAttributeFlags($sAttCode);
|
||||
}
|
||||
|
||||
@@ -1629,7 +1555,7 @@ class ObjectFormManager extends FormManager
|
||||
$sRendered = $this->oFormHandlerHelper->RenderFormFromTwig(
|
||||
999, // doesn't matter here
|
||||
$this->aFormProperties['layout']['content'],
|
||||
array('oRenderer' => $this->oRenderer, 'oObject' => $this->oObject)
|
||||
['oRenderer' => $this->oRenderer, 'oObject' => $this->oObject]
|
||||
);
|
||||
} else {
|
||||
$sRendered = 'Form not rendered because of missing container';
|
||||
|
||||
@@ -39,7 +39,7 @@ use UserRights;
|
||||
class PasswordFormManager extends FormManager
|
||||
{
|
||||
/** @var string FORM_TYPE */
|
||||
const FORM_TYPE = 'change_password';
|
||||
public const FORM_TYPE = 'change_password';
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
@@ -106,87 +106,66 @@ class PasswordFormManager extends FormManager
|
||||
$this->OnUpdate($aArgs);
|
||||
|
||||
// Check if form valid
|
||||
if ($this->oForm->Validate())
|
||||
{
|
||||
if ($this->oForm->Validate()) {
|
||||
// The try catch is essentially to start a MySQL transaction
|
||||
try
|
||||
{
|
||||
try {
|
||||
// Updating password
|
||||
$sAuthUser = Session::Get('auth_user');
|
||||
$sOldPassword = $this->oForm->GetField('old_password')->GetCurrentValue();
|
||||
$sNewPassword = $this->oForm->GetField('new_password')->GetCurrentValue();
|
||||
$sConfirmPassword = $this->oForm->GetField('confirm_password')->GetCurrentValue();
|
||||
|
||||
if ($sOldPassword !== '' && $sNewPassword !== '' && $sConfirmPassword !== '')
|
||||
{
|
||||
if (!UserRights::CanChangePassword())
|
||||
{
|
||||
if ($sOldPassword !== '' && $sNewPassword !== '' && $sConfirmPassword !== '') {
|
||||
if (!UserRights::CanChangePassword()) {
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += array(
|
||||
'_main' => array(
|
||||
$aData['messages']['error'] += [
|
||||
'_main' => [
|
||||
Dict::Format('Brick:Portal:UserProfile:Password:CantChangeContactAdministrator', ITOP_APPLICATION_SHORT),
|
||||
),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sOldPassword))
|
||||
{
|
||||
],
|
||||
];
|
||||
} else {
|
||||
if (!UserRights::CheckCredentials($sAuthUser, $sOldPassword)) {
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += array('old_password' => array(Dict::S('UI:Login:IncorrectOldPassword')));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($sNewPassword !== $sConfirmPassword)
|
||||
{
|
||||
$aData['messages']['error'] += ['old_password' => [Dict::S('UI:Login:IncorrectOldPassword')]];
|
||||
} else {
|
||||
if ($sNewPassword !== $sConfirmPassword) {
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += array('confirm_password' => array(Dict::S('UI:Login:RetypePwdDoesNotMatch')));
|
||||
}
|
||||
elseif ($sNewPassword === $sOldPassword)
|
||||
{
|
||||
$aData['messages']['error'] += ['confirm_password' => [Dict::S('UI:Login:RetypePwdDoesNotMatch')]];
|
||||
} elseif ($sNewPassword === $sOldPassword) {
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += array('new_password' => array(Dict::S('UI:Login:PasswordNotChanged')));
|
||||
}
|
||||
else
|
||||
{
|
||||
$aData['messages']['error'] += ['new_password' => [Dict::S('UI:Login:PasswordNotChanged')]];
|
||||
} else {
|
||||
try {
|
||||
if (!UserRights::ChangePassword($sOldPassword, $sNewPassword))
|
||||
{
|
||||
if (!UserRights::ChangePassword($sOldPassword, $sNewPassword)) {
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += array(
|
||||
'confirm_password' => array(
|
||||
Dict::Format('Brick:Portal:UserProfile:Password:CantChangeForUnknownReason',
|
||||
ITOP_APPLICATION_SHORT),
|
||||
),
|
||||
);
|
||||
$aData['messages']['error'] += [
|
||||
'confirm_password' => [
|
||||
Dict::Format(
|
||||
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason',
|
||||
ITOP_APPLICATION_SHORT
|
||||
),
|
||||
],
|
||||
];
|
||||
} else {
|
||||
$aData['messages']['success'] += ['_main' => [Dict::S('Brick:Portal:Object:Form:Message:Saved')]];
|
||||
}
|
||||
else
|
||||
{
|
||||
$aData['messages']['success'] += array('_main' => array(Dict::S('Brick:Portal:Object:Form:Message:Saved')));
|
||||
}
|
||||
}
|
||||
catch (\CoreCannotSaveObjectException $e)
|
||||
{
|
||||
} catch (\CoreCannotSaveObjectException $e) {
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += array(
|
||||
$aData['messages']['error'] += [
|
||||
'new_password' => $e->getIssues(),
|
||||
'confirm_password' => array(),
|
||||
);
|
||||
'confirm_password' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += array('_main' => array($e->getMessage()));
|
||||
$aData['messages']['error'] += ['_main' => [$e->getMessage()]];
|
||||
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Exception during submit ('.$e->getMessage().')');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Handle errors
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += $this->oForm->GetErrorMessages();
|
||||
@@ -207,12 +186,9 @@ class PasswordFormManager extends FormManager
|
||||
$this->Build();
|
||||
|
||||
// Then we update it with new values
|
||||
if (is_array($aArgs))
|
||||
{
|
||||
if (isset($aArgs['currentValues']))
|
||||
{
|
||||
foreach ($aArgs['currentValues'] as $sPreferenceName => $value)
|
||||
{
|
||||
if (is_array($aArgs)) {
|
||||
if (isset($aArgs['currentValues'])) {
|
||||
foreach ($aArgs['currentValues'] as $sPreferenceName => $value) {
|
||||
$this->oForm->GetField($sPreferenceName)->SetCurrentValue($value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ use UserRights;
|
||||
class PreferencesFormManager extends FormManager
|
||||
{
|
||||
/** @var string FORM_TYPE */
|
||||
const FORM_TYPE = 'preferences';
|
||||
public const FORM_TYPE = 'preferences';
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
@@ -63,9 +63,8 @@ class PreferencesFormManager extends FormManager
|
||||
->SetCurrentValue(Dict::GetUserLanguage())
|
||||
->SetStartsWithNullChoice(false);
|
||||
// - Preparing choices
|
||||
$aChoices = array();
|
||||
foreach (Dict::GetLanguages() as $sCode => $aLanguage)
|
||||
{
|
||||
$aChoices = [];
|
||||
foreach (Dict::GetLanguages() as $sCode => $aLanguage) {
|
||||
$aChoices[$sCode] = $aLanguage['description'].' ('.$aLanguage['localized_description'].')';
|
||||
}
|
||||
asort($aChoices);
|
||||
@@ -109,11 +108,9 @@ class PreferencesFormManager extends FormManager
|
||||
$this->OnUpdate($aArgs);
|
||||
|
||||
// Check if form valid
|
||||
if ($this->oForm->Validate())
|
||||
{
|
||||
if ($this->oForm->Validate()) {
|
||||
// The try catch is essentially to start a MySQL transaction
|
||||
try
|
||||
{
|
||||
try {
|
||||
// Starting transaction
|
||||
CMDBSource::Query('START TRANSACTION');
|
||||
$iFieldChanged = 0;
|
||||
@@ -123,34 +120,28 @@ class PreferencesFormManager extends FormManager
|
||||
$oCurUser = UserRights::GetUserObject();
|
||||
// - Language
|
||||
$sLanguage = $this->oForm->GetField('language')->GetCurrentValue();
|
||||
if (($sLanguage !== null) && ($oCurUser->Get('language') !== $sLanguage))
|
||||
{
|
||||
if (($sLanguage !== null) && ($oCurUser->Get('language') !== $sLanguage)) {
|
||||
$oCurUser->Set('language', $sLanguage);
|
||||
$iFieldChanged++;
|
||||
}
|
||||
|
||||
// Updating only if preferences changed
|
||||
if ($iFieldChanged > 0)
|
||||
{
|
||||
if ($iFieldChanged > 0) {
|
||||
$oCurUser->AllowWrite(true);
|
||||
$oCurUser->DBUpdate();
|
||||
$aData['messages']['success'] += array('_main' => array(Dict::S('Brick:Portal:Object:Form:Message:Saved')));
|
||||
$aData['messages']['success'] += ['_main' => [Dict::S('Brick:Portal:Object:Form:Message:Saved')]];
|
||||
}
|
||||
|
||||
// Ending transaction with a commit as everything was fine
|
||||
CMDBSource::Query('COMMIT');
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
// End transaction with a rollback as something failed
|
||||
CMDBSource::Query('ROLLBACK');
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += array('_main' => array($e->getMessage()));
|
||||
$aData['messages']['error'] += ['_main' => [$e->getMessage()]];
|
||||
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Rollback during submit ('.$e->getMessage().')');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Handle errors
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += $this->oForm->GetErrorMessages();
|
||||
@@ -171,12 +162,9 @@ class PreferencesFormManager extends FormManager
|
||||
$this->Build();
|
||||
|
||||
// Then we update it with new values
|
||||
if (is_array($aArgs))
|
||||
{
|
||||
if (isset($aArgs['currentValues']))
|
||||
{
|
||||
foreach ($aArgs['currentValues'] as $sPreferenceName => $value)
|
||||
{
|
||||
if (is_array($aArgs)) {
|
||||
if (isset($aArgs['currentValues'])) {
|
||||
foreach ($aArgs['currentValues'] as $sPreferenceName => $value) {
|
||||
$this->oForm->GetField($sPreferenceName)->SetCurrentValue($value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Portal\Helper;
|
||||
|
||||
/**
|
||||
@@ -53,14 +52,13 @@ class BrickControllerHelper
|
||||
public function ExtractSortParams()
|
||||
{
|
||||
// Getting sort params
|
||||
$aSortParams = $this->oRequestManipulator->ReadParam('aSortParams', array(), FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY);
|
||||
$aSortParams = $this->oRequestManipulator->ReadParam('aSortParams', [], FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY);
|
||||
|
||||
// Converting sort direction to proper format for DBObjectSet as it only accept real booleans
|
||||
foreach ($aSortParams as $sAttributeAlias => $sDirection)
|
||||
{
|
||||
foreach ($aSortParams as $sAttributeAlias => $sDirection) {
|
||||
$aSortParams[$sAttributeAlias] = ($sDirection === 'true');
|
||||
}
|
||||
|
||||
return $aSortParams;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,8 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Portal\Helper;
|
||||
|
||||
|
||||
use AttributeImage;
|
||||
use AttributeSet;
|
||||
use AttributeTagSet;
|
||||
@@ -44,9 +42,9 @@ use utils;
|
||||
class BrowseBrickHelper
|
||||
{
|
||||
/** @var string LEVEL_SEPARATOR */
|
||||
const LEVEL_SEPARATOR = '-';
|
||||
public const LEVEL_SEPARATOR = '-';
|
||||
/** @var array OPTIONAL_ATTRIBUTES */
|
||||
const OPTIONAL_ATTRIBUTES = array('tooltip_att', 'description_att', 'image_att');
|
||||
public const OPTIONAL_ATTRIBUTES = ['tooltip_att', 'description_att', 'image_att'];
|
||||
|
||||
/** @var \Combodo\iTop\Portal\Helper\SecurityHelper */
|
||||
private $oSecurityHelper;
|
||||
@@ -62,7 +60,10 @@ class BrowseBrickHelper
|
||||
* @param \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator
|
||||
* @param \Symfony\Component\Routing\Generator\UrlGeneratorInterface $oUrlGenerator
|
||||
*/
|
||||
public function __construct(SecurityHelper $oSecurityHelper, ScopeValidatorHelper $oScopeValidator, UrlGeneratorInterface $oUrlGenerator
|
||||
public function __construct(
|
||||
SecurityHelper $oSecurityHelper,
|
||||
ScopeValidatorHelper $oScopeValidator,
|
||||
UrlGeneratorInterface $oUrlGenerator
|
||||
) {
|
||||
$this->oSecurityHelper = $oSecurityHelper;
|
||||
$this->oScopeValidator = $oScopeValidator;
|
||||
@@ -89,24 +90,24 @@ class BrowseBrickHelper
|
||||
*/
|
||||
public function TreeToFlatLevelsProperties(array $aLevels, array &$aLevelsProperties, $sLevelAliasPrefix = 'L')
|
||||
{
|
||||
foreach ($aLevels as $aLevel)
|
||||
{
|
||||
foreach ($aLevels as $aLevel) {
|
||||
$sCurrentLevelAlias = $sLevelAliasPrefix.static::LEVEL_SEPARATOR.$aLevel['id'];
|
||||
$oSearch = DBSearch::CloneWithAlias(DBSearch::FromOQL($aLevel['oql']), $sCurrentLevelAlias);
|
||||
|
||||
// Restricting to the allowed scope
|
||||
$oScopeSearch = $this->oScopeValidator->GetScopeFilterForProfiles(UserRights::ListProfiles(), $oSearch->GetClass(),
|
||||
UR_ACTION_READ);
|
||||
$oScopeSearch = $this->oScopeValidator->GetScopeFilterForProfiles(
|
||||
UserRights::ListProfiles(),
|
||||
$oSearch->GetClass(),
|
||||
UR_ACTION_READ
|
||||
);
|
||||
$oSearch = ($oScopeSearch !== null) ? $oSearch->Intersect($oScopeSearch) : null;
|
||||
// - Allowing all data if necessary
|
||||
if ($oScopeSearch !== null && $oScopeSearch->IsAllDataAllowed())
|
||||
{
|
||||
if ($oScopeSearch !== null && $oScopeSearch->IsAllDataAllowed()) {
|
||||
$oSearch->AllowAllData();
|
||||
}
|
||||
|
||||
if ($oSearch !== null)
|
||||
{
|
||||
$aLevelsProperties[$sCurrentLevelAlias] = array(
|
||||
if ($oSearch !== null) {
|
||||
$aLevelsProperties[$sCurrentLevelAlias] = [
|
||||
'alias' => $sCurrentLevelAlias,
|
||||
'title' => ($aLevel['title'] !== null) ? Dict::S($aLevel['title']) : MetaModel::GetName($oSearch->GetClass()),
|
||||
'parent_att' => $aLevel['parent_att'],
|
||||
@@ -115,42 +116,35 @@ class BrowseBrickHelper
|
||||
'description_att' => $aLevel['description_att'],
|
||||
'image_att' => $aLevel['image_att'],
|
||||
'search' => $oSearch,
|
||||
'fields' => array(),
|
||||
'actions' => array(),
|
||||
);
|
||||
'fields' => [],
|
||||
'actions' => [],
|
||||
];
|
||||
|
||||
// Adding current level's fields
|
||||
if (isset($aLevel['fields']))
|
||||
{
|
||||
$aLevelsProperties[$sCurrentLevelAlias]['fields'] = array();
|
||||
if (isset($aLevel['fields'])) {
|
||||
$aLevelsProperties[$sCurrentLevelAlias]['fields'] = [];
|
||||
|
||||
foreach ($aLevel['fields'] as $sFieldAttCode => $aFieldProperties)
|
||||
{
|
||||
$aLevelsProperties[$sCurrentLevelAlias]['fields'][] = array(
|
||||
foreach ($aLevel['fields'] as $sFieldAttCode => $aFieldProperties) {
|
||||
$aLevelsProperties[$sCurrentLevelAlias]['fields'][] = [
|
||||
'code' => $sFieldAttCode,
|
||||
'label' => MetaModel::GetAttributeDef($oSearch->GetClass(), $sFieldAttCode)->GetLabel(),
|
||||
'hidden' => $aFieldProperties['hidden'],
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Flattening and adding sub levels
|
||||
if (isset($aLevel['levels']))
|
||||
{
|
||||
foreach ($aLevel['levels'] as $aChildLevel)
|
||||
{
|
||||
if (isset($aLevel['levels'])) {
|
||||
foreach ($aLevel['levels'] as $aChildLevel) {
|
||||
// Checking if the sub level if allowed
|
||||
$oChildSearch = DBSearch::FromOQL($aChildLevel['oql']);
|
||||
if ($this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $oChildSearch->GetClass()))
|
||||
{
|
||||
if ($this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $oChildSearch->GetClass())) {
|
||||
// Adding the sub level to this one
|
||||
$aLevelsProperties[$sCurrentLevelAlias]['levels'][] = $sCurrentLevelAlias.static::LEVEL_SEPARATOR.$aChildLevel['id'];
|
||||
|
||||
// Adding drill down action if necessary
|
||||
foreach ($aLevel['actions'] as $sId => $aAction)
|
||||
{
|
||||
if ($aAction['type'] === BrowseBrick::ENUM_ACTION_DRILLDOWN)
|
||||
{
|
||||
foreach ($aLevel['actions'] as $sId => $aAction) {
|
||||
if ($aAction['type'] === BrowseBrick::ENUM_ACTION_DRILLDOWN) {
|
||||
$aLevelsProperties[$sCurrentLevelAlias]['actions'][$sId] = $aAction;
|
||||
break;
|
||||
}
|
||||
@@ -162,49 +156,43 @@ class BrowseBrickHelper
|
||||
}
|
||||
|
||||
// Adding actions to the level
|
||||
foreach ($aLevel['actions'] as $sId => $aAction)
|
||||
{
|
||||
foreach ($aLevel['actions'] as $sId => $aAction) {
|
||||
// ... Only if it's not already there (eg. the drilldown added with the sublevels)
|
||||
if (!array_key_exists($sId, $aLevelsProperties[$sCurrentLevelAlias]['actions']))
|
||||
{
|
||||
if (!array_key_exists($sId, $aLevelsProperties[$sCurrentLevelAlias]['actions'])) {
|
||||
// Adding action only if allowed
|
||||
if (($aAction['type'] === BrowseBrick::ENUM_ACTION_VIEW) && !$this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ,
|
||||
$oSearch->GetClass()))
|
||||
{
|
||||
if (($aAction['type'] === BrowseBrick::ENUM_ACTION_VIEW) && !$this->oSecurityHelper->IsActionAllowed(
|
||||
UR_ACTION_READ,
|
||||
$oSearch->GetClass()
|
||||
)) {
|
||||
continue;
|
||||
}
|
||||
elseif (($aAction['type'] === BrowseBrick::ENUM_ACTION_EDIT) && !$this->oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY,
|
||||
$oSearch->GetClass()))
|
||||
{
|
||||
} elseif (($aAction['type'] === BrowseBrick::ENUM_ACTION_EDIT) && !$this->oSecurityHelper->IsActionAllowed(
|
||||
UR_ACTION_MODIFY,
|
||||
$oSearch->GetClass()
|
||||
)) {
|
||||
continue;
|
||||
}
|
||||
elseif ($aAction['type'] === BrowseBrick::ENUM_ACTION_DRILLDOWN)
|
||||
{
|
||||
} elseif ($aAction['type'] === BrowseBrick::ENUM_ACTION_DRILLDOWN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Setting action title
|
||||
if (isset($aAction['title']))
|
||||
{
|
||||
if (isset($aAction['title'])) {
|
||||
// Note : There could be an enhancement here, by checking if the string code has the '%1' needle and use Dict::S or Dict::Format accordingly.
|
||||
// But it would require to benchmark a potential performance drop as it will be done for all items
|
||||
$aAction['title'] = Dict::S($aAction['title']);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ($aAction['type'])
|
||||
{
|
||||
} else {
|
||||
switch ($aAction['type']) {
|
||||
case BrowseBrick::ENUM_ACTION_CREATE_FROM_THIS:
|
||||
// We can only make translate a dictionary entry with a class placeholder when the action has a class tag. if it has a factory method, we don't know yet what class is going to be created
|
||||
if ($aAction['factory']['type'] === BrowseBrick::ENUM_FACTORY_TYPE_CLASS)
|
||||
{
|
||||
$aAction['title'] = Dict::Format('Brick:Portal:Browse:Action:CreateObjectFromThis',
|
||||
MetaModel::GetName($aAction['factory']['value']));
|
||||
$aAction['url'] = $this->oUrlGenerator->generate('p_object_create',
|
||||
array('sObjectClass' => $aAction['factory']['value']));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($aAction['factory']['type'] === BrowseBrick::ENUM_FACTORY_TYPE_CLASS) {
|
||||
$aAction['title'] = Dict::Format(
|
||||
'Brick:Portal:Browse:Action:CreateObjectFromThis',
|
||||
MetaModel::GetName($aAction['factory']['value'])
|
||||
);
|
||||
$aAction['url'] = $this->oUrlGenerator->generate(
|
||||
'p_object_create',
|
||||
['sObjectClass' => $aAction['factory']['value']]
|
||||
);
|
||||
} else {
|
||||
$aAction['title'] = Dict::S('Brick:Portal:Browse:Action:Create');
|
||||
}
|
||||
break;
|
||||
@@ -221,10 +209,8 @@ class BrowseBrickHelper
|
||||
}
|
||||
|
||||
// Setting action icon class
|
||||
if (!isset($aAction['icon_class']))
|
||||
{
|
||||
switch ($aAction['type'])
|
||||
{
|
||||
if (!isset($aAction['icon_class'])) {
|
||||
switch ($aAction['type']) {
|
||||
case BrowseBrick::ENUM_ACTION_CREATE_FROM_THIS:
|
||||
$aAction['icon_class'] = BrowseBrick::ENUM_ACTION_ICON_CLASS_CREATE_FROM_THIS;
|
||||
break;
|
||||
@@ -241,21 +227,19 @@ class BrowseBrickHelper
|
||||
}
|
||||
|
||||
// Setting action url
|
||||
switch ($aAction['type'])
|
||||
{
|
||||
switch ($aAction['type']) {
|
||||
case BrowseBrick::ENUM_ACTION_CREATE_FROM_THIS:
|
||||
if ($aAction['factory']['type'] === BrowseBrick::ENUM_FACTORY_TYPE_CLASS)
|
||||
{
|
||||
$aAction['url'] = $this->oUrlGenerator->generate('p_object_create',
|
||||
array('sObjectClass' => $aAction['factory']['value']));
|
||||
}
|
||||
else
|
||||
{
|
||||
$aAction['url'] = $this->oUrlGenerator->generate('p_object_create_from_factory', array(
|
||||
if ($aAction['factory']['type'] === BrowseBrick::ENUM_FACTORY_TYPE_CLASS) {
|
||||
$aAction['url'] = $this->oUrlGenerator->generate(
|
||||
'p_object_create',
|
||||
['sObjectClass' => $aAction['factory']['value']]
|
||||
);
|
||||
} else {
|
||||
$aAction['url'] = $this->oUrlGenerator->generate('p_object_create_from_factory', [
|
||||
'sEncodedMethodName' => base64_encode($aAction['factory']['value']),
|
||||
'sObjectClass' => '-objectClass-',
|
||||
'sObjectId' => '-objectId-',
|
||||
));
|
||||
]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -278,10 +262,9 @@ class BrowseBrickHelper
|
||||
*/
|
||||
public function PrepareActionRulesForItems(array $aItems, $sLevelsAlias, array &$aLevelsProperties)
|
||||
{
|
||||
$aActionRules = array();
|
||||
$aActionRules = [];
|
||||
|
||||
foreach ($aLevelsProperties[$sLevelsAlias]['actions'] as $sId => $aAction)
|
||||
{
|
||||
foreach ($aLevelsProperties[$sLevelsAlias]['actions'] as $sId => $aAction) {
|
||||
$aActionRules[$sId] = ContextManipulatorHelper::PrepareAndEncodeRulesToken($aAction['rules'], $aItems);
|
||||
}
|
||||
|
||||
@@ -317,11 +300,10 @@ class BrowseBrickHelper
|
||||
*/
|
||||
public function AddToFlatItems(array $aCurrentRow, array &$aLevelsProperties)
|
||||
{
|
||||
$aRow = array();
|
||||
$aRow = [];
|
||||
|
||||
/** @var \DBObject $value */
|
||||
foreach ($aCurrentRow as $key => $value)
|
||||
{
|
||||
foreach ($aCurrentRow as $key => $value) {
|
||||
// Retrieving objects from all levels
|
||||
$aItems = array_values($aCurrentRow);
|
||||
|
||||
@@ -332,36 +314,31 @@ class BrowseBrickHelper
|
||||
$sNameAttDef = MetaModel::GetAttributeDef($sCurrentObjectClass, $sNameAttCode);
|
||||
$sNameAttDefClass = get_class($sNameAttDef);
|
||||
|
||||
$aRow[$key] = array(
|
||||
$aRow[$key] = [
|
||||
'level_alias' => $key,
|
||||
'id' => $sCurrentObjectId,
|
||||
'name' => utils::EscapeHtml($value->Get($sNameAttCode)),
|
||||
'class' => $sCurrentObjectClass,
|
||||
'action_rules_token' => $this->PrepareActionRulesForItems($aItems, $key, $aLevelsProperties),
|
||||
'metadata' => array(
|
||||
'metadata' => [
|
||||
'object_class' => $sCurrentObjectClass,
|
||||
'object_id' => $sCurrentObjectId,
|
||||
'attribute_code' => $sNameAttCode,
|
||||
'attribute_type' => $sNameAttDefClass,
|
||||
'value_raw' => $value->Get($sNameAttCode),
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
|
||||
// Adding optional attributes if necessary
|
||||
foreach (static::OPTIONAL_ATTRIBUTES as $sOptionalAttribute)
|
||||
{
|
||||
if ($aLevelsProperties[$key][$sOptionalAttribute] !== null)
|
||||
{
|
||||
foreach (static::OPTIONAL_ATTRIBUTES as $sOptionalAttribute) {
|
||||
if ($aLevelsProperties[$key][$sOptionalAttribute] !== null) {
|
||||
$sPropertyName = substr($sOptionalAttribute, 0, -4);
|
||||
$oAttDef = MetaModel::GetAttributeDef($sCurrentObjectClass, $aLevelsProperties[$key][$sOptionalAttribute]);
|
||||
|
||||
if ($oAttDef instanceof AttributeImage)
|
||||
{
|
||||
if ($oAttDef instanceof AttributeImage) {
|
||||
$tmpAttValue = $value->Get($aLevelsProperties[$key][$sOptionalAttribute]);
|
||||
if ($sOptionalAttribute === 'image_att')
|
||||
{
|
||||
if (is_object($tmpAttValue) && !$tmpAttValue->IsEmpty())
|
||||
{
|
||||
if ($sOptionalAttribute === 'image_att') {
|
||||
if (is_object($tmpAttValue) && !$tmpAttValue->IsEmpty()) {
|
||||
$oOrmDoc = $tmpAttValue;
|
||||
$tmpAttValue = $this->oUrlGenerator->generate('p_object_document_display', [
|
||||
'sObjectClass' => $sCurrentObjectClass,
|
||||
@@ -370,15 +347,11 @@ class BrowseBrickHelper
|
||||
'cache' => 86400,
|
||||
's' => $oOrmDoc->GetSignature(),
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$tmpAttValue = $oAttDef->Get('default_image');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$tmpAttValue = $value->GetAsHTML($aLevelsProperties[$key][$sOptionalAttribute]);
|
||||
}
|
||||
|
||||
@@ -386,16 +359,13 @@ class BrowseBrickHelper
|
||||
}
|
||||
}
|
||||
// Adding fields attributes if necessary
|
||||
if (!empty($aLevelsProperties[$key]['fields']))
|
||||
{
|
||||
$aRow[$key]['fields'] = array();
|
||||
foreach ($aLevelsProperties[$key]['fields'] as $aField)
|
||||
{
|
||||
if (!empty($aLevelsProperties[$key]['fields'])) {
|
||||
$aRow[$key]['fields'] = [];
|
||||
foreach ($aLevelsProperties[$key]['fields'] as $aField) {
|
||||
$oAttDef = MetaModel::GetAttributeDef($sCurrentObjectClass, $aField['code']);
|
||||
$sAttDefClass = get_class($oAttDef);
|
||||
|
||||
switch (true)
|
||||
{
|
||||
switch (true) {
|
||||
case $oAttDef instanceof AttributeTagSet:
|
||||
/** @var \ormTagSet $oSetValues */
|
||||
$oSetValues = $value->Get($aField['code']);
|
||||
@@ -412,8 +382,7 @@ class BrowseBrickHelper
|
||||
case $oAttDef instanceof AttributeImage:
|
||||
// Todo: This should be refactored, it has been seen multiple times in the portal
|
||||
$oOrmDoc = $value->Get($aField['code']);
|
||||
if (is_object($oOrmDoc) && !$oOrmDoc->IsEmpty())
|
||||
{
|
||||
if (is_object($oOrmDoc) && !$oOrmDoc->IsEmpty()) {
|
||||
$sUrl = $this->oUrlGenerator->generate('p_object_document_display', [
|
||||
'sObjectClass' => $sCurrentObjectClass,
|
||||
'sObjectId' => $sCurrentObjectId,
|
||||
@@ -421,9 +390,7 @@ class BrowseBrickHelper
|
||||
'cache' => 86400,
|
||||
's' => $oOrmDoc->GetSignature(),
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$sUrl = $oAttDef->Get('default_image');
|
||||
}
|
||||
$sHtmlForFieldValue = '<img src="'.$sUrl.'" />';
|
||||
@@ -436,24 +403,22 @@ class BrowseBrickHelper
|
||||
|
||||
// For simple fields, we get the raw (stored) value as well
|
||||
$bExcludeRawValue = false;
|
||||
foreach (ApplicationHelper::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude)
|
||||
{
|
||||
if (is_a($sAttDefClass, $sAttDefClassToExclude, true))
|
||||
{
|
||||
foreach (ApplicationHelper::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude) {
|
||||
if (is_a($sAttDefClass, $sAttDefClassToExclude, true)) {
|
||||
$bExcludeRawValue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$attValueRaw = ($bExcludeRawValue === false) ? $value->Get($aField['code']) : null;
|
||||
|
||||
$aRow[$key]['fields'][$aField['code']] = array(
|
||||
$aRow[$key]['fields'][$aField['code']] = [
|
||||
'object_class' => $sCurrentObjectClass,
|
||||
'object_id' => $sCurrentObjectId,
|
||||
'attribute_code' => $aField['code'],
|
||||
'attribute_type' => $sAttDefClass,
|
||||
'value_raw' => $attValueRaw,
|
||||
'value_html' => $sHtmlForFieldValue,
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -503,39 +468,34 @@ class BrowseBrickHelper
|
||||
|
||||
// We make sure to keep all row objects through levels by copying them when processing the first level.
|
||||
// Otherwise they will be sliced through levels, one by one.
|
||||
if ($aCurrentRowObjects === null)
|
||||
{
|
||||
if ($aCurrentRowObjects === null) {
|
||||
$aCurrentRowObjects = $aCurrentRowValues;
|
||||
}
|
||||
|
||||
if (!isset($aItems[$sCurrentIndex]))
|
||||
{
|
||||
$aItems[$sCurrentIndex] = array(
|
||||
if (!isset($aItems[$sCurrentIndex])) {
|
||||
$aItems[$sCurrentIndex] = [
|
||||
'level_alias' => $aCurrentRowKeys[0],
|
||||
'id' => $aCurrentRowValues[0]->GetKey(),
|
||||
'name' => utils::EscapeHtml($aCurrentRowValues[0]->Get($aLevelsProperties[$aCurrentRowKeys[0]]['name_att'])),
|
||||
'class' => get_class($aCurrentRowValues[0]),
|
||||
'subitems' => array(),
|
||||
'subitems' => [],
|
||||
'filter_data' => $this->GetFilterData($aLevelsProperties[$aCurrentRowKeys[0]], $aCurrentRowKeys[0], $aCurrentRowValues[0]),
|
||||
'action_rules_token' => $this->PrepareActionRulesForItems($aCurrentRowObjects, $aCurrentRowKeys[0], $aLevelsProperties),
|
||||
);
|
||||
];
|
||||
|
||||
// Adding optional attributes if necessary
|
||||
foreach (static::OPTIONAL_ATTRIBUTES as $sOptionalAttribute)
|
||||
{
|
||||
if ($aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute] !== null)
|
||||
{
|
||||
foreach (static::OPTIONAL_ATTRIBUTES as $sOptionalAttribute) {
|
||||
if ($aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute] !== null) {
|
||||
$sPropertyName = substr($sOptionalAttribute, 0, -4);
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($aCurrentRowValues[0]),
|
||||
$aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute]);
|
||||
$oAttDef = MetaModel::GetAttributeDef(
|
||||
get_class($aCurrentRowValues[0]),
|
||||
$aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute]
|
||||
);
|
||||
|
||||
if ($oAttDef instanceof AttributeImage)
|
||||
{
|
||||
if ($oAttDef instanceof AttributeImage) {
|
||||
$tmpAttValue = $aCurrentRowValues[0]->Get($aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute]);
|
||||
if ($sOptionalAttribute === 'image_att')
|
||||
{
|
||||
if (is_object($tmpAttValue) && !$tmpAttValue->IsEmpty())
|
||||
{
|
||||
if ($sOptionalAttribute === 'image_att') {
|
||||
if (is_object($tmpAttValue) && !$tmpAttValue->IsEmpty()) {
|
||||
$oOrmDoc = $tmpAttValue;
|
||||
$tmpAttValue = $this->oUrlGenerator->generate('p_object_document_display', [
|
||||
'sObjectClass' => get_class($aCurrentRowValues[0]),
|
||||
@@ -544,15 +504,11 @@ class BrowseBrickHelper
|
||||
'cache' => 86400,
|
||||
's' => $oOrmDoc->GetSignature(),
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$tmpAttValue = $oAttDef->Get('default_image');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$tmpAttValue = $aCurrentRowValues[0]->GetAsHTML($aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute]);
|
||||
}
|
||||
|
||||
@@ -562,8 +518,7 @@ class BrowseBrickHelper
|
||||
}
|
||||
|
||||
$aCurrentRowSliced = array_slice($aCurrentRow, 1);
|
||||
if (!empty($aCurrentRowSliced))
|
||||
{
|
||||
if (!empty($aCurrentRowSliced)) {
|
||||
$this->AddToTreeItems($aItems[$sCurrentIndex]['subitems'], $aCurrentRowSliced, $aLevelsProperties, $aCurrentRowObjects);
|
||||
}
|
||||
}
|
||||
@@ -580,7 +535,7 @@ class BrowseBrickHelper
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function GetFilterData(array $aLevelProperties, string $sRowKey, DBObject $oRowValue) : array
|
||||
private function GetFilterData(array $aLevelProperties, string $sRowKey, DBObject $oRowValue): array
|
||||
{
|
||||
// result
|
||||
$sValues = "";
|
||||
@@ -599,17 +554,17 @@ class BrowseBrickHelper
|
||||
$sValue = $oAttDef->GetAsHTML($oRowValue->Get($aField['code']));
|
||||
|
||||
// do not print empty fields
|
||||
if(!utils::IsNullOrEmptyString($sValue)){
|
||||
if (!utils::IsNullOrEmptyString($sValue)) {
|
||||
|
||||
// append to result
|
||||
$sValues .= $sValue;
|
||||
$sValuesAndCodes .= '<span><span class="tree-item-filter-data-label">' . $aField['label'] . ':</span> ' . $sValue . '</span>';
|
||||
$sValuesAndCodes .= '<span><span class="tree-item-filter-data-label">'.$aField['label'].':</span> '.$sValue.'</span>';
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'values' => $sValues,
|
||||
'values_and_codes' => $sValuesAndCodes
|
||||
'values_and_codes' => $sValuesAndCodes,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -93,4 +94,4 @@ class ExtensibilityHelper
|
||||
|
||||
return $aTabSectionExtensions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ use MetaModel;
|
||||
class LifecycleValidatorHelper
|
||||
{
|
||||
/** @var string DEFAULT_GENERATED_CLASS */
|
||||
const DEFAULT_GENERATED_CLASS = 'PortalLifecycleValues';
|
||||
public const DEFAULT_GENERATED_CLASS = 'PortalLifecycleValues';
|
||||
|
||||
/** @var string|null $sCachePath */
|
||||
protected $sCachePath;
|
||||
@@ -64,9 +64,10 @@ class LifecycleValidatorHelper
|
||||
{
|
||||
$this->sFilename = "{$sPortalId}.lifecycle.php";
|
||||
$this->sCachePath = $sPortalCachePath;
|
||||
$this->sInstancePrefix = "{$sPortalId}-";;
|
||||
$this->sInstancePrefix = "{$sPortalId}-";
|
||||
;
|
||||
$this->sGeneratedClass = static::DEFAULT_GENERATED_CLASS;
|
||||
$this->aProfilesMatrix = array();
|
||||
$this->aProfilesMatrix = [];
|
||||
|
||||
$this->Init($moduleDesign->GetNodes('/module_design/classes/class'));
|
||||
}
|
||||
@@ -143,8 +144,7 @@ class LifecycleValidatorHelper
|
||||
public function Init(DOMNodeList $oNodes)
|
||||
{
|
||||
// Checking cache path
|
||||
if ($this->sCachePath === null)
|
||||
{
|
||||
if ($this->sCachePath === null) {
|
||||
$this->sCachePath = utils::GetCachePath();
|
||||
}
|
||||
// Building full pathname for file
|
||||
@@ -152,61 +152,48 @@ class LifecycleValidatorHelper
|
||||
|
||||
// Creating file if not existing
|
||||
// Note: This is a temporary cache system, it should soon evolve to a cache provider (fs, apc, memcache, ...)
|
||||
if (!file_exists($sFilePath))
|
||||
{
|
||||
if (!file_exists($sFilePath)) {
|
||||
// - Build php array from xml
|
||||
$aProfiles = array();
|
||||
$aProfiles = [];
|
||||
// This will be used to know which classes have been set, so we can set the missing ones.
|
||||
$aProfileClasses = array();
|
||||
$aProfileClasses = [];
|
||||
// Iterating over the class nodes
|
||||
/** @var \Combodo\iTop\DesignElement $oClassNode */
|
||||
foreach ($oNodes as $oClassNode)
|
||||
{
|
||||
foreach ($oNodes as $oClassNode) {
|
||||
// Retrieving mandatory class id attribute
|
||||
$sClass = $oClassNode->getAttribute('id');
|
||||
if ($sClass === '')
|
||||
{
|
||||
if ($sClass === '') {
|
||||
throw new DOMFormatException('Class tag must have an id attribute.', null, null, $oClassNode);
|
||||
}
|
||||
|
||||
// Retrieving lifecycle node of the class
|
||||
$oLifecycleNode = $oClassNode->GetOptionalElement('lifecycle');
|
||||
if ($oLifecycleNode !== null)
|
||||
{
|
||||
if ($oLifecycleNode !== null) {
|
||||
// Iterating over scope nodes of the class
|
||||
$oStimuliNode = $oLifecycleNode->GetOptionalElement('stimuli');
|
||||
if ($oStimuliNode !== null)
|
||||
{
|
||||
if ($oStimuliNode !== null) {
|
||||
/** @var \Combodo\iTop\DesignElement $oStimulusNode */
|
||||
foreach ($oStimuliNode->GetNodes('./stimulus') as $oStimulusNode)
|
||||
{
|
||||
foreach ($oStimuliNode->GetNodes('./stimulus') as $oStimulusNode) {
|
||||
// Retrieving mandatory scope id attribute
|
||||
$sStimulusId = $oStimulusNode->getAttribute('id');
|
||||
if ($sStimulusId === '')
|
||||
{
|
||||
if ($sStimulusId === '') {
|
||||
throw new DOMFormatException('Stimulus tag must have an id attribute.', null, null, $oStimulusNode);
|
||||
}
|
||||
|
||||
// Retrieving profiles for the stimulus
|
||||
$oProfilesNode = $oStimulusNode->GetOptionalElement('denied_profiles');
|
||||
$aProfilesNames = array();
|
||||
$aProfilesNames = [];
|
||||
// If no profile is specified, we consider that it's for ALL the profiles
|
||||
if (($oProfilesNode === null) || ($oProfilesNode->GetNodes('./denied_profile')->length === 0))
|
||||
{
|
||||
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
|
||||
{
|
||||
if (($oProfilesNode === null) || ($oProfilesNode->GetNodes('./denied_profile')->length === 0)) {
|
||||
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue) {
|
||||
$aProfilesNames[] = $aValue['name'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/** @var \Combodo\iTop\DesignElement $oProfileNode */
|
||||
foreach ($oProfilesNode->GetNodes('./denied_profile') as $oProfileNode)
|
||||
{
|
||||
foreach ($oProfilesNode->GetNodes('./denied_profile') as $oProfileNode) {
|
||||
// Retrieving mandatory profile id attribute
|
||||
$sProfileId = $oProfileNode->getAttribute('id');
|
||||
if ($sProfileId === '')
|
||||
{
|
||||
if ($sProfileId === '') {
|
||||
throw new DOMFormatException('Profile tag must have an id attribute.', null, null, $oProfileNode);
|
||||
}
|
||||
$aProfilesNames[] = $sProfileId;
|
||||
@@ -214,21 +201,18 @@ class LifecycleValidatorHelper
|
||||
}
|
||||
|
||||
//
|
||||
foreach ($aProfilesNames as $sProfileName)
|
||||
{
|
||||
foreach ($aProfilesNames as $sProfileName) {
|
||||
// Stimulus profile id
|
||||
$iProfileId = $this->GetProfileIdFromProfileName($sProfileName);
|
||||
|
||||
// Now that we have the queries infos, we are going to build the queries for that profile / class
|
||||
$sMatrixPrefix = $iProfileId.'_'.$sClass;
|
||||
// - Creating profile / class entry if not already present
|
||||
if (!array_key_exists($sMatrixPrefix, $aProfiles))
|
||||
{
|
||||
$aProfiles[$sMatrixPrefix] = array();
|
||||
if (!array_key_exists($sMatrixPrefix, $aProfiles)) {
|
||||
$aProfiles[$sMatrixPrefix] = [];
|
||||
}
|
||||
// - Adding stimulus if not already present
|
||||
if (!in_array($sStimulusId, $aProfiles[$sMatrixPrefix]))
|
||||
{
|
||||
if (!in_array($sStimulusId, $aProfiles[$sMatrixPrefix])) {
|
||||
$aProfiles[$sMatrixPrefix][] = $sStimulusId;
|
||||
}
|
||||
}
|
||||
@@ -244,20 +228,15 @@ class LifecycleValidatorHelper
|
||||
// If not, we add them
|
||||
//
|
||||
// Note: Classes / Stimuli not in the matrix are implicitly ALLOWED. That can happen by omitting the <lifecycle> in a <class>
|
||||
foreach ($aProfileClasses as $sProfileClass)
|
||||
{
|
||||
foreach (MetaModel::EnumChildClasses($sProfileClass) as $sChildClass)
|
||||
{
|
||||
foreach ($aProfileClasses as $sProfileClass) {
|
||||
foreach (MetaModel::EnumChildClasses($sProfileClass) as $sChildClass) {
|
||||
// If the child class is not in the scope, we are going to try to add it
|
||||
if (!in_array($sChildClass, $aProfileClasses))
|
||||
{
|
||||
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
|
||||
{
|
||||
if (!in_array($sChildClass, $aProfileClasses)) {
|
||||
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue) {
|
||||
$iProfileId = $iKey;
|
||||
|
||||
// If the current profile has scope for that class in that mode, we duplicate it
|
||||
if (isset($aProfiles[$iProfileId.'_'.$sProfileClass]))
|
||||
{
|
||||
if (isset($aProfiles[$iProfileId.'_'.$sProfileClass])) {
|
||||
$aProfiles[$iProfileId.'_'.$sChildClass] = $aProfiles[$iProfileId.'_'.$sProfileClass];
|
||||
}
|
||||
}
|
||||
@@ -270,14 +249,12 @@ class LifecycleValidatorHelper
|
||||
|
||||
// - Write file on disk
|
||||
// - Creating dir if necessary
|
||||
if (!is_dir($this->sCachePath))
|
||||
{
|
||||
if (!is_dir($this->sCachePath)) {
|
||||
mkdir($this->sCachePath, 0777, true);
|
||||
}
|
||||
// -- Then creating the file
|
||||
$ret = file_put_contents($sFilePath, $sPHP);
|
||||
if ($ret === false)
|
||||
{
|
||||
if ($ret === false) {
|
||||
$iLen = strlen($sPHP);
|
||||
$fFree = @disk_free_space(dirname($sFilePath));
|
||||
$aErr = error_get_last();
|
||||
@@ -285,8 +262,7 @@ class LifecycleValidatorHelper
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists($this->sGeneratedClass))
|
||||
{
|
||||
if (!class_exists($this->sGeneratedClass)) {
|
||||
require_once $this->sCachePath.$this->sFilename;
|
||||
}
|
||||
}
|
||||
@@ -303,7 +279,7 @@ class LifecycleValidatorHelper
|
||||
*/
|
||||
public function GetStimuliForProfile($sProfile, $sClass)
|
||||
{
|
||||
return $this->GetStimuliForProfiles(array($sProfile), $sClass);
|
||||
return $this->GetStimuliForProfiles([$sProfile], $sClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -319,17 +295,15 @@ class LifecycleValidatorHelper
|
||||
*/
|
||||
public function GetStimuliForProfiles($aProfiles, $sClass)
|
||||
{
|
||||
$aStimuli = array();
|
||||
$aStimuli = [];
|
||||
|
||||
// Preparing available stimuli
|
||||
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $aData)
|
||||
{
|
||||
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $aData) {
|
||||
$aStimuli[$sStimulusCode] = true;
|
||||
}
|
||||
|
||||
// Iterating on profiles to retrieving the different OQLs parts
|
||||
foreach ($aProfiles as $sProfile)
|
||||
{
|
||||
foreach ($aProfiles as $sProfile) {
|
||||
// Retrieving matrix information
|
||||
$iProfileId = $this->GetProfileIdFromProfileName($sProfile);
|
||||
|
||||
@@ -337,10 +311,8 @@ class LifecycleValidatorHelper
|
||||
$sLifecycleValuesClass = $this->sGeneratedClass;
|
||||
$aProfileMatrix = $sLifecycleValuesClass::GetProfileStimuli($iProfileId, $sClass);
|
||||
|
||||
foreach ($aProfileMatrix as $sStimulusCode)
|
||||
{
|
||||
if (array_key_exists($sStimulusCode, $aStimuli))
|
||||
{
|
||||
foreach ($aProfileMatrix as $sStimulusCode) {
|
||||
if (array_key_exists($sStimulusCode, $aStimuli)) {
|
||||
unset($aStimuli[$sStimulusCode]);
|
||||
}
|
||||
}
|
||||
@@ -364,18 +336,12 @@ class LifecycleValidatorHelper
|
||||
|
||||
// We try to find the profile from its name in order to retrieve it's id
|
||||
// - If the regular UserRights add-on is installed we check the profiles array
|
||||
if (class_exists('ProfilesConfig'))
|
||||
{
|
||||
if (defined($sProfile) && in_array($sProfile, ProfilesConfig::GetProfilesValues()))
|
||||
{
|
||||
if (class_exists('ProfilesConfig')) {
|
||||
if (defined($sProfile) && in_array($sProfile, ProfilesConfig::GetProfilesValues())) {
|
||||
$iProfileId = constant($sProfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
|
||||
{
|
||||
if ($aValue['name'] === $sProfile)
|
||||
{
|
||||
} else {
|
||||
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue) {
|
||||
if ($aValue['name'] === $sProfile) {
|
||||
$iProfileId = $iKey;
|
||||
break;
|
||||
}
|
||||
@@ -383,14 +349,12 @@ class LifecycleValidatorHelper
|
||||
}
|
||||
}
|
||||
// - Else, we can't find the id from the name as we don't know the used UserRights add-on. It has to be a constant
|
||||
else
|
||||
{
|
||||
else {
|
||||
throw new Exception('Lifecycle validator : Unknown UserRights addon, lifecycle\'s profile must be a constant');
|
||||
}
|
||||
|
||||
// If profile was not found from its name or from a constant, we throw an exception
|
||||
if ($iProfileId === null)
|
||||
{
|
||||
if ($iProfileId === null) {
|
||||
throw new Exception('Lifecycle validator : Could not find "'.$sProfile.'" in the profiles list');
|
||||
}
|
||||
|
||||
@@ -404,7 +368,7 @@ class LifecycleValidatorHelper
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function BuildPHPClass($aProfiles = array())
|
||||
protected function BuildPHPClass($aProfiles = [])
|
||||
{
|
||||
$sProfiles = var_export($aProfiles, true);
|
||||
$sClassName = $this->sGeneratedClass;
|
||||
@@ -447,4 +411,3 @@ EOF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -44,50 +44,50 @@ use utils;
|
||||
class NavigationRuleHelper
|
||||
{
|
||||
// Available point of origin for the navigation
|
||||
const ENUM_ORIGIN_PAGE = 'default';
|
||||
const ENUM_ORIGIN_MODAL = 'modal';
|
||||
public const ENUM_ORIGIN_PAGE = 'default';
|
||||
public const ENUM_ORIGIN_MODAL = 'modal';
|
||||
|
||||
// Available rule categories (of rule types)
|
||||
/** @var string ENUM_RULE_CAT_CLOSE (eg. close modal/window) */
|
||||
const ENUM_RULE_CAT_CLOSE = 'close';
|
||||
public const ENUM_RULE_CAT_CLOSE = 'close';
|
||||
/** @var string ENUM_RULE_CAT_REDIRECT (eg. go-to-homepage, go-to-object, go-to-brick, ...) */
|
||||
const ENUM_RULE_CAT_REDIRECT = 'redirect';
|
||||
public const ENUM_RULE_CAT_REDIRECT = 'redirect';
|
||||
|
||||
// Available rule types
|
||||
/** @var string ENUM_RULE_CLOSE */
|
||||
const ENUM_RULE_CLOSE = 'close';
|
||||
public const ENUM_RULE_CLOSE = 'close';
|
||||
/** @var string ENUM_RULE_GO_TO_HOMEPAGE */
|
||||
const ENUM_RULE_GO_TO_HOMEPAGE = 'go-to-homepage';
|
||||
public const ENUM_RULE_GO_TO_HOMEPAGE = 'go-to-homepage';
|
||||
/** @var string ENUM_RULE_GO_TO_OBJECT */
|
||||
const ENUM_RULE_GO_TO_OBJECT = 'go-to-object';
|
||||
public const ENUM_RULE_GO_TO_OBJECT = 'go-to-object';
|
||||
/** @var string ENUM_RULE_GO_TO_BRICK */
|
||||
const ENUM_RULE_GO_TO_BRICK = 'go-to-brick';
|
||||
public const ENUM_RULE_GO_TO_BRICK = 'go-to-brick';
|
||||
/** @var string ENUM_RULE_GO_TO_MANAGE_BRICK */
|
||||
const ENUM_RULE_GO_TO_MANAGE_BRICK = 'go-to-manage-brick';
|
||||
public const ENUM_RULE_GO_TO_MANAGE_BRICK = 'go-to-manage-brick';
|
||||
/** @var string ENUM_RULE_GO_TO_BROWSE_BRICK */
|
||||
const ENUM_RULE_GO_TO_BROWSE_BRICK = 'go-to-browse-brick';
|
||||
public const ENUM_RULE_GO_TO_BROWSE_BRICK = 'go-to-browse-brick';
|
||||
// - Defaults
|
||||
/** @var string DEFAULT_RULE_SUBMIT_PAGE */
|
||||
const DEFAULT_RULE_SUBMIT_PAGE = self::ENUM_RULE_GO_TO_OBJECT;
|
||||
public const DEFAULT_RULE_SUBMIT_PAGE = self::ENUM_RULE_GO_TO_OBJECT;
|
||||
/** @var string DEFAULT_RULE_SUBMIT_MODAL */
|
||||
const DEFAULT_RULE_SUBMIT_MODAL = self::ENUM_RULE_CLOSE;
|
||||
public const DEFAULT_RULE_SUBMIT_MODAL = self::ENUM_RULE_CLOSE;
|
||||
/** @var string DEFAULT_RULE_CANCEL_PAGE */
|
||||
const DEFAULT_RULE_CANCEL_PAGE = self::ENUM_RULE_CLOSE;
|
||||
public const DEFAULT_RULE_CANCEL_PAGE = self::ENUM_RULE_CLOSE;
|
||||
/** @var string DEFAULT_RULE_CANCEL_MODAL */
|
||||
const DEFAULT_RULE_CANCEL_MODAL = self::ENUM_RULE_CLOSE;
|
||||
public const DEFAULT_RULE_CANCEL_MODAL = self::ENUM_RULE_CLOSE;
|
||||
|
||||
// Rule go-to-object properties
|
||||
/** @var string DEFAULT_RULE_GO_TO_OBJECT_PROP_MODE */
|
||||
const DEFAULT_RULE_GO_TO_OBJECT_PROP_MODE = ObjectFormHandlerHelper::ENUM_MODE_VIEW;
|
||||
public const DEFAULT_RULE_GO_TO_OBJECT_PROP_MODE = ObjectFormHandlerHelper::ENUM_MODE_VIEW;
|
||||
|
||||
/** @var string ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL */
|
||||
const ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL = 'modal';
|
||||
public const ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL = 'modal';
|
||||
/** @var string ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_PAGE */
|
||||
const ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_PAGE = 'page';
|
||||
public const ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_PAGE = 'page';
|
||||
/** @var string ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_CURRENT */
|
||||
const ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_CURRENT = 'current';
|
||||
public const ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_CURRENT = 'current';
|
||||
/** @var string DEFAULT_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET */
|
||||
const DEFAULT_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET = self::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL;
|
||||
public const DEFAULT_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET = self::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL;
|
||||
|
||||
// Rule go-to-brick properties
|
||||
// TODO
|
||||
@@ -112,9 +112,12 @@ class NavigationRuleHelper
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function __construct(
|
||||
ModuleDesign $oModuleDesign, RouterInterface $oRouter, BrickCollection $oBrickCollection, ScopeValidatorHelper $oScopeValidator
|
||||
ModuleDesign $oModuleDesign,
|
||||
RouterInterface $oRouter,
|
||||
BrickCollection $oBrickCollection,
|
||||
ScopeValidatorHelper $oScopeValidator
|
||||
) {
|
||||
$this->aRules = array();
|
||||
$this->aRules = [];
|
||||
$this->oRouter = $oRouter;
|
||||
$this->oBrickCollection = $oBrickCollection;
|
||||
|
||||
@@ -132,31 +135,29 @@ class NavigationRuleHelper
|
||||
*/
|
||||
public function Init(DOMNodeList $oNodes)
|
||||
{
|
||||
$this->aRules = array();
|
||||
$this->aRules = [];
|
||||
|
||||
// Iterating over the navigation_rule nodes
|
||||
/** @var \Combodo\iTop\DesignElement $oRuleNode */
|
||||
foreach ($oNodes as $oRuleNode)
|
||||
{
|
||||
foreach ($oNodes as $oRuleNode) {
|
||||
// Checking node name
|
||||
if ($oRuleNode->nodeName !== 'navigation_rule')
|
||||
{
|
||||
if ($oRuleNode->nodeName !== 'navigation_rule') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Retrieving mandatory attributes
|
||||
// - ID
|
||||
$sRuleId = $oRuleNode->getAttribute('id');
|
||||
if ($sRuleId === '')
|
||||
{
|
||||
if ($sRuleId === '') {
|
||||
throw new DOMFormatException('Rule tag must have an id attribute.', null, null, $oRuleNode);
|
||||
}
|
||||
// - Type
|
||||
$sRuleType = $oRuleNode->getAttribute('xsi:type');
|
||||
if (($sRuleType === '') || !in_array($sRuleType, static::GetAllowedTypes()))
|
||||
{
|
||||
throw new DOMFormatException('Navigation rule tag must have a valid xsi:type, "'.$sRuleType.'" given, expected '.implode('|',
|
||||
static::GetAllowedTypes()), null, null, $oRuleNode);
|
||||
if (($sRuleType === '') || !in_array($sRuleType, static::GetAllowedTypes())) {
|
||||
throw new DOMFormatException('Navigation rule tag must have a valid xsi:type, "'.$sRuleType.'" given, expected '.implode(
|
||||
'|',
|
||||
static::GetAllowedTypes()
|
||||
), null, null, $oRuleNode);
|
||||
}
|
||||
|
||||
// Load rule from XML
|
||||
@@ -176,10 +177,10 @@ class NavigationRuleHelper
|
||||
*/
|
||||
public static function GetAllowedOrigins()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
static::ENUM_ORIGIN_PAGE,
|
||||
static::ENUM_ORIGIN_MODAL,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,14 +190,14 @@ class NavigationRuleHelper
|
||||
*/
|
||||
public static function GetAllowedTypes()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
static::ENUM_RULE_CLOSE,
|
||||
static::ENUM_RULE_GO_TO_HOMEPAGE,
|
||||
static::ENUM_RULE_GO_TO_OBJECT,
|
||||
static::ENUM_RULE_GO_TO_BRICK,
|
||||
static::ENUM_RULE_GO_TO_BROWSE_BRICK,
|
||||
static::ENUM_RULE_GO_TO_MANAGE_BRICK,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,8 +210,7 @@ class NavigationRuleHelper
|
||||
*/
|
||||
public function GetRuleDefinition($sId)
|
||||
{
|
||||
if (!array_key_exists($sId, $this->aRules))
|
||||
{
|
||||
if (!array_key_exists($sId, $this->aRules)) {
|
||||
throw new Exception('NavigationRuleHelper: Could not find "'.$sId.'" in the rules list');
|
||||
}
|
||||
|
||||
@@ -251,10 +251,10 @@ class NavigationRuleHelper
|
||||
*/
|
||||
public function GetDefaultCloseRuleDefinition()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
'category' => static::ENUM_RULE_CAT_CLOSE,
|
||||
'type' => static::ENUM_RULE_CLOSE,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,10 +264,10 @@ class NavigationRuleHelper
|
||||
*/
|
||||
public function GetDefaultGoToHomepageRuleDefinition()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
'category' => static::ENUM_RULE_CAT_REDIRECT,
|
||||
'type' => static::ENUM_RULE_GO_TO_HOMEPAGE,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,15 +277,15 @@ class NavigationRuleHelper
|
||||
*/
|
||||
public function GetDefaultGoToObjectRuleDefinition()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
'category' => static::ENUM_RULE_CAT_REDIRECT,
|
||||
'type' => static::ENUM_RULE_GO_TO_OBJECT,
|
||||
'properties' => array(
|
||||
'properties' => [
|
||||
'mode' => static::DEFAULT_RULE_GO_TO_OBJECT_PROP_MODE,
|
||||
'opening_target' => static::DEFAULT_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET,
|
||||
'oql' => null,
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,16 +295,16 @@ class NavigationRuleHelper
|
||||
*/
|
||||
public function GetDefaultGoToBrickRuleDefinition()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
'category' => static::ENUM_RULE_CAT_REDIRECT,
|
||||
'type' => static::ENUM_RULE_GO_TO_BRICK,
|
||||
'properties' => array(
|
||||
'route' => array(
|
||||
'properties' => [
|
||||
'route' => [
|
||||
'id' => null,
|
||||
'params' => array(),
|
||||
),
|
||||
),
|
||||
);
|
||||
'params' => [],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
//----------------------------
|
||||
@@ -351,21 +351,18 @@ class NavigationRuleHelper
|
||||
// Default values
|
||||
$aRule = $this->GetDefaultGoToObjectRuleDefinition();
|
||||
|
||||
$aAllowedOpeningTarget = array(
|
||||
$aAllowedOpeningTarget = [
|
||||
static::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_CURRENT,
|
||||
static::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL,
|
||||
static::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_PAGE,
|
||||
);
|
||||
];
|
||||
|
||||
/** @var \Combodo\iTop\DesignElement $oPropNode */
|
||||
foreach($oRuleNode->GetNodes('*') as $oPropNode)
|
||||
{
|
||||
switch($oPropNode->nodeName)
|
||||
{
|
||||
foreach ($oRuleNode->GetNodes('*') as $oPropNode) {
|
||||
switch ($oPropNode->nodeName) {
|
||||
case 'mode':
|
||||
$sMode = $oPropNode->GetText();
|
||||
if(!in_array($sMode, ObjectFormHandlerHelper::GetAllowedModes()))
|
||||
{
|
||||
if (!in_array($sMode, ObjectFormHandlerHelper::GetAllowedModes())) {
|
||||
throw new DOMFormatException('mode tag of navigation_rule "'.$sRuleId.'" must be valid. Expected '.implode('|', ObjectFormHandlerHelper::GetAllowedModes()).', "'.$sMode.'" given.', null, null, $oRuleNode);
|
||||
}
|
||||
$aRule['properties']['mode'] = $sMode;
|
||||
@@ -373,8 +370,7 @@ class NavigationRuleHelper
|
||||
|
||||
case 'opening_target':
|
||||
$sOpeningTarget = $oPropNode->GetText();
|
||||
if(!in_array($sOpeningTarget, $aAllowedOpeningTarget))
|
||||
{
|
||||
if (!in_array($sOpeningTarget, $aAllowedOpeningTarget)) {
|
||||
throw new DOMFormatException('opening_target tag of navigation_rule "'.$sRuleId.'" must be valid. Expected '.implode('|', $aAllowedOpeningTarget).', "'.$sOpeningTarget.'" given.', null, null, $oRuleNode);
|
||||
}
|
||||
$aRule['properties']['opening_target'] = $sOpeningTarget;
|
||||
@@ -382,8 +378,7 @@ class NavigationRuleHelper
|
||||
|
||||
case 'oql':
|
||||
$sOQL = $oPropNode->GetText();
|
||||
if(empty($sOQL))
|
||||
{
|
||||
if (empty($sOQL)) {
|
||||
throw new DOMFormatException('oql tag of navigation_rule "'.$sRuleId.'" can not be empty.');
|
||||
}
|
||||
$aRule['properties']['oql'] = $sOQL;
|
||||
@@ -409,30 +404,24 @@ class NavigationRuleHelper
|
||||
$aRule = $this->GetDefaultGoToBrickRuleDefinition();
|
||||
|
||||
/** @var \Combodo\iTop\DesignElement $oPropNode */
|
||||
foreach($oRuleNode->GetNodes('*') as $oPropNode)
|
||||
{
|
||||
switch($oPropNode->nodeName)
|
||||
{
|
||||
foreach ($oRuleNode->GetNodes('*') as $oPropNode) {
|
||||
switch ($oPropNode->nodeName) {
|
||||
case 'route':
|
||||
/** @var array $aRouteProperties Route ID and parameters */
|
||||
$aRouteProperties = array();
|
||||
$aRouteProperties = [];
|
||||
/** @var DesignElement $oRoutePropNode */
|
||||
foreach($oPropNode->GetNodes('*') as $oRoutePropNode)
|
||||
{
|
||||
switch($oRoutePropNode->nodeName)
|
||||
{
|
||||
foreach ($oPropNode->GetNodes('*') as $oRoutePropNode) {
|
||||
switch ($oRoutePropNode->nodeName) {
|
||||
case 'id':
|
||||
$aRouteProperties['id'] = $oRoutePropNode->GetText();
|
||||
break;
|
||||
|
||||
case 'params':
|
||||
/** @var DesignElement $oRouteParamNode */
|
||||
foreach($oRoutePropNode->GetNodes('*') as $oRouteParamNode)
|
||||
{
|
||||
foreach ($oRoutePropNode->GetNodes('*') as $oRouteParamNode) {
|
||||
$sRouteParamId = $oRouteParamNode->getAttribute('id');
|
||||
$sRouteParamValue = $oRouteParamNode->GetText();
|
||||
if(empty($sRouteParamId) || empty($sRouteParamValue))
|
||||
{
|
||||
if (empty($sRouteParamId) || empty($sRouteParamValue)) {
|
||||
throw new DOMFormatException('param tag of navigation_rule "'.$sRuleId.'" must have a valid ID and value.', null, null, $oRuleNode);
|
||||
}
|
||||
|
||||
@@ -443,8 +432,7 @@ class NavigationRuleHelper
|
||||
}
|
||||
|
||||
// Consistency check
|
||||
if(empty($aRouteProperties['id']))
|
||||
{
|
||||
if (empty($aRouteProperties['id'])) {
|
||||
throw new DOMFormatException('navigation_rule "'.$sRuleId.'" must have a valid ID', null, null, $oRuleNode);
|
||||
}
|
||||
|
||||
@@ -474,16 +462,15 @@ class NavigationRuleHelper
|
||||
$aRule['properties']['route']['params']['sDisplayMode'] = ManageBrick::DEFAULT_DISPLAY_MODE;
|
||||
|
||||
// Rule parameters to automatically map to the route parameters
|
||||
$aParamsMapping = array(
|
||||
$aParamsMapping = [
|
||||
'id' => 'sBrickId',
|
||||
'display_mode' => 'sDisplayMode',
|
||||
'grouping_tab' => 'sGroupingTab',
|
||||
'filter' => 'sSearchValue',
|
||||
);
|
||||
];
|
||||
|
||||
/** @var \Combodo\iTop\DesignElement $oPropNode */
|
||||
foreach($oRuleNode->GetNodes('*') as $oPropNode)
|
||||
{
|
||||
foreach ($oRuleNode->GetNodes('*') as $oPropNode) {
|
||||
$sRouteParamId = (array_key_exists($oPropNode->nodeName, $aParamsMapping)) ? $aParamsMapping[$oPropNode->nodeName] : $oPropNode->nodeName;
|
||||
$aRule['properties']['route']['params'][$sRouteParamId] = $oPropNode->GetText();
|
||||
}
|
||||
@@ -509,15 +496,14 @@ class NavigationRuleHelper
|
||||
$aRule['properties']['route']['params']['sBrowseMode'] = BrowseBrick::DEFAULT_BROWSE_MODE;
|
||||
|
||||
// Rule parameters to automatically map to the route parameters
|
||||
$aParamsMapping = array(
|
||||
$aParamsMapping = [
|
||||
'id' => 'sBrickId',
|
||||
'browse_mode' => 'sBrowseMode',
|
||||
'filter' => 'sSearchValue',
|
||||
);
|
||||
];
|
||||
|
||||
/** @var \Combodo\iTop\DesignElement $oPropNode */
|
||||
foreach($oRuleNode->GetNodes('*') as $oPropNode)
|
||||
{
|
||||
foreach ($oRuleNode->GetNodes('*') as $oPropNode) {
|
||||
$sRouteParamId = (array_key_exists($oPropNode->nodeName, $aParamsMapping)) ? $aParamsMapping[$oPropNode->nodeName] : $oPropNode->nodeName;
|
||||
$aRule['properties']['route']['params'][$sRouteParamId] = $oPropNode->GetText();
|
||||
}
|
||||
@@ -555,33 +541,30 @@ class NavigationRuleHelper
|
||||
public function PrepareRulesForForm(array $aFormProperties, DBObject $oCurrentObject, $bIsCurrentFormInModal = false)
|
||||
{
|
||||
// Default values
|
||||
$aResults = array(
|
||||
'submit' => array(
|
||||
$aResults = [
|
||||
'submit' => [
|
||||
'category' => static::ENUM_RULE_CAT_REDIRECT,
|
||||
'url' => null,
|
||||
'modal' => false,
|
||||
),
|
||||
'cancel' => array(
|
||||
],
|
||||
'cancel' => [
|
||||
'category' => static::ENUM_RULE_CAT_CLOSE,
|
||||
'url' => null,
|
||||
'modal' => false,
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
|
||||
// Get form's navigation rules
|
||||
$aFormNavRules = (isset($aFormProperties['properties']['navigation_rules'])) ? $aFormProperties['properties']['navigation_rules'] : array('submit' => null, 'cancel' => null);
|
||||
$aFormNavRules = (isset($aFormProperties['properties']['navigation_rules'])) ? $aFormProperties['properties']['navigation_rules'] : ['submit' => null, 'cancel' => null];
|
||||
|
||||
// Check from which origin the rule will be called
|
||||
$sRuleCallOrigin = ($bIsCurrentFormInModal) ? 'modal' : 'default';
|
||||
|
||||
foreach(array_keys($aResults) as $sButtonCode)
|
||||
{
|
||||
foreach (array_keys($aResults) as $sButtonCode) {
|
||||
// Retrieve rule definition
|
||||
// - Default behavior when no rule specified
|
||||
if(empty($aFormNavRules[$sButtonCode][$sRuleCallOrigin]))
|
||||
{
|
||||
switch($sButtonCode)
|
||||
{
|
||||
if (empty($aFormNavRules[$sButtonCode][$sRuleCallOrigin])) {
|
||||
switch ($sButtonCode) {
|
||||
case 'submit':
|
||||
$sDefaultRuleType = ($bIsCurrentFormInModal) ? static::DEFAULT_RULE_SUBMIT_MODAL : static::DEFAULT_RULE_SUBMIT_PAGE;
|
||||
break;
|
||||
@@ -593,8 +576,7 @@ class NavigationRuleHelper
|
||||
$aRuleDef = $this->GetDefaultRuleDefinitionFromType($sDefaultRuleType);
|
||||
}
|
||||
// - Specified rule
|
||||
else
|
||||
{
|
||||
else {
|
||||
$sRuleId = $aFormNavRules[$sButtonCode][$sRuleCallOrigin];
|
||||
$aRuleDef = $this->GetRuleDefinition($sRuleId);
|
||||
}
|
||||
@@ -603,36 +585,31 @@ class NavigationRuleHelper
|
||||
$aResults[$sButtonCode]['category'] = $aRuleDef['category'];
|
||||
|
||||
// Set properties regarding the type
|
||||
switch($aRuleDef['type'])
|
||||
{
|
||||
switch ($aRuleDef['type']) {
|
||||
case static::ENUM_RULE_GO_TO_HOMEPAGE:
|
||||
$aResults[$sButtonCode]['url'] = $this->oRouter->generate('p_home');
|
||||
break;
|
||||
|
||||
case static::ENUM_RULE_GO_TO_OBJECT:
|
||||
// Target opening mode to modal if specified or should be as current form
|
||||
if( ($aRuleDef['properties']['opening_target'] === static::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL)
|
||||
if (($aRuleDef['properties']['opening_target'] === static::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL)
|
||||
|| (($aRuleDef['properties']['opening_target'] === static::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_CURRENT) && ($bIsCurrentFormInModal === true))
|
||||
)
|
||||
{
|
||||
) {
|
||||
$aResults[$sButtonCode]['modal'] = true;
|
||||
}
|
||||
|
||||
// Target URL
|
||||
// - Find object
|
||||
if(empty($aRuleDef['properties']['oql']))
|
||||
{
|
||||
if (empty($aRuleDef['properties']['oql'])) {
|
||||
$oTargetObject = $oCurrentObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oSearch = DBSearch::FromOQL($aRuleDef['properties']['oql']);
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('this' => $oCurrentObject));
|
||||
$oSet->OptimizeColumnLoad(array($oSearch->GetClassAlias() => array()));
|
||||
$oSet = new DBObjectSet($oSearch, [], ['this' => $oCurrentObject]);
|
||||
$oSet->OptimizeColumnLoad([$oSearch->GetClassAlias() => []]);
|
||||
$oTargetObject = $oSet->Fetch();
|
||||
}
|
||||
// - Build URL
|
||||
$aResults[$sButtonCode]['url'] = $this->oRouter->generate('p_object_'.$aRuleDef['properties']['mode'], array('sObjectClass' => get_class($oTargetObject), 'sObjectId' => $oTargetObject->GetKey()));
|
||||
$aResults[$sButtonCode]['url'] = $this->oRouter->generate('p_object_'.$aRuleDef['properties']['mode'], ['sObjectClass' => get_class($oTargetObject), 'sObjectId' => $oTargetObject->GetKey()]);
|
||||
break;
|
||||
|
||||
case static::ENUM_RULE_GO_TO_BRICK:
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Portal\Helper;
|
||||
|
||||
use ApplicationContext;
|
||||
@@ -51,16 +50,16 @@ use UserRights;
|
||||
class ObjectFormHandlerHelper
|
||||
{
|
||||
/** @var string */
|
||||
const ENUM_MODE_VIEW = 'view';
|
||||
public const ENUM_MODE_VIEW = 'view';
|
||||
/** @var string */
|
||||
const ENUM_MODE_EDIT = 'edit';
|
||||
public const ENUM_MODE_EDIT = 'edit';
|
||||
/** @var string */
|
||||
const ENUM_MODE_CREATE = 'create';
|
||||
public const ENUM_MODE_CREATE = 'create';
|
||||
/**
|
||||
* @var string
|
||||
* @since 2.7.7 3.0.1 3.1.0
|
||||
*/
|
||||
const ENUM_MODE_APPLY_STIMULUS = 'apply_stimulus';
|
||||
public const ENUM_MODE_APPLY_STIMULUS = 'apply_stimulus';
|
||||
|
||||
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
|
||||
private $oRequestManipulator;
|
||||
@@ -95,10 +94,16 @@ class ObjectFormHandlerHelper
|
||||
* @param \Combodo\iTop\Portal\Twig\AppExtension $oAppExtension
|
||||
*/
|
||||
public function __construct(
|
||||
RequestManipulatorHelper $oRequestManipulator, ContextManipulatorHelper $oContextManipulator, NavigationRuleHelper $oNavigationRuleHelper, ScopeValidatorHelper $oScopeValidator, SecurityHelper $oSecurityHelper, UrlGeneratorInterface $oUrlGenerator, $aCombodoPortalInstanceConf, $sPortalId,
|
||||
RequestManipulatorHelper $oRequestManipulator,
|
||||
ContextManipulatorHelper $oContextManipulator,
|
||||
NavigationRuleHelper $oNavigationRuleHelper,
|
||||
ScopeValidatorHelper $oScopeValidator,
|
||||
SecurityHelper $oSecurityHelper,
|
||||
UrlGeneratorInterface $oUrlGenerator,
|
||||
$aCombodoPortalInstanceConf,
|
||||
$sPortalId,
|
||||
AppExtension $oAppExtension
|
||||
)
|
||||
{
|
||||
) {
|
||||
$this->oRequestManipulator = $oRequestManipulator;
|
||||
$this->oContextManipulator = $oContextManipulator;
|
||||
$this->oNavigationRuleHelper = $oNavigationRuleHelper;
|
||||
@@ -126,7 +131,7 @@ class ObjectFormHandlerHelper
|
||||
*/
|
||||
public function HandleForm(Request $oRequest, $sMode, $sObjectClass, $sObjectId = null, array $aFormProperties = null)
|
||||
{
|
||||
$aFormData = array();
|
||||
$aFormData = [];
|
||||
$sOperation = $this->oRequestManipulator->ReadParam('operation', '');
|
||||
$bModal = ($oRequest->isXmlHttpRequest() && empty($sOperation));
|
||||
|
||||
@@ -134,71 +139,58 @@ class ObjectFormHandlerHelper
|
||||
$aFormProperties = $aFormProperties ?? ApplicationHelper::GetLoadedFormFromClass($this->aCombodoPortalInstanceConf['forms'], $sObjectClass, $sMode);
|
||||
|
||||
// - Create and
|
||||
if (empty($sOperation))
|
||||
{
|
||||
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();
|
||||
$aActionRules = (!empty($sActionRulesToken)) ? ContextManipulatorHelper::DecodeRulesToken($sActionRulesToken) : [];
|
||||
|
||||
// Preparing object
|
||||
if ($sObjectId === null)
|
||||
{
|
||||
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(
|
||||
$aPrefillFormParam = [
|
||||
'user' => UserRights::GetUser(),
|
||||
'origin' => 'portal',
|
||||
);
|
||||
];
|
||||
$oObject->PrefillForm('creation_from_0', $aPrefillFormParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
} 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(
|
||||
$aFormData['buttons'] = [
|
||||
'transitions' => [],
|
||||
'actions' => [],
|
||||
'links' => [],
|
||||
'submit' => [
|
||||
'label' => Dict::S('Portal:Button:Submit'),
|
||||
),
|
||||
);
|
||||
if ($sMode !== static::ENUM_MODE_APPLY_STIMULUS)
|
||||
{
|
||||
],
|
||||
];
|
||||
if ($sMode !== static::ENUM_MODE_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))
|
||||
{
|
||||
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)
|
||||
{
|
||||
foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance) {
|
||||
foreach ($oExtensionInstance->EnumItems(iPopupMenuExtension::PORTAL_OBJDETAILS_ACTIONS, ['portal_id' => $this->sPortalId, 'object' => $oObject, 'mode' => $sMode]) as $oMenuItem) {
|
||||
if (is_object($oMenuItem)) {
|
||||
if ($oMenuItem instanceof JSButtonItem) {
|
||||
$aFormData['buttons']['actions'][] = $oMenuItem->GetMenuItem() + ['js_files' => $oMenuItem->GetLinkedScripts()];
|
||||
} elseif ($oMenuItem instanceof URLButtonItem) {
|
||||
$aFormData['buttons']['links'][] = $oMenuItem->GetMenuItem();
|
||||
}
|
||||
}
|
||||
@@ -206,22 +198,17 @@ class ObjectFormHandlerHelper
|
||||
}
|
||||
|
||||
// Hiding submit button or changing its label if necessary
|
||||
if (!empty($aFormData['buttons']['transitions']) && isset($aFormProperties['properties']) && $aFormProperties['properties']['always_show_submit'] === false)
|
||||
{
|
||||
if (!empty($aFormData['buttons']['transitions']) && isset($aFormProperties['properties']) && $aFormProperties['properties']['always_show_submit'] === false) {
|
||||
unset($aFormData['buttons']['submit']);
|
||||
}
|
||||
elseif ($sMode === static::ENUM_MODE_EDIT)
|
||||
{
|
||||
} elseif ($sMode === static::ENUM_MODE_EDIT) {
|
||||
$aFormData['buttons']['submit']['label'] = Dict::S('Portal:Button:Apply');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aPrefillFormParam = array(
|
||||
} else {
|
||||
$aPrefillFormParam = [
|
||||
'user' => UserRights::GetUser(),
|
||||
'origin' => 'portal',
|
||||
'stimulus' => $this->oRequestManipulator->ReadParam('apply_stimulus', null, FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY)['code'],
|
||||
);
|
||||
];
|
||||
$oObject->PrefillForm('state_change', $aPrefillFormParam);
|
||||
}
|
||||
|
||||
@@ -235,32 +222,31 @@ class ObjectFormHandlerHelper
|
||||
|
||||
// Preparing renderer
|
||||
// Note : We might need to distinguish form & renderer endpoints
|
||||
switch($sMode)
|
||||
{
|
||||
switch ($sMode) {
|
||||
case static::ENUM_MODE_CREATE:
|
||||
case static::ENUM_MODE_EDIT:
|
||||
case static::ENUM_MODE_VIEW:
|
||||
if(array_key_exists('submit_endpoint', $aFormProperties)) {
|
||||
$sFormEndpoint = $aFormProperties['submit_endpoint'];
|
||||
} else {
|
||||
$sFormEndpoint = $this->oUrlGenerator->generate(
|
||||
'p_object_' . $sMode,
|
||||
array(
|
||||
'sObjectClass' => $sObjectClass,
|
||||
'sObjectId' => $sObjectId,
|
||||
)
|
||||
);
|
||||
}
|
||||
if (array_key_exists('submit_endpoint', $aFormProperties)) {
|
||||
$sFormEndpoint = $aFormProperties['submit_endpoint'];
|
||||
} else {
|
||||
$sFormEndpoint = $this->oUrlGenerator->generate(
|
||||
'p_object_'.$sMode,
|
||||
[
|
||||
'sObjectClass' => $sObjectClass,
|
||||
'sObjectId' => $sObjectId,
|
||||
]
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case static::ENUM_MODE_APPLY_STIMULUS:
|
||||
$sFormEndpoint = $this->oUrlGenerator->generate(
|
||||
'p_object_apply_stimulus',
|
||||
array(
|
||||
[
|
||||
'sObjectClass' => $sObjectClass,
|
||||
'sObjectId' => $sObjectId,
|
||||
'sStimulusCode' => $this->oRequestManipulator->ReadParam('sStimulusCode'),
|
||||
)
|
||||
]
|
||||
);
|
||||
break;
|
||||
|
||||
@@ -294,8 +280,7 @@ class ObjectFormHandlerHelper
|
||||
/** @var \Combodo\iTop\Portal\Form\ObjectFormManager $sFormManagerClass */
|
||||
$sFormManagerClass = $this->oRequestManipulator->ReadParam('formmanager_class', '', FILTER_UNSAFE_RAW);
|
||||
$sFormManagerData = $this->oRequestManipulator->ReadParam('formmanager_data', '', FILTER_UNSAFE_RAW);
|
||||
if (empty($sFormManagerClass) || empty($sFormManagerData))
|
||||
{
|
||||
if (empty($sFormManagerClass) || empty($sFormManagerData)) {
|
||||
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : 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.');
|
||||
}
|
||||
@@ -312,48 +297,45 @@ class ObjectFormHandlerHelper
|
||||
$oFormManager->SetObject($oObj);
|
||||
}
|
||||
|
||||
switch ($sOperation)
|
||||
{
|
||||
switch ($sOperation) {
|
||||
case 'submit':
|
||||
// Applying modification to object
|
||||
$aFormData['validation'] = $oFormManager->OnSubmit(
|
||||
array(
|
||||
'currentValues' => $this->oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
|
||||
'attachmentIds' => $this->oRequestManipulator->ReadParam('attachment_ids', array(), FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
|
||||
[
|
||||
'currentValues' => $this->oRequestManipulator->ReadParam('current_values', [], FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
|
||||
'attachmentIds' => $this->oRequestManipulator->ReadParam('attachment_ids', [], FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
|
||||
'formProperties' => $aFormProperties,
|
||||
'applyStimulus' => $this->oRequestManipulator->ReadParam('apply_stimulus', null, FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
|
||||
)
|
||||
]
|
||||
);
|
||||
if ($aFormData['validation']['valid'] === true)
|
||||
{
|
||||
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 serialized
|
||||
// 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)),
|
||||
if (!empty($sStimulusCode)) {
|
||||
$aFormData['validation']['redirection'] = [
|
||||
'url' => $this->oUrlGenerator->generate('p_object_apply_stimulus', ['sObjectClass' => $sObjectClass, 'sObjectId' => $oFormManager->GetObject()->GetKey(), 'sStimulusCode' => $sStimulusCode]),
|
||||
'modal' => true,
|
||||
);
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$sErrorMessages = '';
|
||||
foreach ($aFormData['validation']['messages']['error'] as $sFieldId => $aMessages) {
|
||||
if ($sFieldId == '_main') {
|
||||
$sErrorMessages .= implode(' - ', $aFormData['validation']['messages']['error']['_main']);
|
||||
} else {
|
||||
$oObj = $oFormManager->GetObject();
|
||||
$sLabel = $oObj->GetLabel($sFieldId);
|
||||
$sErrorMessages .= Dict::Format('Portal:Error:CheckToWriteFailed', $sLabel, (is_array($aMessages) ? implode(' - ', $aMessages) : $aMessages));
|
||||
}
|
||||
}
|
||||
$sErrorMessages = '';
|
||||
foreach ($aFormData['validation']['messages']['error'] as $sFieldId => $aMessages) {
|
||||
if ($sFieldId == '_main') {
|
||||
$sErrorMessages .= implode(' - ', $aFormData['validation']['messages']['error']['_main']);
|
||||
} else {
|
||||
$oObj = $oFormManager->GetObject();
|
||||
$sLabel = $oObj->GetLabel($sFieldId);
|
||||
$sErrorMessages .= Dict::Format('Portal:Error:CheckToWriteFailed', $sLabel, (is_array($aMessages) ? implode(' - ', $aMessages) : $aMessages));
|
||||
}
|
||||
}
|
||||
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, $sErrorMessages);
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, $sErrorMessages);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
$oFormManager->OnUpdate(array('currentValues' => $this->oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY), 'formProperties' => $aFormProperties));
|
||||
$oFormManager->OnUpdate(['currentValues' => $this->oRequestManipulator->ReadParam('current_values', [], FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY), 'formProperties' => $aFormProperties]);
|
||||
break;
|
||||
|
||||
case 'cancel':
|
||||
@@ -363,33 +345,27 @@ class ObjectFormHandlerHelper
|
||||
}
|
||||
|
||||
// Preparing field_set data
|
||||
$aFieldSetData = array(
|
||||
$aFieldSetData = [
|
||||
//'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, FILTER_REQUIRE_ARRAY);
|
||||
if ($sOperation === 'update') {
|
||||
$aRequestedFields = $this->oRequestManipulator->ReadParam('requested_fields', [], FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY);
|
||||
$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())
|
||||
{
|
||||
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
|
||||
{
|
||||
} else {
|
||||
$aFormData['updated_fields'] = $oFormManager->GetRenderer()->Render($aRequestedFields);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$aFieldSetData['fields_list'] = $oFormManager->GetRenderer()->Render();
|
||||
}
|
||||
|
||||
@@ -407,8 +383,7 @@ class ObjectFormHandlerHelper
|
||||
$aFormData['display_mode'] = (isset($aFormProperties['properties'])) ? $aFormProperties['properties']['display_mode'] : ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE;
|
||||
$aFormData['hidden_fields'] = $oFormManager->GetHiddenFieldsId();
|
||||
// - Set a text to be copied on title if the object is not in creation
|
||||
if($sMode !== static::ENUM_MODE_CREATE && !empty($sObjectId))
|
||||
{
|
||||
if ($sMode !== static::ENUM_MODE_CREATE && !empty($sObjectId)) {
|
||||
$aFormData['title_clipboard_text'] = Dict::Format(
|
||||
'Brick:Portal:Object:Copy:TextToCopy',
|
||||
$aFormData['object_name'],
|
||||
@@ -435,17 +410,15 @@ class ObjectFormHandlerHelper
|
||||
public function RenderFormFromTwig($sId, $sTwigString, $aData)
|
||||
{
|
||||
// Creating sandbox twig env. to load and test the custom form template
|
||||
$oTwig = new Environment(new ArrayLoader(array($sId => $sTwigString)));
|
||||
$oTwig = new Environment(new ArrayLoader([$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)
|
||||
{
|
||||
foreach ($aFilters as $oFilter) {
|
||||
$oTwig->addFilter($oFilter);
|
||||
}
|
||||
$aFunctions = $this->oAppExtension->getFunctions();
|
||||
foreach ($aFunctions as $oFunction)
|
||||
{
|
||||
foreach ($aFunctions as $oFunction) {
|
||||
$oTwig->addFunction($oFunction);
|
||||
}
|
||||
|
||||
@@ -469,9 +442,9 @@ class ObjectFormHandlerHelper
|
||||
public function CheckReadFormDataAllowed($sFormManagerData)
|
||||
{
|
||||
$aJsonFromData = ObjectFormManager::DecodeFormManagerData($sFormManagerData);
|
||||
if(isset($aJsonFromData['formobject_class'])
|
||||
if (isset($aJsonFromData['formobject_class'])
|
||||
&& isset($aJsonFromData['formobject_id'])
|
||||
&& !$this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $aJsonFromData['formobject_class'], $aJsonFromData['formobject_id'])){
|
||||
&& !$this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $aJsonFromData['formobject_class'], $aJsonFromData['formobject_id'])) {
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Form data access denied.');
|
||||
}
|
||||
}
|
||||
@@ -484,11 +457,11 @@ class ObjectFormHandlerHelper
|
||||
*/
|
||||
public static function GetAllowedModes()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
static::ENUM_MODE_VIEW,
|
||||
static::ENUM_MODE_EDIT,
|
||||
static::ENUM_MODE_CREATE,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -530,4 +503,4 @@ class ObjectFormHandlerHelper
|
||||
{
|
||||
return $this->aCombodoPortalInstanceConf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,18 +63,15 @@ class RequestManipulatorHelper
|
||||
*/
|
||||
public function HasParam($sKey)
|
||||
{
|
||||
if ($this->GetCurrentRequest()->query->has($sKey))
|
||||
{
|
||||
if ($this->GetCurrentRequest()->query->has($sKey)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->GetCurrentRequest()->attributes->has($sKey))
|
||||
{
|
||||
if ($this->GetCurrentRequest()->attributes->has($sKey)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->GetCurrentRequest()->request->has($sKey))
|
||||
{
|
||||
if ($this->GetCurrentRequest()->request->has($sKey)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -90,7 +87,7 @@ class RequestManipulatorHelper
|
||||
* @param string $sKey
|
||||
* @param mixed $default
|
||||
* @param int $iFilter Default is FILTER_SANITIZE_SPECIAL_CHARS
|
||||
* @param int $aFilterOptions @since 3.2.0 - N°6934 - Symfony 6.4 - upgrade Symfony bundles to 6.4
|
||||
* @param int $aFilterOptions @since 3.2.0 - N°6934 - Symfony 6.4 - upgrade Symfony bundles to 6.4
|
||||
*
|
||||
* @return mixed|null
|
||||
*
|
||||
@@ -98,18 +95,15 @@ class RequestManipulatorHelper
|
||||
*/
|
||||
public function ReadParam($sKey, $default = null, $iFilter = FILTER_SANITIZE_SPECIAL_CHARS, $aFilterOptions = [])
|
||||
{
|
||||
if ($this->GetCurrentRequest()->query->has($sKey))
|
||||
{
|
||||
if ($this->GetCurrentRequest()->query->has($sKey)) {
|
||||
return $this->GetCurrentRequest()->query->filter($sKey, $default, $iFilter, $aFilterOptions);
|
||||
}
|
||||
|
||||
if ($this->GetCurrentRequest()->attributes->has($sKey))
|
||||
{
|
||||
if ($this->GetCurrentRequest()->attributes->has($sKey)) {
|
||||
return $this->GetCurrentRequest()->attributes->filter($sKey, $default, $iFilter, $aFilterOptions);
|
||||
}
|
||||
|
||||
if ($this->GetCurrentRequest()->request->has($sKey))
|
||||
{
|
||||
if ($this->GetCurrentRequest()->request->has($sKey)) {
|
||||
return $this->GetCurrentRequest()->request->filter($sKey, $default, $iFilter, $aFilterOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,18 +41,18 @@ use utils;
|
||||
class ScopeValidatorHelper
|
||||
{
|
||||
/** @var string ENUM_MODE_READ */
|
||||
const ENUM_MODE_READ = 'r';
|
||||
public const ENUM_MODE_READ = 'r';
|
||||
/** @var string ENUM_MODE_WRITE */
|
||||
const ENUM_MODE_WRITE = 'w';
|
||||
public const ENUM_MODE_WRITE = 'w';
|
||||
/** @var string ENUM_TYPE_ALLOW */
|
||||
const ENUM_TYPE_ALLOW = 'allow';
|
||||
public const ENUM_TYPE_ALLOW = 'allow';
|
||||
/** @var string ENUM_TYPE_RESTRICT */
|
||||
const ENUM_TYPE_RESTRICT = 'restrict';
|
||||
public const ENUM_TYPE_RESTRICT = 'restrict';
|
||||
|
||||
/** @var string DEFAULT_GENERATED_CLASS */
|
||||
const DEFAULT_GENERATED_CLASS = '\\PortalScopesValues';
|
||||
public const DEFAULT_GENERATED_CLASS = '\\PortalScopesValues';
|
||||
/** @var bool DEFAULT_IGNORE_SILOS */
|
||||
const DEFAULT_IGNORE_SILOS = false;
|
||||
public const DEFAULT_IGNORE_SILOS = false;
|
||||
|
||||
/** @var string|null $sCachePath */
|
||||
protected $sCachePath;
|
||||
@@ -80,7 +80,7 @@ class ScopeValidatorHelper
|
||||
$this->sCachePath = $sPortalCachePath;
|
||||
$this->sInstancePrefix = "{$sPortalId}-";
|
||||
$this->sGeneratedClass = static::DEFAULT_GENERATED_CLASS;
|
||||
$this->aProfilesMatrix = array();
|
||||
$this->aProfilesMatrix = [];
|
||||
|
||||
$this->Init($moduleDesign->GetNodes('/module_design/classes/class'));
|
||||
}
|
||||
@@ -96,8 +96,7 @@ class ScopeValidatorHelper
|
||||
public function Init(DOMNodeList $oNodes)
|
||||
{
|
||||
// Checking cache path
|
||||
if ($this->sCachePath === null)
|
||||
{
|
||||
if ($this->sCachePath === null) {
|
||||
$this->sCachePath = utils::GetCachePath();
|
||||
}
|
||||
// Building full pathname for file
|
||||
@@ -105,20 +104,18 @@ class ScopeValidatorHelper
|
||||
|
||||
// Creating file if not existing
|
||||
// Note : This is a temporary cache system, it should soon evolve to a cache provider (fs, apc, memcache, ...)
|
||||
if (!file_exists($sFilePath))
|
||||
{
|
||||
if (!file_exists($sFilePath)) {
|
||||
$this->InitGenerateAndWriteCache($oNodes, $sFilePath);
|
||||
}
|
||||
|
||||
if (!class_exists($this->sGeneratedClass))
|
||||
{
|
||||
if (!class_exists($this->sGeneratedClass)) {
|
||||
require_once $this->sCachePath.$this->sFilename;
|
||||
}
|
||||
}
|
||||
|
||||
public static function EnumTypeValues()
|
||||
{
|
||||
return array(static::ENUM_TYPE_ALLOW, static::ENUM_TYPE_RESTRICT);
|
||||
return [static::ENUM_TYPE_ALLOW, static::ENUM_TYPE_RESTRICT];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,7 +194,7 @@ class ScopeValidatorHelper
|
||||
*/
|
||||
public function GetScopeFilterForProfile($sProfile, $sClass, $iAction = null)
|
||||
{
|
||||
return $this->GetScopeFilterForProfiles(array($sProfile), $sClass, $iAction);
|
||||
return $this->GetScopeFilterForProfiles([$sProfile], $sClass, $iAction);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,19 +214,17 @@ class ScopeValidatorHelper
|
||||
public function GetScopeFilterForProfiles($aProfiles, $sClass, $iAction = null)
|
||||
{
|
||||
$oSearch = null;
|
||||
$aAllowSearches = array();
|
||||
$aRestrictSearches = array();
|
||||
$aAllowSearches = [];
|
||||
$aRestrictSearches = [];
|
||||
$bIgnoreSilos = static::DEFAULT_IGNORE_SILOS;
|
||||
|
||||
// Checking the default mode
|
||||
if ($iAction === null)
|
||||
{
|
||||
if ($iAction === null) {
|
||||
$iAction = UR_ACTION_READ;
|
||||
}
|
||||
|
||||
// Iterating on profiles to retrieving the different OQLs parts
|
||||
foreach ($aProfiles as $sProfile)
|
||||
{
|
||||
foreach ($aProfiles as $sProfile) {
|
||||
// Retrieving matrix information
|
||||
$iProfileId = $this->GetProfileIdFromProfileName($sProfile);
|
||||
$sMode = ($iAction === UR_ACTION_READ) ? static::ENUM_MODE_READ : static::ENUM_MODE_WRITE;
|
||||
@@ -237,39 +232,31 @@ class ScopeValidatorHelper
|
||||
// Retrieving profile OQLs
|
||||
$sScopeValuesClass = $this->sGeneratedClass;
|
||||
$aProfileMatrix = $sScopeValuesClass::GetProfileScope($iProfileId, $sClass, $sMode);
|
||||
if ($aProfileMatrix !== null)
|
||||
{
|
||||
if (isset($aProfileMatrix['allow']) && $aProfileMatrix['allow'] !== null)
|
||||
{
|
||||
if ($aProfileMatrix !== null) {
|
||||
if (isset($aProfileMatrix['allow']) && $aProfileMatrix['allow'] !== null) {
|
||||
$aAllowSearches[] = DBSearch::FromOQL($aProfileMatrix['allow']);
|
||||
}
|
||||
if (isset($aProfileMatrix['restrict']) && $aProfileMatrix['restrict'] !== null)
|
||||
{
|
||||
if (isset($aProfileMatrix['restrict']) && $aProfileMatrix['restrict'] !== null) {
|
||||
$aRestrictSearches[] = DBSearch::FromOQL($aProfileMatrix['restrict']);
|
||||
}
|
||||
// If a profile should ignore allowed org, we set it for all its queries no matter the profile
|
||||
if (isset($aProfileMatrix['ignore_silos']) && $aProfileMatrix['ignore_silos'] === true)
|
||||
{
|
||||
if (isset($aProfileMatrix['ignore_silos']) && $aProfileMatrix['ignore_silos'] === true) {
|
||||
$bIgnoreSilos = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Building the real OQL from all the parts from the different profiles
|
||||
for ($i = 0; $i < count($aAllowSearches); $i++)
|
||||
{
|
||||
foreach ($aRestrictSearches as $oRestrictSearch)
|
||||
{
|
||||
for ($i = 0; $i < count($aAllowSearches); $i++) {
|
||||
foreach ($aRestrictSearches as $oRestrictSearch) {
|
||||
$aAllowSearches[$i] = $aAllowSearches[$i]->Intersect($oRestrictSearch);
|
||||
}
|
||||
}
|
||||
if (count($aAllowSearches) > 0)
|
||||
{
|
||||
if (count($aAllowSearches) > 0) {
|
||||
$oSearch = new DBUnionSearch($aAllowSearches);
|
||||
$oSearch = $oSearch->RemoveDuplicateQueries();
|
||||
}
|
||||
if ($bIgnoreSilos === true)
|
||||
{
|
||||
if ($bIgnoreSilos === true) {
|
||||
$oSearch->AllowAllData();
|
||||
}
|
||||
|
||||
@@ -291,12 +278,10 @@ class ScopeValidatorHelper
|
||||
public function AddScopeToQuery(DBSearch &$oQuery, $sClass, $sAction = UR_ACTION_READ)
|
||||
{
|
||||
$oScopeQuery = $this->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sClass, $sAction);
|
||||
if ($oScopeQuery !== null)
|
||||
{
|
||||
if ($oScopeQuery !== null) {
|
||||
$oQuery = $oQuery->Intersect($oScopeQuery);
|
||||
// - Allowing all data if necessary
|
||||
if ($oScopeQuery->IsAllDataAllowed())
|
||||
{
|
||||
if ($oScopeQuery->IsAllDataAllowed()) {
|
||||
$oQuery->AllowAllData();
|
||||
}
|
||||
|
||||
@@ -321,19 +306,16 @@ class ScopeValidatorHelper
|
||||
$bIgnoreSilos = false;
|
||||
|
||||
// Iterating on profiles to retrieving the different OQLs parts
|
||||
foreach ($aProfiles as $sProfile)
|
||||
{
|
||||
foreach ($aProfiles as $sProfile) {
|
||||
// Retrieving matrix information
|
||||
$iProfileId = $this->GetProfileIdFromProfileName($sProfile);
|
||||
|
||||
// Retrieving profile OQLs
|
||||
$sScopeValuesClass = $this->sGeneratedClass;
|
||||
$aProfileMatrix = $sScopeValuesClass::GetProfileScope($iProfileId, $sClass, static::ENUM_MODE_READ);
|
||||
if ($aProfileMatrix !== null)
|
||||
{
|
||||
if ($aProfileMatrix !== null) {
|
||||
// If a profile should ignore allowed org, we set it for all its queries no matter the profile
|
||||
if (isset($aProfileMatrix['ignore_silos']) && $aProfileMatrix['ignore_silos'] === true)
|
||||
{
|
||||
if (isset($aProfileMatrix['ignore_silos']) && $aProfileMatrix['ignore_silos'] === true) {
|
||||
$bIgnoreSilos = true;
|
||||
}
|
||||
}
|
||||
@@ -357,18 +339,12 @@ class ScopeValidatorHelper
|
||||
|
||||
// We try to find the profile from its name in order to retrieve it's id
|
||||
// - If the regular UserRights add-on is installed we check the profiles array
|
||||
if (class_exists('ProfilesConfig'))
|
||||
{
|
||||
if (defined($sProfile) && in_array($sProfile, ProfilesConfig::GetProfilesValues()))
|
||||
{
|
||||
if (class_exists('ProfilesConfig')) {
|
||||
if (defined($sProfile) && in_array($sProfile, ProfilesConfig::GetProfilesValues())) {
|
||||
$iProfileId = constant($sProfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
|
||||
{
|
||||
if ($aValue['name'] === $sProfile)
|
||||
{
|
||||
} else {
|
||||
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue) {
|
||||
if ($aValue['name'] === $sProfile) {
|
||||
$iProfileId = $iKey;
|
||||
break;
|
||||
}
|
||||
@@ -376,14 +352,12 @@ class ScopeValidatorHelper
|
||||
}
|
||||
}
|
||||
// - Else, we can't find the id from the name as we don't know the used UserRights add-on. It has to be a constant
|
||||
else
|
||||
{
|
||||
else {
|
||||
throw new Exception('Scope validator : Unknown UserRights addon, scope\'s profile must be a constant');
|
||||
}
|
||||
|
||||
// If profile was not found from its name or from a constant, we throw an exception
|
||||
if ($iProfileId === null)
|
||||
{
|
||||
if ($iProfileId === null) {
|
||||
throw new Exception('Scope validator : Could not find "'.$sProfile.'" in the profiles list');
|
||||
}
|
||||
|
||||
@@ -397,7 +371,7 @@ class ScopeValidatorHelper
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function BuildPHPClass($aProfiles = array())
|
||||
protected function BuildPHPClass($aProfiles = [])
|
||||
{
|
||||
$sProfiles = var_export($aProfiles, true);
|
||||
$sClassName = ltrim($this->sGeneratedClass, '\\');
|
||||
@@ -450,31 +424,26 @@ EOF;
|
||||
protected function InitGenerateAndWriteCache(DOMNodeList $oNodes, $sFilePath)
|
||||
{
|
||||
// - Build php array from xml
|
||||
$aProfiles = array();
|
||||
$aProfiles = [];
|
||||
// This will be used to know which classes have been set, so we can set the missing ones.
|
||||
$aProfileClasses = array();
|
||||
$aProfileClasses = [];
|
||||
// Iterating over the class nodes
|
||||
/** @var \Combodo\iTop\DesignElement $oClassNode */
|
||||
foreach ($oNodes as $oClassNode)
|
||||
{
|
||||
foreach ($oNodes as $oClassNode) {
|
||||
// retrieving mandatory class id attribute
|
||||
$sClass = $oClassNode->getAttribute('id');
|
||||
if ($sClass === '')
|
||||
{
|
||||
if ($sClass === '') {
|
||||
throw new DOMFormatException('Class tag must have an id attribute.', null, null, $oClassNode);
|
||||
}
|
||||
|
||||
// Iterating over scope nodes of the class
|
||||
$oScopesNode = $oClassNode->GetOptionalElement('scopes');
|
||||
if ($oScopesNode !== null)
|
||||
{
|
||||
if ($oScopesNode !== null) {
|
||||
/** @var \Combodo\iTop\DesignElement $oScopeNode */
|
||||
foreach ($oScopesNode->GetNodes('./scope') as $oScopeNode)
|
||||
{
|
||||
foreach ($oScopesNode->GetNodes('./scope') as $oScopeNode) {
|
||||
// Retrieving mandatory scope id attribute
|
||||
$sScopeId = $oScopeNode->getAttribute('id');
|
||||
if ($sScopeId === '')
|
||||
{
|
||||
if ($sScopeId === '') {
|
||||
throw new DOMFormatException('Scope tag must have an id attribute.', null, null, $oScopeNode);
|
||||
}
|
||||
|
||||
@@ -486,8 +455,7 @@ EOF;
|
||||
// Retrieving the view query
|
||||
$oOqlViewNode = $oScopeNode->GetUniqueElement('oql_view');
|
||||
$sOqlView = $oOqlViewNode->GetText();
|
||||
if ($sOqlView === null)
|
||||
{
|
||||
if ($sOqlView === null) {
|
||||
throw new DOMFormatException(
|
||||
'Scope tag in class must have a not empty oql_view tag',
|
||||
0,
|
||||
@@ -504,24 +472,18 @@ EOF;
|
||||
|
||||
// Retrieving profiles for the scope
|
||||
$oProfilesNode = $oScopeNode->GetOptionalElement('allowed_profiles');
|
||||
$aProfilesNames = array();
|
||||
$aProfilesNames = [];
|
||||
// If no profile is specified, we consider that it's for ALL the profiles
|
||||
if (($oProfilesNode === null) || ($oProfilesNode->GetNodes('./allowed_profile')->length === 0))
|
||||
{
|
||||
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
|
||||
{
|
||||
if (($oProfilesNode === null) || ($oProfilesNode->GetNodes('./allowed_profile')->length === 0)) {
|
||||
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue) {
|
||||
$aProfilesNames[] = $aValue['name'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/** @var \Combodo\iTop\DesignElement $oProfileNode */
|
||||
foreach ($oProfilesNode->GetNodes('./allowed_profile') as $oProfileNode)
|
||||
{
|
||||
foreach ($oProfilesNode->GetNodes('./allowed_profile') as $oProfileNode) {
|
||||
// Retrieving mandatory profile id attribute
|
||||
$sProfileId = $oProfileNode->getAttribute('id');
|
||||
if ($sProfileId === '')
|
||||
{
|
||||
if ($sProfileId === '') {
|
||||
throw new DOMFormatException(
|
||||
'Scope tag must have an id attribute.',
|
||||
null,
|
||||
@@ -534,8 +496,7 @@ EOF;
|
||||
}
|
||||
|
||||
//
|
||||
foreach ($aProfilesNames as $sProfileName)
|
||||
{
|
||||
foreach ($aProfilesNames as $sProfileName) {
|
||||
// Scope profile id
|
||||
$iProfileId = $this->GetProfileIdFromProfileName($sProfileName);
|
||||
|
||||
@@ -545,48 +506,37 @@ EOF;
|
||||
$oViewFilter = DBSearch::FromOQL($sOqlView);
|
||||
// ... We have to union the query if this profile has another scope for that class
|
||||
if (array_key_exists($sMatrixPrefix.static::ENUM_MODE_READ, $aProfiles) && array_key_exists(
|
||||
$sOqlViewType,
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ]
|
||||
))
|
||||
{
|
||||
$sOqlViewType,
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ]
|
||||
)) {
|
||||
$oExistingFilter = DBSearch::FromOQL(
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ][$sOqlViewType]
|
||||
);
|
||||
$aFilters = array($oExistingFilter, $oViewFilter);
|
||||
$aFilters = [$oExistingFilter, $oViewFilter];
|
||||
$oResFilter = new DBUnionSearch($aFilters);
|
||||
|
||||
// Applying ignore_silos flag on result filter if necessary (As the union will remove it if it is not on all sub-queries)
|
||||
if ($aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ]['ignore_silos'] === true)
|
||||
{
|
||||
if ($aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ]['ignore_silos'] === true) {
|
||||
$bIgnoreSilos = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oResFilter = $oViewFilter;
|
||||
}
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ] = array(
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ] = [
|
||||
$sOqlViewType => $oResFilter->ToOQL(),
|
||||
'ignore_silos' => $bIgnoreSilos,
|
||||
);
|
||||
];
|
||||
// - Edit query
|
||||
if ($sOqlEdit !== null)
|
||||
{
|
||||
if ($sOqlEdit !== null) {
|
||||
$oEditFilter = DBSearch::FromOQL($sOqlEdit);
|
||||
// - If the queries are the same, we don't make an intersect, we just reuse the view query
|
||||
if ($sOqlEdit === $sOqlView)
|
||||
{
|
||||
if ($sOqlEdit === $sOqlView) {
|
||||
// Do not intersect, edit query is identical to view query
|
||||
}
|
||||
else
|
||||
{
|
||||
if (($oEditFilter->GetClass() === $oViewFilter->GetClass()) && $oEditFilter->IsAny())
|
||||
{
|
||||
} else {
|
||||
if (($oEditFilter->GetClass() === $oViewFilter->GetClass()) && $oEditFilter->IsAny()) {
|
||||
$oEditFilter = $oViewFilter;
|
||||
// Do not intersect, edit query is identical to view query
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Intersect
|
||||
$oEditFilter = $oViewFilter->Intersect($oEditFilter);
|
||||
}
|
||||
@@ -594,27 +544,24 @@ EOF;
|
||||
|
||||
// ... We have to union the query if this profile has another scope for that class
|
||||
if (array_key_exists(
|
||||
$sMatrixPrefix.static::ENUM_MODE_WRITE,
|
||||
$aProfiles
|
||||
) && array_key_exists(
|
||||
$sOqlViewType,
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE]
|
||||
))
|
||||
{
|
||||
$sMatrixPrefix.static::ENUM_MODE_WRITE,
|
||||
$aProfiles
|
||||
) && array_key_exists(
|
||||
$sOqlViewType,
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE]
|
||||
)) {
|
||||
$oExistingFilter = DBSearch::FromOQL(
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE][$sOqlViewType]
|
||||
);
|
||||
$aFilters = array($oExistingFilter, $oEditFilter);
|
||||
$aFilters = [$oExistingFilter, $oEditFilter];
|
||||
$oResFilter = new DBUnionSearch($aFilters);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oResFilter = $oEditFilter;
|
||||
}
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE] = array(
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE] = [
|
||||
$sOqlViewType => $oResFilter->ToOQL(),
|
||||
'ignore_silos' => $bIgnoreSilos,
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -626,27 +573,19 @@ EOF;
|
||||
// Filling the array with missing classes from MetaModel, so we can have an inheritance principle on the scope
|
||||
// For each class explicitly given in the scopes, we check if its child classes were also in the scope :
|
||||
// If not, we add them with the same OQL
|
||||
foreach ($aProfileClasses as $sProfileClass)
|
||||
{
|
||||
foreach (MetaModel::EnumChildClasses($sProfileClass) as $sChildClass)
|
||||
{
|
||||
foreach ($aProfileClasses as $sProfileClass) {
|
||||
foreach (MetaModel::EnumChildClasses($sProfileClass) as $sChildClass) {
|
||||
// If the child class is not in the scope, we are going to try to add it
|
||||
if (!in_array($sChildClass, $aProfileClasses))
|
||||
{
|
||||
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
|
||||
{
|
||||
if (!in_array($sChildClass, $aProfileClasses)) {
|
||||
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue) {
|
||||
$iProfileId = $iKey;
|
||||
foreach (array(static::ENUM_MODE_READ, static::ENUM_MODE_WRITE) as $sAction)
|
||||
{
|
||||
foreach ([static::ENUM_MODE_READ, static::ENUM_MODE_WRITE] as $sAction) {
|
||||
// If the current profile has scope for that class in that mode, we duplicate it
|
||||
if (isset($aProfiles[$iProfileId.'_'.$sProfileClass.'_'.$sAction]))
|
||||
{
|
||||
if (isset($aProfiles[$iProfileId.'_'.$sProfileClass.'_'.$sAction])) {
|
||||
$aTmpProfile = $aProfiles[$iProfileId.'_'.$sProfileClass.'_'.$sAction];
|
||||
foreach ($aTmpProfile as $sType => $sOql)
|
||||
{
|
||||
foreach ($aTmpProfile as $sType => $sOql) {
|
||||
// IF condition is just to skip the 'ignore_silos' flag
|
||||
if (in_array($sType, array(static::ENUM_TYPE_ALLOW, static::ENUM_TYPE_RESTRICT)))
|
||||
{
|
||||
if (in_array($sType, [static::ENUM_TYPE_ALLOW, static::ENUM_TYPE_RESTRICT])) {
|
||||
$oTmpFilter = DBSearch::FromOQL($sOql);
|
||||
$oTmpFilter->ChangeClass($sChildClass);
|
||||
|
||||
@@ -667,14 +606,12 @@ EOF;
|
||||
|
||||
// - Write file on disk
|
||||
// - Creating dir if necessary
|
||||
if (!is_dir($this->sCachePath))
|
||||
{
|
||||
if (!is_dir($this->sCachePath)) {
|
||||
mkdir($this->sCachePath, 0777, true);
|
||||
}
|
||||
// -- Then creating the file
|
||||
$ret = file_put_contents($sFilePath, $sPHP);
|
||||
if ($ret === false)
|
||||
{
|
||||
if ($ret === false) {
|
||||
$iLen = strlen($sPHP);
|
||||
$fFree = @disk_free_space(dirname($sFilePath));
|
||||
$aErr = error_get_last();
|
||||
@@ -685,4 +622,3 @@ EOF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -43,10 +43,10 @@ use BinaryExpression;
|
||||
class SecurityHelper
|
||||
{
|
||||
/** @var array $aAllowedScopeObjectsCache */
|
||||
public static $aAllowedScopeObjectsCache = array(
|
||||
UR_ACTION_READ => array(),
|
||||
UR_ACTION_MODIFY => array(),
|
||||
);
|
||||
public static $aAllowedScopeObjectsCache = [
|
||||
UR_ACTION_READ => [],
|
||||
UR_ACTION_MODIFY => [],
|
||||
];
|
||||
|
||||
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator */
|
||||
private $oScopeValidator;
|
||||
@@ -69,7 +69,6 @@ class SecurityHelper
|
||||
$this->bDebug = $bDebug;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the current user is allowed to do the $sAction on an $sObjectClass object (with optional $sObjectId id)
|
||||
* Checks are:
|
||||
@@ -94,45 +93,37 @@ class SecurityHelper
|
||||
$sDebugTracePrefix = __CLASS__.' / '.__METHOD__.' : Returned false for action '.$sAction.' on '.$sObjectClass.'::'.$sObjectId;
|
||||
|
||||
// Checking action type
|
||||
if (!in_array($sAction, array(UR_ACTION_READ, UR_ACTION_MODIFY, UR_ACTION_CREATE)))
|
||||
{
|
||||
if (!in_array($sAction, [UR_ACTION_READ, UR_ACTION_MODIFY, UR_ACTION_CREATE])) {
|
||||
IssueLog::Debug($sDebugTracePrefix.' as the action value could not be understood ('.UR_ACTION_READ.'/'.UR_ACTION_MODIFY.'/'.UR_ACTION_CREATE.' expected', LogChannels::PORTAL);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Forcing allowed writing on the object if necessary. This is used in some particular cases.
|
||||
$bObjectIsCurrentUser = ($sObjectClass === 'Person' && $sObjectId == UserRights::GetContactId());
|
||||
if(in_array($sAction , array(UR_ACTION_MODIFY, UR_ACTION_READ)) && $bObjectIsCurrentUser){
|
||||
if (in_array($sAction, [UR_ACTION_MODIFY, UR_ACTION_READ]) && $bObjectIsCurrentUser) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Checking the scopes layer
|
||||
// - Transforming scope action as there is only 2 values
|
||||
$sScopeAction = ($sAction === UR_ACTION_READ) ? UR_ACTION_READ : UR_ACTION_MODIFY;
|
||||
// - Retrieving the query. If user has no scope, it can't access that kind of objects
|
||||
$oScopeQuery = $this->oScopeValidator->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sObjectClass, $sScopeAction);
|
||||
if ($oScopeQuery === null)
|
||||
{
|
||||
if ($oScopeQuery === null) {
|
||||
IssueLog::Debug($sDebugTracePrefix.' as there was no scope defined for action '.$sScopeAction.' and profiles '.implode('/', UserRights::ListProfiles()), LogChannels::PORTAL);
|
||||
return false;
|
||||
}
|
||||
// - If action != create we do some additionnal checks
|
||||
if ($sAction !== UR_ACTION_CREATE)
|
||||
{
|
||||
if ($sAction !== UR_ACTION_CREATE) {
|
||||
// - Checking specific object if id is specified
|
||||
if ($sObjectId !== null)
|
||||
{
|
||||
if ($sObjectId !== null) {
|
||||
// Checking if object status is in cache (to avoid unnecessary query)
|
||||
if (isset(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId]))
|
||||
{
|
||||
if (static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId] === false)
|
||||
{
|
||||
if (isset(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId])) {
|
||||
if (static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId] === false) {
|
||||
IssueLog::Debug($sDebugTracePrefix.' as it was denied in the scope objects cache', LogChannels::PORTAL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Modifying query to filter on the ID
|
||||
// - Adding expression
|
||||
$sObjectKeyAtt = MetaModel::DBGetKey($sObjectClass);
|
||||
@@ -147,8 +138,7 @@ class SecurityHelper
|
||||
|
||||
// - Checking if query result is null (which means that the user has no right to view this specific object)
|
||||
$oSet = new DBObjectSet($oScopeQuery);
|
||||
if ($oSet->Count() === 0)
|
||||
{
|
||||
if ($oSet->Count() === 0) {
|
||||
// Updating cache
|
||||
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId] = false;
|
||||
|
||||
@@ -163,8 +153,7 @@ class SecurityHelper
|
||||
}
|
||||
|
||||
// Checking reading security layer. The object could be listed, check if it is actually allowed to view it
|
||||
if (UserRights::IsActionAllowed($sObjectClass, $sAction) == UR_ALLOWED_NO)
|
||||
{
|
||||
if (UserRights::IsActionAllowed($sObjectClass, $sAction) == UR_ALLOWED_NO) {
|
||||
// For security reasons, we don't want to give the user too many information on why he cannot access the object.
|
||||
//throw new SecurityException('User not allowed to view this object', array('class' => $sObjectClass, 'id' => $sObjectId));
|
||||
IssueLog::Debug($sDebugTracePrefix.' as the user is not allowed to access this object according to the datamodel security (cf. Console settings)', LogChannels::PORTAL);
|
||||
@@ -187,15 +176,13 @@ class SecurityHelper
|
||||
// Checking DataModel layer
|
||||
$aStimuliFromDatamodel = Metamodel::EnumStimuli($sObjectClass);
|
||||
$iActionAllowed = (get_class($aStimuliFromDatamodel[$sStimulusCode]) == 'StimulusUserAction') ? UserRights::IsStimulusAllowed($sObjectClass, $sStimulusCode, $oInstanceSet) : UR_ALLOWED_NO;
|
||||
if (($iActionAllowed === false) || ($iActionAllowed === UR_ALLOWED_NO))
|
||||
{
|
||||
if (($iActionAllowed === false) || ($iActionAllowed === UR_ALLOWED_NO)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checking portal security layer
|
||||
$aStimuliFromPortal = $this->oLifecycleValidator->GetStimuliForProfiles(UserRights::ListProfiles(), $sObjectClass);
|
||||
if (!in_array($sStimulusCode, $aStimuliFromPortal))
|
||||
{
|
||||
if (!in_array($sStimulusCode, $aStimuliFromPortal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -217,20 +204,17 @@ class SecurityHelper
|
||||
public function PreloadForCache(DBSearch $oSearch, $aExtKeysToPreload = null)
|
||||
{
|
||||
$sObjectClass = $oSearch->GetClass();
|
||||
$aObjectIds = array();
|
||||
$aExtKeysIds = array();
|
||||
$aColumnsToLoad = array();
|
||||
$aObjectIds = [];
|
||||
$aExtKeysIds = [];
|
||||
$aColumnsToLoad = [];
|
||||
|
||||
if ($aExtKeysToPreload !== null)
|
||||
{
|
||||
foreach ($aExtKeysToPreload as $sAttCode)
|
||||
{
|
||||
if ($aExtKeysToPreload !== null) {
|
||||
foreach ($aExtKeysToPreload as $sAttCode) {
|
||||
/** @var \AttributeDefinition $oAttDef */
|
||||
$oAttDef = MetaModel::GetAttributeDef($sObjectClass, $sAttCode);
|
||||
if ($oAttDef->IsExternalKey())
|
||||
{
|
||||
if ($oAttDef->IsExternalKey()) {
|
||||
/** @var \AttributeExternalKey $oAttDef */
|
||||
$aExtKeysIds[$oAttDef->GetTargetClass()] = array();
|
||||
$aExtKeysIds[$oAttDef->GetTargetClass()] = [];
|
||||
$aColumnsToLoad[] = $sAttCode;
|
||||
}
|
||||
}
|
||||
@@ -239,69 +223,56 @@ class SecurityHelper
|
||||
// Retrieving IDs of all objects
|
||||
// Note: We have to clone $oSet otherwise the source object will be modified
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
$oSet->OptimizeColumnLoad(array($oSearch->GetClassAlias() => $aColumnsToLoad));
|
||||
while ($oCurrentRow = $oSet->Fetch())
|
||||
{
|
||||
$oSet->OptimizeColumnLoad([$oSearch->GetClassAlias() => $aColumnsToLoad]);
|
||||
while ($oCurrentRow = $oSet->Fetch()) {
|
||||
// Note: By presetting value to false, it is quicker to find which objects where not returned by the scope query later
|
||||
$aObjectIds[$oCurrentRow->GetKey()] = false;
|
||||
|
||||
// Preparing ExtKeys to preload
|
||||
foreach ($aColumnsToLoad as $sAttCode)
|
||||
{
|
||||
foreach ($aColumnsToLoad as $sAttCode) {
|
||||
$iExtKey = $oCurrentRow->Get($sAttCode);
|
||||
if ($iExtKey > 0)
|
||||
{
|
||||
if ($iExtKey > 0) {
|
||||
/** @var \AttributeExternalKey $oAttDef */
|
||||
$oAttDef = MetaModel::GetAttributeDef($sObjectClass, $sAttCode);
|
||||
if (!in_array($iExtKey, $aExtKeysIds[$oAttDef->GetTargetClass()]))
|
||||
{
|
||||
if (!in_array($iExtKey, $aExtKeysIds[$oAttDef->GetTargetClass()])) {
|
||||
$aExtKeysIds[$oAttDef->GetTargetClass()][] = $iExtKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array(UR_ACTION_READ, UR_ACTION_MODIFY) as $sScopeAction)
|
||||
{
|
||||
foreach ([UR_ACTION_READ, UR_ACTION_MODIFY] as $sScopeAction) {
|
||||
// Retrieving scope query
|
||||
/** @var DBSearch $oScopeQuery */
|
||||
$oScopeQuery = $this->oScopeValidator->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sObjectClass, $sScopeAction);
|
||||
if ($oScopeQuery !== null)
|
||||
{
|
||||
if ($oScopeQuery !== null) {
|
||||
// Restricting scope if specified
|
||||
if (!empty($aObjectIds))
|
||||
{
|
||||
if (!empty($aObjectIds)) {
|
||||
$oScopeQuery->AddCondition('id', array_keys($aObjectIds), 'IN');
|
||||
}
|
||||
|
||||
// Preparing object set
|
||||
$oScopeSet = new DBObjectSet($oScopeQuery);
|
||||
$oScopeSet->OptimizeColumnLoad(array($oScopeQuery->GetClassAlias() => array()));
|
||||
$oScopeSet->OptimizeColumnLoad([$oScopeQuery->GetClassAlias() => []]);
|
||||
|
||||
// Checking objects status
|
||||
$aScopeObjectIds = $aObjectIds;
|
||||
while ($oCurrentRow = $oScopeSet->Fetch())
|
||||
{
|
||||
while ($oCurrentRow = $oScopeSet->Fetch()) {
|
||||
$aScopeObjectIds[$oCurrentRow->GetKey()] = true;
|
||||
}
|
||||
|
||||
// Updating cache
|
||||
if (!isset(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass]))
|
||||
{
|
||||
if (!isset(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass])) {
|
||||
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass] = $aScopeObjectIds;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass] = array_merge_recursive(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass], $aScopeObjectIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Preloading ExtKeys
|
||||
foreach ($aExtKeysIds as $sTargetClass => $aTargetIds)
|
||||
{
|
||||
if (!empty($aTargetIds))
|
||||
{
|
||||
foreach ($aExtKeysIds as $sTargetClass => $aTargetIds) {
|
||||
if (!empty($aTargetIds)) {
|
||||
$oTargetSearch = new DBObjectSearch($sTargetClass);
|
||||
$oTargetSearch->AddCondition('id', $aTargetIds, 'IN');
|
||||
|
||||
|
||||
@@ -18,10 +18,8 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Portal\Helper;
|
||||
|
||||
|
||||
use InvalidParameterException;
|
||||
use iPortalUIExtension;
|
||||
use MetaModel;
|
||||
@@ -66,13 +64,11 @@ class UIExtensionsHelper
|
||||
*/
|
||||
public function __get($sPropName)
|
||||
{
|
||||
if ($this->aUIExtensions === null)
|
||||
{
|
||||
if ($this->aUIExtensions === null) {
|
||||
$this->InitUIExtensions();
|
||||
}
|
||||
|
||||
if (array_key_exists($sPropName, $this->aUIExtensions))
|
||||
{
|
||||
if (array_key_exists($sPropName, $this->aUIExtensions)) {
|
||||
return $this->aUIExtensions[$sPropName];
|
||||
}
|
||||
|
||||
@@ -87,8 +83,7 @@ class UIExtensionsHelper
|
||||
*/
|
||||
public function __isset($sPropName)
|
||||
{
|
||||
if ($this->aUIExtensions === null)
|
||||
{
|
||||
if ($this->aUIExtensions === null) {
|
||||
$this->InitUIExtensions();
|
||||
}
|
||||
|
||||
@@ -110,67 +105,63 @@ class UIExtensionsHelper
|
||||
*/
|
||||
protected function InitUIExtensions()
|
||||
{
|
||||
$aUIExtensions = array(
|
||||
'css_files' => array(),
|
||||
$aUIExtensions = [
|
||||
'css_files' => [],
|
||||
'css_inline' => null,
|
||||
'js_files' => array(),
|
||||
'js_files' => [],
|
||||
'js_inline' => null,
|
||||
'html' => array(),
|
||||
);
|
||||
'html' => [],
|
||||
];
|
||||
|
||||
$aUIExtensionHooks = array(
|
||||
$aUIExtensionHooks = [
|
||||
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)
|
||||
{
|
||||
foreach (MetaModel::EnumPlugins('iPortalUIExtension') as $oExtensionInstance) {
|
||||
// Adding CSS files
|
||||
$aImportPaths = array($_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'].'css/');
|
||||
foreach ($oExtensionInstance->GetCSSFiles($this->oContainer) as $sCSSFile)
|
||||
{
|
||||
$aImportPaths = [$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'].'css/'];
|
||||
foreach ($oExtensionInstance->GetCSSFiles($this->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 = utils::GetAbsoluteUrlAppRoot().utils::GetCSSFromSASS($sCSSFilePath,
|
||||
$aImportPaths);
|
||||
$sCSSFileCompiled = utils::GetAbsoluteUrlAppRoot().utils::GetCSSFromSASS(
|
||||
$sCSSFilePath,
|
||||
$aImportPaths
|
||||
);
|
||||
|
||||
if (!in_array($sCSSFileCompiled, $aUIExtensions['css_files']))
|
||||
{
|
||||
if (!in_array($sCSSFileCompiled, $aUIExtensions['css_files'])) {
|
||||
$aUIExtensions['css_files'][] = $sCSSFileCompiled;
|
||||
}
|
||||
}
|
||||
|
||||
// Adding CSS inline
|
||||
$sCSSInline = $oExtensionInstance->GetCSSInline($this->oContainer);
|
||||
if ($sCSSInline !== null)
|
||||
{
|
||||
if ($sCSSInline !== null) {
|
||||
$aUIExtensions['css_inline'] .= "\n\n".$sCSSInline;
|
||||
}
|
||||
|
||||
// Adding JS files
|
||||
$aUIExtensions['js_files'] = array_merge($aUIExtensions['js_files'],
|
||||
$oExtensionInstance->GetJSFiles($this->oContainer));
|
||||
$aUIExtensions['js_files'] = array_merge(
|
||||
$aUIExtensions['js_files'],
|
||||
$oExtensionInstance->GetJSFiles($this->oContainer)
|
||||
);
|
||||
|
||||
// Adding JS inline
|
||||
$sJSInline = $oExtensionInstance->GetJSInline($this->oContainer);
|
||||
if ($sJSInline !== null)
|
||||
{
|
||||
if ($sJSInline !== null) {
|
||||
// Note: Semi-colon is to prevent previous script that would have omitted it.
|
||||
$aUIExtensions['js_inline'] .= "\n\n;\n".$sJSInline;
|
||||
}
|
||||
|
||||
// Adding HTML for each hook
|
||||
foreach ($aUIExtensionHooks as $sUIExtensionHook)
|
||||
{
|
||||
foreach ($aUIExtensionHooks as $sUIExtensionHook) {
|
||||
$sFunctionName = 'Get'.$sUIExtensionHook.'HTML';
|
||||
$sHTML = $oExtensionInstance->$sFunctionName($this->oContainer);
|
||||
if ($sHTML !== null)
|
||||
{
|
||||
if (!array_key_exists($sUIExtensionHook, $aUIExtensions['html']))
|
||||
{
|
||||
if ($sHTML !== null) {
|
||||
if (!array_key_exists($sUIExtensionHook, $aUIExtensions['html'])) {
|
||||
$aUIExtensions['html'][$sUIExtensionHook] = '';
|
||||
}
|
||||
$aUIExtensions['html'][$sUIExtensionHook] .= "\n\n".$sHTML;
|
||||
@@ -180,4 +171,4 @@ class UIExtensionsHelper
|
||||
|
||||
$this->aUIExtensions = $aUIExtensions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -70,4 +71,4 @@ interface iAbstractPortalTabContentExtension
|
||||
* @since iTop 3.2.1
|
||||
*/
|
||||
public function GetSectionRank(): float;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -59,4 +60,4 @@ interface iAbstractPortalTabExtension
|
||||
* @since iTop 3.2.1
|
||||
*/
|
||||
public function GetTabLabel(): string;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -14,5 +15,4 @@ namespace Combodo\iTop\Portal\Hook;
|
||||
*/
|
||||
interface iUserProfileTabContentExtension extends iAbstractPortalTabContentExtension
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -14,5 +15,4 @@ namespace Combodo\iTop\Portal\Hook;
|
||||
*/
|
||||
interface iUserProfileTabExtension extends iAbstractPortalTabExtension
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -19,7 +20,6 @@
|
||||
|
||||
namespace Combodo\iTop\Portal\Routing;
|
||||
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
@@ -32,13 +32,13 @@ use Exception;
|
||||
class ItopExtensionsExtraRoutes
|
||||
{
|
||||
/** @var array $aRoutes */
|
||||
static private $aRoutes = array();
|
||||
private static $aRoutes = [];
|
||||
|
||||
/**
|
||||
* @var array $aControllersClasses
|
||||
* @since 3.1.0
|
||||
*/
|
||||
static private $aControllersClasses = array();
|
||||
private static $aControllersClasses = [];
|
||||
|
||||
/**
|
||||
* @param array $extraRoutes
|
||||
@@ -85,4 +85,4 @@ class ItopExtensionsExtraRoutes
|
||||
{
|
||||
return self::$aControllersClasses;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -117,4 +118,4 @@ class UrlGenerator implements RouterInterface
|
||||
|
||||
return $aParameters;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,8 +64,7 @@ class TemplateDefinitionDto
|
||||
private ?string $sPath = null,
|
||||
private readonly ?bool $bIsOverridable = false,
|
||||
private readonly ?string $sAlias = null,
|
||||
)
|
||||
{
|
||||
) {
|
||||
// save overridable values
|
||||
$this->sInitialValue = $sPath;
|
||||
}
|
||||
@@ -89,7 +88,7 @@ class TemplateDefinitionDto
|
||||
*/
|
||||
public function GetPath(bool $bInitialValue = false): string
|
||||
{
|
||||
if($bInitialValue){
|
||||
if ($bInitialValue) {
|
||||
return $this->sInitialValue !== null ? $this->sInitialValue : '';
|
||||
}
|
||||
|
||||
@@ -142,4 +141,4 @@ class TemplateDefinitionDto
|
||||
return $this->bIsOverridden;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,4 +36,4 @@ interface TemplatesProviderInterface
|
||||
* @return void
|
||||
*/
|
||||
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,8 +281,7 @@ class TemplatesProviderService
|
||||
if ($oParent) {
|
||||
$sCurrentClass = $oReflexion->getParentClass()->getName();
|
||||
}
|
||||
}
|
||||
catch (Exception) {
|
||||
} catch (Exception) {
|
||||
}
|
||||
|
||||
} while ($oParent); // continue while parent class exists
|
||||
@@ -327,4 +326,4 @@ class TemplatesProviderService
|
||||
&& array_key_exists($sTemplateId, $this->aInstancesOverriddenTemplatesPaths[$sObjectId]['templates']));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -22,7 +23,6 @@ namespace Combodo\iTop\Portal\Twig;
|
||||
use Combodo\iTop\Application\TwigBase\Twig\Extension;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
|
||||
|
||||
/**
|
||||
* Class AppExtension
|
||||
*
|
||||
@@ -50,4 +50,4 @@ class AppExtension extends AbstractExtension
|
||||
{
|
||||
return Extension::GetFunctions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -55,7 +56,7 @@ class AppGlobal extends AbstractExtension implements GlobalsInterface
|
||||
*/
|
||||
public function getGlobals(): array
|
||||
{
|
||||
$data = array();
|
||||
$data = [];
|
||||
$data['allowed_portals'] = $this->userProvider->getAllowedPortals();
|
||||
$data['user_preferences'] = json_decode(appUserPreferences::GetAsJSON(), true);
|
||||
|
||||
@@ -64,4 +65,4 @@ class AppGlobal extends AbstractExtension implements GlobalsInterface
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -33,93 +34,92 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
*/
|
||||
class AppVariable implements ArrayAccess
|
||||
{
|
||||
/** @var ContainerInterface */
|
||||
private $container;
|
||||
/** @var ContainerInterface */
|
||||
private $container;
|
||||
|
||||
/** @var DecoratedAppVariable */
|
||||
private $decorated;
|
||||
/** @var DecoratedAppVariable */
|
||||
private $decorated;
|
||||
|
||||
public function __construct(DecoratedAppVariable $decorated, ContainerInterface $container = null)
|
||||
{
|
||||
$this->decorated = $decorated;
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function __construct(DecoratedAppVariable $decorated, ContainerInterface $container = null)
|
||||
{
|
||||
$this->decorated = $decorated;
|
||||
$this->container = $container;
|
||||
}
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
if ($this->silexApplicationEmulation->offsetExists($name)) {
|
||||
return $this->silexApplicationEmulation->offsetGet($name);
|
||||
}
|
||||
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
if ($this->silexApplicationEmulation->offsetExists($name)) {
|
||||
return $this->silexApplicationEmulation->offsetGet($name);
|
||||
}
|
||||
return $this->decorated->$name(...$arguments); //WARNING: use of http://php.net/manual/fr/functions.arguments.php#functions.variable-arg-list
|
||||
}
|
||||
|
||||
return $this->decorated->$name(...$arguments); //WARNING: use of http://php.net/manual/fr/functions.arguments.php#functions.variable-arg-list
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
if ($this->container->hasParameter($offset)) {
|
||||
return true;
|
||||
}
|
||||
if ($this->container->has($offset)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
if ($this->container->hasParameter($offset)) {
|
||||
return true;
|
||||
}
|
||||
if ($this->container->has($offset)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if ($this->container->hasParameter($offset)) {
|
||||
return $this->container->getParameter($offset);
|
||||
}
|
||||
if ($this->container->has($offset)) {
|
||||
return $this->container->get($offset);
|
||||
}
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if ($this->container->hasParameter($offset)) {
|
||||
return $this->container->getParameter($offset);
|
||||
}
|
||||
if ($this->container->has($offset)) {
|
||||
return $this->container->get($offset);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
|
||||
if ($this->container->hasParameter($offset)) {
|
||||
$this->container->setParameter($offset, $value);
|
||||
return;
|
||||
}
|
||||
if ($this->container->hasParameter($offset)) {
|
||||
$this->container->setParameter($offset, $value);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->container->has($offset)) {
|
||||
$this->container->set($offset, $value);
|
||||
return;
|
||||
}
|
||||
if ($this->container->has($offset)) {
|
||||
$this->container->set($offset, $value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_object($value)) {
|
||||
$this->container->set($offset, $value);
|
||||
return;
|
||||
}
|
||||
if (is_object($value)) {
|
||||
$this->container->set($offset, $value);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->container->setParameter($offset, $value);
|
||||
}
|
||||
$this->container->setParameter($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
if ($this->container->hasParameter($offset)) {
|
||||
$this->container->setParameter($offset, null);
|
||||
} else if ($this->container->has($offset)) {
|
||||
$this->container->set($offset, null);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
if ($this->container->hasParameter($offset)) {
|
||||
$this->container->setParameter($offset, null);
|
||||
} elseif ($this->container->has($offset)) {
|
||||
$this->container->set($offset, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2023 Combodo SARL
|
||||
*
|
||||
@@ -35,7 +36,7 @@ use Twig\TwigFunction;
|
||||
class CKEditorExtension extends AbstractExtension
|
||||
{
|
||||
/** @inheritdoc */
|
||||
public function getFunctions() : array
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('inject_ckeditor_resources', [$this, 'injectCKEditorResources']),
|
||||
@@ -48,17 +49,17 @@ class CKEditorExtension extends AbstractExtension
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function injectCKEditorResources() : string
|
||||
public function injectCKEditorResources(): string
|
||||
{
|
||||
$sScriptTemplate = '';
|
||||
$aJSFilesRelPaths = CKEditorHelper::GetJSFilesRelPathsForCKEditor();
|
||||
|
||||
foreach ($aJSFilesRelPaths as $sJSFileRelPath){
|
||||
$sUrl = \utils::GetAbsoluteUrlAppRoot() . $sJSFileRelPath;
|
||||
foreach ($aJSFilesRelPaths as $sJSFileRelPath) {
|
||||
$sUrl = \utils::GetAbsoluteUrlAppRoot().$sJSFileRelPath;
|
||||
$sUrl = \utils::AddParameterToUrl($sUrl, 't', \utils::GetCacheBusterTimestamp());
|
||||
$sScriptTemplate .= '<script type="text/javascript" src="' . $sUrl . '"></script>';
|
||||
$sScriptTemplate .= '<script type="text/javascript" src="'.$sUrl.'"></script>';
|
||||
}
|
||||
|
||||
return $sScriptTemplate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -70,4 +71,4 @@ class CurrentUserAccessor
|
||||
{
|
||||
return $this->userProvider->getCurrentUserCanLogOff();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -34,7 +35,7 @@ class PortalBlockExtension
|
||||
*
|
||||
* @since iTop 3.2.1
|
||||
*/
|
||||
function __construct(string $sTwig, array $aData = [])
|
||||
public function __construct(string $sTwig, array $aData = [])
|
||||
{
|
||||
$this->sTwig = $sTwig;
|
||||
$this->aData = $aData;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -16,7 +17,6 @@ namespace Combodo\iTop\Portal\Twig;
|
||||
*/
|
||||
class PortalTwigContext
|
||||
{
|
||||
|
||||
private array $aBlockExtension;
|
||||
|
||||
public function __construct()
|
||||
@@ -35,7 +35,7 @@ class PortalTwigContext
|
||||
*
|
||||
* @since iTop 3.2.1
|
||||
*/
|
||||
function AddBlockExtension(string $sBlockName, PortalBlockExtension $oBlockExtension): void
|
||||
public function AddBlockExtension(string $sBlockName, PortalBlockExtension $oBlockExtension): void
|
||||
{
|
||||
$this->aBlockExtension[$sBlockName] = $oBlockExtension;
|
||||
}
|
||||
@@ -58,4 +58,4 @@ class PortalTwigContext
|
||||
$oBlockExtension = $this->aBlockExtension[$sBlockName] ?? null;
|
||||
return $oBlockExtension;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2023 Combodo SARL
|
||||
*
|
||||
@@ -31,7 +32,7 @@ use Twig\TwigFunction;
|
||||
*/
|
||||
class TemplatesTwigExtension extends AbstractExtension
|
||||
{
|
||||
const DEFAULT_PROVIDER_CLASS = 'Combodo\\iTop\\Portal\\Controller\\AbstractController';
|
||||
public const DEFAULT_PROVIDER_CLASS = 'Combodo\\iTop\\Portal\\Controller\\AbstractController';
|
||||
|
||||
public function __construct(private readonly TemplatesProviderService $oTemplatesService)
|
||||
{
|
||||
@@ -78,4 +79,4 @@ class TemplatesTwigExtension extends AbstractExtension
|
||||
{
|
||||
return $this->oTemplatesService->GetTemplatePath($sProviderClass, $sId, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ use utils;
|
||||
abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
|
||||
{
|
||||
/** @var string PORTAL_ID */
|
||||
const PORTAL_ID = '';
|
||||
public const PORTAL_ID = '';
|
||||
|
||||
/** @var \Combodo\iTop\Portal\Kernel[] $aKernels */
|
||||
private static $aKernels = array();
|
||||
private static $aKernels = [];
|
||||
|
||||
/**
|
||||
* Generate an (absolute) URL to an object, either in view or edit mode.
|
||||
@@ -64,8 +64,7 @@ abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
|
||||
|
||||
$sUrl = self::DoPrepareObjectURL($sClass, $iId, $sMode);
|
||||
|
||||
if (!empty($sPreviousPortalId))
|
||||
{
|
||||
if (!empty($sPreviousPortalId)) {
|
||||
$_ENV['PORTAL_ID'] = $sPreviousPortalId;
|
||||
}
|
||||
|
||||
@@ -97,48 +96,39 @@ abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
|
||||
//
|
||||
// Note: Scopes only apply when URL check is triggered from the portal GUI.
|
||||
$sObjectQueryString = null;
|
||||
switch ($sMode)
|
||||
{
|
||||
switch ($sMode) {
|
||||
case 'view':
|
||||
if (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $iId))
|
||||
{
|
||||
$sObjectQueryString = $oUrlGenerator->generate('p_object_view', array('sObjectClass' => $sClass, 'sObjectId' => $iId));
|
||||
if (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $iId)) {
|
||||
$sObjectQueryString = $oUrlGenerator->generate('p_object_view', ['sObjectClass' => $sClass, 'sObjectId' => $iId]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
default:
|
||||
// Checking if user is allowed to edit object, if not we check if it can at least view it.
|
||||
if (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY, $sClass, $iId))
|
||||
{
|
||||
$sObjectQueryString = $oUrlGenerator->generate('p_object_edit', array('sObjectClass' => $sClass, 'sObjectId' => $iId));
|
||||
}
|
||||
elseif (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $iId))
|
||||
{
|
||||
$sObjectQueryString = $oUrlGenerator->generate('p_object_view', array('sObjectClass' => $sClass, 'sObjectId' => $iId));
|
||||
if (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY, $sClass, $iId)) {
|
||||
$sObjectQueryString = $oUrlGenerator->generate('p_object_edit', ['sObjectClass' => $sClass, 'sObjectId' => $iId]);
|
||||
} elseif (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $iId)) {
|
||||
$sObjectQueryString = $oUrlGenerator->generate('p_object_view', ['sObjectClass' => $sClass, 'sObjectId' => $iId]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$sPortalAbsoluteUrl = utils::GetAbsoluteUrlModulePage('itop-portal-base', 'index.php', array('portal_id' => $sPortalId));
|
||||
if ($sObjectQueryString === null)
|
||||
{
|
||||
$sPortalAbsoluteUrl = utils::GetAbsoluteUrlModulePage('itop-portal-base', 'index.php', ['portal_id' => $sPortalId]);
|
||||
if ($sObjectQueryString === null) {
|
||||
$sUrl = null;
|
||||
}
|
||||
elseif (strpos($sPortalAbsoluteUrl, '?') !== false)
|
||||
{
|
||||
} elseif (strpos($sPortalAbsoluteUrl, '?') !== false) {
|
||||
// Removing generated url query parameters so it can be replaced with those from the absolute url
|
||||
// Mostly necessary when iTop instance has multiple portals
|
||||
if (strpos($sObjectQueryString, '?') !== false)
|
||||
{
|
||||
if (strpos($sObjectQueryString, '?') !== false) {
|
||||
$sObjectQueryString = substr($sObjectQueryString, 0, strpos($sObjectQueryString, '?'));
|
||||
}
|
||||
|
||||
$sUrl = substr($sPortalAbsoluteUrl, 0, strpos($sPortalAbsoluteUrl, '?')).$sObjectQueryString.substr($sPortalAbsoluteUrl,
|
||||
strpos($sPortalAbsoluteUrl, '?'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = substr($sPortalAbsoluteUrl, 0, strpos($sPortalAbsoluteUrl, '?')).$sObjectQueryString.substr(
|
||||
$sPortalAbsoluteUrl,
|
||||
strpos($sPortalAbsoluteUrl, '?')
|
||||
);
|
||||
} else {
|
||||
$sUrl = $sPortalAbsoluteUrl.$sObjectQueryString;
|
||||
}
|
||||
|
||||
@@ -153,8 +143,7 @@ abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
|
||||
*/
|
||||
private static function GetKernelInstance()
|
||||
{
|
||||
if (!array_key_exists(static::PORTAL_ID, self::$aKernels))
|
||||
{
|
||||
if (!array_key_exists(static::PORTAL_ID, self::$aKernels)) {
|
||||
self::$aKernels[static::PORTAL_ID] = new Kernel($_SERVER['APP_ENV'], (bool)$_SERVER['APP_DEBUG']);
|
||||
self::$aKernels[static::PORTAL_ID]->boot();
|
||||
}
|
||||
@@ -175,4 +164,3 @@ abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
|
||||
return static::PrepareObjectURL($sClass, $iId, 'edit');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -34,4 +35,4 @@ abstract class AbstractStringVariableAccessor extends AbstractVariableAccessor
|
||||
{
|
||||
return $this->getVariable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -27,22 +28,22 @@ namespace Combodo\iTop\Portal\VariableAccessor;
|
||||
*/
|
||||
abstract class AbstractVariableAccessor
|
||||
{
|
||||
/** @var string $storedVariable */
|
||||
private $storedVariable;
|
||||
/** @var string $storedVariable */
|
||||
private $storedVariable;
|
||||
|
||||
/**
|
||||
* @param string $variableToStore
|
||||
*/
|
||||
public function __construct($variableToStore)
|
||||
{
|
||||
$this->storedVariable = $variableToStore;
|
||||
}
|
||||
/**
|
||||
* @param string $variableToStore
|
||||
*/
|
||||
public function __construct($variableToStore)
|
||||
{
|
||||
$this->storedVariable = $variableToStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getVariable()
|
||||
{
|
||||
return $this->storedVariable;
|
||||
}
|
||||
}
|
||||
public function getVariable()
|
||||
{
|
||||
return $this->storedVariable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -19,7 +20,6 @@
|
||||
|
||||
namespace Combodo\iTop\Portal\VariableAccessor;
|
||||
|
||||
|
||||
use Combodo\iTop\Portal\EventListener\UserProvider;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
@@ -85,8 +85,7 @@ class CombodoCurrentContactPhotoUrl
|
||||
try {
|
||||
/** @var \cmdbAbstractObject $oContact */
|
||||
$oContact = UserRights::GetContactObject();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
$oUser = $this->oUserProvider->getCurrentUser();
|
||||
$oAllowedOrgSet = $oUser->Get('allowed_org_list');
|
||||
if ($oAllowedOrgSet->Count() > 0) {
|
||||
@@ -118,4 +117,4 @@ class CombodoCurrentContactPhotoUrl
|
||||
|
||||
return $sContactPhotoUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -28,5 +29,4 @@ namespace Combodo\iTop\Portal\VariableAccessor;
|
||||
*/
|
||||
class CombodoPortalInstanceConf extends AbstractVariableAccessor
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user