mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
N°2060 [WIP] Initialisation of the portal application: Huge code cleanup
- Rename variables and methods in iTop files to match coding conventions - Format code accordingly to coding conventions - Add / update PHPDoc all over the place - Suppress most of the warnings that did not have a big impact on code's logic
This commit is contained in:
@@ -1,21 +1,24 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2017 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Executes a portal without having a dedicated module.
|
||||
@@ -23,15 +26,15 @@
|
||||
*/
|
||||
|
||||
// Load current environment
|
||||
if (file_exists(__DIR__ . '/../../approot.inc.php'))
|
||||
if (file_exists(__DIR__.'/../../approot.inc.php'))
|
||||
{
|
||||
require_once __DIR__ . '/../../approot.inc.php'; // When in env-xxxx folder
|
||||
require_once __DIR__.'/../../approot.inc.php'; // When in env-xxxx folder
|
||||
}
|
||||
else
|
||||
{
|
||||
require_once __DIR__ . '/../../../approot.inc.php'; // When in datamodels/x.x folder
|
||||
require_once __DIR__.'/../../../approot.inc.php'; // When in datamodels/x.x folder
|
||||
}
|
||||
require_once APPROOT . 'application/startup.inc.php';
|
||||
require_once APPROOT.'application/startup.inc.php';
|
||||
|
||||
// Load frontal
|
||||
require_once MODULESROOT . 'itop-portal-base/portal/public/index.php';
|
||||
require_once MODULESROOT.'itop-portal-base/portal/public/index.php';
|
||||
|
||||
@@ -5,33 +5,35 @@ use Combodo\iTop\Portal\Kernel;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
|
||||
if (false === in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) {
|
||||
echo 'Warning: The console should be invoked via the CLI version of PHP, not the '.\PHP_SAPI.' SAPI'.\PHP_EOL;
|
||||
if (false === in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true))
|
||||
{
|
||||
echo 'Warning: The console should be invoked via the CLI version of PHP, not the '.\PHP_SAPI.' SAPI'.\PHP_EOL;
|
||||
}
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
if(!defined('APPROOT'))
|
||||
if (!defined('APPROOT'))
|
||||
{
|
||||
if (file_exists(__DIR__ . '/../../../../approot.inc.php'))
|
||||
if (file_exists(__DIR__.'/../../../../approot.inc.php'))
|
||||
{
|
||||
require_once __DIR__ . '/../../../../approot.inc.php'; // When in env-xxxx folder
|
||||
require_once __DIR__.'/../../../../approot.inc.php'; // When in env-xxxx folder
|
||||
}
|
||||
else
|
||||
{
|
||||
require_once __DIR__ . '/../../../../../approot.inc.php'; // When in datamodels/x.x folder
|
||||
require_once __DIR__.'/../../../../../approot.inc.php'; // When in datamodels/x.x folder
|
||||
}
|
||||
}
|
||||
require_once APPROOT . 'lib/composer-vendor/autoload.php';
|
||||
require_once APPROOT.'lib/composer-vendor/autoload.php';
|
||||
|
||||
if (!class_exists(Application::class)) {
|
||||
throw new RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.');
|
||||
if (!class_exists(Application::class))
|
||||
{
|
||||
throw new RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.');
|
||||
}
|
||||
|
||||
// Remove --portal_id from CLI params to avoid SF CLI conflicts
|
||||
// Note: The parameter is needed when calling the bin/console to determine which portal to select
|
||||
$aCleanedArgv = $_SERVER['argv'];
|
||||
foreach($aCleanedArgv as $iArg => $sArg)
|
||||
foreach ($aCleanedArgv as $iArg => $sArg)
|
||||
{
|
||||
if (preg_match('/^--portal_id=(.*)$/', $sArg, $aMatches))
|
||||
{
|
||||
@@ -40,17 +42,20 @@ foreach($aCleanedArgv as $iArg => $sArg)
|
||||
}
|
||||
}
|
||||
|
||||
$input = new ArgvInput($aCleanedArgv);
|
||||
if (null !== $env = $input->getParameterOption(['--env', '-e'], null, true)) {
|
||||
putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env);
|
||||
$oInput = new ArgvInput($aCleanedArgv);
|
||||
if (null !== $sEnv = $oInput->getParameterOption(['--env', '-e'], null, true))
|
||||
{
|
||||
putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $sEnv);
|
||||
}
|
||||
|
||||
if ($input->hasParameterOption('--no-debug', true)) {
|
||||
putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
|
||||
if ($oInput->hasParameterOption('--no-debug', true))
|
||||
{
|
||||
putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
|
||||
}
|
||||
|
||||
require_once MODULESROOT . 'itop-portal-base/portal/config/bootstrap.php';
|
||||
require_once MODULESROOT.'itop-portal-base/portal/config/bootstrap.php';
|
||||
|
||||
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
|
||||
$application = new Application($kernel);
|
||||
$application->run($input);
|
||||
$oKernel = new Kernel($_SERVER['APP_ENV'], (bool)$_SERVER['APP_DEBUG']);
|
||||
$oApplication = new Application($oKernel);
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$oApplication->run($oInput);
|
||||
|
||||
@@ -1,63 +1,101 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
// Disable PhpUnhandledExceptionInspection as the exception handling is made by the file including this one
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
use Symfony\Component\Debug\Debug;
|
||||
use Symfony\Component\Dotenv\Dotenv;
|
||||
|
||||
require_once APPROOT.'/lib/composer-vendor/autoload.php';
|
||||
|
||||
// Load current environment if necessary
|
||||
if(!defined('MODULESROOT'))
|
||||
if (!defined('MODULESROOT'))
|
||||
{
|
||||
if (file_exists(__DIR__ . '/../../../../approot.inc.php'))
|
||||
if (file_exists(__DIR__.'/../../../../approot.inc.php'))
|
||||
{
|
||||
require_once __DIR__ . '/../../../../approot.inc.php'; // When in env-xxxx folder
|
||||
require_once __DIR__.'/../../../../approot.inc.php'; // When in env-xxxx folder
|
||||
}
|
||||
else
|
||||
{
|
||||
require_once __DIR__ . '/../../../../../approot.inc.php'; // When in datamodels/x.x folder
|
||||
require_once __DIR__.'/../../../../../approot.inc.php'; // When in datamodels/x.x folder
|
||||
}
|
||||
require_once APPROOT . '/application/startup.inc.php';
|
||||
require_once APPROOT.'/application/startup.inc.php';
|
||||
}
|
||||
|
||||
// Load cached env vars if the .env.local.php file exists
|
||||
// Run "composer dump-env prod" to create it (requires symfony/flex >=1.2)
|
||||
if (is_array($env = @include dirname(__DIR__).'/.env.local.php')) {
|
||||
$_ENV += $env;
|
||||
} elseif (!class_exists(Dotenv::class)) {
|
||||
throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
|
||||
} else {
|
||||
$path = dirname(__DIR__).'/.env';
|
||||
$dotenv = new Dotenv(false);
|
||||
if (is_array($sEnv = @include dirname(__DIR__).'/.env.local.php'))
|
||||
{
|
||||
$_ENV += $sEnv;
|
||||
}
|
||||
elseif (!class_exists(Dotenv::class))
|
||||
{
|
||||
throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sPath = dirname(__DIR__).'/.env';
|
||||
$oDotenv = new Dotenv(false);
|
||||
|
||||
// load all the .env files
|
||||
if (method_exists($dotenv, 'loadEnv')) {
|
||||
$dotenv->loadEnv($path);
|
||||
} else {
|
||||
// fallback code in case your Dotenv component is not 4.2 or higher (when loadEnv() was added)
|
||||
// load all the .env files
|
||||
if (method_exists($oDotenv, 'loadEnv'))
|
||||
{
|
||||
$oDotenv->loadEnv($sPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// fallback code in case your Dotenv component is not 4.2 or higher (when loadEnv() was added)
|
||||
|
||||
if (file_exists($path) || !file_exists($p = "$path.dist")) {
|
||||
$dotenv->load($path);
|
||||
} else {
|
||||
$dotenv->load($p);
|
||||
}
|
||||
if (file_exists($sPath) || !file_exists($sPathDist = "$sPath.dist"))
|
||||
{
|
||||
$oDotenv->load($sPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oDotenv->load($sPathDist);
|
||||
}
|
||||
|
||||
if (null === $env = (isset($_SERVER['APP_ENV']) ? $_SERVER['APP_ENV'] : (isset($_ENV['APP_ENV']) ? $_ENV['APP_ENV'] : null))) {
|
||||
$dotenv->populate(array('APP_ENV' => $env = 'prod'));
|
||||
}
|
||||
if (null === $sEnv = (isset($_SERVER['APP_ENV']) ? $_SERVER['APP_ENV'] : (isset($_ENV['APP_ENV']) ? $_ENV['APP_ENV'] : null)))
|
||||
{
|
||||
$oDotenv->populate(array('APP_ENV' => $sEnv = 'prod'));
|
||||
}
|
||||
|
||||
if ('test' !== $env && file_exists($p = "$path.local")) {
|
||||
$dotenv->load($p);
|
||||
$env = isset($_SERVER['APP_ENV']) ? $_SERVER['APP_ENV'] : (isset($_ENV['APP_ENV']) ? $_ENV['APP_ENV'] : $env);
|
||||
}
|
||||
if ('test' !== $sEnv && file_exists($sPathDist = "$sPath.local"))
|
||||
{
|
||||
$oDotenv->load($sPathDist);
|
||||
$sEnv = isset($_SERVER['APP_ENV']) ? $_SERVER['APP_ENV'] : (isset($_ENV['APP_ENV']) ? $_ENV['APP_ENV'] : $sEnv);
|
||||
}
|
||||
|
||||
if (file_exists($p = "$path.$env")) {
|
||||
$dotenv->load($p);
|
||||
}
|
||||
if (file_exists($sPathDist = "$sPath.$sEnv"))
|
||||
{
|
||||
$oDotenv->load($sPathDist);
|
||||
}
|
||||
|
||||
if (file_exists($p = "$path.$env.local")) {
|
||||
$dotenv->load($p);
|
||||
}
|
||||
}
|
||||
if (file_exists($sPathDist = "$sPath.$sEnv.local"))
|
||||
{
|
||||
$oDotenv->load($sPathDist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set debug mode only when necessary
|
||||
@@ -69,27 +107,30 @@ if (utils::ReadParam('debug', 'false') === 'true')
|
||||
$_SERVER += $_ENV;
|
||||
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = (isset($_SERVER['APP_ENV']) ? $_SERVER['APP_ENV'] : (isset($_ENV['APP_ENV']) ? $_ENV['APP_ENV'] : null)) ?: 'prod';
|
||||
$_SERVER['APP_DEBUG'] = isset($_SERVER['APP_DEBUG']) ? $_SERVER['APP_DEBUG'] : (isset($_ENV['APP_DEBUG']) ? $_ENV['APP_DEBUG'] : ('prod' !== $_SERVER['APP_ENV']));
|
||||
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
|
||||
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int)$_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'],
|
||||
FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
|
||||
|
||||
if ($_SERVER['APP_DEBUG']) {
|
||||
if ($_SERVER['APP_DEBUG'])
|
||||
{
|
||||
umask(0000);
|
||||
|
||||
if (class_exists(Debug::class)) {
|
||||
if (class_exists(Debug::class))
|
||||
{
|
||||
Debug::enable();
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($_ENV['PORTAL_ID']))
|
||||
if (isset($_ENV['PORTAL_ID']))
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
// Note: Default value is set to "false" to differentiate an empty value from a non given parameter
|
||||
elseif($sPortalId = utils::ReadParam('portal_id', false, true))
|
||||
elseif ($sPortalId = utils::ReadParam('portal_id', false, true))
|
||||
{
|
||||
|
||||
$_ENV['PORTAL_ID'] = $sPortalId;
|
||||
}
|
||||
elseif(defined('PORTAL_ID'))
|
||||
elseif (defined('PORTAL_ID'))
|
||||
{
|
||||
$_ENV['PORTAL_ID'] = PORTAL_ID;
|
||||
@trigger_error(
|
||||
@@ -101,7 +142,7 @@ elseif(defined('PORTAL_ID'))
|
||||
);
|
||||
}
|
||||
|
||||
if(empty($_ENV['PORTAL_ID']))
|
||||
if (empty($_ENV['PORTAL_ID']))
|
||||
{
|
||||
echo "Missing argument 'portal_id'";
|
||||
exit;
|
||||
@@ -110,7 +151,7 @@ if(empty($_ENV['PORTAL_ID']))
|
||||
// Env. vars to be used in templates and others
|
||||
$_ENV['COMBODO_CURRENT_ENVIRONMENT'] = utils::GetCurrentEnvironment();
|
||||
$_ENV['COMBODO_ABSOLUTE_URL'] = utils::GetAbsoluteUrlAppRoot();
|
||||
$_ENV['COMBODO_MODULES_ABSOLUTE_URL'] = utils::GetAbsoluteUrlModulesRoot();
|
||||
$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_URL'] = utils::GetAbsoluteUrlModulesRoot() . 'itop-portal-base/portal/public/';
|
||||
$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'] = MODULESROOT . '/itop-portal-base/portal/public/';
|
||||
$_ENV['COMBODO_PORTAL_INSTANCE_ABSOLUTE_URL'] = utils::GetAbsoluteUrlModulesRoot() . $_ENV['PORTAL_ID'] . '/';
|
||||
$_ENV['COMBODO_MODULES_ABSOLUTE_URL'] = utils::GetAbsoluteUrlModulesRoot();
|
||||
$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_URL'] = utils::GetAbsoluteUrlModulesRoot().'itop-portal-base/portal/public/';
|
||||
$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'] = MODULESROOT.'/itop-portal-base/portal/public/';
|
||||
$_ENV['COMBODO_PORTAL_INSTANCE_ABSOLUTE_URL'] = utils::GetAbsoluteUrlModulesRoot().$_ENV['PORTAL_ID'].'/';
|
||||
@@ -1,7 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
return [
|
||||
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true],
|
||||
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true],
|
||||
];
|
||||
|
||||
@@ -20,52 +20,60 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// Disable PhpUnhandledExceptionInspection as the exception handling is made by the file including this one
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
// Loading file
|
||||
use Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration\Basic;
|
||||
use Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration\Forms;
|
||||
use Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration\Lists;
|
||||
|
||||
// Note: ModuleDesign service is not available yet as this script is processed before service generation,
|
||||
// Note: ModuleDesign service is not available yet as this script is processed before services generation,
|
||||
// that's why we have to instantiate it manually.
|
||||
$oModuleDesign = new ModuleDesign($_ENV['PORTAL_ID']);
|
||||
|
||||
// TODO: The following code needs to be refactored to more independent and atomic services.
|
||||
|
||||
// Load portal conf. such as properties, themes, templates, ...
|
||||
// Append into %combodo.portal.instance.conf%
|
||||
$oBasicCompat = new Basic($oModuleDesign);
|
||||
$oBasicCompat->Process($container);
|
||||
|
||||
// Load portal forms definition
|
||||
// Append into %combodo.portal.instance.conf%
|
||||
$oFormsCompat = new Forms($oModuleDesign);
|
||||
$oFormsCompat->Process($container);
|
||||
|
||||
// Load portal lists definition
|
||||
// Append into %combodo.portal.instance.conf%
|
||||
$oListsCompat = new Lists($oModuleDesign);
|
||||
$oListsCompat->Process($container);
|
||||
|
||||
// - Generating CSS files
|
||||
// Generating CSS files
|
||||
$aImportPaths = array($_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'].'css/');
|
||||
$aPortalConf = $container->getParameter('combodo.portal.instance.conf');
|
||||
foreach ($aPortalConf['properties']['themes'] as $key => $value)
|
||||
foreach ($aPortalConf['properties']['themes'] as $sKey => $value)
|
||||
{
|
||||
if (!is_array($value))
|
||||
{
|
||||
$aPortalConf['properties']['themes'][$key] = $_ENV['COMBODO_ABSOLUTE_URL'].utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$value, $aImportPaths);
|
||||
$aPortalConf['properties']['themes'][$sKey] = $_ENV['COMBODO_ABSOLUTE_URL'].utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$value,
|
||||
$aImportPaths);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aValues = array();
|
||||
foreach ($value as $sSubValue)
|
||||
{
|
||||
$aValues[] = $_ENV['COMBODO_ABSOLUTE_URL'].utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$sSubValue, $aImportPaths);
|
||||
$aValues[] = $_ENV['COMBODO_ABSOLUTE_URL'].utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$sSubValue,
|
||||
$aImportPaths);
|
||||
}
|
||||
$aPortalConf['properties']['themes'][$key] = $aValues;
|
||||
$aPortalConf['properties']['themes'][$sKey] = $aValues;
|
||||
}
|
||||
}
|
||||
$container->setParameter('combodo.portal.instance.conf', $aPortalConf);
|
||||
|
||||
//TODO: The following needs to be refactored
|
||||
//session messages
|
||||
// Session messages
|
||||
$aAllMessages = array();
|
||||
if ((array_key_exists('obj_messages', $_SESSION)) && (!empty($_SESSION['obj_messages'])))
|
||||
{
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
framework:
|
||||
cache:
|
||||
# Put the unique name of your app here: the prefix seed
|
||||
# is used to compute stable namespaces for cache keys.
|
||||
#prefix_seed: your_vendor_name/app_name
|
||||
cache:
|
||||
# Put the unique name of your app here: the prefix seed
|
||||
# is used to compute stable namespaces for cache keys.
|
||||
#prefix_seed: your_vendor_name/app_name
|
||||
|
||||
# The app cache caches to the filesystem by default.
|
||||
# Other options include:
|
||||
# The app cache caches to the filesystem by default.
|
||||
# Other options include:
|
||||
|
||||
# Redis
|
||||
#app: cache.adapter.redis
|
||||
#default_redis_provider: redis://localhost
|
||||
# Redis
|
||||
#app: cache.adapter.redis
|
||||
#default_redis_provider: redis://localhost
|
||||
|
||||
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
|
||||
#app: cache.adapter.apcu
|
||||
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
|
||||
#app: cache.adapter.apcu
|
||||
|
||||
# Namespaced pools use the above "app" backend by default
|
||||
#pools:
|
||||
#my.dedicated.cache: ~
|
||||
# Namespaced pools use the above "app" backend by default
|
||||
#pools:
|
||||
#my.dedicated.cache: ~
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
framework:
|
||||
router:
|
||||
strict_requirements: true
|
||||
router:
|
||||
strict_requirements: true
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
framework:
|
||||
secret: '%env(APP_SECRET)%'
|
||||
#default_locale: en
|
||||
#csrf_protection: true
|
||||
#http_method_override: true
|
||||
secret: '%env(APP_SECRET)%'
|
||||
#default_locale: en
|
||||
#csrf_protection: true
|
||||
#http_method_override: true
|
||||
|
||||
# Enables session support. Note that the session will ONLY be started if you read or write from it.
|
||||
# Remove or comment this section to explicitly disable session support.
|
||||
session:
|
||||
handler_id: ~
|
||||
# Enables session support. Note that the session will ONLY be started if you read or write from it.
|
||||
# Remove or comment this section to explicitly disable session support.
|
||||
session:
|
||||
handler_id: ~
|
||||
|
||||
#esi: true
|
||||
#fragments: true
|
||||
php_errors:
|
||||
log: true
|
||||
#esi: true
|
||||
#fragments: true
|
||||
php_errors:
|
||||
log: true
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
framework:
|
||||
router:
|
||||
strict_requirements: ~
|
||||
router:
|
||||
strict_requirements: ~
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
framework:
|
||||
test: true
|
||||
session:
|
||||
storage_id: session.storage.mock_file
|
||||
test: true
|
||||
session:
|
||||
storage_id: session.storage.mock_file
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
framework:
|
||||
router:
|
||||
strict_requirements: true
|
||||
router:
|
||||
strict_requirements: true
|
||||
|
||||
@@ -3,4 +3,4 @@ web_profiler:
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler: { collect: false }
|
||||
profiler: { collect: falseS }
|
||||
@@ -1,4 +1,4 @@
|
||||
twig:
|
||||
default_path: '%combodo.modules.absolute_path%'
|
||||
debug: '%kernel.debug%'
|
||||
strict_variables: '%kernel.debug%'
|
||||
default_path: '%combodo.modules.absolute_path%'
|
||||
debug: '%kernel.debug%'
|
||||
strict_variables: '%kernel.debug%'
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
_errors:
|
||||
resource: '@TwigBundle/Resources/config/routing/errors.xml'
|
||||
prefix: /_error
|
||||
resource: '@TwigBundle/Resources/config/routing/errors.xml'
|
||||
prefix: /_error
|
||||
|
||||
@@ -1,34 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by Bruno DA SILVA, working for Combodo
|
||||
* Date: 30/01/19
|
||||
* Time: 18:06
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Portal\Routing\ItopExtensionsExtraRoutes;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use App\Controller\BlogController;
|
||||
|
||||
$oRouteCollection = new RouteCollection();
|
||||
|
||||
$aRoutes = \Combodo\iTop\Portal\Routing\ItopExtensionsExtraRoutes::getRoutes();
|
||||
$aRoutes = ItopExtensionsExtraRoutes::GetRoutes();
|
||||
foreach ($aRoutes as $aRoute)
|
||||
{
|
||||
$aRoute['values'] = (isset($aRoute['values'])) ? $aRoute['values'] : [];
|
||||
$aRoute['asserts'] = (isset($aRoute['asserts'])) ? $aRoute['asserts'] : [];
|
||||
|
||||
$routes = new RouteCollection();
|
||||
|
||||
foreach ($aRoutes as $route) {
|
||||
$route['values'] = (isset($route['values'])) ? $route['values'] : [];
|
||||
$route['asserts'] = (isset($route['asserts'])) ? $route['asserts'] : [];
|
||||
|
||||
$routes->add(
|
||||
$route['bind'],
|
||||
new Route(
|
||||
$route['pattern'],
|
||||
array_merge(
|
||||
['_controller' => $route['callback']],
|
||||
$route['values']
|
||||
),
|
||||
$route['asserts']
|
||||
)
|
||||
);
|
||||
$oRouteCollection->add(
|
||||
$aRoute['bind'],
|
||||
new Route(
|
||||
$aRoute['pattern'],
|
||||
array_merge(
|
||||
['_controller' => $aRoute['callback']],
|
||||
$aRoute['values']
|
||||
),
|
||||
$aRoute['asserts']
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $routes;
|
||||
return $oRouteCollection;
|
||||
@@ -19,115 +19,115 @@
|
||||
# Files in the packages/ subdirectory configure your dependencies.
|
||||
|
||||
imports:
|
||||
- { resource: "legacy_silex_compat_layer.php" }
|
||||
- { resource: "legacy_silex_compat_layer.php" }
|
||||
|
||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
|
||||
parameters:
|
||||
# Replace default url generator service
|
||||
router.options.generator_base_class: Combodo\iTop\Portal\Routing\UrlGenerator
|
||||
# Replace default url generator service
|
||||
router.options.generator_base_class: Combodo\iTop\Portal\Routing\UrlGenerator
|
||||
|
||||
# Used in templates
|
||||
combodo.current_environment: '%env(string:COMBODO_CURRENT_ENVIRONMENT)%'
|
||||
combodo.absolute_url: '%env(string:COMBODO_ABSOLUTE_URL)%'
|
||||
combodo.modules.absolute_url: '%env(string:COMBODO_MODULES_ABSOLUTE_URL)%'
|
||||
combodo.modules.absolute_path: !php/const MODULESROOT
|
||||
combodo.portal.base.absolute_url: '%env(string:COMBODO_PORTAL_BASE_ABSOLUTE_URL)%'
|
||||
combodo.portal.base.absolute_path: '%env(string:COMBODO_PORTAL_BASE_ABSOLUTE_PATH)%'
|
||||
combodo.portal.instance.absolute_url: '%env(string:COMBODO_PORTAL_INSTANCE_ABSOLUTE_URL)%'
|
||||
combodo.portal.instance.id: '%env(string:PORTAL_ID)%'
|
||||
# Used in templates
|
||||
combodo.current_environment: '%env(string:COMBODO_CURRENT_ENVIRONMENT)%'
|
||||
combodo.absolute_url: '%env(string:COMBODO_ABSOLUTE_URL)%'
|
||||
combodo.modules.absolute_url: '%env(string:COMBODO_MODULES_ABSOLUTE_URL)%'
|
||||
combodo.modules.absolute_path: !php/const MODULESROOT
|
||||
combodo.portal.base.absolute_url: '%env(string:COMBODO_PORTAL_BASE_ABSOLUTE_URL)%'
|
||||
combodo.portal.base.absolute_path: '%env(string:COMBODO_PORTAL_BASE_ABSOLUTE_PATH)%'
|
||||
combodo.portal.instance.absolute_url: '%env(string:COMBODO_PORTAL_INSTANCE_ABSOLUTE_URL)%'
|
||||
combodo.portal.instance.id: '%env(string:PORTAL_ID)%'
|
||||
|
||||
services:
|
||||
# Default configuration for services in *this* file
|
||||
_defaults:
|
||||
autowire: true # Automatically injects dependencies in your services.
|
||||
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||
public: false # Allows optimizing the container by removing unused services; this also means
|
||||
# fetching services directly from the container via $container->get() won't work.
|
||||
# The best practice is to be explicit about your dependencies anyway.
|
||||
bind:
|
||||
$bDebug: '%kernel.debug%'
|
||||
$sPortalCachePath: '%kernel.cache_dir%/'
|
||||
$sPortalId: '%env(string:PORTAL_ID)%'
|
||||
$aCombodoPortalInstanceConf: '%combodo.portal.instance.conf%'
|
||||
$sCombodoPortalInstanceAbsoluteUrl: '%env(string:COMBODO_PORTAL_INSTANCE_ABSOLUTE_URL)%'
|
||||
# Default configuration for services in *this* file
|
||||
_defaults:
|
||||
autowire: true # Automatically injects dependencies in your services.
|
||||
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||
public: false # Allows optimizing the container by removing unused services; this also means
|
||||
# fetching services directly from the container via $container->get() won't work.
|
||||
# The best practice is to be explicit about your dependencies anyway.
|
||||
bind:
|
||||
$bDebug: '%kernel.debug%'
|
||||
$sPortalCachePath: '%kernel.cache_dir%/'
|
||||
$sPortalId: '%env(string:PORTAL_ID)%'
|
||||
$aCombodoPortalInstanceConf: '%combodo.portal.instance.conf%'
|
||||
$sCombodoPortalInstanceAbsoluteUrl: '%env(string:COMBODO_PORTAL_INSTANCE_ABSOLUTE_URL)%'
|
||||
|
||||
# Makes classes in src/ available to be used as services
|
||||
# This creates a service per class whose id is the fully-qualified class name
|
||||
Combodo\iTop\Portal\:
|
||||
resource: '../src/*'
|
||||
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
|
||||
# Makes classes in src/ available to be used as services
|
||||
# This creates a service per class whose id is the fully-qualified class name
|
||||
Combodo\iTop\Portal\:
|
||||
resource: '../src/*'
|
||||
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
|
||||
|
||||
# Controllers are imported separately to make sure services can be injected
|
||||
# as action arguments even if you don't extend any base controller class
|
||||
Combodo\iTop\Portal\Controller\:
|
||||
resource: '../src/Controller'
|
||||
tags: ['controller.service_arguments']
|
||||
# Controllers are imported separately to make sure services can be injected
|
||||
# as action arguments even if you don't extend any base controller class
|
||||
Combodo\iTop\Portal\Controller\:
|
||||
resource: '../src/Controller'
|
||||
tags: ['controller.service_arguments']
|
||||
|
||||
# Tag services without defining them (see https://symfony.com/doc/current/service_container/tags.html#autoconfiguring-tags)
|
||||
_instanceof:
|
||||
Combodo\iTop\Portal\EventListener\UserProvider:
|
||||
tags: [{ name: 'kernel.event_listener', event: 'kernel.request' }]
|
||||
calls:
|
||||
- [setContainer, ['@service_container']]
|
||||
Combodo\iTop\Portal\EventListener\ApplicationContextSetUrlMakerClass:
|
||||
tags: [{ name: 'kernel.event_listener', event: 'kernel.request' }]
|
||||
# Tag services without defining them (see https://symfony.com/doc/current/service_container/tags.html#autoconfiguring-tags)
|
||||
_instanceof:
|
||||
Combodo\iTop\Portal\EventListener\UserProvider:
|
||||
tags: [{ name: 'kernel.event_listener', event: 'kernel.request' }]
|
||||
calls:
|
||||
- [setContainer, ['@service_container']]
|
||||
Combodo\iTop\Portal\EventListener\ApplicationContextSetUrlMakerClass:
|
||||
tags: [{ name: 'kernel.event_listener', event: 'kernel.request' }]
|
||||
|
||||
# Add more service definitions when explicit configuration is needed
|
||||
# Please note that last definitions always *replace* previous ones
|
||||
# Add more service definitions when explicit configuration is needed
|
||||
# Please note that last definitions always *replace* previous ones
|
||||
|
||||
# Legacy code as a service: since it is not in the auto-wiring path, it needs to be explicitly declared
|
||||
ModuleDesign:
|
||||
public: true
|
||||
class: ModuleDesign
|
||||
arguments:
|
||||
- '%combodo.portal.instance.id%'
|
||||
# Legacy code as a service: since it is not in the auto-wiring path, it needs to be explicitly declared
|
||||
ModuleDesign:
|
||||
public: true
|
||||
class: ModuleDesign
|
||||
arguments:
|
||||
- '%combodo.portal.instance.id%'
|
||||
|
||||
# Decoration
|
||||
# - Compatibility layer with Silex\Application which was used almost everywhere in the portal's templates
|
||||
Combodo\iTop\Portal\Twig\AppVariable:
|
||||
decorates: twig.app_variable
|
||||
arguments:
|
||||
- '@Combodo\iTop\Portal\Twig\AppVariable.inner'
|
||||
- '@service_container'
|
||||
# Decoration
|
||||
# - Compatibility layer with Silex\Application which was used almost everywhere in the portal's templates
|
||||
Combodo\iTop\Portal\Twig\AppVariable:
|
||||
decorates: twig.app_variable
|
||||
arguments:
|
||||
- '@Combodo\iTop\Portal\Twig\AppVariable.inner'
|
||||
- '@service_container'
|
||||
|
||||
# Standard services
|
||||
combodo.current_contact.photo_url:
|
||||
public: true
|
||||
class: Combodo\iTop\Portal\VariableAccessor\CombodoCurrentContactPhotoUrl
|
||||
arguments: ['@combodo.current_user']
|
||||
# Note: This service is initialized with a UserLocal object as it needs a class that can be instantiated.
|
||||
# Anyway, it will be replaced with the real class by UserProvider in onKernelRequestEvent.
|
||||
# Note: Services relying on this one should use \User in their signature and not \UserLocal.
|
||||
combodo.current_user:
|
||||
public: true
|
||||
class: UserLocal
|
||||
# Standard services
|
||||
combodo.current_contact.photo_url:
|
||||
public: true
|
||||
class: Combodo\iTop\Portal\VariableAccessor\CombodoCurrentContactPhotoUrl
|
||||
arguments: ['@combodo.current_user']
|
||||
# Note: This service is initialized with a UserLocal object as it needs a class that can be instantiated.
|
||||
# Anyway, it will be replaced with the real class by UserProvider in onKernelRequestEvent.
|
||||
# Note: Services relying on this one should use \User in their signature and not \UserLocal.
|
||||
combodo.current_user:
|
||||
public: true
|
||||
class: UserLocal
|
||||
|
||||
# Aliases
|
||||
brick_collection:
|
||||
alias: Combodo\iTop\Portal\Brick\BrickCollection
|
||||
public: true
|
||||
request_manipulator:
|
||||
alias: Combodo\iTop\Portal\Helper\RequestManipulatorHelper
|
||||
public: true
|
||||
scope_validator:
|
||||
alias: Combodo\iTop\Portal\Helper\ScopeValidatorHelper
|
||||
public: true
|
||||
security_helper:
|
||||
alias: Combodo\iTop\Portal\Helper\SecurityHelper
|
||||
public: true
|
||||
context_manipulator:
|
||||
alias: Combodo\iTop\Portal\Helper\ContextManipulatorHelper
|
||||
public: true
|
||||
lifecycle_validator:
|
||||
alias: Combodo\iTop\Portal\Helper\LifecycleValidatorHelper
|
||||
public: true
|
||||
url_generator:
|
||||
alias: router
|
||||
public: true
|
||||
object_form_handler:
|
||||
alias: Combodo\iTop\Portal\Helper\ObjectFormHandlerHelper
|
||||
public: true
|
||||
browse_brick:
|
||||
alias: Combodo\iTop\Portal\Helper\BrowseBrickHelper
|
||||
public: true
|
||||
# Aliases
|
||||
brick_collection:
|
||||
alias: Combodo\iTop\Portal\Brick\BrickCollection
|
||||
public: true
|
||||
request_manipulator:
|
||||
alias: Combodo\iTop\Portal\Helper\RequestManipulatorHelper
|
||||
public: true
|
||||
scope_validator:
|
||||
alias: Combodo\iTop\Portal\Helper\ScopeValidatorHelper
|
||||
public: true
|
||||
security_helper:
|
||||
alias: Combodo\iTop\Portal\Helper\SecurityHelper
|
||||
public: true
|
||||
context_manipulator:
|
||||
alias: Combodo\iTop\Portal\Helper\ContextManipulatorHelper
|
||||
public: true
|
||||
lifecycle_validator:
|
||||
alias: Combodo\iTop\Portal\Helper\LifecycleValidatorHelper
|
||||
public: true
|
||||
url_generator:
|
||||
alias: router
|
||||
public: true
|
||||
object_form_handler:
|
||||
alias: Combodo\iTop\Portal\Helper\ObjectFormHandlerHelper
|
||||
public: true
|
||||
browse_brick:
|
||||
alias: Combodo\iTop\Portal\Helper\BrowseBrickHelper
|
||||
public: true
|
||||
@@ -1,22 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Portal\Kernel;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
require_once MODULESROOT . 'itop-portal-base/portal/config/bootstrap.php';
|
||||
require_once MODULESROOT.'itop-portal-base/portal/config/bootstrap.php';
|
||||
|
||||
// Note: Manually refactored ternary condition to be PHP 5.x compatible
|
||||
if ($trustedProxies = isset($_SERVER['TRUSTED_PROXIES']) ? $_SERVER['TRUSTED_PROXIES'] : (isset($_ENV['TRUSTED_PROXIES']) ? $_ENV['TRUSTED_PROXIES'] : false) ) {
|
||||
Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);
|
||||
if ($trustedProxies = isset($_SERVER['TRUSTED_PROXIES']) ? $_SERVER['TRUSTED_PROXIES'] : (isset($_ENV['TRUSTED_PROXIES']) ? $_ENV['TRUSTED_PROXIES'] : false))
|
||||
{
|
||||
Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);
|
||||
}
|
||||
|
||||
// Note: Manually refactored ternary condition to be PHP 5.x compatible
|
||||
if ($trustedHosts = isset($_SERVER['TRUSTED_HOSTS']) ? $_SERVER['TRUSTED_HOSTS'] : (isset($_ENV['TRUSTED_HOSTS']) ? $_ENV['TRUSTED_HOSTS'] : false) ) {
|
||||
Request::setTrustedHosts([$trustedHosts]);
|
||||
if ($trustedHosts = isset($_SERVER['TRUSTED_HOSTS']) ? $_SERVER['TRUSTED_HOSTS'] : (isset($_ENV['TRUSTED_HOSTS']) ? $_ENV['TRUSTED_HOSTS'] : false))
|
||||
{
|
||||
Request::setTrustedHosts([$trustedHosts]);
|
||||
}
|
||||
|
||||
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
|
||||
$request = Request::createFromGlobals();
|
||||
$response = $kernel->handle($request);
|
||||
$response->send();
|
||||
$kernel->terminate($request, $response);
|
||||
$oKernel = new Kernel($_SERVER['APP_ENV'], (bool)$_SERVER['APP_DEBUG']);
|
||||
$oRequest = Request::createFromGlobals();
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$oResponse = $oKernel->handle($oRequest);
|
||||
$oResponse->send();
|
||||
$oKernel->terminate($oRequest, $oResponse);
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2018 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\Brick;
|
||||
|
||||
require_once APPROOT . '/core/moduledesign.class.inc.php';
|
||||
require_once APPROOT . '/setup/compiler.class.inc.php';
|
||||
require_once APPROOT.'/core/moduledesign.class.inc.php';
|
||||
require_once APPROOT.'/setup/compiler.class.inc.php';
|
||||
|
||||
use DOMFormatException;
|
||||
use ModuleDesign;
|
||||
@@ -28,40 +31,68 @@ use Combodo\iTop\DesignElement;
|
||||
|
||||
/**
|
||||
* Description of AbstractBrick
|
||||
*
|
||||
* Bricks are used mostly in the portal for now, not the console.
|
||||
* This class defines common functionnalities for the extended classes.
|
||||
*
|
||||
* Bricks are used mostly in the portal for now, not the console.
|
||||
* This class defines common functionalities for the extended classes.
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
*/
|
||||
abstract class AbstractBrick
|
||||
{
|
||||
/** @var string ENUM_DATA_LOADING_LAZY */
|
||||
const ENUM_DATA_LOADING_LAZY = 'lazy';
|
||||
/** @var string ENUM_DATA_LOADING_FULL */
|
||||
const ENUM_DATA_LOADING_FULL = 'full';
|
||||
/** @var string ENUM_DATA_LOADING_AUTO */
|
||||
const ENUM_DATA_LOADING_AUTO = 'auto';
|
||||
|
||||
/** @var bool DEFAULT_MANDATORY */
|
||||
const DEFAULT_MANDATORY = true;
|
||||
/** @var bool DEFAULT_ACTIVE */
|
||||
const DEFAULT_ACTIVE = true;
|
||||
/** @var bool DEFAULT_VISIBLE */
|
||||
const DEFAULT_VISIBLE = true;
|
||||
/** @var float DEFAULT_RANK */
|
||||
const DEFAULT_RANK = 1.0;
|
||||
/** @var string|null DEFAULT_PAGE_TEMPLATE_PATH */
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = null;
|
||||
/** @var string DEFAULT_TITLE */
|
||||
const DEFAULT_TITLE = '';
|
||||
/** @var string|null DEFAULT_DESCRIPTION */
|
||||
const DEFAULT_DESCRIPTION = null;
|
||||
/** @var string DEFAULT_DATA_LOADING */
|
||||
const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_AUTO;
|
||||
/** @var string DEFAULT_ALLOWED_PROFILES_OQL */
|
||||
const DEFAULT_ALLOWED_PROFILES_OQL = '';
|
||||
/** @var string DEFAULT_DENIED_PROFILES_OQL */
|
||||
const DEFAULT_DENIED_PROFILES_OQL = '';
|
||||
|
||||
/** @var string $sId */
|
||||
protected $sId;
|
||||
/** @var bool $bMandatory */
|
||||
protected $bMandatory;
|
||||
/** @var bool $bActive */
|
||||
protected $bActive;
|
||||
/** @var bool $bVisible */
|
||||
protected $bVisible;
|
||||
/** @var float $fRank */
|
||||
protected $fRank;
|
||||
/** @var string|null $sPageTemplatePath */
|
||||
protected $sPageTemplatePath;
|
||||
/** @var string $sTitle */
|
||||
protected $sTitle;
|
||||
/** @var string|null $sDescription */
|
||||
protected $sDescription;
|
||||
/** @var string $sDataLoading */
|
||||
protected $sDataLoading;
|
||||
/** @var array $aAllowedProfiles */
|
||||
protected $aAllowedProfiles;
|
||||
/** @var array $aDeniedProfiles */
|
||||
protected $aDeniedProfiles;
|
||||
/** @var string $sAllowedProfilesOql */
|
||||
protected $sAllowedProfilesOql;
|
||||
/** @var string $sDeniedProfilesOql */
|
||||
protected $sDeniedProfilesOql;
|
||||
|
||||
/**
|
||||
@@ -77,7 +108,7 @@ abstract class AbstractBrick
|
||||
/**
|
||||
* Default attributes values of AbstractBrick are specified in the definition, not the constructor.
|
||||
*/
|
||||
function __construct()
|
||||
public function __construct()
|
||||
{
|
||||
$this->bMandatory = static::DEFAULT_MANDATORY;
|
||||
$this->bActive = static::DEFAULT_ACTIVE;
|
||||
@@ -253,8 +284,8 @@ abstract class AbstractBrick
|
||||
* Sets if the brick is visible
|
||||
*
|
||||
* @param boolean $bVisible
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function SetVisible($bVisible)
|
||||
{
|
||||
@@ -344,12 +375,13 @@ abstract class AbstractBrick
|
||||
* Sets the allowed profiles for the brick
|
||||
*
|
||||
* @param array $aAllowedProfiles
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function SetAllowedProfiles($aAllowedProfiles)
|
||||
{
|
||||
$this->aAllowedProfiles = $aAllowedProfiles;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -357,8 +389,8 @@ abstract class AbstractBrick
|
||||
* Sets the denied profiles for the brick
|
||||
*
|
||||
* @param array $aDeniedProfiles
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function SetDeniedProfiles($aDeniedProfiles)
|
||||
{
|
||||
@@ -382,7 +414,7 @@ abstract class AbstractBrick
|
||||
/**
|
||||
* Sets the denied profiles oql query for the brick
|
||||
*
|
||||
* @param array $sDeniedProfilesOql
|
||||
* @param string $sDeniedProfilesOql
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
@@ -396,12 +428,13 @@ abstract class AbstractBrick
|
||||
* Adds $sProfile to the list of allowed profiles for that brick
|
||||
*
|
||||
* @param string $sProfile
|
||||
*
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function AddAllowedProfile($sProfile)
|
||||
{
|
||||
$this->aAllowedProfiles[] = $sProfile;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -409,7 +442,7 @@ abstract class AbstractBrick
|
||||
* Removes $sProfile from the list of allowed profiles
|
||||
*
|
||||
* @param string $sProfile
|
||||
*
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function RemoveAllowedProfile($sProfile)
|
||||
@@ -418,6 +451,7 @@ abstract class AbstractBrick
|
||||
{
|
||||
unset($this->aAllowedProfiles[$sProfile]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -435,12 +469,13 @@ abstract class AbstractBrick
|
||||
* Adds $sProfile to the list of denied profiles for that brick
|
||||
*
|
||||
* @param string $sProfile
|
||||
*
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function AddDeniedProfile($sProfile)
|
||||
{
|
||||
$this->aDeniedProfiles[] = $sProfile;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -448,7 +483,7 @@ abstract class AbstractBrick
|
||||
* Removes $sProfile from the list of denied profiles
|
||||
*
|
||||
* @param string $sProfile
|
||||
*
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*/
|
||||
public function RemoveDeniedProfile($sProfile)
|
||||
@@ -457,6 +492,7 @@ abstract class AbstractBrick
|
||||
{
|
||||
unset($this->aDeniedProfiles[$sProfile]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -477,7 +513,7 @@ abstract class AbstractBrick
|
||||
* Priority is deny/allow
|
||||
*
|
||||
* @param string $sProfile
|
||||
*
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function IsGrantedForProfile($sProfile)
|
||||
@@ -492,7 +528,7 @@ abstract class AbstractBrick
|
||||
* Priority is deny/allow
|
||||
*
|
||||
* @param array $aProfiles
|
||||
*
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function IsGrantedForProfiles($aProfiles)
|
||||
@@ -543,9 +579,9 @@ abstract class AbstractBrick
|
||||
* This is used to set all the brick attributes at once.
|
||||
*
|
||||
* @param \Combodo\iTop\DesignElement $oMDElement
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
|
||||
*
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function LoadFromXml(DesignElement $oMDElement)
|
||||
@@ -558,28 +594,31 @@ abstract class AbstractBrick
|
||||
$this->SetId($oMDElement->getAttribute('id'));
|
||||
|
||||
// Checking others elements
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
|
||||
{
|
||||
switch ($oBrickSubNode->nodeName)
|
||||
{
|
||||
case 'mandatory':
|
||||
$this->SetMandatory(($oBrickSubNode->GetText() === 'no') ? false : true );
|
||||
$this->SetMandatory(($oBrickSubNode->GetText() === 'no') ? false : true);
|
||||
break;
|
||||
case 'active':
|
||||
$this->SetActive(($oBrickSubNode->GetText() === 'false') ? false : true );
|
||||
$this->SetActive(($oBrickSubNode->GetText() === 'false') ? false : true);
|
||||
break;
|
||||
case 'rank':
|
||||
$oOptionalNode = $oBrickSubNode->GetOptionalElement('default');
|
||||
if ($oOptionalNode !== null)
|
||||
{
|
||||
$this->SetRank((float) $oOptionalNode->GetText(static::DEFAULT_RANK));
|
||||
$this->SetRank((float)$oOptionalNode->GetText(static::DEFAULT_RANK));
|
||||
}
|
||||
break;
|
||||
case 'templates':
|
||||
$oTemplateNodeList = $oBrickSubNode->GetNodes('template[@id=' . ModuleDesign::XPathQuote('page') . ']');
|
||||
$oTemplateNodeList = $oBrickSubNode->GetNodes('template[@id='.ModuleDesign::XPathQuote('page').']');
|
||||
if ($oTemplateNodeList->length > 0)
|
||||
{
|
||||
$this->SetPageTemplatePath($oTemplateNodeList->item(0)->GetText(static::DEFAULT_PAGE_TEMPLATE_PATH));
|
||||
/** @var \Combodo\iTop\DesignElement $oTemplateNode */
|
||||
$oTemplateNode = $oTemplateNodeList->item(0);
|
||||
$this->SetPageTemplatePath($oTemplateNode->GetText(static::DEFAULT_PAGE_TEMPLATE_PATH));
|
||||
}
|
||||
break;
|
||||
case 'title':
|
||||
@@ -596,11 +635,13 @@ abstract class AbstractBrick
|
||||
$this->SetDataLoading($oBrickSubNode->GetText(static::DEFAULT_DATA_LOADING));
|
||||
break;
|
||||
case 'security':
|
||||
/** @var \Combodo\iTop\DesignElement $oSecurityNode */
|
||||
foreach ($oBrickSubNode->childNodes 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);
|
||||
throw new DOMFormatException('Brick security node "'.$oSecurityNode->nodeName.'" must contain an OQL query, it cannot be empty',
|
||||
null, null, $oMDElement);
|
||||
}
|
||||
|
||||
switch ($oSecurityNode->nodeName)
|
||||
|
||||
@@ -1,35 +1,49 @@
|
||||
<?php
|
||||
|
||||
// Copyright (c) 2010-2018 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
//
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\Brick;
|
||||
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Dict;
|
||||
use DOMFormatException;
|
||||
|
||||
/**
|
||||
* Class AggregatePageBrick
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Brick
|
||||
* @since 2.5.0
|
||||
* @author Eric Espie <eric.espie@combodo.com>
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @author Pierre Goiffon <pierre.goiffon@combodo.com>
|
||||
*/
|
||||
class AggregatePageBrick extends PortalBrick
|
||||
{
|
||||
// Overloaded constants
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fa fa-dashboard';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fa fa-dashboard fa-2x';
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/aggregate-page/layout.html.twig';
|
||||
|
||||
static $sRouteName = 'p_aggregatepage_brick';
|
||||
// Overloaded variables
|
||||
public static $sRouteName = 'p_aggregatepage_brick';
|
||||
|
||||
/**
|
||||
* @var string[] list of bricks to use, ordered by rank (key=id, value=rank)
|
||||
@@ -50,23 +64,25 @@ class AggregatePageBrick extends PortalBrick
|
||||
* @param \Combodo\iTop\DesignElement $oMDElement
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\AggregatePageBrick
|
||||
*
|
||||
*
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function LoadFromXml(DesignElement $oMDElement)
|
||||
{
|
||||
parent::LoadFromXml($oMDElement);
|
||||
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
|
||||
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', null,
|
||||
throw new DOMFormatException('AggregatePageBrick : must have an id attribute', null,
|
||||
null, $oAggregatePageBrickNode);
|
||||
}
|
||||
$sBrickName = $oAggregatePageBrickNode->getAttribute('id');
|
||||
|
||||
@@ -31,24 +31,24 @@ use Combodo\iTop\Portal\Helper\ApplicationHelper;
|
||||
* Class BrickCollection
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Brick
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class BrickCollection
|
||||
{
|
||||
/** @var \ModuleDesign */
|
||||
/** @var \ModuleDesign $oModuleDesign */
|
||||
private $oModuleDesign;
|
||||
/** @var array|null $aAllowedBricks Lazily computed */
|
||||
private $aAllowedBricks;
|
||||
/** @var int $iDisplayedInHome Lazily computed */
|
||||
private $iDisplayedInHome;
|
||||
/** @var int $iDisplayedInNavigationMenu Lazily computed */
|
||||
private $iDisplayedInNavigationMenu;
|
||||
/** @var array $aHomeOrdering */
|
||||
private $aHomeOrdering;
|
||||
/** @var array $aNavigationMenuOrdering */
|
||||
private $aNavigationMenuOrdering;
|
||||
/** @var array|null $aAllowedBricks Lazily computed */
|
||||
private $aAllowedBricks;
|
||||
/** @var int $iDisplayedInHome Lazily computed */
|
||||
private $iDisplayedInHome;
|
||||
/** @var int $iDisplayedInNavigationMenu Lazily computed */
|
||||
private $iDisplayedInNavigationMenu;
|
||||
/** @var array $aHomeOrdering */
|
||||
private $aHomeOrdering;
|
||||
/** @var array $aNavigationMenuOrdering */
|
||||
private $aNavigationMenuOrdering;
|
||||
|
||||
/**
|
||||
* BrickCollection constructor.
|
||||
@@ -58,16 +58,16 @@ class BrickCollection
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct(ModuleDesign $oModuleDesign)
|
||||
{
|
||||
$this->oModuleDesign = $oModuleDesign;
|
||||
$this->aAllowedBricks = null;
|
||||
$this->iDisplayedInHome = 0;
|
||||
$this->iDisplayedInNavigationMenu = 0;
|
||||
$this->aHomeOrdering = array();
|
||||
$this->aNavigationMenuOrdering = array();
|
||||
{
|
||||
$this->oModuleDesign = $oModuleDesign;
|
||||
$this->aAllowedBricks = null;
|
||||
$this->iDisplayedInHome = 0;
|
||||
$this->iDisplayedInNavigationMenu = 0;
|
||||
$this->aHomeOrdering = array();
|
||||
$this->aNavigationMenuOrdering = array();
|
||||
|
||||
$this->Load();
|
||||
}
|
||||
$this->Load();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $method
|
||||
@@ -78,32 +78,32 @@ class BrickCollection
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __call($method, $arguments)
|
||||
{
|
||||
// Made for cleaner/easier access from twig (eg. app['brick_collection'].bricks)
|
||||
switch($method)
|
||||
{
|
||||
case 'bricks':
|
||||
return $this->GetBricks();
|
||||
break;
|
||||
case 'home_ordering':
|
||||
return $this->GetHomeOrdering();
|
||||
break;
|
||||
case 'navigation_menu_ordering':
|
||||
return $this->GetNavigationMenuOrdering();
|
||||
break;
|
||||
default:
|
||||
throw new PropertyNotFoundException("The property '$method' do not exists in BricksCollection");
|
||||
}
|
||||
}
|
||||
{
|
||||
// Made for cleaner/easier access from twig (eg. app['brick_collection'].bricks)
|
||||
switch ($method)
|
||||
{
|
||||
case 'bricks':
|
||||
return $this->GetBricks();
|
||||
break;
|
||||
case 'home_ordering':
|
||||
return $this->GetHomeOrdering();
|
||||
break;
|
||||
case 'navigation_menu_ordering':
|
||||
return $this->GetNavigationMenuOrdering();
|
||||
break;
|
||||
default:
|
||||
throw new PropertyNotFoundException("The property '$method' do not exists in BricksCollection");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick[]|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetBricks()
|
||||
{
|
||||
return $this->aAllowedBricks;
|
||||
}
|
||||
public function GetBricks()
|
||||
{
|
||||
return $this->aAllowedBricks;
|
||||
}
|
||||
|
||||
public function GetHomeOrdering()
|
||||
{
|
||||
@@ -122,93 +122,95 @@ class BrickCollection
|
||||
* @throws \Combodo\iTop\Portal\Brick\BrickNotFoundException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetBrickById($sId)
|
||||
{
|
||||
foreach ($this->GetBricks() as $oBrick) {
|
||||
if ($oBrick->GetId() === $sId)
|
||||
{
|
||||
return $oBrick;
|
||||
}
|
||||
}
|
||||
public function GetBrickById($sId)
|
||||
{
|
||||
foreach ($this->GetBricks() as $oBrick)
|
||||
{
|
||||
if ($oBrick->GetId() === $sId)
|
||||
{
|
||||
return $oBrick;
|
||||
}
|
||||
}
|
||||
|
||||
throw new BrickNotFoundException('Brick with id = "'.$sId.'" was not found among loaded bricks.');
|
||||
}
|
||||
throw new BrickNotFoundException('Brick with id = "'.$sId.'" was not found among loaded bricks.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function Load()
|
||||
{
|
||||
$aRawBrickList = $this->GetRawBrickList();
|
||||
{
|
||||
$aRawBrickList = $this->GetRawBrickList();
|
||||
|
||||
foreach ($aRawBrickList as $oBrick) {
|
||||
ApplicationHelper::LoadBrickSecurity($oBrick);
|
||||
foreach ($aRawBrickList as $oBrick)
|
||||
{
|
||||
ApplicationHelper::LoadBrickSecurity($oBrick);
|
||||
|
||||
if ($oBrick->GetActive() && $oBrick->IsGrantedForProfiles(UserRights::ListProfiles()))
|
||||
{
|
||||
$this->aAllowedBricks[] = $oBrick;
|
||||
if ($oBrick->GetVisibleHome())
|
||||
{
|
||||
$this->iDisplayedInHome++;
|
||||
}
|
||||
if ($oBrick->GetVisibleNavigationMenu())
|
||||
{
|
||||
$this->iDisplayedInNavigationMenu++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($oBrick->GetActive() && $oBrick->IsGrantedForProfiles(UserRights::ListProfiles()))
|
||||
{
|
||||
$this->aAllowedBricks[] = $oBrick;
|
||||
if ($oBrick->GetVisibleHome())
|
||||
{
|
||||
$this->iDisplayedInHome++;
|
||||
}
|
||||
if ($oBrick->GetVisibleNavigationMenu())
|
||||
{
|
||||
$this->iDisplayedInNavigationMenu++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// - Sorting bricks by rank
|
||||
// - Home
|
||||
$this->aHomeOrdering = $this->aAllowedBricks;
|
||||
usort($this->aHomeOrdering, function (PortalBrick $a, PortalBrick $b) {
|
||||
return $a->GetRankHome() > $b->GetRankHome();
|
||||
});
|
||||
// - Navigation menu
|
||||
$this->aNavigationMenuOrdering = $this->aAllowedBricks;
|
||||
usort($this->aNavigationMenuOrdering, function (PortalBrick $a, PortalBrick $b) {
|
||||
return $a->GetRankNavigationMenu() > $b->GetRankNavigationMenu();
|
||||
});
|
||||
}
|
||||
// - Sorting bricks by rank
|
||||
// - Home
|
||||
$this->aHomeOrdering = $this->aAllowedBricks;
|
||||
usort($this->aHomeOrdering, function (PortalBrick $a, PortalBrick $b) {
|
||||
return $a->GetRankHome() > $b->GetRankHome();
|
||||
});
|
||||
// - Navigation menu
|
||||
$this->aNavigationMenuOrdering = $this->aAllowedBricks;
|
||||
usort($this->aNavigationMenuOrdering, function (PortalBrick $a, PortalBrick $b) {
|
||||
return $a->GetRankNavigationMenu() > $b->GetRankNavigationMenu();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function GetRawBrickList()
|
||||
{
|
||||
$aBricks = array();
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickNode */
|
||||
foreach ($this->oModuleDesign->GetNodes('/module_design/bricks/brick') as $oBrickNode)
|
||||
{
|
||||
$sBrickClass = $oBrickNode->getAttribute('xsi:type');
|
||||
try
|
||||
{
|
||||
if (class_exists($sBrickClass))
|
||||
{
|
||||
/** @var \Combodo\iTop\Portal\Brick\PortalBrick $oBrick */
|
||||
$oBrick = new $sBrickClass();
|
||||
$oBrick->LoadFromXml($oBrickNode);
|
||||
{
|
||||
$aBricks = array();
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickNode */
|
||||
foreach ($this->oModuleDesign->GetNodes('/module_design/bricks/brick') as $oBrickNode)
|
||||
{
|
||||
$sBrickClass = $oBrickNode->getAttribute('xsi:type');
|
||||
try
|
||||
{
|
||||
if (class_exists($sBrickClass))
|
||||
{
|
||||
/** @var \Combodo\iTop\Portal\Brick\PortalBrick $oBrick */
|
||||
$oBrick = new $sBrickClass();
|
||||
$oBrick->LoadFromXml($oBrickNode);
|
||||
|
||||
$aBricks[] = $oBrick;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('Unknown brick class "'.$sBrickClass.'" from xsi:type attribute', null,
|
||||
null, $oBrickNode);
|
||||
}
|
||||
}
|
||||
catch (DOMFormatException $e)
|
||||
{
|
||||
throw new Exception('Could not create brick ('.$sBrickClass.') from XML because of a DOM problem : '.$e->getMessage());
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception('Could not create brick ('.$sBrickClass.') from XML : '.$oBrickNode->Dump().' '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
$aBricks[] = $oBrick;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('Unknown brick class "'.$sBrickClass.'" from xsi:type attribute', null,
|
||||
null, $oBrickNode);
|
||||
}
|
||||
}
|
||||
catch (DOMFormatException $e)
|
||||
{
|
||||
throw new Exception('Could not create brick ('.$sBrickClass.') from XML because of a DOM problem : '.$e->getMessage());
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception('Could not create brick ('.$sBrickClass.') from XML : '.$oBrickNode->Dump().' '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $aBricks;
|
||||
}
|
||||
return $aBricks;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by Bruno DA SILVA, working for Combodo
|
||||
* Date: 24/01/19
|
||||
* Time: 17:28
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\Brick;
|
||||
@@ -14,6 +28,7 @@ use Exception;
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Brick
|
||||
* @since 2.7.0
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
*/
|
||||
class BrickNotFoundException extends Exception
|
||||
{
|
||||
|
||||
@@ -27,49 +27,79 @@ use Combodo\iTop\DesignElement;
|
||||
|
||||
/**
|
||||
* Description of BrowseBrick
|
||||
*
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Brick
|
||||
* @since 2.3.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
*/
|
||||
class BrowseBrick extends PortalBrick
|
||||
{
|
||||
/** @var string ENUM_BROWSE_MODE_LIST */
|
||||
const ENUM_BROWSE_MODE_LIST = 'list';
|
||||
const ENUM_BROWSE_MODE_TREE = 'tree';
|
||||
const ENUM_BROWSE_MODE_MOSAIC = 'mosaic';
|
||||
/** @var string ENUM_BROWSE_MODE_TREE */
|
||||
const ENUM_BROWSE_MODE_TREE = 'tree';
|
||||
/** @var string ENUM_BROWSE_MODE_MOSAIC */
|
||||
const ENUM_BROWSE_MODE_MOSAIC = 'mosaic';
|
||||
|
||||
/** @var string ENUM_ACTION_VIEW */
|
||||
const ENUM_ACTION_VIEW = 'view';
|
||||
/** @var string ENUM_ACTION_EDIT */
|
||||
const ENUM_ACTION_EDIT = 'edit';
|
||||
/** @var string ENUM_ACTION_DRILLDOWN */
|
||||
const ENUM_ACTION_DRILLDOWN = 'drilldown';
|
||||
|
||||
/** @var string ENUM_ACTION_CREATE_FROM_THIS */
|
||||
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';
|
||||
/** @var string ENUM_ACTION_ICON_CLASS_EDIT */
|
||||
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';
|
||||
/** @var string ENUM_ACTION_ICON_CLASS_CREATE_FROM_THIS */
|
||||
const ENUM_ACTION_ICON_CLASS_CREATE_FROM_THIS = 'glyphicon glyphicon-edit';
|
||||
|
||||
/** @var string ENUM_FACTORY_TYPE_METHOD */
|
||||
const ENUM_FACTORY_TYPE_METHOD = 'method';
|
||||
/** @var string ENUM_FACTORY_TYPE_CLASS */
|
||||
const ENUM_FACTORY_TYPE_CLASS = 'class';
|
||||
|
||||
// Overloaded constants
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fa fa-map';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fa fa-map fa-2x';
|
||||
const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_FULL;
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fa fa-map fa-2x';
|
||||
const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_FULL;
|
||||
|
||||
/** @var string DEFAULT_LEVEL_NAME_ATT */
|
||||
const DEFAULT_LEVEL_NAME_ATT = 'name';
|
||||
/** @var string DEFAULT_BROWSE_MODE */
|
||||
const DEFAULT_BROWSE_MODE = self::ENUM_BROWSE_MODE_LIST;
|
||||
/** @var string DEFAULT_ACTION */
|
||||
const DEFAULT_ACTION = self::ENUM_ACTION_DRILLDOWN;
|
||||
/** @var string DEFAULT_ACTION_OPENING_TARGET */
|
||||
const DEFAULT_ACTION_OPENING_TARGET = self::ENUM_OPENING_TARGET_MODAL;
|
||||
/** @var int DEFAULT_LIST_LENGTH */
|
||||
const DEFAULT_LIST_LENGTH = 20;
|
||||
|
||||
static $aBrowseModes = array(
|
||||
self::ENUM_BROWSE_MODE_LIST,
|
||||
self::ENUM_BROWSE_MODE_TREE,
|
||||
self::ENUM_BROWSE_MODE_MOSAIC
|
||||
);
|
||||
// Overloaded variables
|
||||
public static $sRouteName = 'p_browse_brick';
|
||||
|
||||
static $sRouteName = 'p_browse_brick';
|
||||
/** @var array $aBrowseModes */
|
||||
public static $aBrowseModes = array(
|
||||
self::ENUM_BROWSE_MODE_LIST,
|
||||
self::ENUM_BROWSE_MODE_TREE,
|
||||
self::ENUM_BROWSE_MODE_MOSAIC,
|
||||
);
|
||||
|
||||
/** @var array $aLevels */
|
||||
protected $aLevels;
|
||||
/** @var array $aAvailablesBrowseModes */
|
||||
protected $aAvailablesBrowseModes;
|
||||
/** @var string $sDefaultBrowseMode */
|
||||
protected $sDefaultBrowseMode;
|
||||
|
||||
/**
|
||||
* BrowseBrick constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
@@ -90,7 +120,7 @@ class BrowseBrick extends PortalBrick
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the brick availables browse modes
|
||||
* Returns the brick available browse modes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@@ -109,42 +139,45 @@ class BrowseBrick extends PortalBrick
|
||||
return $this->sDefaultBrowseMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the levels of the brick
|
||||
*
|
||||
* @param array $aLevels
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*/
|
||||
/**
|
||||
* Sets the levels of the brick
|
||||
*
|
||||
* @param array $aLevels
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*/
|
||||
public function SetLevels($aLevels)
|
||||
{
|
||||
$this->aLevels = $aLevels;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the availables browse modes of the brick
|
||||
* Sets the available browse modes of the brick
|
||||
*
|
||||
* @param array $aAvailablesBrowseModes
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*/
|
||||
public function SetAvailablesBrowseModes($aAvailablesBrowseModes)
|
||||
{
|
||||
$this->aAvailablesBrowseModes = $aAvailablesBrowseModes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the adefault browse mode of the brick
|
||||
* Sets the default browse mode of the brick
|
||||
*
|
||||
* @param string $sDefaultBrowseMode
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*/
|
||||
public function SetDefaultBrowseMode($sDefaultBrowseMode)
|
||||
{
|
||||
$this->sDefaultBrowseMode = $sDefaultBrowseMode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -162,12 +195,13 @@ class BrowseBrick extends PortalBrick
|
||||
* Adds $aLevel to the list of levels for that brick
|
||||
*
|
||||
* @param array $aLevel
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*/
|
||||
public function AddLevel($aLevel)
|
||||
{
|
||||
$this->aLevels[] = $aLevel;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -175,8 +209,8 @@ class BrowseBrick extends PortalBrick
|
||||
* Removes $aLevel from the list of levels browse modes
|
||||
*
|
||||
* @param string $sLevel
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*/
|
||||
public function RemoveLevels($sLevel)
|
||||
{
|
||||
@@ -184,6 +218,7 @@ class BrowseBrick extends PortalBrick
|
||||
{
|
||||
unset($this->aLevels[$sLevel]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -191,13 +226,14 @@ class BrowseBrick extends PortalBrick
|
||||
* Adds $sModeId to the list of availables browse modes for that brick
|
||||
*
|
||||
* @param string $sModeId
|
||||
* @param array $aData Hash array containing 'template' => TEMPLATE_PATH
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
* @param array $aData Hash array containing 'template' => TEMPLATE_PATH
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*/
|
||||
public function AddAvailableBrowseMode($sModeId, $aData = array())
|
||||
{
|
||||
$this->aAvailablesBrowseModes[$sModeId] = $aData;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -205,8 +241,8 @@ class BrowseBrick extends PortalBrick
|
||||
* Removes $sModeId from the list of availables browse modes
|
||||
*
|
||||
* @param string $sModeId
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*/
|
||||
public function RemoveAvailableBrowseMode($sModeId)
|
||||
{
|
||||
@@ -214,6 +250,7 @@ class BrowseBrick extends PortalBrick
|
||||
{
|
||||
unset($this->aAvailablesBrowseModes[$sModeId]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -222,9 +259,9 @@ class BrowseBrick extends PortalBrick
|
||||
* This is used to set all the brick attributes at once.
|
||||
*
|
||||
* @param \Combodo\iTop\DesignElement $oMDElement
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
|
||||
*
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function LoadFromXml(DesignElement $oMDElement)
|
||||
@@ -232,11 +269,13 @@ class BrowseBrick extends PortalBrick
|
||||
parent::LoadFromXml($oMDElement);
|
||||
|
||||
// Checking specific elements
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
|
||||
{
|
||||
switch ($oBrickSubNode->nodeName)
|
||||
{
|
||||
case 'levels':
|
||||
/** @var \Combodo\iTop\DesignElement $oLevelNode */
|
||||
foreach ($oBrickSubNode->childNodes as $oLevelNode)
|
||||
{
|
||||
if ($oLevelNode->nodeName === 'level')
|
||||
@@ -246,16 +285,19 @@ class BrowseBrick extends PortalBrick
|
||||
}
|
||||
break;
|
||||
case 'browse_modes':
|
||||
/** @var \Combodo\iTop\DesignElement $oBrowseModeNode */
|
||||
foreach ($oBrickSubNode->childNodes as $oBrowseModeNode)
|
||||
{
|
||||
switch ($oBrowseModeNode->nodeName)
|
||||
{
|
||||
case 'availables':
|
||||
/** @var \Combodo\iTop\DesignElement $oModeNode */
|
||||
foreach ($oBrowseModeNode->childNodes as $oModeNode)
|
||||
{
|
||||
if (!$oModeNode->hasAttribute('id'))
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : Browse mode must have a unique ID attribute', null, null, $oModeNode);
|
||||
throw new DOMFormatException('BrowseBrick : Browse mode must have a unique ID attribute', null,
|
||||
null, $oModeNode);
|
||||
}
|
||||
|
||||
$sModeId = $oModeNode->getAttribute('id');
|
||||
@@ -269,7 +311,7 @@ class BrowseBrick extends PortalBrick
|
||||
}
|
||||
else
|
||||
{
|
||||
$sTemplatePath = 'itop-portal-base/portal/templates/bricks/browse/mode_' . $sModeId . '.html.twig';
|
||||
$sTemplatePath = 'itop-portal-base/portal/templates/bricks/browse/mode_'.$sModeId.'.html.twig';
|
||||
}
|
||||
$aModeData['template'] = $sTemplatePath;
|
||||
|
||||
@@ -290,10 +332,11 @@ class BrowseBrick extends PortalBrick
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : Must have at least one browse mode', null, null, $oMDElement);
|
||||
}
|
||||
// Checking that default browse mode in among the availables
|
||||
// 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);
|
||||
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)
|
||||
@@ -305,12 +348,12 @@ class BrowseBrick extends PortalBrick
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the ModuleDesignElement to recursivly load levels
|
||||
* Parses the ModuleDesignElement to recursively load levels
|
||||
*
|
||||
* @param \Combodo\iTop\DesignElement $oMDElement
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
protected function LoadLevelFromXml(DesignElement $oMDElement)
|
||||
@@ -318,12 +361,12 @@ class BrowseBrick extends PortalBrick
|
||||
$aLevel = array(
|
||||
'parent_att' => null,
|
||||
'tooltip_att' => null,
|
||||
'description_att' => null,
|
||||
'image_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()))
|
||||
'actions' => array('default' => array('type' => static::DEFAULT_ACTION, 'rules' => array())),
|
||||
);
|
||||
|
||||
// Getting level ID
|
||||
@@ -333,9 +376,11 @@ class BrowseBrick extends PortalBrick
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : level tag without "id" attribute. It must have one and it must not be empty', null, null, $oMDElement);
|
||||
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->childNodes as $oLevelPropertyNode)
|
||||
{
|
||||
switch ($oLevelPropertyNode->nodeName)
|
||||
@@ -344,17 +389,19 @@ class BrowseBrick extends PortalBrick
|
||||
$sClass = $oLevelPropertyNode->GetText();
|
||||
if ($sClass === '')
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : class tag is empty. Must contain Classname', null, null, $oLevelPropertyNode);
|
||||
throw new DOMFormatException('BrowseBrick : class tag is empty. Must contain Classname', null, null,
|
||||
$oLevelPropertyNode);
|
||||
}
|
||||
|
||||
$aLevel['oql'] = 'SELECT ' . $sClass;
|
||||
$aLevel['oql'] = 'SELECT '.$sClass;
|
||||
break;
|
||||
|
||||
case 'oql':
|
||||
$sOql = $oLevelPropertyNode->GetText();
|
||||
if ($sOql === '')
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : oql tag is empty. Must contain OQL statement', null, null, $oLevelPropertyNode);
|
||||
throw new DOMFormatException('BrowseBrick : oql tag is empty. Must contain OQL statement', null, null,
|
||||
$oLevelPropertyNode);
|
||||
}
|
||||
|
||||
$aLevel['oql'] = $sOql;
|
||||
@@ -362,8 +409,8 @@ class BrowseBrick extends PortalBrick
|
||||
|
||||
case 'parent_att':
|
||||
case 'tooltip_att':
|
||||
case 'description_att':
|
||||
case 'image_att':
|
||||
case 'description_att':
|
||||
case 'image_att':
|
||||
case 'title':
|
||||
$aLevel[$oLevelPropertyNode->nodeName] = $oLevelPropertyNode->GetText(null);
|
||||
break;
|
||||
@@ -378,6 +425,7 @@ class BrowseBrick extends PortalBrick
|
||||
if ($oLevelPropertyNode->hasChildNodes())
|
||||
{
|
||||
$aLevel[$sTagName] = array();
|
||||
/** @var \Combodo\iTop\DesignElement $oFieldNode */
|
||||
foreach ($oLevelPropertyNode->childNodes as $oFieldNode)
|
||||
{
|
||||
if ($oFieldNode->hasAttribute('id') && $oFieldNode->getAttribute('id') !== '')
|
||||
@@ -386,7 +434,8 @@ class BrowseBrick extends PortalBrick
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : ' . $sTagName . '/* tag must have an "id" attribute and it must not be empty', null, null, $oFieldNode);
|
||||
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/* tag must have an "id" attribute and it must not be empty',
|
||||
null, null, $oFieldNode);
|
||||
}
|
||||
|
||||
$oFieldSubNode = $oFieldNode->GetOptionalElement('hidden');
|
||||
@@ -404,13 +453,14 @@ class BrowseBrick extends PortalBrick
|
||||
if ($oLevelPropertyNode->hasChildNodes())
|
||||
{
|
||||
$aLevel[$sTagName] = array();
|
||||
/** @var \Combodo\iTop\DesignElement $oActionNode */
|
||||
foreach ($oLevelPropertyNode->childNodes as $oActionNode)
|
||||
{
|
||||
if ($oActionNode->hasAttribute('id') && $oActionNode->getAttribute('id') !== '')
|
||||
{
|
||||
$aTmpAction = array(
|
||||
'type' => null,
|
||||
'rules' => array()
|
||||
'rules' => array(),
|
||||
);
|
||||
|
||||
// Action type
|
||||
@@ -422,14 +472,14 @@ class BrowseBrick extends PortalBrick
|
||||
{
|
||||
$aTmpAction['factory'] = array(
|
||||
'type' => static::ENUM_FACTORY_TYPE_METHOD,
|
||||
'value' => $oActionNode->GetOptionalElement('factory_method')->GetText()
|
||||
'value' => $oActionNode->GetOptionalElement('factory_method')->GetText(),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aTmpAction['factory'] = array(
|
||||
'type' => static::ENUM_FACTORY_TYPE_CLASS,
|
||||
'value' => $oActionNode->GetUniqueElement('class')->GetText()
|
||||
'value' => $oActionNode->GetUniqueElement('class')->GetText(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -446,21 +496,23 @@ class BrowseBrick extends PortalBrick
|
||||
$aTmpAction['icon_class'] = $oActionIconClassNode->GetText();
|
||||
}
|
||||
// Action opening target
|
||||
$oActionOpeningTargetNode = $oActionNode->GetOptionalElement('opening_target');
|
||||
if($oActionOpeningTargetNode !== null)
|
||||
{
|
||||
$aTmpAction['opening_target'] = $oActionOpeningTargetNode->GetText(static::DEFAULT_ACTION_OPENING_TARGET);
|
||||
}
|
||||
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);
|
||||
}
|
||||
$oActionOpeningTargetNode = $oActionNode->GetOptionalElement('opening_target');
|
||||
if ($oActionOpeningTargetNode !== null)
|
||||
{
|
||||
$aTmpAction['opening_target'] = $oActionOpeningTargetNode->GetText(static::DEFAULT_ACTION_OPENING_TARGET);
|
||||
}
|
||||
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);
|
||||
}
|
||||
// Action rules
|
||||
/** @var \Combodo\iTop\DesignElement $oRuleNode */
|
||||
foreach ($oActionNode->GetNodes('./rules/rule') as $oRuleNode)
|
||||
{
|
||||
if ($oRuleNode->hasAttribute('id') && $oRuleNode->getAttribute('id') !== '')
|
||||
@@ -469,7 +521,8 @@ class BrowseBrick extends PortalBrick
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : ' . $sTagName . '/rules/rule tag must have an "id" attribute and it must not be empty', null, null, $oRuleNode);
|
||||
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/rules/rule tag must have an "id" attribute and it must not be empty',
|
||||
null, null, $oRuleNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,7 +530,8 @@ class BrowseBrick extends PortalBrick
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : ' . $sTagName . '/* tag must have an "id" attribute and it must not be empty', null, null, $oActionNode);
|
||||
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/* tag must have an "id" attribute and it must not be empty',
|
||||
null, null, $oActionNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -495,13 +549,13 @@ class BrowseBrick extends PortalBrick
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Checking if level has an oql
|
||||
if (!isset($aLevel['oql']) || $aLevel['oql'] === '')
|
||||
{
|
||||
throw new DOMFormatException('BrowseBrick : must have a valid <class|oql> tag', null, null, $oMDElement);
|
||||
}
|
||||
|
||||
|
||||
return $aLevel;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,18 +27,27 @@ use Combodo\iTop\DesignElement;
|
||||
|
||||
/**
|
||||
* Description of CreateBrick
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Brick
|
||||
* @since 2.4.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
*/
|
||||
class CreateBrick extends PortalBrick
|
||||
{
|
||||
// Overloaded constants
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fa fa-plus';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fa fa-plus fa-2x';
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/create/modal.html.twig';
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/create/modal.html.twig';
|
||||
|
||||
/** @var string DEFAULT_CLASS */
|
||||
const DEFAULT_CLASS = '';
|
||||
|
||||
static $sRouteName = 'p_create_brick';
|
||||
// Overloaded variables
|
||||
public static $sRouteName = 'p_create_brick';
|
||||
|
||||
/** @var string $sClass */
|
||||
protected $sClass;
|
||||
/** @var array $aRules */
|
||||
protected $aRules;
|
||||
|
||||
/**
|
||||
@@ -62,16 +71,17 @@ class CreateBrick extends PortalBrick
|
||||
return $this->sClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the class of the brick
|
||||
*
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\CreateBrick
|
||||
*/
|
||||
/**
|
||||
* Sets the class of the brick
|
||||
*
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\CreateBrick
|
||||
*/
|
||||
public function SetClass($sClass)
|
||||
{
|
||||
$this->sClass = $sClass;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -89,30 +99,32 @@ class CreateBrick extends PortalBrick
|
||||
* Sets the rules of the brick
|
||||
*
|
||||
* @param array $aRules
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\CreateBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\CreateBrick
|
||||
*/
|
||||
public function SetRules($aRules)
|
||||
{
|
||||
$this->aRules = $aRules;
|
||||
|
||||
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\CreateBrick
|
||||
*
|
||||
* @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\CreateBrick
|
||||
*
|
||||
* @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)
|
||||
@@ -122,6 +134,7 @@ class CreateBrick extends PortalBrick
|
||||
break;
|
||||
|
||||
case 'rules':
|
||||
/** @var \Combodo\iTop\DesignElement $oRuleNode */
|
||||
foreach ($oBrickSubNode->childNodes as $oRuleNode)
|
||||
{
|
||||
if ($oRuleNode->hasAttribute('id') && $oRuleNode->getAttribute('id') !== '')
|
||||
@@ -130,7 +143,8 @@ class CreateBrick extends PortalBrick
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('CreateBrick: /rules/rule tag must have an "id" attribute and it must not be empty', null, null, $oRuleNode);
|
||||
throw new DOMFormatException('CreateBrick: /rules/rule tag must have an "id" attribute and it must not be empty',
|
||||
null, null, $oRuleNode);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -27,28 +27,44 @@ use Combodo\iTop\DesignElement;
|
||||
|
||||
/**
|
||||
* Description of FilterBrick
|
||||
*
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Brick
|
||||
* @since 2.4.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
*/
|
||||
class FilterBrick extends PortalBrick
|
||||
{
|
||||
// Overloaded constants
|
||||
const DEFAULT_VISIBLE_NAVIGATION_MENU = false;
|
||||
const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/filter/tile.html.twig';
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fa fa-search';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fa fa-search fa-2x';
|
||||
|
||||
/** @var string DEFAULT_TARGET_BRICK_CLASS */
|
||||
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';
|
||||
/** @var string DEFAULT_SEARCH_SUBMIT_LABEL */
|
||||
const DEFAULT_SEARCH_SUBMIT_LABEL = 'Brick:Portal:Filter:SearchInput:Submit';
|
||||
/** @var string DEFAULT_SEARCH_SUBMIT_CLASS */
|
||||
const DEFAULT_SEARCH_SUBMIT_CLASS = '';
|
||||
|
||||
/** @var string $sTargetBrickId */
|
||||
protected $sTargetBrickId;
|
||||
/** @var string $sTargetBrickClass */
|
||||
protected $sTargetBrickClass;
|
||||
/** @var string $sTargetBrickTab */
|
||||
protected $sTargetBrickTab;
|
||||
/** @var string $sSearchPlaceholderValue */
|
||||
protected $sSearchPlaceholderValue;
|
||||
/** @var string $sSearchSubmitLabel */
|
||||
protected $sSearchSubmitLabel;
|
||||
/** @var string $sSearchSubmitClass */
|
||||
protected $sSearchSubmitClass;
|
||||
|
||||
/**
|
||||
* FilterBrick constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
@@ -59,65 +75,111 @@ class FilterBrick extends PortalBrick
|
||||
$this->sSearchSubmitClass = static::DEFAULT_SEARCH_SUBMIT_CLASS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetTargetBrickId()
|
||||
{
|
||||
return $this->sTargetBrickId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetTargetBrickClass()
|
||||
{
|
||||
return $this->sTargetBrickClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetTargetBrickTab()
|
||||
{
|
||||
return $this->sTargetBrickTab;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetSearchPlaceholderValue()
|
||||
{
|
||||
return $this->sSearchPlaceholderValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetSearchSubmitLabel()
|
||||
{
|
||||
return $this->sSearchSubmitLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetSearchSubmitClass()
|
||||
{
|
||||
return $this->sSearchSubmitClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTargetBrickId
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetTargetBrickId($sTargetBrickId)
|
||||
{
|
||||
$this->sTargetBrickId = $sTargetBrickId;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTargetBrickClass
|
||||
*/
|
||||
public function SetTargetBrickClass($sTargetBrickClass)
|
||||
{
|
||||
$this->sTargetBrickClass = $sTargetBrickClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTargetBrickTab
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetTargetBrickTab($sTargetBrickTab)
|
||||
{
|
||||
$this->sTargetBrickTab = $sTargetBrickTab;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSearchPlaceholderValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetSearchPlaceholderValue($sSearchPlaceholderValue)
|
||||
{
|
||||
$this->sSearchPlaceholderValue = $sSearchPlaceholderValue;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSearchSubmitLabel
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetSearchSubmitLabel($sSearchSubmitLabel)
|
||||
{
|
||||
$this->sSearchSubmitLabel = $sSearchSubmitLabel;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSearchSubmitClass
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function SetSearchSubmitClass($sSearchSubmitClass)
|
||||
{
|
||||
$this->sSearchSubmitClass = $sSearchSubmitClass;
|
||||
@@ -139,11 +201,13 @@ class FilterBrick extends PortalBrick
|
||||
parent::LoadFromXml($oMDElement);
|
||||
|
||||
// Checking specific elements
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
|
||||
{
|
||||
switch ($oBrickSubNode->nodeName)
|
||||
{
|
||||
case 'target_brick':
|
||||
/** @var \Combodo\iTop\DesignElement $oTargetBrickNode */
|
||||
foreach ($oBrickSubNode->childNodes as $oTargetBrickNode)
|
||||
{
|
||||
switch ($oTargetBrickNode->nodeName)
|
||||
|
||||
@@ -30,149 +30,188 @@ use Combodo\iTop\DesignElement;
|
||||
|
||||
class ManageBrick extends PortalBrick
|
||||
{
|
||||
/** @var string ENUM_ACTION_VIEW */
|
||||
const ENUM_ACTION_VIEW = 'view';
|
||||
/** @var string ENUM_ACTION_EDIT */
|
||||
const ENUM_ACTION_EDIT = 'edit';
|
||||
|
||||
const ENUM_TILE_MODE_TEXT = 'text';
|
||||
const ENUM_TILE_MODE_BADGE = 'badge';
|
||||
const ENUM_TILE_MODE_PIE = 'pie-chart';
|
||||
const ENUM_TILE_MODE_BAR = 'bar-chart';
|
||||
const ENUM_TILE_MODE_TOP = 'top-list';
|
||||
/** @var string ENUM_TILE_MODE_TEXT */
|
||||
const ENUM_TILE_MODE_TEXT = 'text';
|
||||
/** @var string ENUM_TILE_MODE_BADGE */
|
||||
const ENUM_TILE_MODE_BADGE = 'badge';
|
||||
/** @var string ENUM_TILE_MODE_PIE */
|
||||
const ENUM_TILE_MODE_PIE = 'pie-chart';
|
||||
/** @var string ENUM_TILE_MODE_BAR */
|
||||
const ENUM_TILE_MODE_BAR = 'bar-chart';
|
||||
/** @var string ENUM_TILE_MODE_TOP */
|
||||
const ENUM_TILE_MODE_TOP = 'top-list';
|
||||
|
||||
const ENUM_DISPLAY_MODE_LIST = 'list';
|
||||
const ENUM_DISPLAY_MODE_PIE = 'pie-chart';
|
||||
const ENUM_DISPLAY_MODE_BAR = 'bar-chart';
|
||||
/** @var string ENUM_DISPLAY_MODE_LIST */
|
||||
const ENUM_DISPLAY_MODE_LIST = 'list';
|
||||
/** @var string ENUM_DISPLAY_MODE_PIE */
|
||||
const ENUM_DISPLAY_MODE_PIE = 'pie-chart';
|
||||
/** @var string ENUM_DISPLAY_MODE_BAR */
|
||||
const ENUM_DISPLAY_MODE_BAR = 'bar-chart';
|
||||
|
||||
/** @var string ENUM_PAGE_TEMPLATE_PATH_TABLE */
|
||||
const ENUM_PAGE_TEMPLATE_PATH_TABLE = 'itop-portal-base/portal/templates/bricks/manage/layout-table.html.twig';
|
||||
const ENUM_PAGE_TEMPLATE_PATH_CHART = 'itop-portal-base/portal/templates/bricks/manage/layout-chart.html.twig';
|
||||
/** @var string ENUM_PAGE_TEMPLATE_PATH_CHART */
|
||||
const ENUM_PAGE_TEMPLATE_PATH_CHART = 'itop-portal-base/portal/templates/bricks/manage/layout-chart.html.twig';
|
||||
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fa fa-pencil-square';
|
||||
// Overloaded constants
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'fa fa-pencil-square';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fa fa-pencil-square fa-2x';
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = self::ENUM_PAGE_TEMPLATE_PATH_TABLE;
|
||||
const DEFAULT_OQL = '';
|
||||
const DEFAULT_OPENING_MODE = self::ENUM_ACTION_EDIT;
|
||||
const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_LAZY;
|
||||
const DEFAULT_LIST_LENGTH = 20;
|
||||
const DEFAULT_ZLIST_FIELDS = 'list';
|
||||
const DEFAULT_SHOW_TAB_COUNTS = false;
|
||||
const DEFAULT_DISPLAY_MODE = self::ENUM_DISPLAY_MODE_LIST;
|
||||
const DEFAULT_TILE_MODE = self::ENUM_TILE_MODE_TEXT;
|
||||
const DEFAULT_GROUP_LIMIT = 0;
|
||||
const DEFAULT_GROUP_SHOW_OTHERS = true;
|
||||
|
||||
const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/manage/tile-default.html.twig';
|
||||
const DEFAULT_TILE_CONTROLLER_ACTION = 'Combodo\\iTop\\Portal\\Controller\\ManageBrickController::TileAction';
|
||||
|
||||
/** @var string DEFAULT_OQL */
|
||||
const DEFAULT_OQL = '';
|
||||
/** @var string DEFAULT_OPENING_MODE */
|
||||
const DEFAULT_OPENING_MODE = self::ENUM_ACTION_EDIT;
|
||||
/** @var int DEFAULT_LIST_LENGTH */
|
||||
const DEFAULT_LIST_LENGTH = 20;
|
||||
/** @var string DEFAULT_ZLIST_FIELDS */
|
||||
const DEFAULT_ZLIST_FIELDS = 'list';
|
||||
/** @var bool DEFAULT_SHOW_TAB_COUNTS */
|
||||
const DEFAULT_SHOW_TAB_COUNTS = false;
|
||||
/** @var string DEFAULT_DISPLAY_MODE */
|
||||
const DEFAULT_DISPLAY_MODE = self::ENUM_DISPLAY_MODE_LIST;
|
||||
/** @var string DEFAULT_TILE_MODE */
|
||||
const DEFAULT_TILE_MODE = self::ENUM_TILE_MODE_TEXT;
|
||||
/** @var int DEFAULT_GROUP_LIMIT */
|
||||
const DEFAULT_GROUP_LIMIT = 0;
|
||||
/** @var bool DEFAULT_GROUP_SHOW_OTHERS */
|
||||
const DEFAULT_GROUP_SHOW_OTHERS = true;
|
||||
|
||||
/** @var array $aDisplayModes */
|
||||
static $aDisplayModes = array(
|
||||
self::ENUM_DISPLAY_MODE_LIST,
|
||||
self::ENUM_DISPLAY_MODE_PIE,
|
||||
self::ENUM_DISPLAY_MODE_BAR,
|
||||
);
|
||||
static $aTileModes = array(
|
||||
self::ENUM_TILE_MODE_TEXT,
|
||||
self::ENUM_TILE_MODE_BADGE,
|
||||
self::ENUM_TILE_MODE_PIE,
|
||||
self::ENUM_TILE_MODE_BAR,
|
||||
self::ENUM_TILE_MODE_TOP,
|
||||
);
|
||||
static $aPresentationData = array(
|
||||
self::ENUM_TILE_MODE_BADGE => array(
|
||||
'decorationCssClass' => 'fa fa-id-card-o fa-2x',
|
||||
'tileTemplate' => 'itop-portal-base/portal/templates/bricks/manage/tile-badge.html.twig',
|
||||
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_TABLE,
|
||||
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_LIST,
|
||||
'need_details' => true,
|
||||
),
|
||||
self::ENUM_TILE_MODE_TOP => array(
|
||||
'decorationCssClass' => 'fa fa-signal fa-rotate-270 fa-2x',
|
||||
'tileTemplate' => 'itop-portal-base/portal/templates/bricks/manage/tile-top-list.html.twig',
|
||||
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_TABLE,
|
||||
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_LIST,
|
||||
'need_details' => true,
|
||||
),
|
||||
self::ENUM_TILE_MODE_PIE => array(
|
||||
'decorationCssClass' => 'fa fa-pie-chart fa-2x',
|
||||
'tileTemplate' => 'itop-portal-base/portal/templates/bricks/manage/tile-chart.html.twig',
|
||||
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_CHART,
|
||||
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_PIE,
|
||||
'need_details' => false,
|
||||
),
|
||||
self::ENUM_TILE_MODE_BAR => array(
|
||||
'decorationCssClass' => 'fa fa-bar-chart fa-2x',
|
||||
'tileTemplate' => 'itop-portal-base/portal/templates/bricks/manage/tile-chart.html.twig',
|
||||
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_CHART,
|
||||
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_BAR,
|
||||
'need_details' => false,
|
||||
),
|
||||
self::ENUM_TILE_MODE_TEXT => array(
|
||||
'decorationCssClass' => 'fa fa-pencil-square fa-2x',
|
||||
'tileTemplate' => self::DEFAULT_TILE_TEMPLATE_PATH,
|
||||
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_TABLE,
|
||||
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_LIST,
|
||||
'need_details' => true,
|
||||
),
|
||||
);
|
||||
self::ENUM_DISPLAY_MODE_LIST,
|
||||
self::ENUM_DISPLAY_MODE_PIE,
|
||||
self::ENUM_DISPLAY_MODE_BAR,
|
||||
);
|
||||
/** @var array $aTileModes */
|
||||
public static $aTileModes = array(
|
||||
self::ENUM_TILE_MODE_TEXT,
|
||||
self::ENUM_TILE_MODE_BADGE,
|
||||
self::ENUM_TILE_MODE_PIE,
|
||||
self::ENUM_TILE_MODE_BAR,
|
||||
self::ENUM_TILE_MODE_TOP,
|
||||
);
|
||||
/** @var array $aPresentationData */
|
||||
public static $aPresentationData = array(
|
||||
self::ENUM_TILE_MODE_BADGE => array(
|
||||
'decorationCssClass' => 'fa fa-id-card-o fa-2x',
|
||||
'tileTemplate' => 'itop-portal-base/portal/templates/bricks/manage/tile-badge.html.twig',
|
||||
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_TABLE,
|
||||
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_LIST,
|
||||
'need_details' => true,
|
||||
),
|
||||
self::ENUM_TILE_MODE_TOP => array(
|
||||
'decorationCssClass' => 'fa fa-signal fa-rotate-270 fa-2x',
|
||||
'tileTemplate' => 'itop-portal-base/portal/templates/bricks/manage/tile-top-list.html.twig',
|
||||
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_TABLE,
|
||||
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_LIST,
|
||||
'need_details' => true,
|
||||
),
|
||||
self::ENUM_TILE_MODE_PIE => array(
|
||||
'decorationCssClass' => 'fa fa-pie-chart fa-2x',
|
||||
'tileTemplate' => 'itop-portal-base/portal/templates/bricks/manage/tile-chart.html.twig',
|
||||
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_CHART,
|
||||
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_PIE,
|
||||
'need_details' => false,
|
||||
),
|
||||
self::ENUM_TILE_MODE_BAR => array(
|
||||
'decorationCssClass' => 'fa fa-bar-chart fa-2x',
|
||||
'tileTemplate' => 'itop-portal-base/portal/templates/bricks/manage/tile-chart.html.twig',
|
||||
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_CHART,
|
||||
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_BAR,
|
||||
'need_details' => false,
|
||||
),
|
||||
self::ENUM_TILE_MODE_TEXT => array(
|
||||
'decorationCssClass' => 'fa fa-pencil-square fa-2x',
|
||||
'tileTemplate' => self::DEFAULT_TILE_TEMPLATE_PATH,
|
||||
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_TABLE,
|
||||
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_LIST,
|
||||
'need_details' => true,
|
||||
),
|
||||
);
|
||||
|
||||
static $sRouteName = 'p_manage_brick';
|
||||
// Overloaded variables
|
||||
public static $sRouteName = 'p_manage_brick';
|
||||
|
||||
/** @var string $sOql */
|
||||
protected $sOql;
|
||||
/** @var string $sOpeningMode */
|
||||
protected $sOpeningMode;
|
||||
/** @var array $aGrouping */
|
||||
protected $aGrouping;
|
||||
/** @var array $aFields */
|
||||
protected $aFields;
|
||||
/** @var array $aExportFields */
|
||||
protected $aExportFields;
|
||||
/** @var bool $bShowTabCounts */
|
||||
protected $bShowTabCounts;
|
||||
protected $aAvailableDisplayModes = array();
|
||||
protected $sDefaultDisplayMode;
|
||||
|
||||
protected $sTileMode;
|
||||
/** @var array $aAvailableDisplayModes */
|
||||
protected $aAvailableDisplayModes = array();
|
||||
/** @var string $sDefaultDisplayMode */
|
||||
protected $sDefaultDisplayMode;
|
||||
/** @var string $sTileMode */
|
||||
protected $sTileMode;
|
||||
/** @var int $iGroupLimit */
|
||||
protected $iGroupLimit;
|
||||
/** @var bool $bGroupShowOthers */
|
||||
protected $bGroupShowOthers;
|
||||
|
||||
/**
|
||||
* Returns true if the $sDisplayMode need objects details for rendering.
|
||||
*
|
||||
* @param string $sDisplayMode
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
/**
|
||||
* Returns true if the $sDisplayMode need objects details for rendering.
|
||||
*
|
||||
* @param string $sDisplayMode
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static public function AreDetailsNeededForDisplayMode($sDisplayMode)
|
||||
{
|
||||
$bNeedDetails = false;
|
||||
foreach(static::$aPresentationData as $aData)
|
||||
{
|
||||
if($aData['layoutDisplayMode'] === $sDisplayMode)
|
||||
{
|
||||
$bNeedDetails = $aData['need_details'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
$bNeedDetails = false;
|
||||
foreach (static::$aPresentationData as $aData)
|
||||
{
|
||||
if ($aData['layoutDisplayMode'] === $sDisplayMode)
|
||||
{
|
||||
$bNeedDetails = $aData['need_details'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $bNeedDetails;
|
||||
}
|
||||
return $bNeedDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page template path for the $sDisplayMode
|
||||
*
|
||||
* @param string $sDisplayMode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function GetPageTemplateFromDisplayMode($sDisplayMode)
|
||||
{
|
||||
$sTemplate = static::DEFAULT_PAGE_TEMPLATE_PATH;
|
||||
foreach(static::$aPresentationData as $aData)
|
||||
{
|
||||
if($aData['layoutDisplayMode'] === $sDisplayMode)
|
||||
{
|
||||
$sTemplate = $aData['layoutTemplate'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the page template path for the $sDisplayMode
|
||||
*
|
||||
* @param string $sDisplayMode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function GetPageTemplateFromDisplayMode($sDisplayMode)
|
||||
{
|
||||
$sTemplate = static::DEFAULT_PAGE_TEMPLATE_PATH;
|
||||
foreach (static::$aPresentationData as $aData)
|
||||
{
|
||||
if ($aData['layoutDisplayMode'] === $sDisplayMode)
|
||||
{
|
||||
$sTemplate = $aData['layoutTemplate'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $sTemplate;
|
||||
}
|
||||
return $sTemplate;
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
/**
|
||||
* ManageBrick constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
@@ -182,7 +221,7 @@ class ManageBrick extends PortalBrick
|
||||
$this->aFields = array();
|
||||
$this->aExportFields = array();
|
||||
$this->bShowTabCounts = static::DEFAULT_SHOW_TAB_COUNTS;
|
||||
$this->sDefaultDisplayMode = static::DEFAULT_DISPLAY_MODE;
|
||||
$this->sDefaultDisplayMode = static::DEFAULT_DISPLAY_MODE;
|
||||
|
||||
$this->sTileMode = static::DEFAULT_TILE_MODE;
|
||||
$this->iGroupLimit = static::DEFAULT_GROUP_LIMIT;
|
||||
@@ -252,33 +291,33 @@ class ManageBrick extends PortalBrick
|
||||
return $this->bShowTabCounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the brick default display mode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetDefaultDisplayMode()
|
||||
{
|
||||
return $this->sDefaultDisplayMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default display mode of the brick
|
||||
*
|
||||
* @param string $sDefaultDisplayMode
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function SetDefaultDisplayMode($sDefaultDisplayMode)
|
||||
{
|
||||
$this->sDefaultDisplayMode = $sDefaultDisplayMode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Returns the brick default display mode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetDefaultDisplayMode()
|
||||
{
|
||||
return $this->sDefaultDisplayMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tile mode (display)
|
||||
*
|
||||
* Sets the default display mode of the brick
|
||||
*
|
||||
* @param string $sDefaultDisplayMode
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function SetDefaultDisplayMode($sDefaultDisplayMode)
|
||||
{
|
||||
$this->sDefaultDisplayMode = $sDefaultDisplayMode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tile mode (display)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetTileMode()
|
||||
@@ -287,11 +326,11 @@ class ManageBrick extends PortalBrick
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tile mode (display)
|
||||
*
|
||||
* Sets the tile mode (display)
|
||||
*
|
||||
* @param string $sTileMode
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function SetTileMode($sTileMode)
|
||||
{
|
||||
@@ -349,8 +388,8 @@ class ManageBrick extends PortalBrick
|
||||
* Sets the brick's objects opening mode
|
||||
*
|
||||
* @param string $sOpeningMode
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function SetOpeningMode($sOpeningMode)
|
||||
{
|
||||
@@ -363,8 +402,8 @@ class ManageBrick extends PortalBrick
|
||||
* Sets the grouping of the brick
|
||||
*
|
||||
* @param array $aGrouping
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function SetGrouping($aGrouping)
|
||||
{
|
||||
@@ -377,8 +416,8 @@ class ManageBrick extends PortalBrick
|
||||
* Sets the fields of the brick
|
||||
*
|
||||
* @param array $aFields
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function SetFields($aFields)
|
||||
{
|
||||
@@ -391,8 +430,8 @@ class ManageBrick extends PortalBrick
|
||||
* Sets if the brick should display objects count on tab
|
||||
*
|
||||
* @param bool $bShowTabCounts
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function SetShowTabCounts($bShowTabCounts)
|
||||
{
|
||||
@@ -407,9 +446,9 @@ class ManageBrick extends PortalBrick
|
||||
* Grouping "tabs" must be of form array("attribute" => value)
|
||||
*
|
||||
* @param string $sName (Must be "tabs" or -Not implemented yet, implicit grouping on y axis-)
|
||||
* @param array $aGrouping
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
* @param array $aGrouping
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function AddGrouping($sName, $aGrouping)
|
||||
{
|
||||
@@ -430,8 +469,8 @@ class ManageBrick extends PortalBrick
|
||||
* Removes a grouping by its name
|
||||
*
|
||||
* @param string $sName
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function RemoveGrouping($sName)
|
||||
{
|
||||
@@ -447,8 +486,8 @@ class ManageBrick extends PortalBrick
|
||||
* Adds a field to display from its attribute_code.
|
||||
*
|
||||
* @param string $sAttCode
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function AddField($sAttCode)
|
||||
{
|
||||
@@ -464,8 +503,8 @@ class ManageBrick extends PortalBrick
|
||||
* Removes a field
|
||||
*
|
||||
* @param string $sAttCode
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function RemoveField($sAttCode)
|
||||
{
|
||||
@@ -537,44 +576,46 @@ class ManageBrick extends PortalBrick
|
||||
return (isset($this->aGrouping['areas'])) ? $this->aGrouping['areas'] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sModeId
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
/**
|
||||
* @param string $sModeId
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddAvailableDisplayMode($sModeId)
|
||||
{
|
||||
if(!in_array($sModeId, static::$aDisplayModes))
|
||||
{
|
||||
throw new Exception('ManageBrick: Display mode "' . $sModeId. '" must be one of the allowed display modes (' . implode(', ', static::$aDisplayModes) . ')');
|
||||
}
|
||||
if (!in_array($sModeId, static::$aDisplayModes))
|
||||
{
|
||||
throw new Exception('ManageBrick: Display mode "'.$sModeId.'" must be one of the allowed display modes ('.implode(', ',
|
||||
static::$aDisplayModes).')');
|
||||
}
|
||||
|
||||
$this->aAvailableDisplayModes[] = $sModeId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes $sModeId from the list of availables display modes
|
||||
*
|
||||
* @param string $sModeId
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function RemoveAvailableDisplayMode($sModeId)
|
||||
{
|
||||
if (isset($this->aAvailableDisplayModes[$sModeId]))
|
||||
{
|
||||
unset($this->aAvailableDisplayModes[$sModeId]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Removes $sModeId from the list of availables display modes
|
||||
*
|
||||
* @param string $sModeId
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\ManageBrick
|
||||
*/
|
||||
public function RemoveAvailableDisplayMode($sModeId)
|
||||
{
|
||||
if (isset($this->aAvailableDisplayModes[$sModeId]))
|
||||
{
|
||||
unset($this->aAvailableDisplayModes[$sModeId]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the available display modes for the brick (page, not tile)
|
||||
*
|
||||
* Returns the available display modes for the brick (page, not tile)
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function GetAvailablesDisplayModes()
|
||||
@@ -619,24 +660,25 @@ class ManageBrick extends PortalBrick
|
||||
return $this->IsGroupingByDistinctValues('areas');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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\ManageBrick
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \DOMFormatException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
/**
|
||||
* 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\ManageBrick
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \DOMFormatException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function LoadFromXml(DesignElement $oMDElement)
|
||||
{
|
||||
parent::LoadFromXml($oMDElement);
|
||||
$bUseListFieldsForExport = false;
|
||||
|
||||
// Checking specific elements
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
|
||||
{
|
||||
switch ($oBrickSubNode->nodeName)
|
||||
@@ -675,11 +717,13 @@ class ManageBrick extends PortalBrick
|
||||
break;
|
||||
|
||||
case 'display_modes':
|
||||
/** @var \Combodo\iTop\DesignElement $oDisplayNode */
|
||||
foreach ($oBrickSubNode->GetNodes('./*') as $oDisplayNode)
|
||||
{
|
||||
switch ($oDisplayNode->nodeName)
|
||||
{
|
||||
case 'availables';
|
||||
/** @var \Combodo\iTop\DesignElement $oModeNode */
|
||||
foreach ($oDisplayNode->childNodes as $oModeNode)
|
||||
{
|
||||
if (!$oModeNode->hasAttribute('id'))
|
||||
@@ -691,7 +735,8 @@ class ManageBrick extends PortalBrick
|
||||
$sModeId = $oModeNode->getAttribute('id');
|
||||
if (!in_array($sModeId, static::$aDisplayModes))
|
||||
{
|
||||
throw new DOMFormatException('ManageBrick: Display mode has an invalid value. Expected '.implode('/', static::$aDisplayModes.', "'.$sModeId.'" given.'),
|
||||
throw new DOMFormatException('ManageBrick: Display mode has an invalid value. Expected '.implode('/',
|
||||
static::$aDisplayModes.', "'.$sModeId.'" given.'),
|
||||
null, null, $oModeNode);
|
||||
}
|
||||
|
||||
@@ -699,12 +744,12 @@ class ManageBrick extends PortalBrick
|
||||
}
|
||||
break;
|
||||
|
||||
case 'default':
|
||||
$this->SetDefaultDisplayMode($oDisplayNode->GetText(static::DEFAULT_DISPLAY_MODE));
|
||||
break;
|
||||
case 'default':
|
||||
$this->SetDefaultDisplayMode($oDisplayNode->GetText(static::DEFAULT_DISPLAY_MODE));
|
||||
break;
|
||||
|
||||
case 'tile';
|
||||
$this->SetTileMode($oDisplayNode->GetText(static::DEFAULT_TILE_MODE));
|
||||
$this->SetTileMode($oDisplayNode->GetText(static::DEFAULT_TILE_MODE));
|
||||
|
||||
$aTileParametersForType = $this->GetPresentationDataForTileMode($this->sTileMode);
|
||||
$this->SetTileTemplatePath($aTileParametersForType['tileTemplate']);
|
||||
@@ -715,6 +760,7 @@ class ManageBrick extends PortalBrick
|
||||
break;
|
||||
|
||||
case 'fields':
|
||||
/** @var \Combodo\iTop\DesignElement $oFieldNode */
|
||||
foreach ($oBrickSubNode->GetNodes('./field') as $oFieldNode)
|
||||
{
|
||||
if (!$oFieldNode->hasAttribute('id'))
|
||||
@@ -727,11 +773,13 @@ class ManageBrick extends PortalBrick
|
||||
break;
|
||||
|
||||
case 'export':
|
||||
/** @var \Combodo\iTop\DesignElement $oExportNode */
|
||||
foreach ($oBrickSubNode->GetNodes('./*') as $oExportNode)
|
||||
{
|
||||
switch ($oExportNode->nodeName)
|
||||
{
|
||||
case 'fields':
|
||||
/** @var \Combodo\iTop\DesignElement $oFieldNode */
|
||||
foreach ($oExportNode->GetNodes('./field') as $oFieldNode)
|
||||
{
|
||||
if (!$oFieldNode->hasAttribute('id'))
|
||||
@@ -754,6 +802,7 @@ class ManageBrick extends PortalBrick
|
||||
|
||||
case 'grouping':
|
||||
// Tabs grouping
|
||||
/** @var \Combodo\iTop\DesignElement $oGroupingNode */
|
||||
foreach ($oBrickSubNode->GetNodes('./tabs/*') as $oGroupingNode)
|
||||
{
|
||||
switch ($oGroupingNode->nodeName)
|
||||
@@ -781,6 +830,7 @@ class ManageBrick extends PortalBrick
|
||||
break;
|
||||
case 'groups':
|
||||
$aGroups = array();
|
||||
/** @var \Combodo\iTop\DesignElement $oGroupNode */
|
||||
foreach ($oGroupingNode->GetNodes('./group') as $oGroupNode)
|
||||
{
|
||||
if (!$oGroupNode->hasAttribute('id'))
|
||||
@@ -792,6 +842,7 @@ class ManageBrick extends PortalBrick
|
||||
|
||||
$aGroup = array();
|
||||
$aGroup['id'] = $sGroupId; // We don't put the group id as the $aGroups key because the array will be sorted later in AddGrouping, which replace array keys by integer ordered keys
|
||||
/** @var \Combodo\iTop\DesignElement $oGroupProperty */
|
||||
foreach ($oGroupNode->childNodes as $oGroupProperty)
|
||||
{
|
||||
switch ($oGroupProperty->nodeName)
|
||||
@@ -833,21 +884,23 @@ class ManageBrick extends PortalBrick
|
||||
throw new DOMFormatException('ManageBrick: must have a valid <class|oql> tag', null, null, $oMDElement);
|
||||
}
|
||||
|
||||
// Checking that the brick has at least a display mode
|
||||
if (count($this->GetAvailablesDisplayModes()) === 0)
|
||||
{
|
||||
$this->AddAvailableDisplayMode(static::DEFAULT_DISPLAY_MODE);
|
||||
}
|
||||
// Checking that default display mode in among the availables
|
||||
if (!in_array($this->sDefaultDisplayMode, $this->aAvailableDisplayModes))
|
||||
{
|
||||
throw new DOMFormatException('ManageBrick: Default display mode "' . $this->sDefaultDisplayMode . '" must be one of the available display modes (' . implode(', ', $this->aAvailableDisplayModes) . ')', null, null, $oMDElement);
|
||||
}
|
||||
// Checking that tile mode in among the availables
|
||||
if (!in_array($this->sTileMode, static::$aTileModes))
|
||||
{
|
||||
throw new DOMFormatException('ManageBrick: Tile mode "' . $this->sTileMode. '" must be one of the allowed tile modes (' . implode(', ', static::$aTileModes) . ')', null, null, $oMDElement);
|
||||
}
|
||||
// Checking that the brick has at least a display mode
|
||||
if (count($this->GetAvailablesDisplayModes()) === 0)
|
||||
{
|
||||
$this->AddAvailableDisplayMode(static::DEFAULT_DISPLAY_MODE);
|
||||
}
|
||||
// Checking that default display mode in among the availables
|
||||
if (!in_array($this->sDefaultDisplayMode, $this->aAvailableDisplayModes))
|
||||
{
|
||||
throw new DOMFormatException('ManageBrick: Default display mode "'.$this->sDefaultDisplayMode.'" must be one of the available display modes ('.implode(', ',
|
||||
$this->aAvailableDisplayModes).')', null, null, $oMDElement);
|
||||
}
|
||||
// Checking that tile mode in among the availables
|
||||
if (!in_array($this->sTileMode, static::$aTileModes))
|
||||
{
|
||||
throw new DOMFormatException('ManageBrick: Tile mode "'.$this->sTileMode.'" must be one of the allowed tile modes ('.implode(', ',
|
||||
static::$aTileModes).')', null, null, $oMDElement);
|
||||
}
|
||||
|
||||
// Checking if specified fields, if not we put those from the details zlist
|
||||
if (empty($this->aFields))
|
||||
@@ -871,7 +924,7 @@ class ManageBrick extends PortalBrick
|
||||
$sDecorationClassNavigationMenu = $this->GetDecorationClassNavigationMenu();
|
||||
if (empty($sDecorationClassNavigationMenu) && isset(static::$aPresentationData[$this->sTileMode]))
|
||||
{
|
||||
/** @var string $sDecorationClassNavigationMenu */
|
||||
/** @var string $sDecorationClassNavigationMenu */
|
||||
$sDecorationClassNavigationMenu = static::$aPresentationData[$this->sTileMode]['decorationCssClass'];
|
||||
if (!empty($sDecorationClassNavigationMenu))
|
||||
{
|
||||
|
||||
@@ -28,47 +28,82 @@ use Combodo\iTop\DesignElement;
|
||||
|
||||
/**
|
||||
* Description of PortalBrick
|
||||
*
|
||||
*
|
||||
* Classes that will be used only in the portal, not the console.
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @package Combodo\iTop\Portal\Brick
|
||||
* @since 2.3.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
*/
|
||||
abstract class PortalBrick extends AbstractBrick
|
||||
{
|
||||
const ENUM_OPENING_TARGET_MODAL = 'modal';
|
||||
const ENUM_OPENING_TARGET_SELF = 'self';
|
||||
const ENUM_OPENING_TARGET_NEW = 'new';
|
||||
/** @var string ENUM_OPENING_TARGET_MODAL */
|
||||
const ENUM_OPENING_TARGET_MODAL = 'modal';
|
||||
/** @var string ENUM_OPENING_TARGET_SELF */
|
||||
const ENUM_OPENING_TARGET_SELF = 'self';
|
||||
/** @var string ENUM_OPENING_TARGET_NEW */
|
||||
const ENUM_OPENING_TARGET_NEW = 'new';
|
||||
|
||||
/** @var int DEFAULT_WIDTH */
|
||||
const DEFAULT_WIDTH = 6;
|
||||
/** @var int DEFAULT_HEIGHT */
|
||||
const DEFAULT_HEIGHT = 1;
|
||||
/** @var bool DEFAULT_MODAL */
|
||||
const DEFAULT_MODAL = false;
|
||||
/** @var bool DEFAULT_VISIBLE_HOME */
|
||||
const DEFAULT_VISIBLE_HOME = true;
|
||||
/** @var bool DEFAULT_VISIBLE_NAVIGATION_MENU */
|
||||
const DEFAULT_VISIBLE_NAVIGATION_MENU = true;
|
||||
/** @var string DEFAULT_DECORATION_CLASS_HOME */
|
||||
const DEFAULT_DECORATION_CLASS_HOME = '';
|
||||
/** @var string DEFAULT_DECORATION_CLASS_NAVIGATION_MENU */
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = '';
|
||||
/** @var string DEFAULT_TILE_TEMPLATE_PATH */
|
||||
const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/tile.html.twig';
|
||||
/** @var string|null DEFAULT_TILE_CONTROLLER_ACTION */
|
||||
const DEFAULT_TILE_CONTROLLER_ACTION = null;
|
||||
const DEFAULT_OPENING_TARGET = self::ENUM_OPENING_TARGET_MODAL;
|
||||
/** @var string DEFAULT_OPENING_TARGET */
|
||||
const DEFAULT_OPENING_TARGET = self::ENUM_OPENING_TARGET_MODAL;
|
||||
|
||||
/** @var string|null $sRouteName */
|
||||
static $sRouteName = null;
|
||||
static $aOpeningTargets = array(self::ENUM_OPENING_TARGET_MODAL, self::ENUM_OPENING_TARGET_SELF, self::ENUM_OPENING_TARGET_NEW);
|
||||
/** @var array $aOpeningTargets */
|
||||
static $aOpeningTargets = array(self::ENUM_OPENING_TARGET_MODAL, self::ENUM_OPENING_TARGET_SELF, self::ENUM_OPENING_TARGET_NEW);
|
||||
|
||||
/** @var int $iWidth */
|
||||
protected $iWidth;
|
||||
/** @var int $iHeight */
|
||||
protected $iHeight;
|
||||
/** @var bool $bModal */
|
||||
protected $bModal;
|
||||
/** @var bool $bVisibleHome */
|
||||
protected $bVisibleHome;
|
||||
/** @var bool $bVisibleNavigationMenu */
|
||||
protected $bVisibleNavigationMenu;
|
||||
/** @var string $sDecorationClassHome */
|
||||
protected $sDecorationClassHome;
|
||||
/** @var string $sDecorationClassNavigationMenu */
|
||||
protected $sDecorationClassNavigationMenu;
|
||||
/** @var string $sTileTemplatePath */
|
||||
protected $sTileTemplatePath;
|
||||
/** @var string|null $sTileControllerAction */
|
||||
protected $sTileControllerAction;
|
||||
protected $sOpeningTarget;
|
||||
/** @var string $sOpeningTarget */
|
||||
protected $sOpeningTarget;
|
||||
|
||||
// Vars below are itemization from parent class
|
||||
/** @var float $fRankHome */
|
||||
protected $fRankHome;
|
||||
/** @var float $fRankNavigationMenu */
|
||||
protected $fRankNavigationMenu;
|
||||
/** @var string $sTitleHome */
|
||||
protected $sTitleHome;
|
||||
/** @var string $sTitleNavigationMenu */
|
||||
protected $sTitleNavigationMenu;
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public static function GetRouteName()
|
||||
{
|
||||
return static::$sRouteName;
|
||||
@@ -90,7 +125,7 @@ abstract class PortalBrick extends AbstractBrick
|
||||
$this->sDecorationClassNavigationMenu = static::DEFAULT_DECORATION_CLASS_NAVIGATION_MENU;
|
||||
$this->sTileTemplatePath = static::DEFAULT_TILE_TEMPLATE_PATH;
|
||||
$this->sTileControllerAction = static::DEFAULT_TILE_CONTROLLER_ACTION;
|
||||
$this->sOpeningTarget = static::DEFAULT_OPENING_TARGET;
|
||||
$this->sOpeningTarget = static::DEFAULT_OPENING_TARGET;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,26 +258,27 @@ abstract class PortalBrick extends AbstractBrick
|
||||
return $this->sTileTemplatePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the brick's objects opening target (modal, new tab, current window)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetOpeningTarget()
|
||||
{
|
||||
return $this->sOpeningTarget;
|
||||
}
|
||||
/**
|
||||
* Returns the brick's objects opening target (modal, new tab, current window)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetOpeningTarget()
|
||||
{
|
||||
return $this->sOpeningTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the width of the brick
|
||||
*
|
||||
* @param boolean $iWidth
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetWidth($iWidth)
|
||||
{
|
||||
$this->iWidth = $iWidth;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -250,12 +286,13 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Sets the width of the brick
|
||||
*
|
||||
* @param integer $iHeight
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetHeight($iHeight)
|
||||
{
|
||||
$this->iHeight = $iHeight;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -263,12 +300,13 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Sets if the brick will show in a modal dialog or not
|
||||
*
|
||||
* @param boolean $bModal
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetModal($bModal)
|
||||
{
|
||||
$this->bModal = $bModal;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -276,12 +314,13 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Sets if the brick is visible on the portal's home
|
||||
*
|
||||
* @param boolean $bVisibleHome
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetVisibleHome($bVisibleHome)
|
||||
{
|
||||
$this->bVisibleHome = $bVisibleHome;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -289,12 +328,13 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Sets if the brick is visible on the portal's navigation menu
|
||||
*
|
||||
* @param boolean $bVisibleNavigationMenu
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetVisibleNavigationMenu($bVisibleNavigationMenu)
|
||||
{
|
||||
$this->bVisibleNavigationMenu = $bVisibleNavigationMenu;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -302,12 +342,13 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Sets if the brick's rank on the portal's home
|
||||
*
|
||||
* @param float $fRankHome
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetRankHome($fRankHome)
|
||||
{
|
||||
$this->fRankHome = $fRankHome;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -315,12 +356,13 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Sets if the brick's rank on the portal's navigation menu
|
||||
*
|
||||
* @param float $fRankNavigationMenu
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetRankNavigationMenu($fRankNavigationMenu)
|
||||
{
|
||||
$this->fRankNavigationMenu = $fRankNavigationMenu;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -328,12 +370,13 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Sets if the brick's decoration class on the portal's home
|
||||
*
|
||||
* @param string $sDecorationClassHome
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetDecorationClassHome($sDecorationClassHome)
|
||||
{
|
||||
$this->sDecorationClassHome = $sDecorationClassHome;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -341,12 +384,13 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Sets if the brick's decoration class on the portal's navigation menu
|
||||
*
|
||||
* @param string $sDecorationClassNavigationMenu
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetDecorationClassNavigationMenu($sDecorationClassNavigationMenu)
|
||||
{
|
||||
$this->sDecorationClassNavigationMenu = $sDecorationClassNavigationMenu;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -354,12 +398,13 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Sets if the brick's title on the portal's home
|
||||
*
|
||||
* @param string $sTitleHome
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetTitleHome($sTitleHome)
|
||||
{
|
||||
$this->sTitleHome = $sTitleHome;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -367,12 +412,13 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Sets if the brick's title on the portal's navigation menu
|
||||
*
|
||||
* @param string $sTitleNavigationMenu
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetTitleNavigationMenu($sTitleNavigationMenu)
|
||||
{
|
||||
$this->sTitleNavigationMenu = $sTitleNavigationMenu;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -380,12 +426,13 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Sets the brick tile template path
|
||||
*
|
||||
* @param string $sTileTemplatePath
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetTileTemplatePath($sTileTemplatePath)
|
||||
{
|
||||
$this->sTileTemplatePath = $sTileTemplatePath;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -393,53 +440,56 @@ abstract class PortalBrick extends AbstractBrick
|
||||
* Sets the brick tile controller action
|
||||
*
|
||||
* @param string $sTileControllerAction
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetTileControllerAction($sTileControllerAction)
|
||||
{
|
||||
$this->sTileControllerAction = $sTileControllerAction;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the brick's objects opening target
|
||||
*
|
||||
* @param string $sOpeningTarget
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetOpeningTarget($sOpeningTarget)
|
||||
{
|
||||
$this->sOpeningTarget = $sOpeningTarget;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Sets the brick's objects opening target
|
||||
*
|
||||
* @param string $sOpeningTarget
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Brick\PortalBrick
|
||||
*/
|
||||
public function SetOpeningTarget($sOpeningTarget)
|
||||
{
|
||||
$this->sOpeningTarget = $sOpeningTarget;
|
||||
|
||||
/**
|
||||
* 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\PortalBrick
|
||||
*
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
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\PortalBrick
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
case 'width':
|
||||
$this->SetWidth((int) $oBrickSubNode->GetText(static::DEFAULT_WIDTH));
|
||||
$this->SetWidth((int)$oBrickSubNode->GetText(static::DEFAULT_WIDTH));
|
||||
break;
|
||||
|
||||
case 'height':
|
||||
$this->SetHeight((int) $oBrickSubNode->GetText(static::DEFAULT_HEIGHT));
|
||||
$this->SetHeight((int)$oBrickSubNode->GetText(static::DEFAULT_HEIGHT));
|
||||
break;
|
||||
|
||||
case 'modal':
|
||||
@@ -473,10 +523,12 @@ abstract class PortalBrick extends AbstractBrick
|
||||
break;
|
||||
|
||||
case 'templates':
|
||||
$oTemplateNodeList = $oBrickSubNode->GetNodes('template[@id=' . ModuleDesign::XPathQuote('tile') . ']');
|
||||
$oTemplateNodeList = $oBrickSubNode->GetNodes('template[@id='.ModuleDesign::XPathQuote('tile').']');
|
||||
if ($oTemplateNodeList->length > 0)
|
||||
{
|
||||
$this->SetTileTemplatePath($oTemplateNodeList->item(0)->GetText(static::DEFAULT_TILE_TEMPLATE_PATH));
|
||||
/** @var \Combodo\iTop\DesignElement $oTemplateNode */
|
||||
$oTemplateNode = $oTemplateNodeList->item(0);
|
||||
$this->SetTileTemplatePath($oTemplateNode->GetText(static::DEFAULT_TILE_TEMPLATE_PATH));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -569,15 +621,17 @@ abstract class PortalBrick extends AbstractBrick
|
||||
$this->SetTileControllerAction($oBrickSubNode->GetText(static::DEFAULT_TILE_CONTROLLER_ACTION));
|
||||
break;
|
||||
|
||||
case 'opening_target':
|
||||
$sOpeningTarget = $oBrickSubNode->GetText(static::DEFAULT_OPENING_TARGET);
|
||||
if (!in_array($sOpeningTarget, array(static::ENUM_OPENING_TARGET_MODAL, static::ENUM_OPENING_TARGET_NEW, static::ENUM_OPENING_TARGET_SELF)))
|
||||
{
|
||||
throw new DOMFormatException('PortalBrick : opening_target tag value must be modal|new|self ("' . $sOpeningTarget . '" given)', null, null, $oBrickSubNode);
|
||||
}
|
||||
case 'opening_target':
|
||||
$sOpeningTarget = $oBrickSubNode->GetText(static::DEFAULT_OPENING_TARGET);
|
||||
if (!in_array($sOpeningTarget,
|
||||
array(static::ENUM_OPENING_TARGET_MODAL, static::ENUM_OPENING_TARGET_NEW, static::ENUM_OPENING_TARGET_SELF)))
|
||||
{
|
||||
throw new DOMFormatException('PortalBrick : opening_target tag value must be modal|new|self ("'.$sOpeningTarget.'" given)',
|
||||
null, null, $oBrickSubNode);
|
||||
}
|
||||
|
||||
$this->SetOpeningTarget($sOpeningTarget);
|
||||
break;
|
||||
$this->SetOpeningTarget($sOpeningTarget);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Created by Bruno DA SILVA, working for Combodo
|
||||
* Date: 24/01/19
|
||||
* Time: 17:28
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\Brick;
|
||||
@@ -14,6 +29,7 @@ use Exception;
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Brick
|
||||
* @since 2.7.0
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
*/
|
||||
class PropertyNotFoundException extends Exception
|
||||
{
|
||||
|
||||
@@ -27,27 +27,43 @@ use Combodo\iTop\DesignElement;
|
||||
/**
|
||||
* Description of UserProfileBrick
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Brick
|
||||
* @since 2.7.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
*/
|
||||
class UserProfileBrick extends PortalBrick
|
||||
{
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/user-profile/layout.html.twig';
|
||||
// Overloaded constants
|
||||
const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/user-profile/layout.html.twig';
|
||||
const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/user-profile/tile.html.twig';
|
||||
const DEFAULT_VISIBLE_NAVIGATION_MENU = false;
|
||||
const DEFAULT_VISIBLE_HOME = false;
|
||||
const DEFAUT_TITLE = 'Brick:Portal:UserProfile:Title';
|
||||
const DEFAULT_DECORATION_CLASS_HOME = 'glyphicon glyphicon-user';
|
||||
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'glyphicon glyphicon-user';
|
||||
const DEFAULT_SHOW_PICTURE_FORM = true;
|
||||
|
||||
/** @var bool DEFAULT_SHOW_PICTURE_FORM */
|
||||
const DEFAULT_SHOW_PICTURE_FORM = true;
|
||||
/** @var bool DEFAULT_SHOW_PREFERENCES_FORM */
|
||||
const DEFAULT_SHOW_PREFERENCES_FORM = true;
|
||||
/** @var bool DEFAULT_SHOW_PASSWORD_FORM */
|
||||
const DEFAULT_SHOW_PASSWORD_FORM = true;
|
||||
|
||||
// Overloaded variables
|
||||
static $sRouteName = 'p_user_profile_brick';
|
||||
|
||||
/** @var array $aForm */
|
||||
protected $aForm;
|
||||
/** @var bool $bShowPictureForm */
|
||||
protected $bShowPictureForm;
|
||||
/** @var bool $bShowPreferencesForm */
|
||||
protected $bShowPreferencesForm;
|
||||
/** @var bool $bShowPasswordForm */
|
||||
protected $bShowPasswordForm;
|
||||
|
||||
/**
|
||||
* UserProfileBrick constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
@@ -56,7 +72,7 @@ class UserProfileBrick extends PortalBrick
|
||||
'id' => 'default-user-profile',
|
||||
'type' => 'zlist',
|
||||
'fields' => 'details',
|
||||
'layout' => null
|
||||
'layout' => null,
|
||||
);
|
||||
$this->bShowPictureForm = static::DEFAULT_SHOW_PICTURE_FORM;
|
||||
$this->bShowPreferencesForm = static::DEFAULT_SHOW_PREFERENCES_FORM;
|
||||
@@ -142,14 +158,17 @@ class UserProfileBrick extends PortalBrick
|
||||
* This is used to set all the brick attributes at once.
|
||||
*
|
||||
* @param \Combodo\iTop\DesignElement $oMDElement
|
||||
*
|
||||
* @return UserProfileBrick
|
||||
* @throws DOMFormatException
|
||||
* @throws DOMFormatException*@throws \Exception
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function LoadFromXml(DesignElement $oMDElement)
|
||||
{
|
||||
parent::LoadFromXml($oMDElement);
|
||||
|
||||
// Checking specific elements
|
||||
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
|
||||
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
|
||||
{
|
||||
switch ($oBrickSubNode->nodeName)
|
||||
@@ -162,6 +181,7 @@ class UserProfileBrick extends PortalBrick
|
||||
$this->aForm['type'] = 'custom_list';
|
||||
$this->aForm['fields'] = array();
|
||||
|
||||
/** @var \Combodo\iTop\DesignElement $oFieldNode */
|
||||
foreach ($oBrickSubNode->GetOptionalElement('fields')->GetNodes('field') as $oFieldNode)
|
||||
{
|
||||
$sFieldId = $oFieldNode->getAttribute('id');
|
||||
@@ -201,7 +221,7 @@ class UserProfileBrick extends PortalBrick
|
||||
|
||||
$this->aForm['layout'] = array(
|
||||
'type' => (preg_match('/\{\{|\{\#|\{\%/', $sXml) === 1) ? 'twig' : 'xhtml',
|
||||
'content' => $sXml
|
||||
'content' => $sXml,
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -28,8 +28,8 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
* Class AbstractController
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Controller
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
*/
|
||||
abstract class AbstractController extends Controller
|
||||
{
|
||||
|
||||
@@ -26,8 +26,8 @@ namespace Combodo\iTop\Portal\Controller;
|
||||
* Class BrickController
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Controller
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
*/
|
||||
abstract class BrickController extends AbstractController
|
||||
{
|
||||
|
||||
@@ -40,8 +40,8 @@ use Combodo\iTop\Portal\Brick\BrowseBrick;
|
||||
* Class BrowseBrickController
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Controller
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class BrowseBrickController extends BrickController
|
||||
{
|
||||
@@ -60,6 +60,7 @@ class BrowseBrickController extends BrickController
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function DisplayAction(Request $oRequest, $sBrickId, $sBrowseMode = null, $sDataLoading = null)
|
||||
{
|
||||
@@ -77,7 +78,8 @@ class BrowseBrickController extends BrickController
|
||||
// Getting current browse mode (First from router pamater, 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 : $oRequestManipulator->ReadParam('sDataLoading', $oBrick->GetDataLoading());
|
||||
$sDataLoading = ($sDataLoading !== null) ? $sDataLoading : $oRequestManipulator->ReadParam('sDataLoading',
|
||||
$oBrick->GetDataLoading());
|
||||
// Getting search value
|
||||
$sSearchValue = $oRequestManipulator->ReadParam('sSearchValue', '');
|
||||
if (!empty($sSearchValue))
|
||||
@@ -93,17 +95,22 @@ class BrowseBrickController extends BrickController
|
||||
// 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)));
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'Browse brick "'.$sBrickId.'" : Unknown browse mode "'.$sBrowseMode.'", availables are '.implode(' / ',
|
||||
array_keys($aBrowseModes)));
|
||||
}
|
||||
if (empty($aLevelsProperties))
|
||||
{
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Browse brick "' . $sBrickId . '" : No levels to display.');
|
||||
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(BrowseBrick::ENUM_BROWSE_MODE_TREE, BrowseBrick::ENUM_BROWSE_MODE_MOSAIC)) && ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY))
|
||||
if (in_array($sBrowseMode, array(
|
||||
BrowseBrick::ENUM_BROWSE_MODE_TREE,
|
||||
BrowseBrick::ENUM_BROWSE_MODE_MOSAIC,
|
||||
)) && ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY))
|
||||
{
|
||||
// Will be handled later in the pagination part
|
||||
}
|
||||
@@ -123,12 +130,15 @@ class BrowseBrickController extends BrickController
|
||||
if ($i < $iLoopMax)
|
||||
{
|
||||
$aRealiasingMap = array();
|
||||
$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);
|
||||
$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))
|
||||
{
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->RenameAlias($aRealiasingMap[$sLevelAlias], $sLevelAlias);
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->RenameAlias($aRealiasingMap[$sLevelAlias],
|
||||
$sLevelAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,7 +174,8 @@ class BrowseBrickController extends BrickController
|
||||
|
||||
for ($k = 0; $k <= $iSearchLoopMax; $k++)
|
||||
{
|
||||
$oSearchBinExpr = new BinaryExpression(new FieldExpression($sTmpFieldAttCode, $aLevelsPropertiesKeys[$i]), 'LIKE', new VariableExpression('search_value_' . $k));
|
||||
$oSearchBinExpr = new BinaryExpression(new FieldExpression($sTmpFieldAttCode, $aLevelsPropertiesKeys[$i]),
|
||||
'LIKE', new VariableExpression('search_value_'.$k));
|
||||
if ($k === 0)
|
||||
{
|
||||
$oFieldBinExpr = $oSearchBinExpr;
|
||||
@@ -214,7 +225,7 @@ class BrowseBrickController extends BrickController
|
||||
// Note : $iSearchloopMax was initialized on the previous loop
|
||||
for ($j = 0; $j <= $iSearchLoopMax; $j++)
|
||||
{
|
||||
$aQueryParams['search_value_' . $j] = '%' . $aSearchValues[$j] . '%';
|
||||
$aQueryParams['search_value_'.$j] = '%'.$aSearchValues[$j].'%';
|
||||
}
|
||||
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->SetInternalParams($aQueryParams);
|
||||
}
|
||||
@@ -228,7 +239,8 @@ 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($this->getParameter('combodo.portal.instance.id'), 'lazy_loading_threshold');
|
||||
$fThreshold = (float)MetaModel::GetModuleSetting($this->getParameter('combodo.portal.instance.id'),
|
||||
'lazy_loading_threshold');
|
||||
$sDataLoading = ($oCountSet->Count() > $fThreshold) ? AbstractBrick::ENUM_DATA_LOADING_LAZY : AbstractBrick::ENUM_DATA_LOADING_FULL;
|
||||
unset($oCountSet);
|
||||
}
|
||||
@@ -241,8 +253,9 @@ class BrowseBrickController extends BrickController
|
||||
{
|
||||
case BrowseBrick::ENUM_BROWSE_MODE_LIST:
|
||||
// Retrieving parameters
|
||||
$iPageNumber = (int) $oRequestManipulator->ReadParam('iPageNumber', 1, FILTER_SANITIZE_NUMBER_INT);
|
||||
$iListLength = (int) $oRequestManipulator->ReadParam('iListLength', BrowseBrick::DEFAULT_LIST_LENGTH, FILTER_SANITIZE_NUMBER_INT);
|
||||
$iPageNumber = (int)$oRequestManipulator->ReadParam('iPageNumber', 1, FILTER_SANITIZE_NUMBER_INT);
|
||||
$iListLength = (int)$oRequestManipulator->ReadParam('iListLength', BrowseBrick::DEFAULT_LIST_LENGTH,
|
||||
FILTER_SANITIZE_NUMBER_INT);
|
||||
|
||||
// Getting total records number
|
||||
$oCountSet = new DBObjectSet($oQuery);
|
||||
@@ -293,7 +306,8 @@ 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.');
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'Browse brick "'.$sBrickId.'" : Level alias "'.$sLevelAlias.'" is not defined for that brick.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
* Class DefaultController
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Controller
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class DefaultController extends AbstractController
|
||||
{
|
||||
@@ -49,7 +49,7 @@ class DefaultController extends AbstractController
|
||||
|
||||
// Rendering tiles
|
||||
$aData['aTilesRendering'] = array();
|
||||
foreach($oBricksCollection->GetBricks() as $oBrick)
|
||||
foreach ($oBricksCollection->GetBricks() as $oBrick)
|
||||
{
|
||||
// Doing it only for tile visible on home page to avoid unnecessary rendering
|
||||
if (($oBrick->GetVisibleHome() === true) && ($oBrick->GetTileControllerAction() !== null))
|
||||
@@ -57,16 +57,17 @@ class DefaultController extends AbstractController
|
||||
$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);
|
||||
return new Response('Tile controller action must be of form "\Namespace\ControllerClass::FunctionName" for brick "'.$oBrick->GetId().'"',
|
||||
500);
|
||||
}
|
||||
|
||||
$sControllerName = $aControllerActionParts[0];
|
||||
$sControllerAction = $aControllerActionParts[1];
|
||||
|
||||
$oController = new $sControllerName();
|
||||
if(!$oController instanceof ContainerAwareInterface)
|
||||
if (!$oController instanceof ContainerAwareInterface)
|
||||
{
|
||||
return new Response('Tile controller must be implement ContainerAwareInterface for brick "' . $oBrick->GetId() . '"', 500);
|
||||
return new Response('Tile controller must be implement ContainerAwareInterface for brick "'.$oBrick->GetId().'"', 500);
|
||||
}
|
||||
$oController->setContainer($this->container);
|
||||
/** @var Response $oResponse */
|
||||
|
||||
@@ -50,14 +50,15 @@ use VariableExpression;
|
||||
* Class ManageBrickController
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Controller
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
* @author Eric Espie <eric.espie@combodo.com>
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @author Pierre Goiffon <pierre.goiffon@combodo.com>
|
||||
* @since 2.3.0
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
* @author Eric Espie <eric.espie@combodo.com>
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @author Pierre Goiffon <pierre.goiffon@combodo.com>
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class ManageBrickController extends BrickController
|
||||
{
|
||||
/** @var string EXCEL_EXPORT_TEMPLATE_PATH */
|
||||
const EXCEL_EXPORT_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig';
|
||||
|
||||
/**
|
||||
@@ -78,9 +79,9 @@ class ManageBrickController extends BrickController
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function DisplayAction(Request $oRequest, $sBrickId, $sGroupingTab, $sDisplayMode = null)
|
||||
{
|
||||
/** @var \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection */
|
||||
$oBrickCollection = $this->get('brick_collection');
|
||||
{
|
||||
/** @var \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection */
|
||||
$oBrickCollection = $this->get('brick_collection');
|
||||
|
||||
/** @var \Combodo\iTop\Portal\Brick\ManageBrick $oBrick */
|
||||
$oBrick = $oBrickCollection->GetBrickById($sBrickId);
|
||||
@@ -157,6 +158,7 @@ class ManageBrickController extends BrickController
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function ExcelExportStartAction(Request $oRequest, $sBrickId, $sGroupingTab, $sGroupingArea)
|
||||
{
|
||||
@@ -266,6 +268,7 @@ class ManageBrickController extends BrickController
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetData(Request $oRequest, $sBrickId, $sGroupingTab, $bNeedDetails = false)
|
||||
{
|
||||
@@ -395,8 +398,8 @@ class ManageBrickController extends BrickController
|
||||
}
|
||||
}
|
||||
|
||||
// - Adding search clause if necessary
|
||||
$this->ManageSearchValue($aData, $oQuery, $sClass, $aColumnsAttrs);
|
||||
// - Adding search clause if necessary
|
||||
$this->ManageSearchValue($aData, $oQuery, $sClass, $aColumnsAttrs);
|
||||
|
||||
// Preparing areas
|
||||
// - We need to retrieve distinct values for the grouping attribute
|
||||
@@ -427,7 +430,7 @@ class ManageBrickController extends BrickController
|
||||
'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_']
|
||||
'count' => $aDistinctResult['_itop_count_'],
|
||||
);
|
||||
unset($oConditionQuery);
|
||||
}
|
||||
@@ -441,7 +444,7 @@ class ManageBrickController extends BrickController
|
||||
'label' => MetaModel::GetName($sClass),
|
||||
// Caution : This works only because we froze the grouping areas on the finalclass attribute.
|
||||
'condition' => null,
|
||||
'count' => 0
|
||||
'count' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -501,7 +504,8 @@ class ManageBrickController extends BrickController
|
||||
{
|
||||
// Retrieving parameters
|
||||
$iPageNumber = (int)$oRequestManipulator->ReadParam('iPageNumber', 1, FILTER_SANITIZE_NUMBER_INT);
|
||||
$iListLength = (int)$oRequestManipulator->ReadParam('iListLength', ManageBrick::DEFAULT_LIST_LENGTH, FILTER_SANITIZE_NUMBER_INT);
|
||||
$iListLength = (int)$oRequestManipulator->ReadParam('iListLength', ManageBrick::DEFAULT_LIST_LENGTH,
|
||||
FILTER_SANITIZE_NUMBER_INT);
|
||||
|
||||
// Getting total records number
|
||||
$oCountSet = new DBObjectSet($oQuery);
|
||||
@@ -579,7 +583,8 @@ class ManageBrickController extends BrickController
|
||||
if ($sItemAttr === $sMainActionAttrCode)
|
||||
{
|
||||
// Checking if we can edit the object
|
||||
if (($oBrick->GetOpeningMode() === ManageBrick::ENUM_ACTION_EDIT) && $oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY, $sCurrentClass, $oCurrentRow->GetKey()))
|
||||
if (($oBrick->GetOpeningMode() === ManageBrick::ENUM_ACTION_EDIT) && $oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY,
|
||||
$sCurrentClass, $oCurrentRow->GetKey()))
|
||||
{
|
||||
$sActionType = ManageBrick::ENUM_ACTION_EDIT;
|
||||
}
|
||||
@@ -605,10 +610,11 @@ class ManageBrickController extends BrickController
|
||||
}
|
||||
}
|
||||
|
||||
/** @var AttributeDefinition $oAttDef */
|
||||
/** @var \AttributeDefinition $oAttDef */
|
||||
$oAttDef = MetaModel::GetAttributeDef($sCurrentClass, $sItemAttr);
|
||||
if ($oAttDef->IsExternalKey())
|
||||
{
|
||||
/** @var \AttributeExternalKey $oAttDef */
|
||||
$sValue = $oCurrentRow->GetAsHTML($sItemAttr.'_friendlyname');
|
||||
$sSortValue = $oCurrentRow->Get($sItemAttr.'_friendlyname');
|
||||
|
||||
@@ -629,19 +635,24 @@ class ManageBrickController extends BrickController
|
||||
}
|
||||
}
|
||||
elseif ($oAttDef instanceof AttributeImage)
|
||||
{
|
||||
$oOrmDoc = $oCurrentRow->Get($sItemAttr);
|
||||
if (is_object($oOrmDoc) && !$oOrmDoc->IsEmpty())
|
||||
{
|
||||
$sUrl = $oUrlGenerator->generate('p_object_document_display', array('sObjectClass' => get_class($oCurrentRow), 'sObjectId' => $oCurrentRow->GetKey(), 'sObjectField' => $sItemAttr, 'cache' => 86400));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $oAttDef->Get('default_image');
|
||||
}
|
||||
$sValue = '<img src="' . $sUrl . '" />';
|
||||
$sSortValue = null;
|
||||
}
|
||||
{
|
||||
$oOrmDoc = $oCurrentRow->Get($sItemAttr);
|
||||
if (is_object($oOrmDoc) && !$oOrmDoc->IsEmpty())
|
||||
{
|
||||
$sUrl = $oUrlGenerator->generate('p_object_document_display', array(
|
||||
'sObjectClass' => get_class($oCurrentRow),
|
||||
'sObjectId' => $oCurrentRow->GetKey(),
|
||||
'sObjectField' => $sItemAttr,
|
||||
'cache' => 86400,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $oAttDef->Get('default_image');
|
||||
}
|
||||
$sValue = '<img src="'.$sUrl.'" />';
|
||||
$sSortValue = null;
|
||||
}
|
||||
elseif ($oAttDef instanceof AttributeTagSet)
|
||||
{
|
||||
/** @var \ormTagSet $oSetValues */
|
||||
@@ -653,8 +664,8 @@ class ManageBrickController extends BrickController
|
||||
}
|
||||
else
|
||||
{
|
||||
$sValue = $oAttDef->GetAsHTML($oCurrentRow->Get($sItemAttr));
|
||||
$sSortValue = $oCurrentRow->Get($sItemAttr);
|
||||
$sValue = $oAttDef->GetAsHTML($oCurrentRow->Get($sItemAttr));
|
||||
$sSortValue = $oCurrentRow->Get($sItemAttr);
|
||||
}
|
||||
unset($oAttDef);
|
||||
|
||||
@@ -662,18 +673,18 @@ class ManageBrickController extends BrickController
|
||||
'att_code' => $sItemAttr,
|
||||
'value' => $sValue,
|
||||
'sort_value' => $sSortValue,
|
||||
'actions' => $aActions
|
||||
'actions' => $aActions,
|
||||
);
|
||||
}
|
||||
|
||||
// ... Checking menu extensions
|
||||
$aItemButtons = array();
|
||||
/** @var iPopupMenuExtension $oExtensionInstance */
|
||||
foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance)
|
||||
foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance)
|
||||
{
|
||||
foreach ($oExtensionInstance->EnumItems(iPopupMenuExtension::PORTAL_OBJLISTITEM_ACTIONS, array(
|
||||
'portal_id' => $sPortalId,
|
||||
'object' => $oCurrentRow
|
||||
'object' => $oCurrentRow,
|
||||
)) as $oMenuItem)
|
||||
{
|
||||
if (is_object($oMenuItem))
|
||||
@@ -682,7 +693,7 @@ class ManageBrickController extends BrickController
|
||||
{
|
||||
$aItemButtons[] = $oMenuItem->GetMenuItem() + array(
|
||||
'js_files' => $oMenuItem->GetLinkedScripts(),
|
||||
'type' => 'button'
|
||||
'type' => 'button',
|
||||
);
|
||||
}
|
||||
elseif ($oMenuItem instanceof URLButtonItem)
|
||||
@@ -722,7 +733,7 @@ class ManageBrickController extends BrickController
|
||||
'sTitle' => $aGroupingAreasValues[$sKey]['label'],
|
||||
'aItems' => $aItems,
|
||||
'iItemsCount' => $oSet->Count(),
|
||||
'aColumnsDefinition' => $aColumnsDefinition
|
||||
'aColumnsDefinition' => $aColumnsDefinition,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -736,7 +747,7 @@ class ManageBrickController extends BrickController
|
||||
if ($oRequest->isXmlHttpRequest())
|
||||
{
|
||||
$aData = $aData + array(
|
||||
'data' => $aGroupingAreasData[$sGroupingArea]['aItems']
|
||||
'data' => $aGroupingAreasData[$sGroupingArea]['aItems'],
|
||||
);
|
||||
}
|
||||
else
|
||||
@@ -757,7 +768,7 @@ class ManageBrickController extends BrickController
|
||||
$aUrls[] = $oUrlGenerator->generate('p_manage_brick', array(
|
||||
'sBrickId' => $sBrickId,
|
||||
'sDisplayMode' => 'default',
|
||||
'sGroupingTab' => $aValues['value']
|
||||
'sGroupingTab' => $aValues['value'],
|
||||
));
|
||||
}
|
||||
|
||||
@@ -812,16 +823,16 @@ class ManageBrickController extends BrickController
|
||||
// Note : This is a very naive search at the moment
|
||||
if (!empty($sSearchValue))
|
||||
{
|
||||
// Putting only valid attributes as one can define attributes of leaf classes in the brick definition (<fields>), but at this stage we are working on the abstract class.
|
||||
// Note: This won't fix everything as the search will not be looking in all fields.
|
||||
$aSearchListItems = array();
|
||||
foreach($aColumnsAttrs as $sColumnAttr)
|
||||
{
|
||||
if(MetaModel::IsValidAttCode($sClass, $sColumnAttr))
|
||||
{
|
||||
$aSearchListItems[] = $sColumnAttr;
|
||||
}
|
||||
}
|
||||
// Putting only valid attributes as one can define attributes of leaf classes in the brick definition (<fields>), but at this stage we are working on the abstract class.
|
||||
// Note: This won't fix everything as the search will not be looking in all fields.
|
||||
$aSearchListItems = array();
|
||||
foreach ($aColumnsAttrs as $sColumnAttr)
|
||||
{
|
||||
if (MetaModel::IsValidAttCode($sClass, $sColumnAttr))
|
||||
{
|
||||
$aSearchListItems[] = $sColumnAttr;
|
||||
}
|
||||
}
|
||||
|
||||
$oFullBinExpr = null;
|
||||
foreach ($aSearchListItems as $sSearchItemAttr)
|
||||
@@ -857,17 +868,18 @@ class ManageBrickController extends BrickController
|
||||
|
||||
/**
|
||||
* Get the groups using a given attribute code.
|
||||
* If a limit is given, the remaining groups are aggregated (groupby result and search request).
|
||||
* If a limit is given, the remaining groups are aggregated (group by result and search request).
|
||||
*
|
||||
* @param \DBSearch $oQuery Initial query
|
||||
* @param string $sGroupingTabAttCode Attribute code to group by
|
||||
* @param \Combodo\iTop\Portal\Brick\ManageBrick $oBrick
|
||||
*
|
||||
* @return array of results from the groupby request and the corrsponding search.
|
||||
* @return array of results from the group by request and the corresponding search.
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \MySQLException
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function GroupByAttribute(
|
||||
DBSearch $oQuery, $sGroupingTabAttCode, ManageBrick $oBrick
|
||||
@@ -912,7 +924,7 @@ class ManageBrickController extends BrickController
|
||||
{
|
||||
$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GTAB');
|
||||
$oExpression = new BinaryExpression(new FieldExpression($sGroupingTabAttCode,
|
||||
$oConditionQuery->GetClassAlias()), '=', new UnaryExpression($aDistinctResult['grouped_by_1']));
|
||||
$oConditionQuery->GetClassAlias()), '=', new UnaryExpression($aDistinctResult['grouped_by_1']));
|
||||
$oConditionQuery->AddConditionExpression($oExpression);
|
||||
|
||||
$sHtmlLabel = $oFieldExp->MakeValueLabel($oDistinctQuery, $aDistinctResult['grouped_by_1'], '');
|
||||
@@ -935,7 +947,7 @@ class ManageBrickController extends BrickController
|
||||
{
|
||||
$iOtherCount += $aResult['_itop_count_'];
|
||||
$oExpr = new BinaryExpression(new FieldExpression($sGroupingTabAttCode,
|
||||
$oConditionQuery->GetClassAlias()), '=', new UnaryExpression($aResult['grouped_by_1']));
|
||||
$oConditionQuery->GetClassAlias()), '=', new UnaryExpression($aResult['grouped_by_1']));
|
||||
if (is_null($oExpression))
|
||||
{
|
||||
$oExpression = $oExpr;
|
||||
|
||||
@@ -42,11 +42,12 @@ use Combodo\iTop\Renderer\Bootstrap\BsFormRenderer;
|
||||
* Class UserProfileBrickController
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Controller
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class UserProfileBrickController extends BrickController
|
||||
{
|
||||
/** @var string ENUM_FORM_TYPE_PICTURE */
|
||||
const ENUM_FORM_TYPE_PICTURE = 'picture';
|
||||
|
||||
/**
|
||||
@@ -133,16 +134,17 @@ class UserProfileBrickController extends BrickController
|
||||
$sCurContactId = $oCurContact->GetKey();
|
||||
|
||||
// Preparing forms
|
||||
$aData['forms']['contact'] = $ObjectFormHandler->HandleForm($oRequest, $sFormMode, $sCurContactClass, $sCurContactId, $oBrick->GetForm());
|
||||
$aData['forms']['contact'] = $ObjectFormHandler->HandleForm($oRequest, $sFormMode, $sCurContactClass, $sCurContactId,
|
||||
$oBrick->GetForm());
|
||||
$aData['forms']['preferences'] = $this->HandlePreferencesForm($oRequest, $sFormMode);
|
||||
// - If user can change password, we display the form
|
||||
$aData['forms']['password'] = (UserRights::CanChangePassword()) ? $this->HandlePasswordForm($oRequest, $sFormMode) : null;
|
||||
|
||||
$aData = $aData + array(
|
||||
'oBrick' => $oBrick,
|
||||
'sFormMode' => $sFormMode,
|
||||
'bDemoMode' => $bDemoMode,
|
||||
);
|
||||
'oBrick' => $oBrick,
|
||||
'sFormMode' => $sFormMode,
|
||||
'bDemoMode' => $bDemoMode,
|
||||
);
|
||||
|
||||
$oResponse = $this->render($oBrick->GetPageTemplatePath(), $aData);
|
||||
}
|
||||
@@ -186,29 +188,36 @@ class UserProfileBrickController extends BrickController
|
||||
}
|
||||
}
|
||||
// - Submit
|
||||
else if ($sOperation === 'submit')
|
||||
else
|
||||
{
|
||||
$sFormManagerClass = $oRequestManipulator->ReadParam('formmanager_class', null, FILTER_UNSAFE_RAW);
|
||||
$sFormManagerData = $oRequestManipulator->ReadParam('formmanager_data', null, FILTER_UNSAFE_RAW);
|
||||
if ($sFormManagerClass === null || $sFormManagerData === null)
|
||||
if ($sOperation === 'submit')
|
||||
{
|
||||
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Parameters formmanager_class and formamanager_data must be defined.');
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Parameters formmanager_class and formmanager_data must be defined.');
|
||||
}
|
||||
$sFormManagerClass = $oRequestManipulator->ReadParam('formmanager_class', null, FILTER_UNSAFE_RAW);
|
||||
$sFormManagerData = $oRequestManipulator->ReadParam('formmanager_data', null, FILTER_UNSAFE_RAW);
|
||||
if ($sFormManagerClass === null || $sFormManagerData === null)
|
||||
{
|
||||
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Parameters formmanager_class and formamanager_data must be defined.');
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'Parameters formmanager_class and formmanager_data must be defined.');
|
||||
}
|
||||
|
||||
// Rebuilding manager from json
|
||||
$oFormManager = $sFormManagerClass::FromJSON($sFormManagerData);
|
||||
// Applying modification to object
|
||||
$aFormData['validation'] = $oFormManager->OnSubmit(array('currentValues' => $oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW)));
|
||||
// Reloading page only if preferences were changed
|
||||
if (($aFormData['validation']['valid'] === true) && !empty($aFormData['validation']['messages']['success']))
|
||||
{
|
||||
$aFormData['validation']['redirection'] = array(
|
||||
'url' => $oUrlGenerator->generate('p_user_profile_brick'),
|
||||
);
|
||||
// Rebuilding manager from json
|
||||
/** @var \Combodo\iTop\Form\FormManager $oFormManager */
|
||||
$oFormManager = $sFormManagerClass::FromJSON($sFormManagerData);
|
||||
// Applying modification to object
|
||||
$aFormData['validation'] = $oFormManager->OnSubmit(array(
|
||||
'currentValues' => $oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW),
|
||||
));
|
||||
// Reloading page only if preferences were changed
|
||||
if (($aFormData['validation']['valid'] === true) && !empty($aFormData['validation']['messages']['success']))
|
||||
{
|
||||
$aFormData['validation']['redirection'] = array(
|
||||
'url' => $oUrlGenerator->generate('p_user_profile_brick'),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Else, submit from another form
|
||||
// Else, submit from another form
|
||||
|
||||
// Preparing field_set data
|
||||
$aFieldSetData = array(
|
||||
@@ -244,7 +253,7 @@ class UserProfileBrickController extends BrickController
|
||||
|
||||
// Handling form
|
||||
$sOperation = /** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
|
||||
$oRequestManipulator->ReadParam('operation', null);
|
||||
$oRequestManipulator->ReadParam('operation', null);
|
||||
// - Create
|
||||
if ($sOperation === null)
|
||||
{
|
||||
@@ -255,27 +264,34 @@ class UserProfileBrickController extends BrickController
|
||||
$oFormManager = new PasswordFormManager();
|
||||
$oFormManager->SetRenderer($oFormRenderer)
|
||||
->Build();
|
||||
// - Checking if we have to make the form read only
|
||||
if ($sFormMode === ObjectFormHandlerHelper::ENUM_MODE_VIEW)
|
||||
{
|
||||
$oFormManager->GetForm()->MakeReadOnly();
|
||||
}
|
||||
// - Checking if we have to make the form read only
|
||||
if ($sFormMode === ObjectFormHandlerHelper::ENUM_MODE_VIEW)
|
||||
{
|
||||
$oFormManager->GetForm()->MakeReadOnly();
|
||||
}
|
||||
}
|
||||
// - Submit
|
||||
else if ($sOperation === 'submit')
|
||||
else
|
||||
{
|
||||
$sFormManagerClass = $oRequestManipulator->ReadParam('formmanager_class', null, FILTER_UNSAFE_RAW);
|
||||
$sFormManagerData = $oRequestManipulator->ReadParam('formmanager_data', null, FILTER_UNSAFE_RAW);
|
||||
if ($sFormManagerClass === null || $sFormManagerData === null)
|
||||
if ($sOperation === 'submit')
|
||||
{
|
||||
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Parameters formmanager_class and formamanager_data must be defined.');
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Parameters formmanager_class and formmanager_data must be defined.');
|
||||
}
|
||||
$sFormManagerClass = $oRequestManipulator->ReadParam('formmanager_class', null, FILTER_UNSAFE_RAW);
|
||||
$sFormManagerData = $oRequestManipulator->ReadParam('formmanager_data', null, FILTER_UNSAFE_RAW);
|
||||
if ($sFormManagerClass === null || $sFormManagerData === null)
|
||||
{
|
||||
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Parameters formmanager_class and formamanager_data must be defined.');
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'Parameters formmanager_class and formmanager_data must be defined.');
|
||||
}
|
||||
|
||||
// Rebuilding manager from json
|
||||
$oFormManager = $sFormManagerClass::FromJSON($sFormManagerData);
|
||||
// Applying modification to object
|
||||
$aFormData['validation'] = $oFormManager->OnSubmit(array('currentValues' => $oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW)));
|
||||
// Rebuilding manager from json
|
||||
/** @var \Combodo\iTop\Form\FormManager $oFormManager */
|
||||
$oFormManager = $sFormManagerClass::FromJSON($sFormManagerData);
|
||||
// Applying modification to object
|
||||
$aFormData['validation'] = $oFormManager->OnSubmit(array(
|
||||
'currentValues' => $oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW),
|
||||
));
|
||||
}
|
||||
}
|
||||
// Else, submit from another form
|
||||
|
||||
@@ -316,48 +332,53 @@ class UserProfileBrickController extends BrickController
|
||||
// - No operation specified
|
||||
if ($sOperation === null)
|
||||
{
|
||||
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Operation parameter must be specified.');
|
||||
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Operation parameter must be specified.');
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Operation parameter must be specified.');
|
||||
}
|
||||
// - Submit
|
||||
else if ($sOperation === 'submit')
|
||||
else
|
||||
{
|
||||
$oRequestFiles = $oRequest->files;
|
||||
$oPictureFile = $oRequestFiles->get($sPictureAttCode);
|
||||
if ($oPictureFile === null)
|
||||
if ($sOperation === 'submit')
|
||||
{
|
||||
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Parameter picture must be defined.');
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Parameter picture must be defined.');
|
||||
}
|
||||
$oRequestFiles = $oRequest->files;
|
||||
$oPictureFile = $oRequestFiles->get($sPictureAttCode);
|
||||
if ($oPictureFile === null)
|
||||
{
|
||||
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Parameter picture must be defined.');
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Parameter picture must be defined.');
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Retrieving image as an ORMDocument
|
||||
$oImage = utils::ReadPostedDocument($sPictureAttCode);
|
||||
// Retrieving current contact
|
||||
/** @var \DBObject $oCurContact */
|
||||
$oCurContact = UserRights::GetContactObject();
|
||||
// Resizing image
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($oCurContact), $sPictureAttCode);
|
||||
$aSize = utils::GetImageSize($oImage->GetData());
|
||||
$oImage = utils::ResizeImageToFit($oImage, $aSize[0], $aSize[1], $oAttDef->Get('storage_max_width'), $oAttDef->Get('storage_max_height'));
|
||||
// Setting it to the contact
|
||||
$oCurContact->Set($sPictureAttCode, $oImage);
|
||||
// Forcing allowed writing on the object if necessary.
|
||||
$oCurContact->AllowWrite(true);
|
||||
$oCurContact->DBUpdate();
|
||||
}
|
||||
catch (FileUploadException $e)
|
||||
{
|
||||
$aFormData['error'] = $e->GetMessage();
|
||||
}
|
||||
try
|
||||
{
|
||||
// Retrieving image as an ORMDocument
|
||||
$oImage = utils::ReadPostedDocument($sPictureAttCode);
|
||||
// Retrieving current contact
|
||||
/** @var \cmdbAbstractObject $oCurContact */
|
||||
$oCurContact = UserRights::GetContactObject();
|
||||
// Resizing image
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($oCurContact), $sPictureAttCode);
|
||||
$aSize = utils::GetImageSize($oImage->GetData());
|
||||
$oImage = utils::ResizeImageToFit($oImage, $aSize[0], $aSize[1], $oAttDef->Get('storage_max_width'),
|
||||
$oAttDef->Get('storage_max_height'));
|
||||
// Setting it to the contact
|
||||
$oCurContact->Set($sPictureAttCode, $oImage);
|
||||
// Forcing allowed writing on the object if necessary.
|
||||
$oCurContact->AllowWrite(true);
|
||||
$oCurContact->DBUpdate();
|
||||
}
|
||||
catch (FileUploadException $e)
|
||||
{
|
||||
$aFormData['error'] = $e->GetMessage();
|
||||
}
|
||||
|
||||
$aFormData['picture_url'] = $oImage->GetDownloadURL(get_class($oCurContact), $oCurContact->GetKey(), $sPictureAttCode);
|
||||
$aFormData['validation'] = array(
|
||||
'valid' => true,
|
||||
'messages' => array(),
|
||||
);
|
||||
$aFormData['picture_url'] = $oImage->GetDownloadURL(get_class($oCurContact), $oCurContact->GetKey(), $sPictureAttCode);
|
||||
$aFormData['validation'] = array(
|
||||
'valid' => true,
|
||||
'messages' => array(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Else, submit from another form
|
||||
|
||||
return $aFormData;
|
||||
|
||||
@@ -28,30 +28,30 @@ use ModuleDesign;
|
||||
* Class AbstractConfiguration
|
||||
*
|
||||
* @package Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class AbstractConfiguration
|
||||
{
|
||||
/** @var \ModuleDesign $oModuleDesign */
|
||||
private $oModuleDesign;
|
||||
/** @var \ModuleDesign $oModuleDesign */
|
||||
private $oModuleDesign;
|
||||
|
||||
/**
|
||||
* AbstractConfiguration constructor.
|
||||
*
|
||||
* @param \ModuleDesign $oModuleDesign
|
||||
*/
|
||||
public function __construct(ModuleDesign $oModuleDesign)
|
||||
{
|
||||
$this->oModuleDesign = $oModuleDesign;
|
||||
}
|
||||
public function __construct(ModuleDesign $oModuleDesign)
|
||||
{
|
||||
$this->oModuleDesign = $oModuleDesign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \ModuleDesign
|
||||
*/
|
||||
public function GetModuleDesign()
|
||||
{
|
||||
return $this->oModuleDesign;
|
||||
}
|
||||
/**
|
||||
* @return \ModuleDesign
|
||||
*/
|
||||
public function GetModuleDesign()
|
||||
{
|
||||
return $this->oModuleDesign;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,8 +34,8 @@ use DOMFormatException;
|
||||
* Class Basic
|
||||
*
|
||||
* @package Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class Basic extends AbstractConfiguration
|
||||
{
|
||||
@@ -44,76 +44,76 @@ class Basic extends AbstractConfiguration
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function Process(Container $oContainer)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parsing file
|
||||
// - Default values
|
||||
$aPortalConf = $this->GetInitialPortalConf();
|
||||
// - Global portal properties
|
||||
$aPortalConf = $this->ParseGlobalProperties($aPortalConf);
|
||||
// - Rectifying portal logo url
|
||||
$aPortalConf = $this->AppendLogoUri($aPortalConf);
|
||||
// - User allowed portals
|
||||
$aPortalConf['portals'] = UserRights::GetAllowedPortals();
|
||||
public function Process(Container $oContainer)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parsing file
|
||||
// - Default values
|
||||
$aPortalConf = $this->GetInitialPortalConf();
|
||||
// - Global portal properties
|
||||
$aPortalConf = $this->ParseGlobalProperties($aPortalConf);
|
||||
// - Rectifying portal logo url
|
||||
$aPortalConf = $this->AppendLogoUri($aPortalConf);
|
||||
// - User allowed portals
|
||||
$aPortalConf['portals'] = UserRights::GetAllowedPortals();
|
||||
|
||||
// - class list
|
||||
$aPortalConf['ui_extensions'] = $this->GetUiExtensions($oContainer);
|
||||
}
|
||||
catch (Exception $oException)
|
||||
{
|
||||
throw new Exception('Error while parsing portal configuration file : '.$oException->getMessage());
|
||||
}
|
||||
// - class list
|
||||
$aPortalConf['ui_extensions'] = $this->GetUiExtensions($oContainer);
|
||||
}
|
||||
catch (Exception $oException)
|
||||
{
|
||||
throw new Exception('Error while parsing portal configuration file : '.$oException->getMessage());
|
||||
}
|
||||
|
||||
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
|
||||
}
|
||||
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing the initial portal configuration with all default values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function GetInitialPortalConf()
|
||||
{
|
||||
$aPortalConf = array(
|
||||
'properties' => array(
|
||||
'id' => $_ENV['PORTAL_ID'],
|
||||
'name' => 'Page:DefaultTitle',
|
||||
'logo' => (file_exists(MODULESROOT.'branding/portal-logo.png')) ? utils::GetAbsoluteUrlModulesRoot().'branding/portal-logo.png' : '../images/logo-itop-dark-bg.svg',
|
||||
'themes' => array(
|
||||
'bootstrap' => 'itop-portal-base/portal/public/css/bootstrap-theme-combodo.scss',
|
||||
'portal' => 'itop-portal-base/portal/public/css/portal.scss',
|
||||
'others' => array(),
|
||||
),
|
||||
'templates' => array(
|
||||
'layout' => 'itop-portal-base/portal/templates/layout.html.twig',
|
||||
'home' => 'itop-portal-base/portal/templates/home/layout.html.twig',
|
||||
),
|
||||
'urlmaker_class' => null,
|
||||
'triggers_query' => null,
|
||||
'attachments' => array(
|
||||
'allow_delete' => true,
|
||||
),
|
||||
'allowed_portals' => array(
|
||||
'opening_mode' => null,
|
||||
),
|
||||
),
|
||||
'portals' => array(),
|
||||
'forms' => array(),
|
||||
'ui_extensions' => array(
|
||||
'css_files' => array(),
|
||||
'css_inline' => null,
|
||||
'js_files' => array(),
|
||||
'js_inline' => null,
|
||||
'html' => array(),
|
||||
),
|
||||
'bricks' => array(),
|
||||
'bricks_total_width' => 0,
|
||||
);
|
||||
/**
|
||||
* Returns an array containing the initial portal configuration with all default values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function GetInitialPortalConf()
|
||||
{
|
||||
$aPortalConf = array(
|
||||
'properties' => array(
|
||||
'id' => $_ENV['PORTAL_ID'],
|
||||
'name' => 'Page:DefaultTitle',
|
||||
'logo' => (file_exists(MODULESROOT.'branding/portal-logo.png')) ? utils::GetAbsoluteUrlModulesRoot().'branding/portal-logo.png' : '../images/logo-itop-dark-bg.svg',
|
||||
'themes' => array(
|
||||
'bootstrap' => 'itop-portal-base/portal/public/css/bootstrap-theme-combodo.scss',
|
||||
'portal' => 'itop-portal-base/portal/public/css/portal.scss',
|
||||
'others' => array(),
|
||||
),
|
||||
'templates' => array(
|
||||
'layout' => 'itop-portal-base/portal/templates/layout.html.twig',
|
||||
'home' => 'itop-portal-base/portal/templates/home/layout.html.twig',
|
||||
),
|
||||
'urlmaker_class' => null,
|
||||
'triggers_query' => null,
|
||||
'attachments' => array(
|
||||
'allow_delete' => true,
|
||||
),
|
||||
'allowed_portals' => array(
|
||||
'opening_mode' => null,
|
||||
),
|
||||
),
|
||||
'portals' => array(),
|
||||
'forms' => array(),
|
||||
'ui_extensions' => array(
|
||||
'css_files' => array(),
|
||||
'css_inline' => null,
|
||||
'js_files' => array(),
|
||||
'js_inline' => null,
|
||||
'html' => array(),
|
||||
),
|
||||
'bricks' => array(),
|
||||
'bricks_total_width' => 0,
|
||||
);
|
||||
|
||||
return $aPortalConf;
|
||||
}
|
||||
return $aPortalConf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aPortalConf
|
||||
@@ -121,40 +121,40 @@ class Basic extends AbstractConfiguration
|
||||
* @return array
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
private function ParseGlobalProperties(array $aPortalConf)
|
||||
{
|
||||
/** @var \MFElement $oPropertyNode */
|
||||
foreach ($this->GetModuleDesign()->GetNodes('/module_design/properties/*') as $oPropertyNode)
|
||||
{
|
||||
switch ($oPropertyNode->nodeName)
|
||||
{
|
||||
case 'name':
|
||||
case 'urlmaker_class':
|
||||
case 'triggers_query':
|
||||
$aPortalConf['properties'][$oPropertyNode->nodeName] = $oPropertyNode->GetText(
|
||||
$aPortalConf['properties'][$oPropertyNode->nodeName]
|
||||
);
|
||||
break;
|
||||
case 'logo':
|
||||
$aPortalConf['properties'][$oPropertyNode->nodeName] = $oPropertyNode->GetText(
|
||||
$aPortalConf['properties'][$oPropertyNode->nodeName]
|
||||
);
|
||||
break;
|
||||
case 'themes':
|
||||
case 'templates':
|
||||
$aPortalConf = $this->ParseTemplateAndTheme($aPortalConf, $oPropertyNode);
|
||||
break;
|
||||
case 'attachments':
|
||||
$aPortalConf = $this->ParseAttachments($aPortalConf, $oPropertyNode);
|
||||
break;
|
||||
case 'allowed_portals':
|
||||
$aPortalConf = $this->ParseAllowedPortals($aPortalConf, $oPropertyNode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
private function ParseGlobalProperties(array $aPortalConf)
|
||||
{
|
||||
/** @var \MFElement $oPropertyNode */
|
||||
foreach ($this->GetModuleDesign()->GetNodes('/module_design/properties/*') as $oPropertyNode)
|
||||
{
|
||||
switch ($oPropertyNode->nodeName)
|
||||
{
|
||||
case 'name':
|
||||
case 'urlmaker_class':
|
||||
case 'triggers_query':
|
||||
$aPortalConf['properties'][$oPropertyNode->nodeName] = $oPropertyNode->GetText(
|
||||
$aPortalConf['properties'][$oPropertyNode->nodeName]
|
||||
);
|
||||
break;
|
||||
case 'logo':
|
||||
$aPortalConf['properties'][$oPropertyNode->nodeName] = $oPropertyNode->GetText(
|
||||
$aPortalConf['properties'][$oPropertyNode->nodeName]
|
||||
);
|
||||
break;
|
||||
case 'themes':
|
||||
case 'templates':
|
||||
$aPortalConf = $this->ParseTemplateAndTheme($aPortalConf, $oPropertyNode);
|
||||
break;
|
||||
case 'attachments':
|
||||
$aPortalConf = $this->ParseAttachments($aPortalConf, $oPropertyNode);
|
||||
break;
|
||||
case 'allowed_portals':
|
||||
$aPortalConf = $this->ParseAllowedPortals($aPortalConf, $oPropertyNode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $aPortalConf;
|
||||
}
|
||||
return $aPortalConf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aPortalConf
|
||||
@@ -163,54 +163,54 @@ class Basic extends AbstractConfiguration
|
||||
* @return array
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
private function ParseTemplateAndTheme(array $aPortalConf, DesignElement $oPropertyNode)
|
||||
{
|
||||
/** @var \MFElement $oSubNode */
|
||||
foreach ($oPropertyNode->GetNodes('template|theme') as $oSubNode)
|
||||
{
|
||||
if (!$oSubNode->hasAttribute('id') || $oSubNode->GetText(null) === null)
|
||||
{
|
||||
throw new DOMFormatException(
|
||||
'Tag ' . $oSubNode->nodeName.' must have a "id" attribute as well as a value',
|
||||
null, null, $oSubNode
|
||||
);
|
||||
}
|
||||
private function ParseTemplateAndTheme(array $aPortalConf, DesignElement $oPropertyNode)
|
||||
{
|
||||
/** @var \MFElement $oSubNode */
|
||||
foreach ($oPropertyNode->GetNodes('template|theme') as $oSubNode)
|
||||
{
|
||||
if (!$oSubNode->hasAttribute('id') || $oSubNode->GetText(null) === null)
|
||||
{
|
||||
throw new DOMFormatException(
|
||||
'Tag '.$oSubNode->nodeName.' must have a "id" attribute as well as a value',
|
||||
null, null, $oSubNode
|
||||
);
|
||||
}
|
||||
|
||||
$sNodeId = $oSubNode->getAttribute('id');
|
||||
switch ($oSubNode->nodeName)
|
||||
{
|
||||
case 'theme':
|
||||
switch ($sNodeId)
|
||||
{
|
||||
case 'bootstrap':
|
||||
case 'portal':
|
||||
case 'custom':
|
||||
$aPortalConf['properties']['themes'][$sNodeId] = $oSubNode->GetText(null);
|
||||
break;
|
||||
default:
|
||||
$aPortalConf['properties']['themes']['others'][] = $oSubNode->GetText(null);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'template':
|
||||
switch ($sNodeId)
|
||||
{
|
||||
case 'layout':
|
||||
case 'home':
|
||||
$aPortalConf['properties']['templates'][$sNodeId] = $oSubNode->GetText(null);
|
||||
break;
|
||||
default:
|
||||
throw new DOMFormatException(
|
||||
'Value "'.$sNodeId.'" is not handled for template[@id]',
|
||||
null, null, $oSubNode
|
||||
);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
$sNodeId = $oSubNode->getAttribute('id');
|
||||
switch ($oSubNode->nodeName)
|
||||
{
|
||||
case 'theme':
|
||||
switch ($sNodeId)
|
||||
{
|
||||
case 'bootstrap':
|
||||
case 'portal':
|
||||
case 'custom':
|
||||
$aPortalConf['properties']['themes'][$sNodeId] = $oSubNode->GetText(null);
|
||||
break;
|
||||
default:
|
||||
$aPortalConf['properties']['themes']['others'][] = $oSubNode->GetText(null);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'template':
|
||||
switch ($sNodeId)
|
||||
{
|
||||
case 'layout':
|
||||
case 'home':
|
||||
$aPortalConf['properties']['templates'][$sNodeId] = $oSubNode->GetText(null);
|
||||
break;
|
||||
default:
|
||||
throw new DOMFormatException(
|
||||
'Value "'.$sNodeId.'" is not handled for template[@id]',
|
||||
null, null, $oSubNode
|
||||
);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $aPortalConf;
|
||||
return $aPortalConf;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,26 +219,26 @@ class Basic extends AbstractConfiguration
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function ParseAttachments(array $aPortalConf, DesignElement $oPropertyNode)
|
||||
{
|
||||
/** @var \MFElement $oSubNode */
|
||||
foreach ($oPropertyNode->GetNodes('*') as $oSubNode)
|
||||
{
|
||||
switch ($oSubNode->nodeName)
|
||||
{
|
||||
case 'allow_delete':
|
||||
$sValue = $oSubNode->GetText();
|
||||
// If the text is null, we keep the default value
|
||||
// Else we set it
|
||||
if ($sValue !== null)
|
||||
{
|
||||
$aPortalConf['properties']['attachments'][$oSubNode->nodeName] = ($sValue === 'true') ? true : false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
private function ParseAttachments(array $aPortalConf, DesignElement $oPropertyNode)
|
||||
{
|
||||
/** @var \MFElement $oSubNode */
|
||||
foreach ($oPropertyNode->GetNodes('*') as $oSubNode)
|
||||
{
|
||||
switch ($oSubNode->nodeName)
|
||||
{
|
||||
case 'allow_delete':
|
||||
$sValue = $oSubNode->GetText();
|
||||
// If the text is null, we keep the default value
|
||||
// Else we set it
|
||||
if ($sValue !== null)
|
||||
{
|
||||
$aPortalConf['properties']['attachments'][$oSubNode->nodeName] = ($sValue === 'true') ? true : false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return$aPortalConf;
|
||||
return $aPortalConf;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,26 +247,26 @@ class Basic extends AbstractConfiguration
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function ParseAllowedPortals(array $aPortalConf, DesignElement $oPropertyNode)
|
||||
{
|
||||
/** @var \MFElement $oSubNode */
|
||||
foreach ($oPropertyNode->GetNodes('*') as $oSubNode)
|
||||
{
|
||||
switch ($oSubNode->nodeName)
|
||||
{
|
||||
case 'opening_mode':
|
||||
$sValue = $oSubNode->GetText();
|
||||
// If the text is null, we keep the default value
|
||||
// Else we set it
|
||||
if ($sValue !== null)
|
||||
{
|
||||
$aPortalConf['properties']['allowed_portals'][$oSubNode->nodeName] = ($sValue === 'self') ? 'self' : 'tab';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
private function ParseAllowedPortals(array $aPortalConf, DesignElement $oPropertyNode)
|
||||
{
|
||||
/** @var \MFElement $oSubNode */
|
||||
foreach ($oPropertyNode->GetNodes('*') as $oSubNode)
|
||||
{
|
||||
switch ($oSubNode->nodeName)
|
||||
{
|
||||
case 'opening_mode':
|
||||
$sValue = $oSubNode->GetText();
|
||||
// If the text is null, we keep the default value
|
||||
// Else we set it
|
||||
if ($sValue !== null)
|
||||
{
|
||||
$aPortalConf['properties']['allowed_portals'][$oSubNode->nodeName] = ($sValue === 'self') ? 'self' : 'tab';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $aPortalConf;
|
||||
return $aPortalConf;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,17 +275,17 @@ class Basic extends AbstractConfiguration
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function AppendLogoUri(array $aPortalConf)
|
||||
{
|
||||
$sLogoUri = $aPortalConf['properties']['logo'];
|
||||
if (!preg_match('/^http/', $sLogoUri))
|
||||
{
|
||||
// We prefix it with the server base url
|
||||
$sLogoUri = utils::GetAbsoluteUrlAppRoot().'env-'.utils::GetCurrentEnvironment().'/'.$sLogoUri;
|
||||
}
|
||||
$aPortalConf['properties']['logo'] = $sLogoUri;
|
||||
private function AppendLogoUri(array $aPortalConf)
|
||||
{
|
||||
$sLogoUri = $aPortalConf['properties']['logo'];
|
||||
if (!preg_match('/^http/', $sLogoUri))
|
||||
{
|
||||
// We prefix it with the server base url
|
||||
$sLogoUri = utils::GetAbsoluteUrlAppRoot().'env-'.utils::GetCurrentEnvironment().'/'.$sLogoUri;
|
||||
}
|
||||
$aPortalConf['properties']['logo'] = $sLogoUri;
|
||||
|
||||
return $aPortalConf;
|
||||
return $aPortalConf;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,74 +295,74 @@ class Basic extends AbstractConfiguration
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function GetUiExtensions(Container $oContainer)
|
||||
{
|
||||
$aUIExtensions = array(
|
||||
'css_files' => array(),
|
||||
'css_inline' => null,
|
||||
'js_files' => array(),
|
||||
'js_inline' => null,
|
||||
'html' => array(),
|
||||
);
|
||||
$aUIExtensionHooks = array(
|
||||
iPortalUIExtension::ENUM_PORTAL_EXT_UI_BODY,
|
||||
iPortalUIExtension::ENUM_PORTAL_EXT_UI_NAVIGATION_MENU,
|
||||
iPortalUIExtension::ENUM_PORTAL_EXT_UI_MAIN_CONTENT,
|
||||
);
|
||||
{
|
||||
$aUIExtensions = array(
|
||||
'css_files' => array(),
|
||||
'css_inline' => null,
|
||||
'js_files' => array(),
|
||||
'js_inline' => null,
|
||||
'html' => array(),
|
||||
);
|
||||
$aUIExtensionHooks = array(
|
||||
iPortalUIExtension::ENUM_PORTAL_EXT_UI_BODY,
|
||||
iPortalUIExtension::ENUM_PORTAL_EXT_UI_NAVIGATION_MENU,
|
||||
iPortalUIExtension::ENUM_PORTAL_EXT_UI_MAIN_CONTENT,
|
||||
);
|
||||
|
||||
/** @var iPortalUIExtension $oExtensionInstance */
|
||||
foreach (MetaModel::EnumPlugins('iPortalUIExtension') as $oExtensionInstance)
|
||||
{
|
||||
// Adding CSS files
|
||||
$aImportPaths = array($oContainer->getParameter('combodo.portal.base.absolute_path').'css/');
|
||||
foreach($oExtensionInstance->GetCSSFiles($oContainer) as $sCSSFile)
|
||||
{
|
||||
// Removing app root url as we need to pass a path on the file system (relative to app root)
|
||||
$sCSSFilePath = str_replace(utils::GetAbsoluteUrlAppRoot(), '', $sCSSFile);
|
||||
// Compiling SCSS file
|
||||
$sCSSFileCompiled = $oContainer->getParameter('combodo.absolute_url').utils::GetCSSFromSASS($sCSSFilePath,
|
||||
$aImportPaths);
|
||||
/** @var iPortalUIExtension $oExtensionInstance */
|
||||
foreach (MetaModel::EnumPlugins('iPortalUIExtension') as $oExtensionInstance)
|
||||
{
|
||||
// Adding CSS files
|
||||
$aImportPaths = array($oContainer->getParameter('combodo.portal.base.absolute_path').'css/');
|
||||
foreach ($oExtensionInstance->GetCSSFiles($oContainer) as $sCSSFile)
|
||||
{
|
||||
// Removing app root url as we need to pass a path on the file system (relative to app root)
|
||||
$sCSSFilePath = str_replace(utils::GetAbsoluteUrlAppRoot(), '', $sCSSFile);
|
||||
// Compiling SCSS file
|
||||
$sCSSFileCompiled = $oContainer->getParameter('combodo.absolute_url').utils::GetCSSFromSASS($sCSSFilePath,
|
||||
$aImportPaths);
|
||||
|
||||
if(!in_array($sCSSFileCompiled, $aUIExtensions['css_files']))
|
||||
{
|
||||
$aUIExtensions['css_files'][] = $sCSSFileCompiled;
|
||||
}
|
||||
}
|
||||
if (!in_array($sCSSFileCompiled, $aUIExtensions['css_files']))
|
||||
{
|
||||
$aUIExtensions['css_files'][] = $sCSSFileCompiled;
|
||||
}
|
||||
}
|
||||
|
||||
// Adding CSS inline
|
||||
$sCSSInline = $oExtensionInstance->GetCSSInline($oContainer);
|
||||
if ($sCSSInline !== null)
|
||||
{
|
||||
$aUIExtensions['css_inline'] .= "\n\n".$sCSSInline;
|
||||
}
|
||||
// Adding CSS inline
|
||||
$sCSSInline = $oExtensionInstance->GetCSSInline($oContainer);
|
||||
if ($sCSSInline !== null)
|
||||
{
|
||||
$aUIExtensions['css_inline'] .= "\n\n".$sCSSInline;
|
||||
}
|
||||
|
||||
// Adding JS files
|
||||
$aUIExtensions['js_files'] = array_merge($aUIExtensions['js_files'],
|
||||
$oExtensionInstance->GetJSFiles($oContainer));
|
||||
// Adding JS files
|
||||
$aUIExtensions['js_files'] = array_merge($aUIExtensions['js_files'],
|
||||
$oExtensionInstance->GetJSFiles($oContainer));
|
||||
|
||||
// Adding JS inline
|
||||
$sJSInline = $oExtensionInstance->GetJSInline($oContainer);
|
||||
if ($sJSInline !== null)
|
||||
{
|
||||
// Note: Semi-colon is to prevent previous script that would have omitted it.
|
||||
$aUIExtensions['js_inline'] .= "\n\n;\n".$sJSInline;
|
||||
}
|
||||
// Adding JS inline
|
||||
$sJSInline = $oExtensionInstance->GetJSInline($oContainer);
|
||||
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)
|
||||
{
|
||||
$sFunctionName = 'Get'.$sUIExtensionHook.'HTML';
|
||||
$sHTML = $oExtensionInstance->$sFunctionName($oContainer);
|
||||
if ($sHTML !== null)
|
||||
{
|
||||
if (!array_key_exists($sUIExtensionHook, $aUIExtensions['html']))
|
||||
{
|
||||
$aUIExtensions['html'][$sUIExtensionHook] = '';
|
||||
}
|
||||
$aUIExtensions['html'][$sUIExtensionHook] .= "\n\n".$sHTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Adding HTML for each hook
|
||||
foreach ($aUIExtensionHooks as $sUIExtensionHook)
|
||||
{
|
||||
$sFunctionName = 'Get'.$sUIExtensionHook.'HTML';
|
||||
$sHTML = $oExtensionInstance->$sFunctionName($oContainer);
|
||||
if ($sHTML !== null)
|
||||
{
|
||||
if (!array_key_exists($sUIExtensionHook, $aUIExtensions['html']))
|
||||
{
|
||||
$aUIExtensions['html'][$sUIExtensionHook] = '';
|
||||
}
|
||||
$aUIExtensions['html'][$sUIExtensionHook] .= "\n\n".$sHTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aUIExtensions;
|
||||
}
|
||||
return $aUIExtensions;
|
||||
}
|
||||
}
|
||||
@@ -31,8 +31,8 @@ use MetaModel;
|
||||
* Class Forms
|
||||
*
|
||||
* @package Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class Forms extends AbstractConfiguration
|
||||
{
|
||||
@@ -41,239 +41,239 @@ class Forms extends AbstractConfiguration
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function Process(Container $oContainer)
|
||||
{
|
||||
$aForms = array();
|
||||
public function Process(Container $oContainer)
|
||||
{
|
||||
$aForms = array();
|
||||
|
||||
/** @var \MFElement $oFormNode */
|
||||
foreach ($this->GetModuleDesign()->GetNodes('/module_design/forms/form') as $oFormNode)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parsing form id
|
||||
if ($oFormNode->getAttribute('id') === '')
|
||||
{
|
||||
throw new DOMFormatException('form tag must have an id attribute', null, null, $oFormNode);
|
||||
}
|
||||
/** @var \MFElement $oFormNode */
|
||||
foreach ($this->GetModuleDesign()->GetNodes('/module_design/forms/form') as $oFormNode)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parsing form id
|
||||
if ($oFormNode->getAttribute('id') === '')
|
||||
{
|
||||
throw new DOMFormatException('form tag must have an id attribute', null, null, $oFormNode);
|
||||
}
|
||||
|
||||
// Parsing form object class
|
||||
if ($oFormNode->GetUniqueElement('class')->GetText() !== null)
|
||||
{
|
||||
// Parsing class
|
||||
$sFormClass = $oFormNode->GetUniqueElement('class')->GetText();
|
||||
// Parsing form object class
|
||||
if ($oFormNode->GetUniqueElement('class')->GetText() !== null)
|
||||
{
|
||||
// Parsing class
|
||||
$sFormClass = $oFormNode->GetUniqueElement('class')->GetText();
|
||||
|
||||
// Parsing properties
|
||||
$aFormProperties = array(
|
||||
'display_mode' => ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE,
|
||||
'always_show_submit' => ApplicationHelper::FORM_DEFAULT_ALWAYS_SHOW_SUBMIT,
|
||||
);
|
||||
if ($oFormNode->GetOptionalElement('properties') !== null)
|
||||
{
|
||||
/** @var \MFElement $oPropertyNode */
|
||||
foreach ($oFormNode->GetOptionalElement('properties')->childNodes as $oPropertyNode)
|
||||
{
|
||||
switch ($oPropertyNode->nodeName)
|
||||
{
|
||||
case 'display_mode':
|
||||
$aFormProperties['display_mode'] = $oPropertyNode->GetText(ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE);
|
||||
break;
|
||||
case 'always_show_submit':
|
||||
$aFormProperties['always_show_submit'] = ($oPropertyNode->GetText('false') === 'true') ? true : false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Parsing properties
|
||||
$aFormProperties = array(
|
||||
'display_mode' => ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE,
|
||||
'always_show_submit' => ApplicationHelper::FORM_DEFAULT_ALWAYS_SHOW_SUBMIT,
|
||||
);
|
||||
if ($oFormNode->GetOptionalElement('properties') !== null)
|
||||
{
|
||||
/** @var \MFElement $oPropertyNode */
|
||||
foreach ($oFormNode->GetOptionalElement('properties')->childNodes as $oPropertyNode)
|
||||
{
|
||||
switch ($oPropertyNode->nodeName)
|
||||
{
|
||||
case 'display_mode':
|
||||
$aFormProperties['display_mode'] = $oPropertyNode->GetText(ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE);
|
||||
break;
|
||||
case 'always_show_submit':
|
||||
$aFormProperties['always_show_submit'] = ($oPropertyNode->GetText('false') === 'true') ? true : false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
/** @var \MFElement $oModeNode */
|
||||
foreach ($oFormNode->GetOptionalElement('modes')->GetNodes('mode') as $oModeNode)
|
||||
{
|
||||
if ($oModeNode->getAttribute('id') !== '')
|
||||
{
|
||||
$aModes[] = $oModeNode->getAttribute('id');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('Mode tag must have an id attribute', null, null,
|
||||
$oFormNode);
|
||||
}
|
||||
// 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();
|
||||
/** @var \MFElement $oModeNode */
|
||||
foreach ($oFormNode->GetOptionalElement('modes')->GetNodes('mode') as $oModeNode)
|
||||
{
|
||||
if ($oModeNode->getAttribute('id') !== '')
|
||||
{
|
||||
$aModes[] = $oModeNode->getAttribute('id');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('Mode tag must have an id attribute', null, null,
|
||||
$oFormNode);
|
||||
}
|
||||
|
||||
// If apply_stimulus mode, checking if stimuli are defined
|
||||
if ($oModeNode->getAttribute('id') === '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)
|
||||
{
|
||||
/** @var \MFElement $oStimulusNode */
|
||||
foreach ($oStimuliNode->GetNodes('stimulus') as $oStimulusNode)
|
||||
{
|
||||
$sStimulusCode = $oStimulusNode->getAttribute('id');
|
||||
// If apply_stimulus mode, checking if stimuli are defined
|
||||
if ($oModeNode->getAttribute('id') === '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)
|
||||
{
|
||||
/** @var \MFElement $oStimulusNode */
|
||||
foreach ($oStimuliNode->GetNodes('stimulus') as $oStimulusNode)
|
||||
{
|
||||
$sStimulusCode = $oStimulusNode->getAttribute('id');
|
||||
|
||||
// Removing default form is present (in case the default forms were parsed before the current one (from current or parent class))
|
||||
if (isset($aForms[$sFormClass]['apply_stimulus'][$sStimulusCode]))
|
||||
{
|
||||
unset($aForms[$sFormClass]['apply_stimulus'][$sStimulusCode]);
|
||||
}
|
||||
// Removing default form is present (in case the default forms were parsed before the current one (from current or parent class))
|
||||
if (isset($aForms[$sFormClass]['apply_stimulus'][$sStimulusCode]))
|
||||
{
|
||||
unset($aForms[$sFormClass]['apply_stimulus'][$sStimulusCode]);
|
||||
}
|
||||
|
||||
$aFormStimuli[] = $oStimulusNode->getAttribute('id');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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');
|
||||
}
|
||||
$aFormStimuli[] = $oStimulusNode->getAttribute('id');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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');
|
||||
}
|
||||
|
||||
// Parsing fields
|
||||
$aFields = array(
|
||||
'id' => $oFormNode->getAttribute('id'),
|
||||
'type' => null,
|
||||
'properties' => $aFormProperties,
|
||||
'fields' => null,
|
||||
'layout' => null,
|
||||
);
|
||||
// ... either enumerated fields ...
|
||||
if ($oFormNode->GetOptionalElement('fields') !== null)
|
||||
{
|
||||
$aFields['type'] = 'custom_list';
|
||||
$aFields['fields'] = array();
|
||||
// Parsing fields
|
||||
$aFields = array(
|
||||
'id' => $oFormNode->getAttribute('id'),
|
||||
'type' => null,
|
||||
'properties' => $aFormProperties,
|
||||
'fields' => null,
|
||||
'layout' => null,
|
||||
);
|
||||
// ... either enumerated fields ...
|
||||
if ($oFormNode->GetOptionalElement('fields') !== null)
|
||||
{
|
||||
$aFields['type'] = 'custom_list';
|
||||
$aFields['fields'] = array();
|
||||
|
||||
/** @var \MFElement $oFieldNode */
|
||||
foreach ($oFormNode->GetOptionalElement('fields')->GetNodes('field') as $oFieldNode)
|
||||
{
|
||||
$sFieldId = $oFieldNode->getAttribute('id');
|
||||
if ($sFieldId !== '')
|
||||
{
|
||||
$aField = array();
|
||||
// Parsing field options like read_only, hidden and mandatory
|
||||
if ($oFieldNode->GetOptionalElement('read_only'))
|
||||
{
|
||||
$aField['readonly'] = ($oFieldNode->GetOptionalElement('read_only')->GetText('true') === 'true') ? true : false;
|
||||
}
|
||||
if ($oFieldNode->GetOptionalElement('mandatory'))
|
||||
{
|
||||
$aField['mandatory'] = ($oFieldNode->GetOptionalElement('mandatory')->GetText('true') === 'true') ? true : false;
|
||||
}
|
||||
if ($oFieldNode->GetOptionalElement('hidden'))
|
||||
{
|
||||
$aField['hidden'] = ($oFieldNode->GetOptionalElement('hidden')->GetText('true') === 'true') ? true : false;
|
||||
}
|
||||
/** @var \MFElement $oFieldNode */
|
||||
foreach ($oFormNode->GetOptionalElement('fields')->GetNodes('field') as $oFieldNode)
|
||||
{
|
||||
$sFieldId = $oFieldNode->getAttribute('id');
|
||||
if ($sFieldId !== '')
|
||||
{
|
||||
$aField = array();
|
||||
// Parsing field options like read_only, hidden and mandatory
|
||||
if ($oFieldNode->GetOptionalElement('read_only'))
|
||||
{
|
||||
$aField['readonly'] = ($oFieldNode->GetOptionalElement('read_only')->GetText('true') === 'true') ? true : false;
|
||||
}
|
||||
if ($oFieldNode->GetOptionalElement('mandatory'))
|
||||
{
|
||||
$aField['mandatory'] = ($oFieldNode->GetOptionalElement('mandatory')->GetText('true') === 'true') ? true : false;
|
||||
}
|
||||
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', null, null,
|
||||
$oFormNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ... or the default zlist
|
||||
else
|
||||
{
|
||||
$aFields['type'] = 'zlist';
|
||||
$aFields['fields'] = 'details';
|
||||
}
|
||||
$aFields['fields'][$sFieldId] = $aField;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new DOMFormatException('Field tag must have an id attribute', null, null,
|
||||
$oFormNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ... or the default zlist
|
||||
else
|
||||
{
|
||||
$aFields['type'] = 'zlist';
|
||||
$aFields['fields'] = 'details';
|
||||
}
|
||||
|
||||
// Parsing presentation
|
||||
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);
|
||||
// Parsing presentation
|
||||
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(
|
||||
'type' => (preg_match('/\{\{|\{\#|\{\%/', $sXml) === 1) ? 'twig' : 'xhtml',
|
||||
'content' => $sXml,
|
||||
);
|
||||
}
|
||||
$aFields['layout'] = array(
|
||||
'type' => (preg_match('/\{\{|\{\#|\{\%/', $sXml) === 1) ? 'twig' : 'xhtml',
|
||||
'content' => $sXml,
|
||||
);
|
||||
}
|
||||
|
||||
// Adding form for each class / mode
|
||||
foreach ($aModes as $sMode)
|
||||
{
|
||||
// Initializing current class if necessary
|
||||
if (!isset($aForms[$sFormClass]))
|
||||
{
|
||||
$aForms[$sFormClass] = array();
|
||||
}
|
||||
// Adding form for each class / mode
|
||||
foreach ($aModes as $sMode)
|
||||
{
|
||||
// Initializing current class if necessary
|
||||
if (!isset($aForms[$sFormClass]))
|
||||
{
|
||||
$aForms[$sFormClass] = array();
|
||||
}
|
||||
|
||||
if ($sMode === 'apply_stimulus')
|
||||
{
|
||||
// Iterating over current class and child classes to fill stimuli forms
|
||||
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 ($sMode === 'apply_stimulus')
|
||||
{
|
||||
// Iterating over current class and child classes to fill stimuli forms
|
||||
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 stimuli are implicitly defined (empty tag), we define all those that have not already been by other forms.
|
||||
$aChildStimuli = $aFormStimuli;
|
||||
if (empty($aChildStimuli))
|
||||
{
|
||||
// Stimuli already declared
|
||||
$aDeclaredStimuli = array();
|
||||
if (array_key_exists($sChildClass, $aForms) && array_key_exists('apply_stimulus',
|
||||
$aForms[$sChildClass]))
|
||||
{
|
||||
$aDeclaredStimuli = array_keys($aForms[$sChildClass]['apply_stimulus']);
|
||||
}
|
||||
// All stimuli
|
||||
$aDatamodelStimuli = array_keys(MetaModel::EnumStimuli($sChildClass));
|
||||
// Missing stimuli
|
||||
$aChildStimuli = array_diff($aDatamodelStimuli, $aDeclaredStimuli);
|
||||
}
|
||||
// If stimuli are implicitly defined (empty tag), we define all those that have not already been by other forms.
|
||||
$aChildStimuli = $aFormStimuli;
|
||||
if (empty($aChildStimuli))
|
||||
{
|
||||
// Stimuli already declared
|
||||
$aDeclaredStimuli = array();
|
||||
if (array_key_exists($sChildClass, $aForms) && array_key_exists('apply_stimulus',
|
||||
$aForms[$sChildClass]))
|
||||
{
|
||||
$aDeclaredStimuli = array_keys($aForms[$sChildClass]['apply_stimulus']);
|
||||
}
|
||||
// All stimuli
|
||||
$aDatamodelStimuli = array_keys(MetaModel::EnumStimuli($sChildClass));
|
||||
// Missing stimuli
|
||||
$aChildStimuli = array_diff($aDatamodelStimuli, $aDeclaredStimuli);
|
||||
}
|
||||
|
||||
foreach ($aChildStimuli as $sFormStimulus)
|
||||
{
|
||||
// Setting form if not defined OR if it was defined by a parent (abstract) class
|
||||
if (!isset($aForms[$sChildClass][$sMode][$sFormStimulus]) || !empty($aFormStimuli))
|
||||
{
|
||||
$aForms[$sChildClass][$sMode][$sFormStimulus] = $aFields;
|
||||
$aForms[$sChildClass][$sMode][$sFormStimulus]['id'] = 'apply_stimulus-'.$sChildClass.'-'.$sFormStimulus;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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('Class tag must be defined', null, null, $oFormNode);
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
throw new Exception('Could not create from from XML : '.$oFormNode->Dump().' '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
foreach ($aChildStimuli as $sFormStimulus)
|
||||
{
|
||||
// Setting form if not defined OR if it was defined by a parent (abstract) class
|
||||
if (!isset($aForms[$sChildClass][$sMode][$sFormStimulus]) || !empty($aFormStimuli))
|
||||
{
|
||||
$aForms[$sChildClass][$sMode][$sFormStimulus] = $aFields;
|
||||
$aForms[$sChildClass][$sMode][$sFormStimulus]['id'] = 'apply_stimulus-'.$sChildClass.'-'.$sFormStimulus;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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('Class tag must be defined', null, null, $oFormNode);
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
throw new Exception('Could not create from from XML : '.$oFormNode->Dump().' '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$aPortalConf = $oContainer->getParameter('combodo.portal.instance.conf');
|
||||
$aPortalConf['forms'] = $aForms;
|
||||
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
|
||||
}
|
||||
$aPortalConf = $oContainer->getParameter('combodo.portal.instance.conf');
|
||||
$aPortalConf['forms'] = $aForms;
|
||||
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,8 @@ use Symfony\Component\DependencyInjection\Container;
|
||||
* Class Lists
|
||||
*
|
||||
* @package Combodo\iTop\Portal\DependencyInjection\SilexCompatBootstrap\PortalXmlConfiguration
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class Lists extends AbstractConfiguration
|
||||
{
|
||||
@@ -38,75 +38,75 @@ class Lists extends AbstractConfiguration
|
||||
*
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function Process(Container $oContainer)
|
||||
{
|
||||
$iDefaultItemRank = 0;
|
||||
$aClassesLists = array();
|
||||
public function Process(Container $oContainer)
|
||||
{
|
||||
$iDefaultItemRank = 0;
|
||||
$aClassesLists = array();
|
||||
|
||||
// Parsing XML file
|
||||
// - Each classes
|
||||
/** @var \MFElement $oClassNode */
|
||||
foreach ($this->GetModuleDesign()->GetNodes('/module_design/classes/class') as $oClassNode)
|
||||
{
|
||||
$aClassLists = array();
|
||||
$sClassId = $oClassNode->getAttribute('id');
|
||||
if ($sClassId === null)
|
||||
{
|
||||
throw new DOMFormatException('Class tag must have an id attribute', null, null, $oClassNode);
|
||||
}
|
||||
// Parsing XML file
|
||||
// - Each classes
|
||||
/** @var \MFElement $oClassNode */
|
||||
foreach ($this->GetModuleDesign()->GetNodes('/module_design/classes/class') as $oClassNode)
|
||||
{
|
||||
$aClassLists = array();
|
||||
$sClassId = $oClassNode->getAttribute('id');
|
||||
if ($sClassId === null)
|
||||
{
|
||||
throw new DOMFormatException('Class tag must have an id attribute', null, null, $oClassNode);
|
||||
}
|
||||
|
||||
// - Each lists
|
||||
/** @var \MFElement $oListNode */
|
||||
foreach ($oClassNode->GetNodes('./lists/list') as $oListNode)
|
||||
{
|
||||
$aListItems = array();
|
||||
$sListId = $oListNode->getAttribute('id');
|
||||
if ($sListId === null)
|
||||
{
|
||||
throw new DOMFormatException('List tag of "'.$sClassId.'" class must have an id attribute', null,
|
||||
null, $oListNode);
|
||||
}
|
||||
// - Each lists
|
||||
/** @var \MFElement $oListNode */
|
||||
foreach ($oClassNode->GetNodes('./lists/list') as $oListNode)
|
||||
{
|
||||
$aListItems = array();
|
||||
$sListId = $oListNode->getAttribute('id');
|
||||
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)
|
||||
{
|
||||
$sItemId = $oItemNode->getAttribute('id');
|
||||
if ($sItemId === null)
|
||||
{
|
||||
throw new DOMFormatException('Item tag of "'.$sItemId.'" list must have an id attribute', null,
|
||||
null, $oItemNode);
|
||||
}
|
||||
// - Each items
|
||||
/** @var \MFElement $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);
|
||||
}
|
||||
|
||||
$aItem = array(
|
||||
'att_code' => $sItemId,
|
||||
'rank' => $iDefaultItemRank,
|
||||
);
|
||||
$aItem = array(
|
||||
'att_code' => $sItemId,
|
||||
'rank' => $iDefaultItemRank,
|
||||
);
|
||||
|
||||
$oRankNode = $oItemNode->GetOptionalElement('rank');
|
||||
if ($oRankNode !== null)
|
||||
{
|
||||
$aItem['rank'] = $oRankNode->GetText($iDefaultItemRank);
|
||||
}
|
||||
$oRankNode = $oItemNode->GetOptionalElement('rank');
|
||||
if ($oRankNode !== null)
|
||||
{
|
||||
$aItem['rank'] = $oRankNode->GetText($iDefaultItemRank);
|
||||
}
|
||||
|
||||
$aListItems[] = $aItem;
|
||||
}
|
||||
// - Sorting list items by rank
|
||||
usort($aListItems, function ($a, $b) {
|
||||
return $a['rank'] > $b['rank'];
|
||||
});
|
||||
$aClassLists[$sListId] = $aListItems;
|
||||
}
|
||||
$aListItems[] = $aItem;
|
||||
}
|
||||
// - Sorting list items by rank
|
||||
usort($aListItems, function ($a, $b) {
|
||||
return $a['rank'] > $b['rank'];
|
||||
});
|
||||
$aClassLists[$sListId] = $aListItems;
|
||||
}
|
||||
|
||||
// - Adding class only if it has at least one list
|
||||
if (!empty($aClassLists))
|
||||
{
|
||||
$aClassesLists[$sClassId] = $aClassLists;
|
||||
}
|
||||
}
|
||||
$aPortalConf = $oContainer->getParameter('combodo.portal.instance.conf');
|
||||
$aPortalConf['lists'] = $aClassLists;
|
||||
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
|
||||
}
|
||||
// - Adding class only if it has at least one list
|
||||
if (!empty($aClassLists))
|
||||
{
|
||||
$aClassesLists[$sClassId] = $aClassLists;
|
||||
}
|
||||
}
|
||||
$aPortalConf = $oContainer->getParameter('combodo.portal.instance.conf');
|
||||
$aPortalConf['lists'] = $aClassLists;
|
||||
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,21 +19,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Created by Bruno DA SILVA, working for Combodo
|
||||
* Date: 04/03/19
|
||||
* Time: 17:36
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\EventListener;
|
||||
|
||||
use ApplicationContext;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
|
||||
/**
|
||||
* Class ApplicationContextSetUrlMakerClass
|
||||
*
|
||||
* @package Combodo\iTop\Portal\EventListener
|
||||
* @since 2.7.0
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
*/
|
||||
class ApplicationContextSetUrlMakerClass
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
/** @var array $aCombodoPortalInstanceConf */
|
||||
private $aCombodoPortalInstanceConf;
|
||||
|
||||
/**
|
||||
@@ -44,11 +44,14 @@ class ApplicationContextSetUrlMakerClass
|
||||
$this->aCombodoPortalInstanceConf = $aCombodoPortalInstanceConf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $oGetResponseEvent
|
||||
*/
|
||||
public function onKernelRequest(GetResponseEvent $oGetResponseEvent)
|
||||
{
|
||||
if ($this->aCombodoPortalInstanceConf['properties']['urlmaker_class'] !== null)
|
||||
{
|
||||
\ApplicationContext::SetUrlMakerClass($this->aCombodoPortalInstanceConf['properties']['urlmaker_class']);
|
||||
ApplicationContext::SetUrlMakerClass($this->aCombodoPortalInstanceConf['properties']['urlmaker_class']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ use Exception;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use User;
|
||||
use Dict;
|
||||
use LoginWebPage;
|
||||
use UserRights;
|
||||
@@ -39,18 +38,18 @@ use ModuleDesign;
|
||||
*/
|
||||
class UserProvider implements ContainerAwareInterface
|
||||
{
|
||||
/** @var \ModuleDesign */
|
||||
/** @var \ModuleDesign $oModuleDesign */
|
||||
private $oModuleDesign;
|
||||
/** @var string $sPortalId */
|
||||
private $sPortalId;
|
||||
/** @var \Symfony\Component\DependencyInjection\ContainerInterface */
|
||||
private $container;
|
||||
/** @var \Symfony\Component\DependencyInjection\ContainerInterface $container */
|
||||
private $oContainer;
|
||||
|
||||
/**
|
||||
* UserProvider constructor.
|
||||
*
|
||||
* @param \ModuleDesign $oModuleDesign
|
||||
* @param \User $oUser
|
||||
* @param string $sPortalId
|
||||
*/
|
||||
public function __construct(ModuleDesign $oModuleDesign, $sPortalId)
|
||||
{
|
||||
@@ -86,16 +85,16 @@ class UserProvider implements ContainerAwareInterface
|
||||
{
|
||||
throw new Exception('Could not load connected user.');
|
||||
}
|
||||
$this->container->set('combodo.current_user', $oUser);
|
||||
$this->oContainer->set('combodo.current_user', $oUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the container.
|
||||
*
|
||||
* @param \Symfony\Component\DependencyInjection\ContainerInterface|null $container
|
||||
* @param \Symfony\Component\DependencyInjection\ContainerInterface|null $oContainer
|
||||
*/
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
public function setContainer(ContainerInterface $oContainer = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->oContainer = $oContainer;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,16 +35,17 @@ use Combodo\iTop\Form\Field\PasswordField;
|
||||
* Description of PasswordFormManager
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class PasswordFormManager extends FormManager
|
||||
{
|
||||
/** @var string FORM_TYPE */
|
||||
const FORM_TYPE = 'change_password';
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function Build()
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function Build()
|
||||
{
|
||||
// Building the form
|
||||
$oForm = new Form('change_password');
|
||||
@@ -75,23 +76,23 @@ class PasswordFormManager extends FormManager
|
||||
$this->oRenderer->SetForm($this->oForm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the form and returns an array with the validation status and the messages.
|
||||
* If the form is valid, creates/updates the object.
|
||||
*
|
||||
* eg :
|
||||
* array(
|
||||
* 'status' => true|false
|
||||
* 'messages' => array(
|
||||
* 'errors' => array()
|
||||
* )
|
||||
*
|
||||
* @param array $aArgs
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
/**
|
||||
* Validates the form and returns an array with the validation status and the messages.
|
||||
* If the form is valid, creates/updates the object.
|
||||
*
|
||||
* eg :
|
||||
* array(
|
||||
* 'status' => true|false
|
||||
* 'messages' => array(
|
||||
* 'errors' => array()
|
||||
* )
|
||||
*
|
||||
* @param array $aArgs
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function OnSubmit($aArgs = null)
|
||||
{
|
||||
$aData = array(
|
||||
@@ -99,8 +100,8 @@ class PasswordFormManager extends FormManager
|
||||
'messages' => array(
|
||||
'success' => array(),
|
||||
'warnings' => array(), // Not used as of today, just to show that the structure is ready for change like this.
|
||||
'error' => array()
|
||||
)
|
||||
'error' => array(),
|
||||
),
|
||||
);
|
||||
|
||||
// Update object and form
|
||||
@@ -117,32 +118,50 @@ class PasswordFormManager extends FormManager
|
||||
$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())
|
||||
{
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += array('_main' => array(Dict::Format('Brick:Portal:UserProfile:Password:CantChangeContactAdministrator', ITOP_APPLICATION_SHORT)));
|
||||
}
|
||||
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['valid'] = false;
|
||||
$aData['messages']['error'] += array('confirm_password' => array(Dict::S('UI:Login:RetypePwdDoesNotMatch')));
|
||||
}
|
||||
else 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'] += array(
|
||||
'_main' => array(
|
||||
Dict::Format('Brick:Portal:UserProfile:Password:CantChangeContactAdministrator', ITOP_APPLICATION_SHORT),
|
||||
),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aData['messages']['success'] += array('_main' => array(Dict::S('Brick:Portal:Object:Form:Message:Saved')));
|
||||
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['valid'] = false;
|
||||
$aData['messages']['error'] += array('confirm_password' => array(Dict::S('UI:Login:RetypePwdDoesNotMatch')));
|
||||
}
|
||||
else
|
||||
{
|
||||
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),
|
||||
),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aData['messages']['success'] += array('_main' => array(Dict::S('Brick:Portal:Object:Form:Message:Saved')));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,7 +169,7 @@ class PasswordFormManager extends FormManager
|
||||
{
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += array('_main' => array($e->getMessage()));
|
||||
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Exception during submit (' . $e->getMessage() . ')');
|
||||
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Exception during submit ('.$e->getMessage().')');
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -159,16 +178,16 @@ class PasswordFormManager extends FormManager
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += $this->oForm->GetErrorMessages();
|
||||
}
|
||||
|
||||
|
||||
return $aData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aArgs
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function OnUpdate($aArgs = null)
|
||||
/**
|
||||
* @param array $aArgs
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function OnUpdate($aArgs = null)
|
||||
{
|
||||
|
||||
// We build the form
|
||||
@@ -187,12 +206,12 @@ class PasswordFormManager extends FormManager
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aArgs
|
||||
*/
|
||||
/**
|
||||
* @param array $aArgs
|
||||
*/
|
||||
public function OnCancel($aArgs = null)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,16 +36,17 @@ use Combodo\iTop\Form\Field\SelectField;
|
||||
* Description of PreferencesFormManager
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.3.0
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class PreferencesFormManager extends FormManager
|
||||
{
|
||||
/** @var string FORM_TYPE */
|
||||
const FORM_TYPE = 'preferences';
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function Build()
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function Build()
|
||||
{
|
||||
// Building the form
|
||||
$oForm = new Form('preferences');
|
||||
@@ -65,7 +66,7 @@ class PreferencesFormManager extends FormManager
|
||||
$aChoices = array();
|
||||
foreach (Dict::GetLanguages() as $sCode => $aLanguage)
|
||||
{
|
||||
$aChoices[$sCode] = $aLanguage['description'] . ' (' . $aLanguage['localized_description'] . ')';
|
||||
$aChoices[$sCode] = $aLanguage['description'].' ('.$aLanguage['localized_description'].')';
|
||||
}
|
||||
asort($aChoices);
|
||||
$oField->SetChoices($aChoices);
|
||||
@@ -77,25 +78,25 @@ class PreferencesFormManager extends FormManager
|
||||
$this->oRenderer->SetForm($this->oForm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the form and returns an array with the validation status and the messages.
|
||||
* If the form is valid, creates/updates the object.
|
||||
*
|
||||
* eg :
|
||||
* array(
|
||||
* 'status' => true|false
|
||||
* 'messages' => array(
|
||||
* 'errors' => array()
|
||||
* )
|
||||
*
|
||||
* @param array $aArgs
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*/
|
||||
/**
|
||||
* Validates the form and returns an array with the validation status and the messages.
|
||||
* If the form is valid, creates/updates the object.
|
||||
*
|
||||
* eg :
|
||||
* array(
|
||||
* 'status' => true|false
|
||||
* 'messages' => array(
|
||||
* 'errors' => array()
|
||||
* )
|
||||
*
|
||||
* @param array $aArgs
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*/
|
||||
public function OnSubmit($aArgs = null)
|
||||
{
|
||||
$aData = array(
|
||||
@@ -103,8 +104,8 @@ class PreferencesFormManager extends FormManager
|
||||
'messages' => array(
|
||||
'success' => array(),
|
||||
'warnings' => array(), // Not used as of today, just to show that the structure is ready for change like this.
|
||||
'error' => array()
|
||||
)
|
||||
'error' => array(),
|
||||
),
|
||||
);
|
||||
|
||||
// Update object and form
|
||||
@@ -130,7 +131,7 @@ class PreferencesFormManager extends FormManager
|
||||
$oCurUser->Set('language', $sLanguage);
|
||||
$iFieldChanged++;
|
||||
}
|
||||
|
||||
|
||||
// Updating only if preferences changed
|
||||
if ($iFieldChanged > 0)
|
||||
{
|
||||
@@ -148,7 +149,7 @@ class PreferencesFormManager extends FormManager
|
||||
CMDBSource::Query('ROLLBACK');
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += array('_main' => array($e->getMessage()));
|
||||
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Rollback during submit (' . $e->getMessage() . ')');
|
||||
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Rollback during submit ('.$e->getMessage().')');
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -157,16 +158,16 @@ class PreferencesFormManager extends FormManager
|
||||
$aData['valid'] = false;
|
||||
$aData['messages']['error'] += $this->oForm->GetErrorMessages();
|
||||
}
|
||||
|
||||
|
||||
return $aData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aArgs
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function OnUpdate($aArgs = null)
|
||||
/**
|
||||
* @param array $aArgs
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function OnUpdate($aArgs = null)
|
||||
{
|
||||
|
||||
// We build the form
|
||||
@@ -185,12 +186,12 @@ class PreferencesFormManager extends FormManager
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aArgs
|
||||
*/
|
||||
/**
|
||||
* @param array $aArgs
|
||||
*/
|
||||
public function OnCancel($aArgs = null)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,52 +22,47 @@
|
||||
|
||||
namespace Combodo\iTop\Portal\Helper;
|
||||
|
||||
use ApplicationContext;
|
||||
use cmdbAbstractObject;
|
||||
use Combodo\iTop\Portal\Brick\AbstractBrick;
|
||||
use Combodo\iTop\Portal\Brick\PortalBrick;
|
||||
use DBObjectSearch;
|
||||
use DBObjectSet;
|
||||
use Dict;
|
||||
use DOMFormatException;
|
||||
use Exception;
|
||||
use iPortalUIExtension;
|
||||
use IssueLog;
|
||||
use MetaModel;
|
||||
use ModuleDesign;
|
||||
use Silex\Application;
|
||||
use Symfony\Component\Debug\ErrorHandler;
|
||||
use Symfony\Component\Debug\ExceptionHandler;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Twig_Environment;
|
||||
use Twig_SimpleFilter;
|
||||
use Twig_SimpleFunction;
|
||||
use UserRights;
|
||||
use utils;
|
||||
|
||||
/**
|
||||
* Contains static methods to help loading / registering classes of the application.
|
||||
* Mostly used for Controllers / Routers / Entities initialization.
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class ApplicationHelper
|
||||
{
|
||||
/** @var string FORM_ENUM_DISPLAY_MODE_COSY */
|
||||
const FORM_ENUM_DISPLAY_MODE_COSY = 'cosy';
|
||||
/** @var string FORM_ENUM_DISPLAY_MODE_COMPACT */
|
||||
const FORM_ENUM_DISPLAY_MODE_COMPACT = 'compact';
|
||||
/** @var string FORM_DEFAULT_DISPLAY_MODE */
|
||||
const FORM_DEFAULT_DISPLAY_MODE = self::FORM_ENUM_DISPLAY_MODE_COSY;
|
||||
/** @var bool FORM_DEFAULT_ALWAYS_SHOW_SUBMIT */
|
||||
const FORM_DEFAULT_ALWAYS_SHOW_SUBMIT = false;
|
||||
|
||||
/**
|
||||
* Loads classes from the base portal
|
||||
*
|
||||
* @deprecated Since 2.7.0
|
||||
*
|
||||
* @param string $sScannedDir Directory to load the files from
|
||||
* @param string $sScannedDir Directory to load the files from
|
||||
* @param string $sFilePattern Pattern of files to load
|
||||
* @param string $sType Type of files to load, used only in the Exception message, can be anything
|
||||
* @param string $sType Type of files to load, used only in the Exception message, can be anything
|
||||
*
|
||||
* @throws \Exception
|
||||
* @deprecated Since 2.7.0
|
||||
*
|
||||
*/
|
||||
public static function LoadClasses($sScannedDir, $sFilePattern, $sType)
|
||||
{
|
||||
@@ -101,6 +96,8 @@ class ApplicationHelper
|
||||
* Note : It is only active when $oApp['debug'] is false
|
||||
*
|
||||
* @param Application $oApp
|
||||
*
|
||||
* @todo
|
||||
*/
|
||||
public static function RegisterExceptionHandler(Application $oApp)
|
||||
{
|
||||
@@ -118,7 +115,7 @@ class ApplicationHelper
|
||||
'exception' => $oException,
|
||||
'code' => $iErrorCode,
|
||||
'error_title' => '',
|
||||
'error_message' => $oException->getMessage()
|
||||
'error_message' => $oException->getMessage(),
|
||||
);
|
||||
|
||||
switch ($iErrorCode)
|
||||
@@ -264,6 +261,7 @@ class ApplicationHelper
|
||||
*/
|
||||
public static function GetLoadedFormFromClass($aForms, $sClass, $sMode)
|
||||
{
|
||||
$aForm = null;
|
||||
|
||||
// We try to find the form for that class
|
||||
if (isset($aForms[$sClass]) && isset($aForms[$sClass][$sMode]))
|
||||
@@ -364,7 +362,7 @@ class ApplicationHelper
|
||||
* Form will look like the "Properties" tab of a $sClass object in the console.
|
||||
*
|
||||
* @param string $sClass
|
||||
* @param bool $bAddLinksets
|
||||
* @param bool $bAddLinksets
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@@ -394,13 +392,13 @@ class ApplicationHelper
|
||||
|
||||
// Count cols (not linksets)
|
||||
$iColCount = 0;
|
||||
foreach($aPropertiesStruct as $sColId => $aColFieldsets)
|
||||
foreach ($aPropertiesStruct as $sColId => $aColFieldsets)
|
||||
{
|
||||
if(substr($sColId, 0, 1) !== '_')
|
||||
if (substr($sColId, 0, 1) !== '_')
|
||||
{
|
||||
foreach($aColFieldsets as $sFieldsetName => $aAttCodes)
|
||||
foreach ($aColFieldsets as $sFieldsetName => $aAttCodes)
|
||||
{
|
||||
if(substr($sFieldsetName, 0, 1) !== '_')
|
||||
if (substr($sFieldsetName, 0, 1) !== '_')
|
||||
{
|
||||
$iColCount++;
|
||||
break;
|
||||
@@ -409,32 +407,32 @@ class ApplicationHelper
|
||||
}
|
||||
}
|
||||
// If no cols, return a default form with all fields one after another
|
||||
if($iColCount === 0)
|
||||
if ($iColCount === 0)
|
||||
{
|
||||
return array(
|
||||
'id' => 'default',
|
||||
'type' => 'zlist',
|
||||
'fields' => 'details',
|
||||
'layout' => null
|
||||
'layout' => null,
|
||||
);
|
||||
}
|
||||
// Warning, this might not be great when 12 modulo $iColCount is greater than 0.
|
||||
$sColCSSClass = 'col-sm-'.floor(12/$iColCount);
|
||||
$sColCSSClass = 'col-sm-'.floor(12 / $iColCount);
|
||||
|
||||
$sLinksetsHTML = "";
|
||||
$sRowHTML = "<div class=\"row\">\n";
|
||||
foreach($aPropertiesStruct as $sColId => $aColFieldsets)
|
||||
foreach ($aPropertiesStruct as $sColId => $aColFieldsets)
|
||||
{
|
||||
$sColsHTML = "\t<div class=\"".$sColCSSClass."\">\n";
|
||||
foreach($aColFieldsets as $sFieldsetName => $aAttCodes)
|
||||
foreach ($aColFieldsets as $sFieldsetName => $aAttCodes)
|
||||
{
|
||||
// Add fieldset, not linkset
|
||||
if(substr($sFieldsetName, 0, 1) !== '_')
|
||||
if (substr($sFieldsetName, 0, 1) !== '_')
|
||||
{
|
||||
$sFieldsetHTML = "\t\t<fieldset>\n";
|
||||
$sFieldsetHTML .= "\t\t\t<legend>".htmlentities(Dict::S($sFieldsetName), ENT_QUOTES, 'UTF-8')."</legend>\n";
|
||||
|
||||
foreach($aAttCodes as $sAttCode)
|
||||
foreach ($aAttCodes as $sAttCode)
|
||||
{
|
||||
$sFieldsetHTML .= "\t\t\t<div class=\"form_field\" data-field-id=\"".$sAttCode."\"></div>\n";
|
||||
}
|
||||
@@ -444,9 +442,9 @@ class ApplicationHelper
|
||||
// Add to col
|
||||
$sColsHTML .= $sFieldsetHTML;
|
||||
}
|
||||
elseif($bAddLinksets)
|
||||
elseif ($bAddLinksets)
|
||||
{
|
||||
foreach($aAttCodes as $sAttCode)
|
||||
foreach ($aAttCodes as $sAttCode)
|
||||
{
|
||||
$sLinksetsHTML .= "<div class=\"form_field\" data-field-id=\"".$sAttCode."\"></div>\n";
|
||||
}
|
||||
|
||||
@@ -31,24 +31,26 @@ use Dict;
|
||||
use MetaModel;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use UserRights;
|
||||
use Combodo\iTop\Portal\Routing\UrlGenerator;
|
||||
|
||||
/**
|
||||
* Class BrowseBrickHelper
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Helper
|
||||
* @since 2.7.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
*/
|
||||
class BrowseBrickHelper
|
||||
{
|
||||
/** @var string LEVEL_SEPARATOR */
|
||||
const LEVEL_SEPARATOR = '-';
|
||||
/** @var array OPTIONAL_ATTRIBUTES */
|
||||
const OPTIONAL_ATTRIBUTES = array('tooltip_att', 'description_att', 'image_att');
|
||||
|
||||
/**
|
||||
* @var \Combodo\iTop\Portal\Helper\SecurityHelper
|
||||
*/
|
||||
/** @var \Combodo\iTop\Portal\Helper\SecurityHelper */
|
||||
private $oSecurityHelper;
|
||||
/**
|
||||
* @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper
|
||||
*/
|
||||
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper */
|
||||
private $oScopeValidator;
|
||||
/**
|
||||
* @var \Combodo\iTop\Portal\Routing\UrlGenerator
|
||||
*/
|
||||
/** @var \Combodo\iTop\Portal\Routing\UrlGenerator */
|
||||
private $oUrlGenerator;
|
||||
|
||||
/**
|
||||
@@ -58,8 +60,8 @@ 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;
|
||||
$this->oUrlGenerator = $oUrlGenerator;
|
||||
@@ -81,16 +83,18 @@ class BrowseBrickHelper
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function TreeToFlatLevelsProperties(array $aLevels, array &$aLevelsProperties, $sLevelAliasPrefix = 'L')
|
||||
{
|
||||
foreach ($aLevels as $aLevel)
|
||||
{
|
||||
$sCurrentLevelAlias = $sLevelAliasPrefix . static::LEVEL_SEPARATOR . $aLevel['id'];
|
||||
$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())
|
||||
@@ -110,7 +114,7 @@ class BrowseBrickHelper
|
||||
'image_att' => $aLevel['image_att'],
|
||||
'search' => $oSearch,
|
||||
'fields' => array(),
|
||||
'actions' => array()
|
||||
'actions' => array(),
|
||||
);
|
||||
|
||||
// Adding current level's fields
|
||||
@@ -123,24 +127,24 @@ class BrowseBrickHelper
|
||||
$aLevelsProperties[$sCurrentLevelAlias]['fields'][] = array(
|
||||
'code' => $sFieldAttCode,
|
||||
'label' => MetaModel::GetAttributeDef($oSearch->GetClass(), $sFieldAttCode)->GetLabel(),
|
||||
'hidden' => $aFieldProperties['hidden']
|
||||
'hidden' => $aFieldProperties['hidden'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Flattening and adding sublevels
|
||||
// Flattening and adding sub levels
|
||||
if (isset($aLevel['levels']))
|
||||
{
|
||||
foreach ($aLevel['levels'] as $aChildLevel)
|
||||
{
|
||||
// Checking if the sublevel if allowed
|
||||
// Checking if the sub level if allowed
|
||||
$oChildSearch = DBSearch::FromOQL($aChildLevel['oql']);
|
||||
if ($this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $oChildSearch->GetClass()))
|
||||
{
|
||||
// Adding the sublevel to this one
|
||||
$aLevelsProperties[$sCurrentLevelAlias]['levels'][] = $sCurrentLevelAlias . static::LEVEL_SEPARATOR . $aChildLevel['id'];
|
||||
// Adding the sub level to this one
|
||||
$aLevelsProperties[$sCurrentLevelAlias]['levels'][] = $sCurrentLevelAlias.static::LEVEL_SEPARATOR.$aChildLevel['id'];
|
||||
|
||||
// Adding drilldown action if necessary
|
||||
// Adding drill down action if necessary
|
||||
foreach ($aLevel['actions'] as $sId => $aAction)
|
||||
{
|
||||
if ($aAction['type'] === BrowseBrick::ENUM_ACTION_DRILLDOWN)
|
||||
@@ -162,11 +166,13 @@ class BrowseBrickHelper
|
||||
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;
|
||||
}
|
||||
@@ -190,8 +196,10 @@ class BrowseBrickHelper
|
||||
// We can only make translate a dictionnary 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']));
|
||||
$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
|
||||
{
|
||||
@@ -236,11 +244,16 @@ class BrowseBrickHelper
|
||||
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']));
|
||||
$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('sEncodedMethodName' => base64_encode($aAction['factory']['value']), 'sObjectClass' => '-objectClass-', 'sObjectId' => '-objectId-'));
|
||||
$aAction['url'] = $this->oUrlGenerator->generate('p_object_create_from_factory', array(
|
||||
'sEncodedMethodName' => base64_encode($aAction['factory']['value']),
|
||||
'sObjectClass' => '-objectClass-',
|
||||
'sObjectId' => '-objectId-',
|
||||
));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -255,9 +268,9 @@ class BrowseBrickHelper
|
||||
/**
|
||||
* Prepares the action rules for an array of DBObject items.
|
||||
*
|
||||
* @param array $aItems
|
||||
* @param array $aItems
|
||||
* @param string $sLevelsAlias
|
||||
* @param array $aLevelsProperties
|
||||
* @param array $aLevelsProperties
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@@ -298,11 +311,13 @@ class BrowseBrickHelper
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function AddToFlatItems(array $aCurrentRow, array &$aLevelsProperties)
|
||||
{
|
||||
$aRow = array();
|
||||
|
||||
/** @var \DBObject $value */
|
||||
foreach ($aCurrentRow as $key => $value)
|
||||
{
|
||||
// Retrieving objects from all levels
|
||||
@@ -313,18 +328,18 @@ class BrowseBrickHelper
|
||||
'id' => $value->GetKey(),
|
||||
'name' => $value->Get($aLevelsProperties[$key]['name_att']),
|
||||
'class' => get_class($value),
|
||||
'action_rules_token' => $this->PrepareActionRulesForItems($aItems, $key, $aLevelsProperties)
|
||||
'action_rules_token' => $this->PrepareActionRulesForItems($aItems, $key, $aLevelsProperties),
|
||||
);
|
||||
|
||||
// Adding optional attributes if necessary
|
||||
foreach(static::OPTIONAL_ATTRIBUTES as $sOptionalAttribute)
|
||||
foreach (static::OPTIONAL_ATTRIBUTES as $sOptionalAttribute)
|
||||
{
|
||||
if ($aLevelsProperties[$key][$sOptionalAttribute] !== null)
|
||||
{
|
||||
$sPropertyName = substr($sOptionalAttribute, 0, -4);
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($value), $aLevelsProperties[$key][$sOptionalAttribute]);
|
||||
|
||||
if($oAttDef instanceof AttributeImage)
|
||||
if ($oAttDef instanceof AttributeImage)
|
||||
{
|
||||
$tmpAttValue = $value->Get($aLevelsProperties[$key][$sOptionalAttribute]);
|
||||
if ($sOptionalAttribute === 'image_att')
|
||||
@@ -335,7 +350,7 @@ class BrowseBrickHelper
|
||||
'sObjectClass' => get_class($value),
|
||||
'sObjectId' => $value->GetKey(),
|
||||
'sObjectField' => $aLevelsProperties[$key][$sOptionalAttribute],
|
||||
'cache' => 86400
|
||||
'cache' => 86400,
|
||||
));
|
||||
}
|
||||
else
|
||||
@@ -360,7 +375,6 @@ class BrowseBrickHelper
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($value), $aField['code']);
|
||||
|
||||
$sHtmlForFieldValue = '';
|
||||
switch (get_class($oAttDef))
|
||||
{
|
||||
case 'AttributeTagSet':
|
||||
@@ -420,11 +434,12 @@ class BrowseBrickHelper
|
||||
{
|
||||
$aCurrentRowKeys = array_keys($aCurrentRow);
|
||||
$aCurrentRowValues = array_values($aCurrentRow);
|
||||
$sCurrentIndex = $aCurrentRowKeys[0] . '::' . $aCurrentRowValues[0]->GetKey();
|
||||
/** @var \DBObject[] $aCurrentRowValues */
|
||||
$sCurrentIndex = $aCurrentRowKeys[0].'::'.$aCurrentRowValues[0]->GetKey();
|
||||
|
||||
// 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;
|
||||
}
|
||||
@@ -437,25 +452,31 @@ class BrowseBrickHelper
|
||||
'name' => $aCurrentRowValues[0]->Get($aLevelsProperties[$aCurrentRowKeys[0]]['name_att']),
|
||||
'class' => get_class($aCurrentRowValues[0]),
|
||||
'subitems' => array(),
|
||||
'action_rules_token' => $this->PrepareActionRulesForItems($aCurrentRowObjects, $aCurrentRowKeys[0], $aLevelsProperties)
|
||||
'action_rules_token' => $this->PrepareActionRulesForItems($aCurrentRowObjects, $aCurrentRowKeys[0], $aLevelsProperties),
|
||||
);
|
||||
|
||||
// Adding optional attributes if necessary
|
||||
foreach(static::OPTIONAL_ATTRIBUTES as $sOptionalAttribute)
|
||||
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 ($sOptionalAttribute === 'image_att')
|
||||
{
|
||||
if (is_object($tmpAttValue) && !$tmpAttValue->IsEmpty())
|
||||
{
|
||||
$tmpAttValue = $this->oUrlGenerator->generate('p_object_document_display', array('sObjectClass' => get_class($aCurrentRowValues[0]), 'sObjectId' => $aCurrentRowValues[0]->GetKey(), 'sObjectField' => $aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute], 'cache' => 86400));
|
||||
$tmpAttValue = $this->oUrlGenerator->generate('p_object_document_display', array(
|
||||
'sObjectClass' => get_class($aCurrentRowValues[0]),
|
||||
'sObjectId' => $aCurrentRowValues[0]->GetKey(),
|
||||
'sObjectField' => $aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute],
|
||||
'cache' => 86400,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -36,52 +36,64 @@ use BinaryExpression;
|
||||
use FieldExpression;
|
||||
use ScalarExpression;
|
||||
|
||||
/**
|
||||
* Class ContextManipulatorHelper
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Helper
|
||||
* @since 2.3.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
*/
|
||||
class ContextManipulatorHelper
|
||||
{
|
||||
/** @var string ENUM_RULE_CALLBACK_BACK */
|
||||
const ENUM_RULE_CALLBACK_BACK = 'back';
|
||||
/** @var string ENUM_RULE_CALLBACK_GOTO */
|
||||
const ENUM_RULE_CALLBACK_GOTO = 'goto';
|
||||
/** @var string ENUM_RULE_CALLBACK_OPEN */
|
||||
const ENUM_RULE_CALLBACK_OPEN = 'open';
|
||||
/** @var string ENUM_RULE_CALLBACK_OPEN_VIEW */
|
||||
const ENUM_RULE_CALLBACK_OPEN_VIEW = 'view';
|
||||
/** @var string ENUM_RULE_CALLBACK_OPEN_EDIT */
|
||||
const ENUM_RULE_CALLBACK_OPEN_EDIT = 'edit';
|
||||
/** @var string DEFAULT_RULE_CALLBACK_OPEN */
|
||||
const DEFAULT_RULE_CALLBACK_OPEN = self::ENUM_RULE_CALLBACK_OPEN_VIEW;
|
||||
|
||||
/** @var array $aRules */
|
||||
protected $aRules;
|
||||
|
||||
/** @var \Symfony\Component\Routing\RouterInterface */
|
||||
private $oRouter;
|
||||
/** @var \Combodo\iTop\Portal\Brick\BrickCollection */
|
||||
private $oBrickCollection;
|
||||
/**
|
||||
* @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper
|
||||
*/
|
||||
private $oScopeValidator;
|
||||
/** @var \Symfony\Component\Routing\RouterInterface */
|
||||
private $oRouter;
|
||||
/** @var \Combodo\iTop\Portal\Brick\BrickCollection */
|
||||
private $oBrickCollection;
|
||||
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper */
|
||||
private $oScopeValidator;
|
||||
|
||||
/**
|
||||
* ContextManipulatorHelper constructor.
|
||||
*
|
||||
* @param \ModuleDesign $oModuleDesign
|
||||
* @param \Symfony\Component\Routing\RouterInterface $oRouter
|
||||
* @param \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection
|
||||
* @param \ModuleDesign $oModuleDesign
|
||||
* @param \Symfony\Component\Routing\RouterInterface $oRouter
|
||||
* @param \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection
|
||||
* @param \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator
|
||||
*
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function __construct(ModuleDesign $oModuleDesign, RouterInterface $oRouter, BrickCollection $oBrickCollection, ScopeValidatorHelper $oScopeValidator)
|
||||
{
|
||||
public function __construct(
|
||||
ModuleDesign $oModuleDesign, RouterInterface $oRouter, BrickCollection $oBrickCollection, ScopeValidatorHelper $oScopeValidator
|
||||
) {
|
||||
$this->aRules = array();
|
||||
$this->oRouter = $oRouter;
|
||||
$this->oBrickCollection = $oBrickCollection;
|
||||
$this->oRouter = $oRouter;
|
||||
$this->oBrickCollection = $oBrickCollection;
|
||||
|
||||
$this->Init($oModuleDesign->GetNodes('/module_design/action_rules/action_rule'));
|
||||
$this->oScopeValidator = $oScopeValidator;
|
||||
}
|
||||
$this->Init($oModuleDesign->GetNodes('/module_design/action_rules/action_rule'));
|
||||
$this->oScopeValidator = $oScopeValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the ScopeValidator by generating and caching the scopes compilation in the $this->sCachePath.$this->sFilename file.
|
||||
*
|
||||
* @param \DOMNodeList $oNodes
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function Init(DOMNodeList $oNodes)
|
||||
@@ -89,7 +101,8 @@ class ContextManipulatorHelper
|
||||
$this->aRules = array();
|
||||
|
||||
// Iterating over the scope nodes
|
||||
foreach ($oNodes as $oRuleNode)
|
||||
/** @var \Combodo\iTop\DesignElement $oRuleNode */
|
||||
foreach ($oNodes as $oRuleNode)
|
||||
{
|
||||
// Retrieving mandatory id attribute
|
||||
$sRuleId = $oRuleNode->getAttribute('id');
|
||||
@@ -107,17 +120,18 @@ class ContextManipulatorHelper
|
||||
'preset' => array(),
|
||||
'retrofit' => array(),
|
||||
'submit' => null,
|
||||
'cancel' => null
|
||||
'cancel' => null,
|
||||
);
|
||||
|
||||
// Iterating over the rule's nodes
|
||||
/** @var \Combodo\iTop\DesignElement $oSubNode */
|
||||
foreach ($oRuleNode->childNodes as $oSubNode)
|
||||
{
|
||||
$sSubNodeName = $oSubNode->nodeName;
|
||||
switch ($sSubNodeName)
|
||||
{
|
||||
case 'source_class':
|
||||
$aRule['source_oql'] = 'SELECT ' . $oSubNode->GetText();
|
||||
$aRule['source_oql'] = 'SELECT '.$oSubNode->GetText();
|
||||
break;
|
||||
|
||||
case 'source_oql':
|
||||
@@ -127,6 +141,7 @@ class ContextManipulatorHelper
|
||||
|
||||
case 'presets':
|
||||
case 'retrofits':
|
||||
/** @var \Combodo\iTop\DesignElement $oActionNode */
|
||||
foreach ($oSubNode->childNodes as $oActionNode)
|
||||
{
|
||||
// Note : Caution, the index of $aRule is now $oActionNode->nodeName instead of $sSubNodeName, as we want to match iTopObjectCopier specs like told previously
|
||||
@@ -150,11 +165,11 @@ class ContextManipulatorHelper
|
||||
$sType = $oSubNode->getAttribute('xsi:type');
|
||||
if ($sType === '')
|
||||
{
|
||||
throw new DOMFormatException($sSubNodeName . ' must have an xsi:type attribute.', null, null, $oSubNode);
|
||||
throw new DOMFormatException($sSubNodeName.' must have an xsi:type attribute.', null, null, $oSubNode);
|
||||
}
|
||||
if (($sType === static::ENUM_RULE_CALLBACK_OPEN) && ($sSubNodeName === 'cancel'))
|
||||
{
|
||||
throw new DOMFormatException('Cancel tag cannot be of type ' . $sType . '.', null, null, $oSubNode);
|
||||
throw new DOMFormatException('Cancel tag cannot be of type '.$sType.'.', null, null, $oSubNode);
|
||||
}
|
||||
|
||||
$aRule[$sSubNodeName] = array('type' => $sType);
|
||||
@@ -220,47 +235,48 @@ class ContextManipulatorHelper
|
||||
return $this->aRules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the rule identified by its ID, as a hash array
|
||||
*
|
||||
* @param string $sId
|
||||
*
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
/**
|
||||
* Return the rule identified by its ID, as a hash array
|
||||
*
|
||||
* @param string $sId
|
||||
*
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetRule($sId)
|
||||
{
|
||||
if (!array_key_exists($sId, $this->aRules))
|
||||
{
|
||||
throw new Exception('Context creator : Could not find "' . $sId . '" in the rules list');
|
||||
throw new Exception('Context creator : Could not find "'.$sId.'" in the rules list');
|
||||
}
|
||||
|
||||
return $this->aRules[$sId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the $oObject passed as a reference with the $aData
|
||||
*
|
||||
* $aData must be of the form :
|
||||
* array(
|
||||
* 'rules' => array(
|
||||
* 'rule-id-1',
|
||||
* 'rule-id-2',
|
||||
* ...
|
||||
* ),
|
||||
* 'sources' => array(
|
||||
* <DBObject1 class> => <DBObject1 id>,
|
||||
* <DBObject2 class> => <DBObject2 id>,
|
||||
* ...
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @param array $aData
|
||||
* @param \DBObject $oObject
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
/**
|
||||
* Prepare the $oObject passed as a reference with the $aData
|
||||
*
|
||||
* $aData must be of the form :
|
||||
* array(
|
||||
* 'rules' => array(
|
||||
* 'rule-id-1',
|
||||
* 'rule-id-2',
|
||||
* ...
|
||||
* ),
|
||||
* 'sources' => array(
|
||||
* <DBObject1 class> => <DBObject1 id>,
|
||||
* <DBObject2 class> => <DBObject2 id>,
|
||||
* ...
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @param array $aData
|
||||
* @param \DBObject $oObject
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function PrepareObject(array $aData, DBObject &$oObject)
|
||||
{
|
||||
if (isset($aData['rules']) && isset($aData['sources']))
|
||||
@@ -289,7 +305,7 @@ class ContextManipulatorHelper
|
||||
{
|
||||
if (is_array($sourceId))
|
||||
{
|
||||
throw new Exception('Context creator : ":id" parameter in rule "' . $sId . '" cannot be an array (This is a limitation of DBSearch)');
|
||||
throw new Exception('Context creator : ":id" parameter in rule "'.$sId.'" cannot be an array (This is a limitation of DBSearch)');
|
||||
}
|
||||
|
||||
$aSearchParams['id'] = $sourceId;
|
||||
@@ -306,7 +322,8 @@ class ContextManipulatorHelper
|
||||
for ($i = 0; $i < $iLoopMax; $i++)
|
||||
{
|
||||
// - Building full search expression
|
||||
$oBinExpr = new BinaryExpression(new FieldExpression('id', $oSearch->GetClassAlias()), '=', new ScalarExpression($sourceId[$i]));
|
||||
$oBinExpr = new BinaryExpression(new FieldExpression('id', $oSearch->GetClassAlias()), '=',
|
||||
new ScalarExpression($sourceId[$i]));
|
||||
if ($i === 0)
|
||||
{
|
||||
$oFullBinExpr = $oBinExpr;
|
||||
@@ -326,7 +343,8 @@ class ContextManipulatorHelper
|
||||
}
|
||||
|
||||
// Checking for silos
|
||||
$oScopeSearch = $this->oScopeValidator->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sSearchClass, UR_ACTION_READ);
|
||||
$oScopeSearch = $this->oScopeValidator->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sSearchClass,
|
||||
UR_ACTION_READ);
|
||||
if ($oScopeSearch->IsAllDataAllowed())
|
||||
{
|
||||
$oSearch->AllowAllData();
|
||||
@@ -364,28 +382,28 @@ class ContextManipulatorHelper
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash array of urls for each type of callback
|
||||
*
|
||||
* eg :
|
||||
* array(
|
||||
* 'submit' => 'http://localhost/',
|
||||
* 'cancel' => null
|
||||
* );
|
||||
*
|
||||
* @param array $aData
|
||||
* @param \DBObject $oObject
|
||||
* @param boolean $bModal
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
/**
|
||||
* Returns a hash array of urls for each type of callback
|
||||
*
|
||||
* eg :
|
||||
* array(
|
||||
* 'submit' => 'http://localhost/',
|
||||
* 'cancel' => null
|
||||
* );
|
||||
*
|
||||
* @param array $aData
|
||||
* @param \DBObject $oObject
|
||||
* @param boolean $bModal
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetCallbackUrls(array $aData, DBObject $oObject, $bModal = false)
|
||||
{
|
||||
$aResults = array(
|
||||
'submit' => null,
|
||||
'cancel' => null
|
||||
'cancel' => null,
|
||||
);
|
||||
|
||||
if (isset($aData['rules']))
|
||||
@@ -417,7 +435,8 @@ class ContextManipulatorHelper
|
||||
break;
|
||||
|
||||
case static::ENUM_RULE_CALLBACK_OPEN:
|
||||
$sCallbackUrl = ($oObject->IsNew()) ? null : $this->oRouter->generate('p_object_' . $aRule[$sCallbackName]['mode'], array('sObjectClass' => get_class($oObject), 'sObjectId' => $oObject->GetKey()));
|
||||
$sCallbackUrl = ($oObject->IsNew()) ? null : $this->oRouter->generate('p_object_'.$aRule[$sCallbackName]['mode'],
|
||||
array('sObjectClass' => get_class($oObject), 'sObjectId' => $oObject->GetKey()));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -430,30 +449,31 @@ class ContextManipulatorHelper
|
||||
return $aResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the rules as an array of rules and source objects so it can be tokenised
|
||||
*
|
||||
* @param array $aRules
|
||||
* @param array $aObjects
|
||||
* @return array
|
||||
*/
|
||||
/**
|
||||
* Prepares the rules as an array of rules and source objects so it can be tokenised
|
||||
*
|
||||
* @param array $aRules
|
||||
* @param array $aObjects
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function PrepareRulesForToken($aRules, $aObjects = array())
|
||||
{
|
||||
// Getting necessary information from objects
|
||||
$aSources = array();
|
||||
foreach ($aObjects as $oObject)
|
||||
{
|
||||
$aSources[get_class($oObject)] = $oObject->GetKey();
|
||||
}
|
||||
{
|
||||
// Getting necessary information from objects
|
||||
$aSources = array();
|
||||
foreach ($aObjects as $oObject)
|
||||
{
|
||||
$aSources[get_class($oObject)] = $oObject->GetKey();
|
||||
}
|
||||
|
||||
// Preparing data
|
||||
$aTokenRules = array(
|
||||
'rules' => $aRules,
|
||||
'sources' => $aSources
|
||||
);
|
||||
// Preparing data
|
||||
$aTokenRules = array(
|
||||
'rules' => $aRules,
|
||||
'sources' => $aSources,
|
||||
);
|
||||
|
||||
return $aTokenRules;
|
||||
}
|
||||
return $aTokenRules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a token made out of the rules.
|
||||
@@ -463,33 +483,35 @@ class ContextManipulatorHelper
|
||||
* To retrieve it has
|
||||
*
|
||||
* @param array $aTokenRules
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function EncodeRulesToken($aTokenRules)
|
||||
{
|
||||
// Returning tokenised data
|
||||
// Returning tokenised data
|
||||
return base64_encode(json_encode($aTokenRules));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aRules
|
||||
* @param array $aObjects
|
||||
* @return string
|
||||
*/
|
||||
/**
|
||||
* @param array $aRules
|
||||
* @param array $aObjects
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function PrepareAndEncodeRulesToken($aRules, $aObjects = array())
|
||||
{
|
||||
// Preparing rules before making a token
|
||||
$aTokenRules = static::PrepareRulesForToken($aRules, $aObjects);
|
||||
{
|
||||
// Preparing rules before making a token
|
||||
$aTokenRules = static::PrepareRulesForToken($aRules, $aObjects);
|
||||
|
||||
// Returning tokenised data
|
||||
return static::EncodeRulesToken($aTokenRules);
|
||||
}
|
||||
// Returning tokenised data
|
||||
return static::EncodeRulesToken($aTokenRules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a token made out of the rules
|
||||
*
|
||||
* @param string $sToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function DecodeRulesToken($sToken)
|
||||
|
||||
@@ -25,21 +25,44 @@ namespace Combodo\iTop\Portal\Helper;
|
||||
use Exception;
|
||||
use DOMNodeList;
|
||||
use DOMFormatException;
|
||||
use ModuleDesign;
|
||||
use utils;
|
||||
use ProfilesConfig;
|
||||
use MetaModel;
|
||||
|
||||
/**
|
||||
* Class LifecycleValidatorHelper
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Helper
|
||||
* @since 2.3.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
*/
|
||||
class LifecycleValidatorHelper
|
||||
{
|
||||
/** @var string DEFAULT_GENERATED_CLASS */
|
||||
const DEFAULT_GENERATED_CLASS = 'PortalLifecycleValues';
|
||||
|
||||
/** @var string|null $sCachePath */
|
||||
protected $sCachePath;
|
||||
/** @var string $sFilename */
|
||||
protected $sFilename;
|
||||
/** @var string $sInstancePrefix */
|
||||
protected $sInstancePrefix;
|
||||
/** @var string $sGeneratedClass */
|
||||
protected $sGeneratedClass;
|
||||
/** @var array $aProfilesMatrix */
|
||||
protected $aProfilesMatrix;
|
||||
|
||||
public function __construct(\ModuleDesign $moduleDesign, $sPortalId, $sPortalCachePath = null)
|
||||
/**
|
||||
* LifecycleValidatorHelper constructor.
|
||||
*
|
||||
* @param \ModuleDesign $moduleDesign
|
||||
* @param string $sPortalId
|
||||
* @param string|null $sPortalCachePath
|
||||
*
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function __construct(ModuleDesign $moduleDesign, $sPortalId, $sPortalCachePath = null)
|
||||
{
|
||||
$this->sFilename = "{$sPortalId}.lifecycle.php";
|
||||
$this->sCachePath = $sPortalCachePath;
|
||||
@@ -47,7 +70,7 @@ class LifecycleValidatorHelper
|
||||
$this->sGeneratedClass = static::DEFAULT_GENERATED_CLASS;
|
||||
$this->aProfilesMatrix = array();
|
||||
|
||||
$this->Init($moduleDesign->GetNodes('/module_design/classes/class'));
|
||||
$this->Init($moduleDesign->GetNodes('/module_design/classes/class'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,7 +119,7 @@ class LifecycleValidatorHelper
|
||||
* This is used to create a unique lifecycle values class in the cache directory (/data/cache-<ENV>) as there can be several instance of the portal.
|
||||
*
|
||||
* @param string $sInstancePrefix
|
||||
*
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Helper\LifecycleValidatorHelper
|
||||
*/
|
||||
public function SetInstancePrefix($sInstancePrefix)
|
||||
@@ -106,7 +129,8 @@ class LifecycleValidatorHelper
|
||||
$sInstancePrefix = str_replace(' ', '', $sInstancePrefix);
|
||||
|
||||
$this->sInstancePrefix = $sInstancePrefix;
|
||||
$this->sGeneratedClass = $this->sInstancePrefix . static::DEFAULT_GENERATED_CLASS;
|
||||
$this->sGeneratedClass = $this->sInstancePrefix.static::DEFAULT_GENERATED_CLASS;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -114,7 +138,7 @@ class LifecycleValidatorHelper
|
||||
* Initializes the LifecycleValidator by generating and caching the lifecycles compilation in the $this->sCachePath.$this->sFilename file.
|
||||
*
|
||||
* @param \DOMNodeList $oNodes
|
||||
*
|
||||
*
|
||||
* @throws \DOMFormatException
|
||||
* @throws \Exception
|
||||
*/
|
||||
@@ -126,7 +150,7 @@ class LifecycleValidatorHelper
|
||||
$this->sCachePath = utils::GetCachePath();
|
||||
}
|
||||
// Building full pathname for file
|
||||
$sFilePath = $this->sCachePath . $this->sFilename;
|
||||
$sFilePath = $this->sCachePath.$this->sFilename;
|
||||
|
||||
// Creating file if not existing
|
||||
// Note: This is a temporary cache system, it should soon evolve to a cache provider (fs, apc, memcache, ...)
|
||||
@@ -137,7 +161,8 @@ class LifecycleValidatorHelper
|
||||
// This will be used to know which classes have been set, so we can set the missing ones.
|
||||
$aProfileClasses = array();
|
||||
// Iterating over the class nodes
|
||||
foreach ($oNodes as $oClassNode)
|
||||
/** @var \Combodo\iTop\DesignElement $oClassNode */
|
||||
foreach ($oNodes as $oClassNode)
|
||||
{
|
||||
// Retrieving mandatory class id attribute
|
||||
$sClass = $oClassNode->getAttribute('id');
|
||||
@@ -147,78 +172,80 @@ class LifecycleValidatorHelper
|
||||
}
|
||||
|
||||
// Retrieving lifecycle node of the class
|
||||
$oLifecycleNode = $oClassNode->GetOptionalElement('lifecycle');
|
||||
if($oLifecycleNode !== null)
|
||||
{
|
||||
// Iterating over scope nodes of the class
|
||||
$oStimuliNode = $oLifecycleNode->GetOptionalElement('stimuli');
|
||||
if ($oStimuliNode !== null)
|
||||
{
|
||||
foreach ($oStimuliNode->GetNodes('./stimulus') as $oStimulusNode)
|
||||
{
|
||||
// Retrieving mandatory scope id attribute
|
||||
$sStimulusId = $oStimulusNode->getAttribute('id');
|
||||
if ($sStimulusId === '')
|
||||
{
|
||||
throw new DOMFormatException('Stimulus tag must have an id attribute.', null, null, $oStimulusNode);
|
||||
}
|
||||
$oLifecycleNode = $oClassNode->GetOptionalElement('lifecycle');
|
||||
if ($oLifecycleNode !== null)
|
||||
{
|
||||
// Iterating over scope nodes of the class
|
||||
$oStimuliNode = $oLifecycleNode->GetOptionalElement('stimuli');
|
||||
if ($oStimuliNode !== null)
|
||||
{
|
||||
/** @var \Combodo\iTop\DesignElement $oStimulusNode */
|
||||
foreach ($oStimuliNode->GetNodes('./stimulus') as $oStimulusNode)
|
||||
{
|
||||
// Retrieving mandatory scope id attribute
|
||||
$sStimulusId = $oStimulusNode->getAttribute('id');
|
||||
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();
|
||||
// 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)
|
||||
{
|
||||
$aProfilesNames[] = $aValue['name'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($oProfilesNode->GetNodes('./denied_profile') as $oProfileNode)
|
||||
{
|
||||
// Retrieving mandatory profile id attribute
|
||||
$sProfileId = $oProfileNode->getAttribute('id');
|
||||
if ($sProfileId === '')
|
||||
{
|
||||
throw new DOMFormatException('Profile tag must have an id attribute.', null, null, $oProfileNode);
|
||||
}
|
||||
$aProfilesNames[] = $sProfileId;
|
||||
}
|
||||
}
|
||||
// Retrieving profiles for the stimulus
|
||||
$oProfilesNode = $oStimulusNode->GetOptionalElement('denied_profiles');
|
||||
$aProfilesNames = array();
|
||||
// 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)
|
||||
{
|
||||
$aProfilesNames[] = $aValue['name'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/** @var \Combodo\iTop\DesignElement $oProfileNode */
|
||||
foreach ($oProfilesNode->GetNodes('./denied_profile') as $oProfileNode)
|
||||
{
|
||||
// Retrieving mandatory profile id attribute
|
||||
$sProfileId = $oProfileNode->getAttribute('id');
|
||||
if ($sProfileId === '')
|
||||
{
|
||||
throw new DOMFormatException('Profile tag must have an id attribute.', null, null, $oProfileNode);
|
||||
}
|
||||
$aProfilesNames[] = $sProfileId;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
foreach ($aProfilesNames as $sProfileName)
|
||||
{
|
||||
// Stimulus profile id
|
||||
$iProfileId = $this->GetProfileIdFromProfileName($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();
|
||||
}
|
||||
// - Adding stimulus if not already present
|
||||
if(!in_array($sStimulusId, $aProfiles[$sMatrixPrefix]))
|
||||
{
|
||||
$aProfiles[$sMatrixPrefix][] = $sStimulusId;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
// - Adding stimulus if not already present
|
||||
if (!in_array($sStimulusId, $aProfiles[$sMatrixPrefix]))
|
||||
{
|
||||
$aProfiles[$sMatrixPrefix][] = $sStimulusId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aProfileClasses[] = $sClass;
|
||||
}
|
||||
}
|
||||
$aProfileClasses[] = $sClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Filling the array with missing classes from MetaModel, so we can have an inheritance principle on the stimuli
|
||||
// For each class explicitly given in the stimuli, we check if its child classes were also in the stimuli :
|
||||
// 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>
|
||||
//
|
||||
// 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)
|
||||
@@ -230,11 +257,11 @@ class LifecycleValidatorHelper
|
||||
{
|
||||
$iProfileId = $iKey;
|
||||
|
||||
// If the current profile has scope for that class in that mode, we duplicate it
|
||||
if (isset($aProfiles[$iProfileId . '_' . $sProfileClass]))
|
||||
{
|
||||
$aProfiles[$iProfileId . '_' . $sChildClass] = $aProfiles[$iProfileId . '_' . $sProfileClass];
|
||||
}
|
||||
// If the current profile has scope for that class in that mode, we duplicate it
|
||||
if (isset($aProfiles[$iProfileId.'_'.$sProfileClass]))
|
||||
{
|
||||
$aProfiles[$iProfileId.'_'.$sChildClass] = $aProfiles[$iProfileId.'_'.$sProfileClass];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -262,63 +289,63 @@ class LifecycleValidatorHelper
|
||||
|
||||
if (!class_exists($this->sGeneratedClass))
|
||||
{
|
||||
require_once $this->sCachePath . $this->sFilename;
|
||||
require_once $this->sCachePath.$this->sFilename;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of available stimuli for the $sProfile for the class $sClass
|
||||
*
|
||||
* @param string $sProfile
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return \DBSearch
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
/**
|
||||
* Returns an array of available stimuli for the $sProfile for the class $sClass
|
||||
*
|
||||
* @param string $sProfile
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetStimuliForProfile($sProfile, $sClass)
|
||||
{
|
||||
return $this->GetStimuliForProfiles(array($sProfile), $sClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of available stimuli for the $aProfiles for the class $sClass.
|
||||
* Profiles are a OR condition.
|
||||
*
|
||||
* @param array $aProfiles
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return \DBSearch
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
/**
|
||||
* Returns an array of available stimuli for the $aProfiles for the class $sClass.
|
||||
* Profiles are a OR condition.
|
||||
*
|
||||
* @param array $aProfiles
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetStimuliForProfiles($aProfiles, $sClass)
|
||||
{
|
||||
$aStimuli = array();
|
||||
|
||||
// Preparing available stimuli
|
||||
foreach(MetaModel::EnumStimuli($sClass) as $sStimulusCode => $aData)
|
||||
{
|
||||
$aStimuli[$sStimulusCode] = true;
|
||||
}
|
||||
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $aData)
|
||||
{
|
||||
$aStimuli[$sStimulusCode] = true;
|
||||
}
|
||||
|
||||
// Iterating on profiles to retrieving the different OQLs parts
|
||||
foreach ($aProfiles as $sProfile)
|
||||
{
|
||||
// Retrieving matrix informtions
|
||||
// Retrieving matrix information
|
||||
$iProfileId = $this->GetProfileIdFromProfileName($sProfile);
|
||||
|
||||
// Retrieving profile stimuli
|
||||
$sLifecycleValuesClass = $this->sGeneratedClass;
|
||||
$aProfileMatrix = $sLifecycleValuesClass::GetProfileStimuli($iProfileId, $sClass);
|
||||
|
||||
foreach($aProfileMatrix as $sStimulusCode)
|
||||
{
|
||||
if(array_key_exists($sStimulusCode, $aStimuli))
|
||||
{
|
||||
unset($aStimuli[$sStimulusCode]);
|
||||
}
|
||||
}
|
||||
foreach ($aProfileMatrix as $sStimulusCode)
|
||||
{
|
||||
if (array_key_exists($sStimulusCode, $aStimuli))
|
||||
{
|
||||
unset($aStimuli[$sStimulusCode]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array_keys($aStimuli);
|
||||
@@ -328,9 +355,9 @@ class LifecycleValidatorHelper
|
||||
* Returns the profile id from a string being either a constant or its name.
|
||||
*
|
||||
* @param string $sProfile
|
||||
*
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function GetProfileIdFromProfileName($sProfile)
|
||||
@@ -366,7 +393,7 @@ class LifecycleValidatorHelper
|
||||
// If profile was not found from its name or from a constant, we throw an exception
|
||||
if ($iProfileId === null)
|
||||
{
|
||||
throw new Exception('Lifecycle validator : Could not find "' . $sProfile . '" in the profiles list');
|
||||
throw new Exception('Lifecycle validator : Could not find "'.$sProfile.'" in the profiles list');
|
||||
}
|
||||
|
||||
return $iProfileId;
|
||||
@@ -376,7 +403,7 @@ class LifecycleValidatorHelper
|
||||
* Returns a string containing the generated PHP class for the compiled scopes
|
||||
*
|
||||
* @param array $aProfiles
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function BuildPHPClass($aProfiles = array())
|
||||
@@ -417,6 +444,7 @@ class $sClassName
|
||||
}
|
||||
|
||||
EOF;
|
||||
|
||||
return $sPHP;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,13 +46,16 @@ use UserRights;
|
||||
* Class ObjectFormHandlerHelper
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Helper
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class ObjectFormHandlerHelper
|
||||
{
|
||||
/** @var string ENUM_MODE_VIEW */
|
||||
const ENUM_MODE_VIEW = 'view';
|
||||
/** @var string ENUM_MODE_EDIT */
|
||||
const ENUM_MODE_EDIT = 'edit';
|
||||
/** @var string ENUM_MODE_CREATE */
|
||||
const ENUM_MODE_CREATE = 'create';
|
||||
|
||||
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper */
|
||||
@@ -145,8 +148,10 @@ class ObjectFormHandlerHelper
|
||||
// Retrieve action rules information to auto-fill the form if available
|
||||
// Preparing object
|
||||
$this->oContextManipulator->PrepareObject($aActionRules, $oObject);
|
||||
$aPrefillFormParam = array( 'user' => $_SESSION["auth_user"],
|
||||
'origin' => 'portal');
|
||||
$aPrefillFormParam = array(
|
||||
'user' => $_SESSION["auth_user"],
|
||||
'origin' => 'portal',
|
||||
);
|
||||
$oObject->PrefillForm('creation_from_0', $aPrefillFormParam);
|
||||
}
|
||||
else
|
||||
@@ -170,7 +175,7 @@ class ObjectFormHandlerHelper
|
||||
$aStimuli = Metamodel::EnumStimuli($sObjectClass);
|
||||
foreach ($oObject->EnumTransitions() as $sStimulusCode => $aTransitionDef)
|
||||
{
|
||||
if($this->oSecurityHelper->IsStimulusAllowed($sStimulusCode, $sObjectClass, $oSetToCheckRights))
|
||||
if ($this->oSecurityHelper->IsStimulusAllowed($sStimulusCode, $sObjectClass, $oSetToCheckRights))
|
||||
{
|
||||
$aFormData['buttons']['transitions'][$sStimulusCode] = $aStimuli[$sStimulusCode]->GetLabel();
|
||||
}
|
||||
@@ -180,15 +185,15 @@ class ObjectFormHandlerHelper
|
||||
/** @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)
|
||||
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)
|
||||
if ($oMenuItem instanceof JSButtonItem)
|
||||
{
|
||||
$aFormData['buttons']['actions'][] = $oMenuItem->GetMenuItem() + array('js_files' => $oMenuItem->GetLinkedScripts());
|
||||
}
|
||||
elseif($oMenuItem instanceof URLButtonItem)
|
||||
elseif ($oMenuItem instanceof URLButtonItem)
|
||||
{
|
||||
$aFormData['buttons']['links'][] = $oMenuItem->GetMenuItem();
|
||||
}
|
||||
@@ -197,11 +202,11 @@ 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');
|
||||
}
|
||||
@@ -225,7 +230,7 @@ class ObjectFormHandlerHelper
|
||||
// Note : We might need to distinguish form & renderer endpoints
|
||||
if (in_array($sMode, array('create', 'edit', 'view')))
|
||||
{
|
||||
$sFormEndpoint = $this->oUrlGenerator->generate('p_object_' . $sMode, array('sObjectClass' => $sObjectClass, 'sObjectId' => $sObjectId));
|
||||
$sFormEndpoint = $this->oUrlGenerator->generate('p_object_'.$sMode, array('sObjectClass' => $sObjectClass, 'sObjectId' => $sObjectId));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -252,9 +257,9 @@ class ObjectFormHandlerHelper
|
||||
// Update / Submit / Cancel
|
||||
$sFormManagerClass = $this->oRequestManipulator->ReadParam('formmanager_class', '', FILTER_UNSAFE_RAW);
|
||||
$sFormManagerData = $this->oRequestManipulator->ReadParam('formmanager_data', '', FILTER_UNSAFE_RAW);
|
||||
if ( empty($sFormManagerClass) || empty($sFormManagerData) )
|
||||
if (empty($sFormManagerClass) || empty($sFormManagerData))
|
||||
{
|
||||
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Parameters formmanager_class and formamanager_data must be defined.');
|
||||
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Parameters formmanager_class and formamanager_data must be defined.');
|
||||
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Parameters formmanager_class and formmanager_data must be defined.');
|
||||
}
|
||||
|
||||
@@ -280,7 +285,7 @@ class ObjectFormHandlerHelper
|
||||
'currentValues' => $this->oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW),
|
||||
'attachmentIds' => $this->oRequestManipulator->ReadParam('attachment_ids', array(), FILTER_UNSAFE_RAW),
|
||||
'formProperties' => $aFormProperties,
|
||||
'applyStimulus' => $this->oRequestManipulator->ReadParam('apply_stimulus', null)
|
||||
'applyStimulus' => $this->oRequestManipulator->ReadParam('apply_stimulus', null),
|
||||
)
|
||||
);
|
||||
if ($aFormData['validation']['valid'] === true)
|
||||
@@ -329,7 +334,7 @@ class ObjectFormHandlerHelper
|
||||
$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);
|
||||
@@ -362,19 +367,32 @@ class ObjectFormHandlerHelper
|
||||
return $aFormData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sId
|
||||
* @param $sTwigString
|
||||
* @param $aData
|
||||
*
|
||||
* @return string
|
||||
* @throws \Twig\Error\LoaderError
|
||||
* @throws \Twig\Error\RuntimeError
|
||||
* @throws \Twig\Error\SyntaxError
|
||||
* @throws \Twig_Error_Loader
|
||||
* @throws \Twig_Error_Runtime
|
||||
* @throws \Twig_Error_Syntax
|
||||
*/
|
||||
public function RenderFormFromTwig($sId, $sTwigString, $aData)
|
||||
{
|
||||
// Creating sandbox twig env. to load and test the custom form template
|
||||
$oTwig = new Twig_Environment(new Twig_Loader_Array( array($sId => $sTwigString) ));
|
||||
$oTwig = new Twig_Environment(new Twig_Loader_Array(array($sId => $sTwigString)));
|
||||
|
||||
// Manually registering filters and functions as we didn't find how to do it automatically
|
||||
$aFilters = $this->oAppExtension->getFilters();
|
||||
foreach($aFilters as $oFilter)
|
||||
foreach ($aFilters as $oFilter)
|
||||
{
|
||||
$oTwig->addFilter($oFilter);
|
||||
}
|
||||
$aFunctions = $this->oAppExtension->getFunctions();
|
||||
foreach($aFunctions as $oFunction)
|
||||
foreach ($aFunctions as $oFunction)
|
||||
{
|
||||
$oTwig->addFunction($oFunction);
|
||||
}
|
||||
|
||||
@@ -30,91 +30,91 @@ use Symfony\Component\HttpFoundation\RequestStack;
|
||||
* Handle basic requests manipulation.
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @since 2.5.1
|
||||
* @since 2.5.1
|
||||
*/
|
||||
class RequestManipulatorHelper
|
||||
{
|
||||
/** @var \Symfony\Component\HttpFoundation\RequestStack $oRequestStack */
|
||||
protected $oRequestStack;
|
||||
/** @var \Symfony\Component\HttpFoundation\RequestStack $oRequestStack */
|
||||
protected $oRequestStack;
|
||||
|
||||
/**
|
||||
* RequestManipulatorHelper constructor.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\RequestStack $oRequestStack
|
||||
*/
|
||||
public function __construct(RequestStack $oRequestStack)
|
||||
{
|
||||
$this->oRequestStack = $oRequestStack;
|
||||
}
|
||||
/**
|
||||
* RequestManipulatorHelper constructor.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\RequestStack $oRequestStack
|
||||
*/
|
||||
public function __construct(RequestStack $oRequestStack)
|
||||
{
|
||||
$this->oRequestStack = $oRequestStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\HttpFoundation\Request
|
||||
*/
|
||||
public function GetCurrentRequest()
|
||||
{
|
||||
return $this->oRequestStack->getCurrentRequest();
|
||||
}
|
||||
/**
|
||||
* @return \Symfony\Component\HttpFoundation\Request
|
||||
*/
|
||||
public function GetCurrentRequest()
|
||||
{
|
||||
return $this->oRequestStack->getCurrentRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the request has a $sKey parameter.
|
||||
* This looks in the GET arguments first, then PATH and finally the POST data.
|
||||
*
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function HasParam($sKey)
|
||||
{
|
||||
if ($this->GetCurrentRequest()->query->has($sKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Returns if the request has a $sKey parameter.
|
||||
* This looks in the GET arguments first, then PATH and finally the POST data.
|
||||
*
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function HasParam($sKey)
|
||||
{
|
||||
if ($this->GetCurrentRequest()->query->has($sKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->GetCurrentRequest()->attributes->has($sKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ($this->GetCurrentRequest()->attributes->has($sKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->GetCurrentRequest()->request->has($sKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ($this->GetCurrentRequest()->request->has($sKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the $sKey parameter from the request filtered with $iFilter.
|
||||
* This looks in the GET arguments first, then the PATH and finally the POST data.
|
||||
*
|
||||
* Note: It is inspired by the \Symfony\Component\HttpFoundation\ParameterBag::filter() function and was necessary as we sometimes have parameters that can be either in the GET/PATH/POST arguments and need to be filtered. Silex only offer the possibility to filter parameter from a single ParameterBag, so we created this helper.
|
||||
*
|
||||
* @param string $sKey
|
||||
* @param mixed $default
|
||||
* @param int $iFilter Default is FILTER_SANITIZE_STRING
|
||||
*
|
||||
* @return mixed|null
|
||||
*
|
||||
* @since 2.5.1
|
||||
*/
|
||||
public function ReadParam($sKey, $default = null, $iFilter = FILTER_SANITIZE_STRING)
|
||||
{
|
||||
if ($this->GetCurrentRequest()->query->has($sKey))
|
||||
{
|
||||
return $this->GetCurrentRequest()->query->filter($sKey, $default, $iFilter);
|
||||
}
|
||||
/**
|
||||
* Returns the $sKey parameter from the request filtered with $iFilter.
|
||||
* This looks in the GET arguments first, then the PATH and finally the POST data.
|
||||
*
|
||||
* Note: It is inspired by the \Symfony\Component\HttpFoundation\ParameterBag::filter() function and was necessary as we sometimes have parameters that can be either in the GET/PATH/POST arguments and need to be filtered. Silex only offer the possibility to filter parameter from a single ParameterBag, so we created this helper.
|
||||
*
|
||||
* @param string $sKey
|
||||
* @param mixed $default
|
||||
* @param int $iFilter Default is FILTER_SANITIZE_STRING
|
||||
*
|
||||
* @return mixed|null
|
||||
*
|
||||
* @since 2.5.1
|
||||
*/
|
||||
public function ReadParam($sKey, $default = null, $iFilter = FILTER_SANITIZE_STRING)
|
||||
{
|
||||
if ($this->GetCurrentRequest()->query->has($sKey))
|
||||
{
|
||||
return $this->GetCurrentRequest()->query->filter($sKey, $default, $iFilter);
|
||||
}
|
||||
|
||||
if ($this->GetCurrentRequest()->attributes->has($sKey))
|
||||
{
|
||||
return $this->GetCurrentRequest()->attributes->filter($sKey, $default, $iFilter);
|
||||
}
|
||||
if ($this->GetCurrentRequest()->attributes->has($sKey))
|
||||
{
|
||||
return $this->GetCurrentRequest()->attributes->filter($sKey, $default, $iFilter);
|
||||
}
|
||||
|
||||
if ($this->GetCurrentRequest()->request->has($sKey))
|
||||
{
|
||||
return $this->GetCurrentRequest()->request->filter($sKey, $default, $iFilter);
|
||||
}
|
||||
if ($this->GetCurrentRequest()->request->has($sKey))
|
||||
{
|
||||
return $this->GetCurrentRequest()->request->filter($sKey, $default, $iFilter);
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ use DOMFormatException;
|
||||
use DOMNodeList;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use ModuleDesign;
|
||||
use ProfilesConfig;
|
||||
use UserRights;
|
||||
use utils;
|
||||
@@ -41,23 +42,44 @@ use utils;
|
||||
*/
|
||||
class ScopeValidatorHelper
|
||||
{
|
||||
/** @var string ENUM_MODE_READ */
|
||||
const ENUM_MODE_READ = 'r';
|
||||
/** @var string ENUM_MODE_WRITE */
|
||||
const ENUM_MODE_WRITE = 'w';
|
||||
/** @var string ENUM_TYPE_ALLOW */
|
||||
const ENUM_TYPE_ALLOW = 'allow';
|
||||
/** @var string ENUM_TYPE_RESTRICT */
|
||||
const ENUM_TYPE_RESTRICT = 'restrict';
|
||||
|
||||
/** @var string DEFAULT_GENERATED_CLASS */
|
||||
const DEFAULT_GENERATED_CLASS = '\\PortalScopesValues';
|
||||
/** @var bool DEFAULT_IGNORE_SILOS */
|
||||
const DEFAULT_IGNORE_SILOS = false;
|
||||
|
||||
/** @var string|null $sCachePath */
|
||||
protected $sCachePath;
|
||||
/** @var string $sFilename */
|
||||
protected $sFilename;
|
||||
/** @var string $sInstancePrefix */
|
||||
protected $sInstancePrefix;
|
||||
/** @var string $sGeneratedClass */
|
||||
protected $sGeneratedClass;
|
||||
/** @var array $aProfilesMatrix */
|
||||
protected $aProfilesMatrix;
|
||||
|
||||
public function __construct(\ModuleDesign $moduleDesign, $sPortalId, $sPortalCachePath = null)
|
||||
/**
|
||||
* ScopeValidatorHelper constructor.
|
||||
*
|
||||
* @param \ModuleDesign $moduleDesign
|
||||
* @param string $sPortalId
|
||||
* @param string|null $sPortalCachePath
|
||||
*
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function __construct(ModuleDesign $moduleDesign, $sPortalId, $sPortalCachePath = null)
|
||||
{
|
||||
$this->sFilename = "{$sPortalId}.scopes.php";
|
||||
$this->sCachePath = $sPortalCachePath;
|
||||
$this->sFilename = "{$sPortalId}.scopes.php";
|
||||
$this->sCachePath = $sPortalCachePath;
|
||||
$this->sInstancePrefix = "{$sPortalId}-";
|
||||
$this->sGeneratedClass = static::DEFAULT_GENERATED_CLASS;
|
||||
$this->aProfilesMatrix = array();
|
||||
@@ -65,40 +87,41 @@ class ScopeValidatorHelper
|
||||
$this->Init($moduleDesign->GetNodes('/module_design/classes/class'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the ScopeValidator by generating and caching the scopes compilation in the $this->sCachePath.$this->sFilename file.
|
||||
*
|
||||
* @param DOMNodeList $oNodes
|
||||
* @throws DOMFormatException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function Init(DOMNodeList $oNodes)
|
||||
{
|
||||
// Checking cache path
|
||||
if ($this->sCachePath === null)
|
||||
{
|
||||
$this->sCachePath = utils::GetCachePath();
|
||||
}
|
||||
// Building full pathname for file
|
||||
$sFilePath = $this->sCachePath . $this->sFilename;
|
||||
/**
|
||||
* Initializes the ScopeValidator by generating and caching the scopes compilation in the $this->sCachePath.$this->sFilename file.
|
||||
*
|
||||
* @param DOMNodeList $oNodes
|
||||
*
|
||||
* @throws DOMFormatException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function Init(DOMNodeList $oNodes)
|
||||
{
|
||||
// Checking cache path
|
||||
if ($this->sCachePath === null)
|
||||
{
|
||||
$this->sCachePath = utils::GetCachePath();
|
||||
}
|
||||
// Building full pathname for file
|
||||
$sFilePath = $this->sCachePath.$this->sFilename;
|
||||
|
||||
// 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))
|
||||
{
|
||||
$this->InitGenerateAndWriteCache($oNodes, $sFilePath);
|
||||
}
|
||||
// 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))
|
||||
{
|
||||
$this->InitGenerateAndWriteCache($oNodes, $sFilePath);
|
||||
}
|
||||
|
||||
if (!class_exists($this->sGeneratedClass))
|
||||
{
|
||||
require_once $this->sCachePath . $this->sFilename;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
public static function EnumTypeValues()
|
||||
{
|
||||
return array(static::ENUM_TYPE_ALLOW, static::ENUM_TYPE_RESTRICT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path where to cache the compiled scopes file
|
||||
@@ -146,6 +169,7 @@ class ScopeValidatorHelper
|
||||
* This is used to create a unique scope values class in the cache directory (/data/cache-<ENV>) as there can be several instance of the portal.
|
||||
*
|
||||
* @param string $sInstancePrefix
|
||||
*
|
||||
* @return \Combodo\iTop\Portal\Helper\ScopeValidatorHelper
|
||||
*/
|
||||
public function SetInstancePrefix($sInstancePrefix)
|
||||
@@ -155,7 +179,7 @@ class ScopeValidatorHelper
|
||||
$sInstancePrefix = str_replace(' ', '', $sInstancePrefix);
|
||||
|
||||
$this->sInstancePrefix = $sInstancePrefix;
|
||||
$this->sGeneratedClass = $this->sInstancePrefix . static::DEFAULT_GENERATED_CLASS;
|
||||
$this->sGeneratedClass = $this->sInstancePrefix.static::DEFAULT_GENERATED_CLASS;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -163,35 +187,35 @@ class ScopeValidatorHelper
|
||||
/**
|
||||
* Returns the DBSearch for the $sProfile in $iAction for the class $sClass
|
||||
*
|
||||
* @param string $sProfile
|
||||
* @param string $sClass
|
||||
* @param string $sProfile
|
||||
* @param string $sClass
|
||||
* @param integer $iAction
|
||||
*
|
||||
*
|
||||
* @return \DBSearch
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function GetScopeFilterForProfile($sProfile, $sClass, $iAction = null)
|
||||
{
|
||||
return $this->GetScopeFilterForProfiles(array($sProfile), $sClass, $iAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DBSearch for the $aProfiles in $iAction for the class $sClass.
|
||||
* Profiles are a OR condition.
|
||||
*
|
||||
* @param array $aProfiles
|
||||
* @param string $sClass
|
||||
* @param integer $iAction
|
||||
*
|
||||
* @return \DBSearch
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
/**
|
||||
* Returns the DBSearch for the $aProfiles in $iAction for the class $sClass.
|
||||
* Profiles are a OR condition.
|
||||
*
|
||||
* @param array $aProfiles
|
||||
* @param string $sClass
|
||||
* @param integer $iAction
|
||||
*
|
||||
* @return \DBSearch
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function GetScopeFilterForProfiles($aProfiles, $sClass, $iAction = null)
|
||||
{
|
||||
$oSearch = null;
|
||||
@@ -254,18 +278,18 @@ class ScopeValidatorHelper
|
||||
return $oSearch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the scope query (view or edit depending on $sAction) for $sClass to the $oQuery.
|
||||
*
|
||||
* @param \DBSearch $oQuery
|
||||
* @param string $sClass
|
||||
* @param int $sAction
|
||||
*
|
||||
* @return bool true if scope exists, false if scope is null
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
/**
|
||||
* Add the scope query (view or edit depending on $sAction) for $sClass to the $oQuery.
|
||||
*
|
||||
* @param \DBSearch $oQuery
|
||||
* @param string $sClass
|
||||
* @param int $sAction
|
||||
*
|
||||
* @return bool true if scope exists, false if scope is null
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function AddScopeToQuery(DBSearch &$oQuery, $sClass, $sAction = UR_ACTION_READ)
|
||||
{
|
||||
$oScopeQuery = $this->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sClass, $sAction);
|
||||
@@ -284,16 +308,16 @@ class ScopeValidatorHelper
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if at least one of the $aProfiles has the ignore_silos flag set to true for the $sClass.
|
||||
*
|
||||
* @param array $aProfiles
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
/**
|
||||
* Returns true if at least one of the $aProfiles has the ignore_silos flag set to true for the $sClass.
|
||||
*
|
||||
* @param array $aProfiles
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function IsAllDataAllowedForScope($aProfiles, $sClass)
|
||||
{
|
||||
$bIgnoreSilos = false;
|
||||
@@ -301,7 +325,7 @@ class ScopeValidatorHelper
|
||||
// Iterating on profiles to retrieving the different OQLs parts
|
||||
foreach ($aProfiles as $sProfile)
|
||||
{
|
||||
// Retrieving matrix informtions
|
||||
// Retrieving matrix information
|
||||
$iProfileId = $this->GetProfileIdFromProfileName($sProfile);
|
||||
|
||||
// Retrieving profile OQLs
|
||||
@@ -324,9 +348,9 @@ class ScopeValidatorHelper
|
||||
* Returns the profile id from a string being either a constant or its name.
|
||||
*
|
||||
* @param string $sProfile
|
||||
*
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function GetProfileIdFromProfileName($sProfile)
|
||||
@@ -362,7 +386,7 @@ class ScopeValidatorHelper
|
||||
// If profile was not found from its name or from a constant, we throw an exception
|
||||
if ($iProfileId === null)
|
||||
{
|
||||
throw new Exception('Scope validator : Could not find "' . $sProfile . '" in the profiles list');
|
||||
throw new Exception('Scope validator : Could not find "'.$sProfile.'" in the profiles list');
|
||||
}
|
||||
|
||||
return $iProfileId;
|
||||
@@ -372,6 +396,7 @@ class ScopeValidatorHelper
|
||||
* Returns a string containing the generated PHP class for the compiled scopes
|
||||
*
|
||||
* @param array $aProfiles
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function BuildPHPClass($aProfiles = array())
|
||||
@@ -415,212 +440,251 @@ EOF;
|
||||
return $sPHP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DOMNodeList $oNodes
|
||||
* @param $sFilePath
|
||||
*
|
||||
* @throws DOMFormatException
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
protected function InitGenerateAndWriteCache(DOMNodeList $oNodes, $sFilePath)
|
||||
{
|
||||
// - Build php array from xml
|
||||
$aProfiles = array();
|
||||
// This will be used to know which classes have been set, so we can set the missing ones.
|
||||
$aProfileClasses = array();
|
||||
// Iterating over the class nodes
|
||||
foreach ($oNodes as $oClassNode) {
|
||||
// retrieving mandatory class id attribute
|
||||
$sClass = $oClassNode->getAttribute('id');
|
||||
if ($sClass === '') {
|
||||
throw new DOMFormatException('Class tag must have an id attribute.', null, null, $oClassNode);
|
||||
}
|
||||
/**
|
||||
* @param DOMNodeList $oNodes
|
||||
* @param string $sFilePath
|
||||
*
|
||||
* @throws DOMFormatException
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function InitGenerateAndWriteCache(DOMNodeList $oNodes, $sFilePath)
|
||||
{
|
||||
// - Build php array from xml
|
||||
$aProfiles = array();
|
||||
// This will be used to know which classes have been set, so we can set the missing ones.
|
||||
$aProfileClasses = array();
|
||||
// Iterating over the class nodes
|
||||
/** @var \Combodo\iTop\DesignElement $oClassNode */
|
||||
foreach ($oNodes as $oClassNode)
|
||||
{
|
||||
// retrieving mandatory class id attribute
|
||||
$sClass = $oClassNode->getAttribute('id');
|
||||
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) {
|
||||
foreach ($oScopesNode->GetNodes('./scope') as $oScopeNode) {
|
||||
// Retrieving mandatory scope id attribute
|
||||
$sScopeId = $oScopeNode->getAttribute('id');
|
||||
if ($sScopeId === '') {
|
||||
throw new DOMFormatException('Scope tag must have an id attribute.', null, null, $oScopeNode);
|
||||
}
|
||||
// Iterating over scope nodes of the class
|
||||
$oScopesNode = $oClassNode->GetOptionalElement('scopes');
|
||||
if ($oScopesNode !== null)
|
||||
{
|
||||
/** @var \Combodo\iTop\DesignElement $oScopeNode */
|
||||
foreach ($oScopesNode->GetNodes('./scope') as $oScopeNode)
|
||||
{
|
||||
// Retrieving mandatory scope id attribute
|
||||
$sScopeId = $oScopeNode->getAttribute('id');
|
||||
if ($sScopeId === '')
|
||||
{
|
||||
throw new DOMFormatException('Scope tag must have an id attribute.', null, null, $oScopeNode);
|
||||
}
|
||||
|
||||
// Retrieving the type of query
|
||||
// Note : This has been disabled as we don't want deny rules for now
|
||||
// $oOqlViewTypeNode = $oClassNode->GetOptionalElement('oql_view_type');
|
||||
// $sOqlViewType = ($oOqlViewTypeNode !== null && ($oOqlViewTypeNode->GetText() === static::ENUM_TYPE_RESTRICT)) ? static::ENUM_TYPE_RESTRICT : static::ENUM_TYPE_ALLOW;
|
||||
$sOqlViewType = static::ENUM_TYPE_ALLOW;
|
||||
// Retrieving the view query
|
||||
$oOqlViewNode = $oScopeNode->GetUniqueElement('oql_view');
|
||||
$sOqlView = $oOqlViewNode->GetText();
|
||||
if ($sOqlView === null) {
|
||||
throw new DOMFormatException(
|
||||
'Scope tag in class must have a not empty oql_view tag',
|
||||
null,
|
||||
null,
|
||||
$oScopeNode
|
||||
);
|
||||
}
|
||||
// Retrieving the edit query
|
||||
$oOqlEditNode = $oScopeNode->GetOptionalElement('oql_edit');
|
||||
$sOqlEdit = (($oOqlEditNode !== null) && ($oOqlEditNode->GetText(
|
||||
) !== null)) ? $oOqlEditNode->GetText() : null;
|
||||
// Retrieving ignore allowed org flag
|
||||
$oIgnoreSilosNode = $oScopeNode->GetOptionalElement('ignore_silos');
|
||||
$bIgnoreSilos = (($oIgnoreSilosNode !== null) && ($oIgnoreSilosNode->GetText(
|
||||
) === 'true')) ? true : static::DEFAULT_IGNORE_SILOS;
|
||||
// Retrieving the type of query
|
||||
// Note : This has been disabled as we don't want deny rules for now
|
||||
// $oOqlViewTypeNode = $oClassNode->GetOptionalElement('oql_view_type');
|
||||
// $sOqlViewType = ($oOqlViewTypeNode !== null && ($oOqlViewTypeNode->GetText() === static::ENUM_TYPE_RESTRICT)) ? static::ENUM_TYPE_RESTRICT : static::ENUM_TYPE_ALLOW;
|
||||
$sOqlViewType = static::ENUM_TYPE_ALLOW;
|
||||
// Retrieving the view query
|
||||
$oOqlViewNode = $oScopeNode->GetUniqueElement('oql_view');
|
||||
$sOqlView = $oOqlViewNode->GetText();
|
||||
if ($sOqlView === null)
|
||||
{
|
||||
throw new DOMFormatException(
|
||||
'Scope tag in class must have a not empty oql_view tag',
|
||||
null,
|
||||
null,
|
||||
$oScopeNode
|
||||
);
|
||||
}
|
||||
// Retrieving the edit query
|
||||
$oOqlEditNode = $oScopeNode->GetOptionalElement('oql_edit');
|
||||
$sOqlEdit = (($oOqlEditNode !== null) && ($oOqlEditNode->GetText() !== null)) ? $oOqlEditNode->GetText() : null;
|
||||
// Retrieving ignore allowed org flag
|
||||
$oIgnoreSilosNode = $oScopeNode->GetOptionalElement('ignore_silos');
|
||||
$bIgnoreSilos = (($oIgnoreSilosNode !== null) && ($oIgnoreSilosNode->GetText() === 'true')) ? true : static::DEFAULT_IGNORE_SILOS;
|
||||
|
||||
// Retrieving profiles for the scope
|
||||
$oProfilesNode = $oScopeNode->GetOptionalElement('allowed_profiles');
|
||||
$aProfilesNames = array();
|
||||
// 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) {
|
||||
$aProfilesNames[] = $aValue['name'];
|
||||
}
|
||||
} else {
|
||||
foreach ($oProfilesNode->GetNodes('./allowed_profile') as $oProfileNode) {
|
||||
// Retrieving mandatory profile id attribute
|
||||
$sProfileId = $oProfileNode->getAttribute('id');
|
||||
if ($sProfileId === '') {
|
||||
throw new DOMFormatException(
|
||||
'Scope tag must have an id attribute.',
|
||||
null,
|
||||
null,
|
||||
$oProfileNode
|
||||
);
|
||||
}
|
||||
$aProfilesNames[] = $sProfileId;
|
||||
}
|
||||
}
|
||||
// Retrieving profiles for the scope
|
||||
$oProfilesNode = $oScopeNode->GetOptionalElement('allowed_profiles');
|
||||
$aProfilesNames = array();
|
||||
// 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)
|
||||
{
|
||||
$aProfilesNames[] = $aValue['name'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/** @var \Combodo\iTop\DesignElement $oProfileNode */
|
||||
foreach ($oProfilesNode->GetNodes('./allowed_profile') as $oProfileNode)
|
||||
{
|
||||
// Retrieving mandatory profile id attribute
|
||||
$sProfileId = $oProfileNode->getAttribute('id');
|
||||
if ($sProfileId === '')
|
||||
{
|
||||
throw new DOMFormatException(
|
||||
'Scope tag must have an id attribute.',
|
||||
null,
|
||||
null,
|
||||
$oProfileNode
|
||||
);
|
||||
}
|
||||
$aProfilesNames[] = $sProfileId;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
foreach ($aProfilesNames as $sProfileName) {
|
||||
// Scope profile id
|
||||
$iProfileId = $this->GetProfileIdFromProfileName($sProfileName);
|
||||
//
|
||||
foreach ($aProfilesNames as $sProfileName)
|
||||
{
|
||||
// Scope 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.'_';
|
||||
// - View query
|
||||
$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]
|
||||
)) {
|
||||
$oExistingFilter = DBSearch::FromOQL(
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ][$sOqlViewType]
|
||||
);
|
||||
$aFilters = array($oExistingFilter, $oViewFilter);
|
||||
$oResFilter = new DBUnionSearch($aFilters);
|
||||
// Now that we have the queries infos, we are going to build the queries for that profile / class
|
||||
$sMatrixPrefix = $iProfileId.'_'.$sClass.'_';
|
||||
// - View query
|
||||
$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]
|
||||
))
|
||||
{
|
||||
$oExistingFilter = DBSearch::FromOQL(
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ][$sOqlViewType]
|
||||
);
|
||||
$aFilters = array($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) {
|
||||
$bIgnoreSilos = true;
|
||||
}
|
||||
} else {
|
||||
$oResFilter = $oViewFilter;
|
||||
}
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ] = array(
|
||||
$sOqlViewType => $oResFilter->ToOQL(),
|
||||
'ignore_silos' => $bIgnoreSilos
|
||||
);
|
||||
// - Edit query
|
||||
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) {
|
||||
// Do not intersect, edit query is identical to view query
|
||||
} else {
|
||||
if (($oEditFilter->GetClass() === $oViewFilter->GetClass()) && $oEditFilter->IsAny()) {
|
||||
$oEditFilter = $oViewFilter;
|
||||
// Do not intersect, edit query is identical to view query
|
||||
} else {
|
||||
// Intersect
|
||||
$oEditFilter = $oViewFilter->Intersect($oEditFilter);
|
||||
}
|
||||
}
|
||||
// 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)
|
||||
{
|
||||
$bIgnoreSilos = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oResFilter = $oViewFilter;
|
||||
}
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ] = array(
|
||||
$sOqlViewType => $oResFilter->ToOQL(),
|
||||
'ignore_silos' => $bIgnoreSilos,
|
||||
);
|
||||
// - Edit query
|
||||
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)
|
||||
{
|
||||
// Do not intersect, edit query is identical to view query
|
||||
}
|
||||
else
|
||||
{
|
||||
if (($oEditFilter->GetClass() === $oViewFilter->GetClass()) && $oEditFilter->IsAny())
|
||||
{
|
||||
$oEditFilter = $oViewFilter;
|
||||
// Do not intersect, edit query is identical to view query
|
||||
}
|
||||
else
|
||||
{
|
||||
// Intersect
|
||||
$oEditFilter = $oViewFilter->Intersect($oEditFilter);
|
||||
}
|
||||
}
|
||||
|
||||
// ... 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]
|
||||
)) {
|
||||
$oExistingFilter = DBSearch::FromOQL(
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE][$sOqlViewType]
|
||||
);
|
||||
$aFilters = array($oExistingFilter, $oEditFilter);
|
||||
$oResFilter = new DBUnionSearch($aFilters);
|
||||
} else {
|
||||
$oResFilter = $oEditFilter;
|
||||
}
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE] = array(
|
||||
$sOqlViewType => $oResFilter->ToOQL(),
|
||||
'ignore_silos' => $bIgnoreSilos
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ... 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]
|
||||
))
|
||||
{
|
||||
$oExistingFilter = DBSearch::FromOQL(
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE][$sOqlViewType]
|
||||
);
|
||||
$aFilters = array($oExistingFilter, $oEditFilter);
|
||||
$oResFilter = new DBUnionSearch($aFilters);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oResFilter = $oEditFilter;
|
||||
}
|
||||
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE] = array(
|
||||
$sOqlViewType => $oResFilter->ToOQL(),
|
||||
'ignore_silos' => $bIgnoreSilos,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aProfileClasses[] = $sClass;
|
||||
}
|
||||
}
|
||||
$aProfileClasses[] = $sClass;
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// 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) {
|
||||
$iProfileId = $iKey;
|
||||
foreach (array(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])) {
|
||||
$aTmpProfile = $aProfiles[$iProfileId.'_'.$sProfileClass.'_'.$sAction];
|
||||
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))) {
|
||||
$oTmpFilter = DBSearch::FromOQL($sOql);
|
||||
$oTmpFilter->ChangeClass($sChildClass);
|
||||
// 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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
$iProfileId = $iKey;
|
||||
foreach (array(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]))
|
||||
{
|
||||
$aTmpProfile = $aProfiles[$iProfileId.'_'.$sProfileClass.'_'.$sAction];
|
||||
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)))
|
||||
{
|
||||
$oTmpFilter = DBSearch::FromOQL($sOql);
|
||||
$oTmpFilter->ChangeClass($sChildClass);
|
||||
|
||||
$aTmpProfile[$sType] = $oTmpFilter->ToOQL();
|
||||
}
|
||||
}
|
||||
$aTmpProfile[$sType] = $oTmpFilter->ToOQL();
|
||||
}
|
||||
}
|
||||
|
||||
$aProfiles[$iProfileId.'_'.$sChildClass.'_'.$sAction] = $aTmpProfile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$aProfiles[$iProfileId.'_'.$sChildClass.'_'.$sAction] = $aTmpProfile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// - Build php class
|
||||
$sPHP = $this->BuildPHPClass($aProfiles);
|
||||
// - Build php class
|
||||
$sPHP = $this->BuildPHPClass($aProfiles);
|
||||
|
||||
// - Write file on disk
|
||||
// - Creating dir if necessary
|
||||
if (!is_dir($this->sCachePath)) {
|
||||
mkdir($this->sCachePath, 0777, true);
|
||||
}
|
||||
// -- Then creating the file
|
||||
$ret = file_put_contents($sFilePath, $sPHP);
|
||||
if ($ret === false) {
|
||||
$iLen = strlen($sPHP);
|
||||
$fFree = @disk_free_space(dirname($sFilePath));
|
||||
$aErr = error_get_last();
|
||||
throw new Exception(
|
||||
"Failed to write '$sFilePath'. Last error: '{$aErr['message']}', content to write: $iLen bytes, available free space on disk: $fFree."
|
||||
);
|
||||
}
|
||||
}
|
||||
// - Write file on disk
|
||||
// - Creating dir if necessary
|
||||
if (!is_dir($this->sCachePath))
|
||||
{
|
||||
mkdir($this->sCachePath, 0777, true);
|
||||
}
|
||||
// -- Then creating the file
|
||||
$ret = file_put_contents($sFilePath, $sPHP);
|
||||
if ($ret === false)
|
||||
{
|
||||
$iLen = strlen($sPHP);
|
||||
$fFree = @disk_free_space(dirname($sFilePath));
|
||||
$aErr = error_get_last();
|
||||
throw new Exception(
|
||||
"Failed to write '$sFilePath'. Last error: '{$aErr['message']}', content to write: $iLen bytes, available free space on disk: $fFree."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
namespace Combodo\iTop\Portal\Helper;
|
||||
|
||||
use Silex\Application;
|
||||
use UserRights;
|
||||
use IssueLog;
|
||||
use MetaModel;
|
||||
@@ -35,22 +34,21 @@ use BinaryExpression;
|
||||
*
|
||||
* Handle security checks through the different layers (portal scopes, iTop silos, user rights)
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @package Combodo\iTop\Portal\Helper
|
||||
* @since 2.3.0
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
*/
|
||||
class SecurityHelper
|
||||
{
|
||||
public static $aAllowedScopeObjectsCache = array(
|
||||
UR_ACTION_READ => array(),
|
||||
UR_ACTION_MODIFY => array(),
|
||||
);
|
||||
/** @var array $aAllowedScopeObjectsCache */
|
||||
public static $aAllowedScopeObjectsCache = array(
|
||||
UR_ACTION_READ => array(),
|
||||
UR_ACTION_MODIFY => array(),
|
||||
);
|
||||
|
||||
/**
|
||||
* @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper
|
||||
*/
|
||||
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator */
|
||||
private $oScopeValidator;
|
||||
/**
|
||||
* @var \Combodo\iTop\Portal\Helper\LifecycleValidatorHelper
|
||||
*/
|
||||
/** @var \Combodo\iTop\Portal\Helper\LifecycleValidatorHelper $oLifecycleValidator */
|
||||
private $oLifecycleValidator;
|
||||
/** @var bool $bDebug */
|
||||
private $bDebug;
|
||||
@@ -71,32 +69,36 @@ class SecurityHelper
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the current user is allowed to do the $sAction on an $sObjectClass object (with optionnal $sObjectId id)
|
||||
* Checks are:
|
||||
* - Has a scope query for the $sObjectClass / $sAction
|
||||
* - Optionally, if $sObjectId provided: Is object within scope for $sObjectClass / $sObjectId / $sAction
|
||||
* - Is allowed by datamodel for $sObjectClass / $sAction
|
||||
*
|
||||
* @param \Silex\Application $oApp
|
||||
* @param string $sAction Must be in UR_ACTION_READ|UR_ACTION_MODIFY|UR_ACTION_CREATE
|
||||
* @param string $sObjectClass
|
||||
* @param string $sObjectId
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @throws \CoreException
|
||||
*/
|
||||
* Returns true if the current user is allowed to do the $sAction on an $sObjectClass object (with optionnal $sObjectId id)
|
||||
* Checks are:
|
||||
* - Has a scope query for the $sObjectClass / $sAction
|
||||
* - Optionally, if $sObjectId provided: Is object within scope for $sObjectClass / $sObjectId / $sAction
|
||||
* - Is allowed by datamodel for $sObjectClass / $sAction
|
||||
*
|
||||
* @param string $sAction Must be in UR_ACTION_READ|UR_ACTION_MODIFY|UR_ACTION_CREATE
|
||||
* @param string $sObjectClass
|
||||
* @param string $sObjectId
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function IsActionAllowed($sAction, $sObjectClass, $sObjectId = null)
|
||||
{
|
||||
$sDebugTracePrefix = __CLASS__ . ' / ' . __METHOD__ . ' : Returned false for action ' . $sAction . ' on ' . $sObjectClass . '::' . $sObjectId;
|
||||
$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 ($this->bDebug)
|
||||
{
|
||||
IssueLog::Info($sDebugTracePrefix . ' as the action value could not be understood (' . UR_ACTION_READ . '/' . UR_ACTION_MODIFY . '/' . UR_ACTION_CREATE . ' expected');
|
||||
IssueLog::Info($sDebugTracePrefix.' as the action value could not be understood ('.UR_ACTION_READ.'/'.UR_ACTION_MODIFY.'/'.UR_ACTION_CREATE.' expected');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -109,8 +111,9 @@ class SecurityHelper
|
||||
{
|
||||
if ($this->bDebug)
|
||||
{
|
||||
IssueLog::Info($sDebugTracePrefix . ' as there was no scope defined for action ' . $sScopeAction . ' and profiles ' . implode('/', UserRights::ListProfiles()));
|
||||
IssueLog::Info($sDebugTracePrefix.' as there was no scope defined for action '.$sScopeAction.' and profiles '.implode('/', UserRights::ListProfiles()));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// - If action != create we do some additionnal checks
|
||||
@@ -119,49 +122,51 @@ class SecurityHelper
|
||||
// - Checking specific object if id is specified
|
||||
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 ($this->bDebug)
|
||||
{
|
||||
IssueLog::Info($sDebugTracePrefix . ' as it was denied in the scope objects cache');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Modifying query to filter on the ID
|
||||
// - Adding expression
|
||||
$sObjectKeyAtt = MetaModel::DBGetKey($sObjectClass);
|
||||
$oFieldExp = new FieldExpression($sObjectKeyAtt, $oScopeQuery->GetClassAlias());
|
||||
$oBinExp = new BinaryExpression($oFieldExp, '=', new VariableExpression('object_id'));
|
||||
$oScopeQuery->AddConditionExpression($oBinExp);
|
||||
// - Setting value
|
||||
$aQueryParams = $oScopeQuery->GetInternalParams();
|
||||
$aQueryParams['object_id'] = $sObjectId;
|
||||
$oScopeQuery->SetInternalParams($aQueryParams);
|
||||
unset($aQueryParams);
|
||||
// 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 ($this->bDebug)
|
||||
{
|
||||
IssueLog::Info($sDebugTracePrefix.' as it was denied in the scope objects cache');
|
||||
}
|
||||
|
||||
// - 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)
|
||||
{
|
||||
// Updating cache
|
||||
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId] = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Modifying query to filter on the ID
|
||||
// - Adding expression
|
||||
$sObjectKeyAtt = MetaModel::DBGetKey($sObjectClass);
|
||||
$oFieldExp = new FieldExpression($sObjectKeyAtt, $oScopeQuery->GetClassAlias());
|
||||
$oBinExp = new BinaryExpression($oFieldExp, '=', new VariableExpression('object_id'));
|
||||
$oScopeQuery->AddConditionExpression($oBinExp);
|
||||
// - Setting value
|
||||
$aQueryParams = $oScopeQuery->GetInternalParams();
|
||||
$aQueryParams['object_id'] = $sObjectId;
|
||||
$oScopeQuery->SetInternalParams($aQueryParams);
|
||||
unset($aQueryParams);
|
||||
|
||||
if ($this->bDebug)
|
||||
{
|
||||
IssueLog::Info($sDebugTracePrefix . ' as there was no result for the following scope query : ' . $oScopeQuery->ToOQL(true));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// - 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)
|
||||
{
|
||||
// Updating cache
|
||||
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId] = false;
|
||||
|
||||
// Updating cache
|
||||
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId] = true;
|
||||
}
|
||||
if ($this->bDebug)
|
||||
{
|
||||
IssueLog::Info($sDebugTracePrefix.' as there was no result for the following scope query : '.$oScopeQuery->ToOQL(true));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Updating cache
|
||||
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,32 +177,41 @@ class SecurityHelper
|
||||
//throw new SecurityException('User not allowed to view this object', array('class' => $sObjectClass, 'id' => $sObjectId));
|
||||
if ($this->bDebug)
|
||||
{
|
||||
IssueLog::Info($sDebugTracePrefix . ' as the user is not allowed to access this object according to the datamodel security (cf. Console settings)');
|
||||
IssueLog::Info($sDebugTracePrefix.' as the user is not allowed to access this object according to the datamodel security (cf. Console settings)');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sStimulusCode
|
||||
* @param string $sObjectClass
|
||||
* @param \DBObjectSet|null $oInstanceSet
|
||||
*
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function IsStimulusAllowed($sStimulusCode, $sObjectClass, $oInstanceSet = null)
|
||||
{
|
||||
// Checking DataModel layer
|
||||
$aStimuliFromDatamodel = Metamodel::EnumStimuli($sObjectClass);
|
||||
// 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) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
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))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Checking portal security layer
|
||||
$aStimuliFromPortal = $this->oLifecycleValidator->GetStimuliForProfiles(UserRights::ListProfiles(), $sObjectClass);
|
||||
if (!in_array($sStimulusCode, $aStimuliFromPortal))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,99 +224,101 @@ class SecurityHelper
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function PreloadForCache(DBSearch $oSearch, $aExtKeysToPreload = null)
|
||||
{
|
||||
$sObjectClass = $oSearch->GetClass();
|
||||
$aObjectIds = array();
|
||||
$aExtKeysIds = array();
|
||||
$aColumnsToLoad = array();
|
||||
{
|
||||
$sObjectClass = $oSearch->GetClass();
|
||||
$aObjectIds = array();
|
||||
$aExtKeysIds = array();
|
||||
$aColumnsToLoad = array();
|
||||
|
||||
if($aExtKeysToPreload !== null)
|
||||
{
|
||||
foreach($aExtKeysToPreload as $sAttCode)
|
||||
{
|
||||
/** @var \AttributeDefinition $oAttDef */
|
||||
$oAttDef = MetaModel::GetAttributeDef($sObjectClass, $sAttCode);
|
||||
if($oAttDef->IsExternalKey())
|
||||
{
|
||||
$aExtKeysIds[$oAttDef->GetTargetClass()] = array();
|
||||
$aColumnsToLoad[] = $sAttCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($aExtKeysToPreload !== null)
|
||||
{
|
||||
foreach ($aExtKeysToPreload as $sAttCode)
|
||||
{
|
||||
/** @var \AttributeDefinition $oAttDef */
|
||||
$oAttDef = MetaModel::GetAttributeDef($sObjectClass, $sAttCode);
|
||||
if ($oAttDef->IsExternalKey())
|
||||
{
|
||||
/** @var \AttributeExternalKey $oAttDef */
|
||||
$aExtKeysIds[$oAttDef->GetTargetClass()] = array();
|
||||
$aColumnsToLoad[] = $sAttCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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())
|
||||
{
|
||||
// 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;
|
||||
// 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())
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
$iExtKey = $oCurrentRow->Get($sAttCode);
|
||||
if($iExtKey > 0)
|
||||
{
|
||||
/** @var \AttributeExternalKey $oAttDef */
|
||||
$oAttDef = MetaModel::GetAttributeDef($sObjectClass, $sAttCode);
|
||||
if(!in_array($iExtKey, $aExtKeysIds[$oAttDef->GetTargetClass()]))
|
||||
{
|
||||
$aExtKeysIds[$oAttDef->GetTargetClass()][] = $iExtKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Preparing ExtKeys to preload
|
||||
foreach ($aColumnsToLoad as $sAttCode)
|
||||
{
|
||||
$iExtKey = $oCurrentRow->Get($sAttCode);
|
||||
if ($iExtKey > 0)
|
||||
{
|
||||
/** @var \AttributeExternalKey $oAttDef */
|
||||
$oAttDef = MetaModel::GetAttributeDef($sObjectClass, $sAttCode);
|
||||
if (!in_array($iExtKey, $aExtKeysIds[$oAttDef->GetTargetClass()]))
|
||||
{
|
||||
$aExtKeysIds[$oAttDef->GetTargetClass()][] = $iExtKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach(array(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)
|
||||
{
|
||||
// Restricting scope if specified
|
||||
if(!empty($aObjectIds))
|
||||
{
|
||||
$oScopeQuery->AddCondition('id', array_keys($aObjectIds), 'IN');
|
||||
}
|
||||
foreach (array(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)
|
||||
{
|
||||
// Restricting scope if specified
|
||||
if (!empty($aObjectIds))
|
||||
{
|
||||
$oScopeQuery->AddCondition('id', array_keys($aObjectIds), 'IN');
|
||||
}
|
||||
|
||||
// Preparing object set
|
||||
$oScopeSet = new DBObjectSet($oScopeQuery);
|
||||
$oScopeSet->OptimizeColumnLoad(array());
|
||||
// Preparing object set
|
||||
$oScopeSet = new DBObjectSet($oScopeQuery);
|
||||
$oScopeSet->OptimizeColumnLoad(array());
|
||||
|
||||
// Checking objects status
|
||||
$aScopeObjectIds = $aObjectIds;
|
||||
while($oCurrentRow = $oScopeSet->Fetch())
|
||||
{
|
||||
$aScopeObjectIds[$oCurrentRow->GetKey()] = true;
|
||||
}
|
||||
// Checking objects status
|
||||
$aScopeObjectIds = $aObjectIds;
|
||||
while ($oCurrentRow = $oScopeSet->Fetch())
|
||||
{
|
||||
$aScopeObjectIds[$oCurrentRow->GetKey()] = true;
|
||||
}
|
||||
|
||||
// Updating cache
|
||||
if(!isset(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass]))
|
||||
{
|
||||
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass] = $aScopeObjectIds;
|
||||
}
|
||||
else
|
||||
{
|
||||
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass] = array_merge_recursive(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass], $aScopeObjectIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Updating cache
|
||||
if (!isset(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass]))
|
||||
{
|
||||
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass] = $aScopeObjectIds;
|
||||
}
|
||||
else
|
||||
{
|
||||
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass] = array_merge_recursive(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass], $aScopeObjectIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Preloading ExtKeys
|
||||
foreach($aExtKeysIds as $sTargetClass => $aTargetIds)
|
||||
{
|
||||
if(!empty($aTargetIds))
|
||||
{
|
||||
$oTargetSearch = new DBObjectSearch($sTargetClass);
|
||||
$oTargetSearch->AddCondition('id', $aTargetIds, 'IN');
|
||||
// Preloading ExtKeys
|
||||
foreach ($aExtKeysIds as $sTargetClass => $aTargetIds)
|
||||
{
|
||||
if (!empty($aTargetIds))
|
||||
{
|
||||
$oTargetSearch = new DBObjectSearch($sTargetClass);
|
||||
$oTargetSearch->AddCondition('id', $aTargetIds, 'IN');
|
||||
|
||||
static::PreloadForCache($oTargetSearch);
|
||||
}
|
||||
}
|
||||
}
|
||||
static::PreloadForCache($oTargetSearch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal;
|
||||
|
||||
@@ -10,27 +29,43 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
|
||||
use Symfony\Component\Routing\RouteCollectionBuilder;
|
||||
|
||||
/**
|
||||
* Class Kernel
|
||||
*
|
||||
* @package Combodo\iTop\Portal
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class Kernel extends BaseKernel
|
||||
{
|
||||
use MicroKernelTrait;
|
||||
|
||||
/** @var string CONFIG_EXTS */
|
||||
const CONFIG_EXTS = '.{php,xml,yaml,yml}';
|
||||
|
||||
public function getCacheDir()
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCacheDir()
|
||||
{
|
||||
$cacheDir = $_ENV['PORTAL_ID'] . '-' . $this->environment;
|
||||
|
||||
return utils::GetCachePath() . "/portals/$cacheDir";
|
||||
}
|
||||
|
||||
public function getLogDir()
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLogDir()
|
||||
{
|
||||
$logDir = $_ENV['PORTAL_ID'] . '-' . $this->environment;
|
||||
|
||||
return utils::GetLogPath() . "/portals/$logDir";
|
||||
}
|
||||
|
||||
public function registerBundles()
|
||||
/**
|
||||
* @return \Generator|iterable|\Symfony\Component\HttpKernel\Bundle\BundleInterface[]
|
||||
*/
|
||||
public function registerBundles()
|
||||
{
|
||||
$contents = require $this->getProjectDir().'/config/bundles.php';
|
||||
foreach ($contents as $class => $envs) {
|
||||
@@ -40,7 +75,13 @@ class Kernel extends BaseKernel
|
||||
}
|
||||
}
|
||||
|
||||
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
|
||||
/**
|
||||
* @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
|
||||
* @param \Symfony\Component\Config\Loader\LoaderInterface $loader
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
|
||||
{
|
||||
$container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
|
||||
// Feel free to remove the "container.autowiring.strict_mode" parameter
|
||||
@@ -55,7 +96,12 @@ class Kernel extends BaseKernel
|
||||
$loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');
|
||||
}
|
||||
|
||||
protected function configureRoutes(RouteCollectionBuilder $routes)
|
||||
/**
|
||||
* @param \Symfony\Component\Routing\RouteCollectionBuilder $routes
|
||||
*
|
||||
* @throws \Symfony\Component\Config\Exception\FileLoaderLoadException
|
||||
*/
|
||||
protected function configureRoutes(RouteCollectionBuilder $routes)
|
||||
{
|
||||
$confDir = $this->getProjectDir().'/config';
|
||||
|
||||
@@ -63,4 +109,20 @@ class Kernel extends BaseKernel
|
||||
$routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
|
||||
$routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given class name belongs to an active bundle.
|
||||
*
|
||||
* @param string $class A class name
|
||||
*
|
||||
* @return void true if the class belongs to an active bundle, false otherwise
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @deprecated Deprecated since version 2.6, to be removed in 3.0.
|
||||
*/
|
||||
public function isClassInActiveBundle($class)
|
||||
{
|
||||
// TODO: Implement isClassInActiveBundle() method.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Created by Bruno DA SILVA, working for Combodo
|
||||
* Date: 31/01/19
|
||||
* Time: 16:44
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\Routing;
|
||||
|
||||
|
||||
@@ -34,38 +28,45 @@ use Exception;
|
||||
* Class ItopExtensionsExtraRoutes
|
||||
*
|
||||
* @deprecated Compatibility layer for migrating brick's routes to iTop 2.7+
|
||||
* @package Combodo\iTop\Portal\Routing
|
||||
* @package Combodo\iTop\Portal\Routing
|
||||
* @since 2.7.0
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
*/
|
||||
class ItopExtensionsExtraRoutes
|
||||
{
|
||||
static private $routes = array();
|
||||
/** @var array $aRoutes */
|
||||
static private $aRoutes = array();
|
||||
|
||||
/**
|
||||
* @deprecated Since 2.7.0
|
||||
*
|
||||
* @param array $extraRoutes
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function addRoutes($extraRoutes)
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'Usage of legacy route "%s" is deprecated. You should declare routes in YAML format.',
|
||||
__FILE__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
/**
|
||||
* @param array $extraRoutes
|
||||
*
|
||||
* @throws Exception
|
||||
* @deprecated Since 2.7.0
|
||||
*
|
||||
*/
|
||||
public static function AddRoutes($extraRoutes)
|
||||
{
|
||||
@trigger_error(
|
||||
sprintf(
|
||||
'Usage of legacy route "%s" is deprecated. You should declare routes in YAML format.',
|
||||
__FILE__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
if (!is_array($extraRoutes)) {
|
||||
throw new Exception('Only array are allowed as parameter to '.__METHOD__);
|
||||
}
|
||||
if (!is_array($extraRoutes))
|
||||
{
|
||||
throw new Exception('Only array are allowed as parameter to '.__METHOD__);
|
||||
}
|
||||
|
||||
self::$routes = array_merge(self::$routes, $extraRoutes);
|
||||
}
|
||||
self::$aRoutes = array_merge(self::$aRoutes, $extraRoutes);
|
||||
}
|
||||
|
||||
public static function getRoutes()
|
||||
{
|
||||
return self::$routes;
|
||||
}
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function GetRoutes()
|
||||
{
|
||||
return self::$aRoutes;
|
||||
}
|
||||
}
|
||||
@@ -28,13 +28,16 @@ use Symfony\Component\Routing\Generator\UrlGenerator as BaseUrlGenerator;
|
||||
* Class UrlGenerator
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Routing
|
||||
* @since 2.7.0
|
||||
* @since 2.7.0
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
*/
|
||||
class UrlGenerator extends BaseUrlGenerator
|
||||
{
|
||||
/** @noinspection PhpTooManyParametersInspection */
|
||||
/**
|
||||
* Overloading of the parent function to add the $_REQUEST parameters to the url parameters.
|
||||
* This is used to keep additionnal parameters in the url, especially when portal is accessed from the /pages/exec.php
|
||||
* This is used to keep additional parameters in the url, especially when portal is accessed from the /pages/exec.php
|
||||
*
|
||||
* Note: As of now, it only adds the exec_module/exec_page/portal_id/env_switch/debug parameters. Any other parameter will be ignored.
|
||||
*
|
||||
@@ -66,22 +69,26 @@ class UrlGenerator extends BaseUrlGenerator
|
||||
{
|
||||
$sExecModule = utils::ReadParam('exec_module', '', false, 'string');
|
||||
$sExecPage = utils::ReadParam('exec_page', '', false, 'string');
|
||||
if ($sExecModule !== '' && $sExecPage !== '') {
|
||||
if ($sExecModule !== '' && $sExecPage !== '')
|
||||
{
|
||||
$aParameters['exec_module'] = $sExecModule;
|
||||
$aParameters['exec_page'] = $sExecPage;
|
||||
}
|
||||
|
||||
// Optional parameters
|
||||
$sPortalId = utils::ReadParam('portal_id', '', false, 'string');
|
||||
if ($sPortalId !== '') {
|
||||
if ($sPortalId !== '')
|
||||
{
|
||||
$aParameters['portal_id'] = $sPortalId;
|
||||
}
|
||||
$sEnvSwitch = utils::ReadParam('env_switch', '', false, 'string');
|
||||
if ($sEnvSwitch !== '') {
|
||||
if ($sEnvSwitch !== '')
|
||||
{
|
||||
$aParameters['env_switch'] = $sEnvSwitch;
|
||||
}
|
||||
$sDebug = utils::ReadParam('debug', '', false, 'string');
|
||||
if ($sDebug !== '') {
|
||||
if ($sDebug !== '')
|
||||
{
|
||||
$aParameters['debug'] = $sDebug;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by Bruno DA SILVA, working for Combodo
|
||||
* Date: 24/01/19
|
||||
* Time: 15:36
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\Twig;
|
||||
|
||||
use Twig\Extension\AbstractExtension;
|
||||
@@ -14,94 +29,106 @@ use utils;
|
||||
use Dict;
|
||||
use MetaModel;
|
||||
|
||||
/**
|
||||
* Class AppExtension
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Twig
|
||||
* @since 2.7.0
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
*/
|
||||
class AppExtension extends AbstractExtension
|
||||
{
|
||||
public function getFilters()
|
||||
{
|
||||
$filters = array();
|
||||
// Filter to translate a string via the Dict::S function
|
||||
// Usage in twig: {{ 'String:ToTranslate'|dict_s }}
|
||||
$filters[] = new Twig_SimpleFilter('dict_s',
|
||||
function ($sStringCode, $sDefault = null, $bUserLanguageOnly = false) {
|
||||
return Dict::S($sStringCode, $sDefault, $bUserLanguageOnly);
|
||||
}
|
||||
);
|
||||
/**
|
||||
* @return array|\Twig\TwigFilter[]|\Twig_SimpleFilter[]
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
$filters = array();
|
||||
// Filter to translate a string via the Dict::S function
|
||||
// Usage in twig: {{ 'String:ToTranslate'|dict_s }}
|
||||
$filters[] = new Twig_SimpleFilter('dict_s',
|
||||
function ($sStringCode, $sDefault = null, $bUserLanguageOnly = false) {
|
||||
return Dict::S($sStringCode, $sDefault, $bUserLanguageOnly);
|
||||
}
|
||||
);
|
||||
|
||||
// Filter to format a string via the Dict::Format function
|
||||
// Usage in twig: {{ 'String:ToTranslate'|dict_format() }}
|
||||
$filters[] = new Twig_SimpleFilter('dict_format',
|
||||
function ($sStringCode, $sParam01 = null, $sParam02 = null, $sParam03 = null, $sParam04 = null) {
|
||||
return Dict::Format($sStringCode, $sParam01, $sParam02, $sParam03, $sParam04);
|
||||
}
|
||||
);
|
||||
// Filter to format a string via the Dict::Format function
|
||||
// Usage in twig: {{ 'String:ToTranslate'|dict_format() }}
|
||||
$filters[] = new Twig_SimpleFilter('dict_format',
|
||||
function ($sStringCode, $sParam01 = null, $sParam02 = null, $sParam03 = null, $sParam04 = null) {
|
||||
return Dict::Format($sStringCode, $sParam01, $sParam02, $sParam03, $sParam04);
|
||||
}
|
||||
);
|
||||
|
||||
// Filter to enable base64 encode/decode
|
||||
// Usage in twig: {{ 'String to encode'|base64_encode }}
|
||||
$filters[] = new Twig_SimpleFilter('base64_encode', 'base64_encode');
|
||||
$filters[] = new Twig_SimpleFilter('base64_decode', 'base64_decode');
|
||||
// Filter to enable base64 encode/decode
|
||||
// Usage in twig: {{ 'String to encode'|base64_encode }}
|
||||
$filters[] = new Twig_SimpleFilter('base64_encode', 'base64_encode');
|
||||
$filters[] = new Twig_SimpleFilter('base64_decode', 'base64_decode');
|
||||
|
||||
// Filter to enable json decode (encode already exists)
|
||||
// Usage in twig: {{ aSomeArray|json_decode }}
|
||||
$filters[] = new Twig_SimpleFilter('json_decode', function ($sJsonString, $bAssoc = false) {
|
||||
return json_decode($sJsonString, $bAssoc);
|
||||
}
|
||||
);
|
||||
// Filter to enable json decode (encode already exists)
|
||||
// Usage in twig: {{ aSomeArray|json_decode }}
|
||||
$filters[] = new Twig_SimpleFilter('json_decode', function ($sJsonString, $bAssoc = false) {
|
||||
return json_decode($sJsonString, $bAssoc);
|
||||
}
|
||||
);
|
||||
|
||||
// Filter to add itopversion to an url
|
||||
$filters[] = new Twig_SimpleFilter('add_itop_version', function ($sUrl) {
|
||||
if (strpos($sUrl, '?') === false)
|
||||
{
|
||||
$sUrl = $sUrl."?itopversion=".ITOP_VERSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sUrl."&itopversion=".ITOP_VERSION;
|
||||
}
|
||||
// Filter to add itopversion to an url
|
||||
$filters[] = new Twig_SimpleFilter('add_itop_version', function ($sUrl) {
|
||||
if (strpos($sUrl, '?') === false)
|
||||
{
|
||||
$sUrl = $sUrl."?itopversion=".ITOP_VERSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sUrl."&itopversion=".ITOP_VERSION;
|
||||
}
|
||||
|
||||
return $sUrl;
|
||||
});
|
||||
return $sUrl;
|
||||
});
|
||||
|
||||
// Filter to add a module's version to an url
|
||||
$filters[] = new Twig_SimpleFilter('add_module_version', function ($sUrl, $sModuleName) {
|
||||
$sModuleVersion = utils::GetCompiledModuleVersion($sModuleName);
|
||||
// Filter to add a module's version to an url
|
||||
$filters[] = new Twig_SimpleFilter('add_module_version', function ($sUrl, $sModuleName) {
|
||||
$sModuleVersion = utils::GetCompiledModuleVersion($sModuleName);
|
||||
|
||||
if (strpos($sUrl, '?') === false)
|
||||
{
|
||||
$sUrl = $sUrl."?moduleversion=".$sModuleVersion;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sUrl."&moduleversion=".$sModuleVersion;
|
||||
}
|
||||
if (strpos($sUrl, '?') === false)
|
||||
{
|
||||
$sUrl = $sUrl."?moduleversion=".$sModuleVersion;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUrl = $sUrl."&moduleversion=".$sModuleVersion;
|
||||
}
|
||||
|
||||
return $sUrl;
|
||||
});
|
||||
return $sUrl;
|
||||
});
|
||||
|
||||
|
||||
return $filters;
|
||||
}
|
||||
return $filters;
|
||||
}
|
||||
|
||||
public function getFunctions()
|
||||
{
|
||||
$functions = array();
|
||||
/**
|
||||
* @return array|\Twig\TwigFunction[]|\Twig_SimpleFunction[]
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
$functions = array();
|
||||
|
||||
// Function to check our current environment
|
||||
// Usage in twig: {% if is_development_environment() %}
|
||||
$functions[] = new Twig_SimpleFunction('is_development_environment', function()
|
||||
{
|
||||
return utils::IsDevelopmentEnvironment();
|
||||
});
|
||||
// Function to check our current environment
|
||||
// Usage in twig: {% if is_development_environment() %}
|
||||
$functions[] = new Twig_SimpleFunction('is_development_environment', function () {
|
||||
return utils::IsDevelopmentEnvironment();
|
||||
});
|
||||
|
||||
// Function to get configuration parameter
|
||||
// Usage in twig: {{ get_config_parameter('foo') }}
|
||||
$functions[] = new Twig_SimpleFunction('get_config_parameter', function($sParamName)
|
||||
{
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
return $oConfig->Get($sParamName);
|
||||
});
|
||||
// Function to get configuration parameter
|
||||
// Usage in twig: {{ get_config_parameter('foo') }}
|
||||
$functions[] = new Twig_SimpleFunction('get_config_parameter', function ($sParamName) {
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
|
||||
return $functions;
|
||||
}
|
||||
return $oConfig->Get($sParamName);
|
||||
});
|
||||
|
||||
return $functions;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -31,42 +31,42 @@ use utils;
|
||||
|
||||
/**
|
||||
* AbstractPortalUrlMaker
|
||||
*
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
* @since 2.3.0
|
||||
* @since 2.3.0
|
||||
*/
|
||||
abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
|
||||
{
|
||||
/** @var string PORTAL_ID */
|
||||
/** @var string PORTAL_ID */
|
||||
const PORTAL_ID = '';
|
||||
|
||||
/** @var \Combodo\iTop\Portal\Kernel[] $aKernels */
|
||||
private static $aKernels = array();
|
||||
|
||||
/**
|
||||
* Generate an (absolute) URL to an object, either in view or edit mode.
|
||||
* Returns null if the current user is not allowed to view / edit object.
|
||||
*
|
||||
* @param string $sClass The class of the object
|
||||
* @param int $iId The identifier of the object
|
||||
* @param string $sMode edit|view
|
||||
*
|
||||
* @return string | null
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws CoreException
|
||||
*/
|
||||
/**
|
||||
* Generate an (absolute) URL to an object, either in view or edit mode.
|
||||
* Returns null if the current user is not allowed to view / edit object.
|
||||
*
|
||||
* @param string $sClass The class of the object
|
||||
* @param int $iId The identifier of the object
|
||||
* @param string $sMode edit|view
|
||||
*
|
||||
* @return string | null
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws CoreException
|
||||
*/
|
||||
public static function PrepareObjectURL($sClass, $iId, $sMode)
|
||||
{
|
||||
$sPreviousPortalId = (isset($_ENV['PORTAL_ID'])) ? $_ENV['PORTAL_ID'] : '';
|
||||
$_ENV['PORTAL_ID'] = static::PORTAL_ID;
|
||||
|
||||
require MODULESROOT . 'itop-portal-base/portal/config/bootstrap.php';
|
||||
require MODULESROOT.'itop-portal-base/portal/config/bootstrap.php';
|
||||
|
||||
$sUrl = self::DoPrepareObjectURL($sClass, $iId, $sMode);
|
||||
|
||||
if(!empty($sPreviousPortalId))
|
||||
if (!empty($sPreviousPortalId))
|
||||
{
|
||||
$_ENV['PORTAL_ID'] = $sPreviousPortalId;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
|
||||
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param int $iId
|
||||
* @param int $iId
|
||||
* @param string $sMode
|
||||
*
|
||||
* @return string|null
|
||||
@@ -155,9 +155,9 @@ 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] = new Kernel($_SERVER['APP_ENV'], (bool)$_SERVER['APP_DEBUG']);
|
||||
self::$aKernels[static::PORTAL_ID]->boot();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by Bruno DA SILVA, working for Combodo
|
||||
* Date: 28/02/19
|
||||
* Time: 16:59
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\VariableAccessor;
|
||||
|
||||
|
||||
/**
|
||||
* Class AbstractStringVariableAccessor
|
||||
*
|
||||
* @package Combodo\iTop\Portal\VariableAccessor
|
||||
* @since 2.7.0
|
||||
*/
|
||||
abstract class AbstractStringVariableAccessor extends AbstractVariableAccessor
|
||||
{
|
||||
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getVariable();
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getVariable();
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by Bruno DA SILVA, working for Combodo
|
||||
* Date: 28/02/19
|
||||
* Time: 16:59
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\VariableAccessor;
|
||||
|
||||
|
||||
/**
|
||||
* Class AbstractVariableAccessor
|
||||
*
|
||||
* @package Combodo\iTop\Portal\VariableAccessor
|
||||
* @since 2.7.0
|
||||
*/
|
||||
abstract class AbstractVariableAccessor
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $mStoredVariable;
|
||||
/** @var string $storedVariable */
|
||||
private $storedVariable;
|
||||
|
||||
/**
|
||||
* @param string $mVariableToStore
|
||||
* @param string $variableToStore
|
||||
*/
|
||||
public function __construct($mVariableToStore)
|
||||
public function __construct($variableToStore)
|
||||
{
|
||||
$this->mStoredVariable = $mVariableToStore;
|
||||
$this->storedVariable = $variableToStore;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getVariable()
|
||||
{
|
||||
return $this->mStoredVariable;
|
||||
return $this->storedVariable;
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Created by Bruno DA SILVA, working for Combodo
|
||||
* Date: 28/02/19
|
||||
* Time: 16:59
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\VariableAccessor;
|
||||
|
||||
|
||||
@@ -33,15 +27,28 @@ use MetaModel;
|
||||
use User;
|
||||
use UserRights;
|
||||
|
||||
/**
|
||||
* Class CombodoCurrentContactPhotoUrl
|
||||
*
|
||||
* @package Combodo\iTop\Portal\VariableAccessor
|
||||
* @since 2.7.0
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
*/
|
||||
class CombodoCurrentContactPhotoUrl
|
||||
{
|
||||
/**
|
||||
* @var \User
|
||||
*/
|
||||
/** @var \User $oUser */
|
||||
private $oUser;
|
||||
/** @var string $sCombodoPortalInstanceAbsoluteUrl */
|
||||
private $sCombodoPortalInstanceAbsoluteUrl;
|
||||
/** @var string|null $sContactPhotoUrl */
|
||||
private $sContactPhotoUrl;
|
||||
|
||||
/**
|
||||
* CombodoCurrentContactPhotoUrl constructor.
|
||||
*
|
||||
* @param \User $oUser
|
||||
* @param string $sCombodoPortalInstanceAbsoluteUrl
|
||||
*/
|
||||
public function __construct(User $oUser, $sCombodoPortalInstanceAbsoluteUrl)
|
||||
{
|
||||
$this->oUser = $oUser;
|
||||
@@ -51,10 +58,11 @@ class CombodoCurrentContactPhotoUrl
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
if($this->sContactPhotoUrl === null)
|
||||
if ($this->sContactPhotoUrl === null)
|
||||
{
|
||||
$this->sContactPhotoUrl = $this->ComputeContactPhotoUrl();
|
||||
}
|
||||
@@ -75,6 +83,7 @@ class CombodoCurrentContactPhotoUrl
|
||||
// - Checking if we can load the contact
|
||||
try
|
||||
{
|
||||
/** @var \cmdbAbstractObject $oContact */
|
||||
$oContact = UserRights::GetContactObject();
|
||||
}
|
||||
catch (Exception $e)
|
||||
@@ -94,6 +103,7 @@ class CombodoCurrentContactPhotoUrl
|
||||
{
|
||||
if (MetaModel::IsValidAttCode(get_class($oContact), 'picture'))
|
||||
{
|
||||
/** @var \ormDocument $oImage */
|
||||
$oImage = $oContact->Get('picture');
|
||||
if (is_object($oImage) && !$oImage->IsEmpty())
|
||||
{
|
||||
|
||||
@@ -1,13 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by Bruno DA SILVA, working for Combodo
|
||||
* Date: 04/03/19
|
||||
* Time: 17:43
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Portal\VariableAccessor;
|
||||
|
||||
|
||||
/**
|
||||
* Class CombodoPortalInstanceConf
|
||||
*
|
||||
* @package Combodo\iTop\Portal\VariableAccessor
|
||||
* @since 2.7.0
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
*/
|
||||
class CombodoPortalInstanceConf extends AbstractVariableAccessor
|
||||
{
|
||||
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2017 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
/**
|
||||
* Copyright (C) 2013-2019 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Backward Compatibility file for default portal.
|
||||
@@ -37,15 +40,15 @@
|
||||
);
|
||||
|
||||
// Load current environment
|
||||
if (file_exists(__DIR__ . '/../../approot.inc.php'))
|
||||
if (file_exists(__DIR__.'/../../approot.inc.php'))
|
||||
{
|
||||
require_once __DIR__ . '/../../approot.inc.php'; // When in env-xxxx folder
|
||||
require_once __DIR__.'/../../approot.inc.php'; // When in env-xxxx folder
|
||||
}
|
||||
else
|
||||
{
|
||||
require_once __DIR__ . '/../../../approot.inc.php'; // When in datamodels/x.x folder
|
||||
require_once __DIR__.'/../../../approot.inc.php'; // When in datamodels/x.x folder
|
||||
}
|
||||
require_once APPROOT . 'application/startup.inc.php';
|
||||
require_once APPROOT.'application/startup.inc.php';
|
||||
|
||||
// Protection against setup in the following configuration : ITIL Ticket with Enhanced Portal selected but neither UserRequest or Incident. Which would crash the portal.
|
||||
if (!class_exists('UserRequest') && !class_exists('Incident'))
|
||||
@@ -58,4 +61,4 @@ $sDir = basename(__DIR__);
|
||||
define('PORTAL_ID', $sDir);
|
||||
|
||||
// Load frontal
|
||||
require_once MODULESROOT . 'itop-portal-base/index.php';
|
||||
require_once MODULESROOT.'itop-portal-base/index.php';
|
||||
|
||||
@@ -25,14 +25,14 @@ require_once APPROOT.'/lib/composer-vendor/autoload.php';
|
||||
|
||||
/**
|
||||
* iTopPortalEditUrlMaker
|
||||
*
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
* @since 2.3.0
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class iTopPortalEditUrlMaker extends AbstractPortalUrlMaker
|
||||
{
|
||||
/** @var string PORTAL_ID */
|
||||
/** @var string PORTAL_ID */
|
||||
const PORTAL_ID = 'itop-portal';
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class iTopPortalEditUrlMaker extends AbstractPortalUrlMaker
|
||||
*
|
||||
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
* @since 2.3.0
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class iTopPortalViewUrlMaker extends iTopPortalEditUrlMaker
|
||||
{
|
||||
@@ -52,7 +52,7 @@ class iTopPortalViewUrlMaker extends iTopPortalEditUrlMaker
|
||||
{
|
||||
return static::PrepareObjectURL($sClass, $iId, 'view');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Default portal hyperlink (for notifications) is the edit hyperlink
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-portal/2.7.0', array(
|
||||
|
||||
Reference in New Issue
Block a user