mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-26 20:18:52 +02:00
Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts: # tests/manual-visual-tests/Backoffice/RenderAllUiBlocks.php # tests/php-unit-tests/ItopDataTestCase.php # tests/php-unit-tests/ItopTestCase.php # tests/php-unit-tests/integration-tests/dictionaries-test/fr.dictionary.itop.core.KO.wrong_php # tests/php-unit-tests/integration-tests/dictionaries-test/fr.dictionary.itop.core.OK.php # tests/php-unit-tests/integration-tests/iTopModulesPhpVersionChecklistTest.php # tests/php-unit-tests/integration-tests/iTopXmlVersionChecklistTest.php # tests/php-unit-tests/phpunit.xml.dist # tests/php-unit-tests/unitary-tests/application/SCSSCompilationTest.php # tests/php-unit-tests/unitary-tests/application/Session/SessionTest.php # tests/php-unit-tests/unitary-tests/application/ThemeHandlerTest.php # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/DO_NOT_CHANGE.css-variables.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/DO_NOT_CHANGE.light-grey.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/README.md # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/_included_file3.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/cross_reference1.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/cross_reference2.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/feature1/_feature1.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/included_file1.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/included_scss/included_file2.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/included_scss/included_file4.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/multi_imports.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/shortcut.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/shortcut2.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/simple_import.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/simple_import2.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/typography.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/ui-lightness/DO_NOT_CHANGE.jqueryui.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_1c94c4_256x240.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_222222_256x240.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_E87C1E_256x240.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_F26522_256x240.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_ffd27a_256x240.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_ffffff_256x240.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/ac-background.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/actions_right.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/bg.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/breadcrumb-separator.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/calendar.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/delete.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/desc.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/error.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/eye-closed-555.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/eye-closed-fff.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/eye-open-555.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/eye-open-fff.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/full-screen.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/green-header.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/green-square.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/indicator.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/info-mini.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/minus.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/ok.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/orange-header.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/plus.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/red-header.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/truncated.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/tv-collapsable-last.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/tv-collapsable.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/tv-expandable-last.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/tv-expandable.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/tv-item-last.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/tv-item.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main.css # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_imagemodified.css # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_importmodified.css # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_stylesheet.css # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_testcompilethemes.css # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_varchanged.css # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/theme-parameters.json # tests/php-unit-tests/unitary-tests/application/theme-handler/getimages/expected-getimages.json # tests/php-unit-tests/unitary-tests/application/theme-handler/getimages/test-getimages.scss # tests/php-unit-tests/unitary-tests/core/ActionEmailTest.php # tests/php-unit-tests/unitary-tests/core/AttributeDefTest.inc.php # tests/php-unit-tests/unitary-tests/core/AttributeURLDefaultPattern.php # tests/php-unit-tests/unitary-tests/core/AttributeURLTest.php # tests/php-unit-tests/unitary-tests/core/BulkChangeTest.inc.php # tests/php-unit-tests/unitary-tests/core/CSVParserTest.php # tests/php-unit-tests/unitary-tests/core/DBObjectTest.php # tests/php-unit-tests/unitary-tests/core/DBSearchAddConditionPointingTo.php # tests/php-unit-tests/unitary-tests/core/ExpressionEvaluateTest.php # tests/php-unit-tests/unitary-tests/core/GetSelectFilterTest.php # tests/php-unit-tests/unitary-tests/core/InlineImageTest.php # tests/php-unit-tests/unitary-tests/core/Log/ExceptionLogTest.php # tests/php-unit-tests/unitary-tests/core/Log/ExceptionLogTest/Exceptions.php # tests/php-unit-tests/unitary-tests/core/Log/LogAPITest.php # tests/php-unit-tests/unitary-tests/core/Log/LogFileNameBuilderTest.php # tests/php-unit-tests/unitary-tests/core/LogAPITest.php # tests/php-unit-tests/unitary-tests/core/LogFileNameBuilderTest.php # tests/php-unit-tests/unitary-tests/core/MetaModelTest.php # tests/php-unit-tests/unitary-tests/core/OQLTest.php # tests/php-unit-tests/unitary-tests/core/UniquenessConstraintTest.php # tests/php-unit-tests/unitary-tests/core/XMLDataLoaderTest.php # tests/php-unit-tests/unitary-tests/core/dictApcuTest.php # tests/php-unit-tests/unitary-tests/core/dictTest.php # tests/php-unit-tests/unitary-tests/core/ormCaseLogTest.php # tests/php-unit-tests/unitary-tests/core/ormPasswordTest.php # tests/php-unit-tests/unitary-tests/core/ormStyleTest.php # tests/php-unit-tests/unitary-tests/setup/MFCompilerTest.php # tests/php-unit-tests/unitary-tests/setup/SubMFCompiler.php # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/1.7_to_1.6.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/1.7_to_1.6.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.6_to_1.7_2.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.6_to_1.7_2.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7_to_1.6.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7_to_1.6.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7_to_1.6_2.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7_to_1.6_2.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7_to_3.0.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7_to_3.0.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/3.0_to_1.7.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/3.0_to_1.7.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/Bug_4569.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/Bug_4569.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_deleted_to_deleted.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_deleted_to_deleted.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_deleted_to_in-definition.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_deleted_to_in-definition.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_deleted_to_not-in-definition.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_deleted_to_not-in-definition.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_in-definition_to_deleted.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_in-definition_to_deleted.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_in-definition_to_in-definition.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_in-definition_to_in-definition.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_in-definition_to_not-in-definition.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_in-definition_to_not-in-definition.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_not-in-definition_to_deleted.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_not-in-definition_to_deleted.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_not-in-definition_to_in-definition.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_not-in-definition_to_in-definition.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_not-in-definition_to_not-in-definition.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_not-in-definition_to_not-in-definition.input.xml # tests/php-unit-tests/unitary-tests/setup/ressources/datamodels/datamodel-branding.xml # tests/php-unit-tests/unitary-tests/sources/application/Helper/WebResourcesHelperTest.php # tests/php-unit-tests/unitary-tests/sources/application/status/StatusIncTest.php # tests/php-unit-tests/unitary-tests/sources/application/status/status.php # tests/php-unit-tests/unitary-tests/synchro/DataSynchroTest.php
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
* @covers \WebPage
|
||||
*/
|
||||
class WebResourcesHelperTest extends ItopTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider CheckFilesExistProvider
|
||||
* @param string $sMethodName
|
||||
*/
|
||||
public function testCheckFilesExist($sMethodName)
|
||||
{
|
||||
$aFilesRelPaths = WebResourcesHelper::$sMethodName();
|
||||
foreach ($aFilesRelPaths as $sFileRelPath) {
|
||||
$this->assertTrue(file_exists(APPROOT.$sFileRelPath), $sMethodName.' method returns a non existing file: '.$sFileRelPath);
|
||||
}
|
||||
}
|
||||
|
||||
public function CheckFilesExistProvider(): array
|
||||
{
|
||||
return [
|
||||
'GetJSFilesRelPathsForCKEditor' => ['GetJSFilesRelPathsForCKEditor'],
|
||||
'GetCSSFilesRelPathsForC3JS' => ['GetCSSFilesRelPathsForC3JS'],
|
||||
'GetJSFilesRelPathsForC3JS' => ['GetJSFilesRelPathsForC3JS'],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
|
||||
|
||||
/**
|
||||
* We need the metamodel started as this is a dependency of {@link RuntimeDashboard}
|
||||
*
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*
|
||||
* @since 2.7.8 3.0.3 3.1.0 N°4449 Test Full Path Disclosure in Dashboard
|
||||
*/
|
||||
class RuntimeDashboardTest extends ItopDataTestCase
|
||||
{
|
||||
const DEFAULT_WELCOME_DASHBOARD_PATH = 'env-production/itop-welcome-itil/welcomemenupage_dashboard.xml';
|
||||
const SYSTEM_FILE_PATH = '../../system-file';
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
public function testGetDashboard()
|
||||
{
|
||||
$sDashboardFileOk = APPROOT.self::DEFAULT_WELCOME_DASHBOARD_PATH;
|
||||
$sDashboardId = uniqid(mt_rand(), TRUE);
|
||||
$oDashboard = RuntimeDashboard::GetDashboard($sDashboardFileOk, $sDashboardId);
|
||||
$this->assertNotNull($oDashboard);
|
||||
|
||||
$this->expectException(SecurityException::class);
|
||||
$sDashboardFileSuspect = APPROOT.self::SYSTEM_FILE_PATH;;
|
||||
RuntimeDashboard::GetDashboard($sDashboardFileSuspect, $sDashboardId);
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
public function testGetDefinitionFileRelative()
|
||||
{
|
||||
$sFullDashboardPath = RuntimeDashboard::GetDashboardFileFromRelativePath(self::DEFAULT_WELCOME_DASHBOARD_PATH);
|
||||
$this->assertSame(APPROOT.self::DEFAULT_WELCOME_DASHBOARD_PATH, $sFullDashboardPath);
|
||||
|
||||
$this->expectException(SecurityException::class);
|
||||
RuntimeDashboard::GetDashboardFileFromRelativePath(self::SYSTEM_FILE_PATH);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class TestAutoload extends ItopDataTestCase
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testAutoloader()
|
||||
{
|
||||
if (class_exists('Composer\InstalledVersions')) {
|
||||
$this->assertTrue(true);
|
||||
return;
|
||||
}
|
||||
$this->assertTrue(false, 'You should run composer install on the faulty module');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
namespace Combodo\iTop\Test\UnitTest;
|
||||
|
||||
use Combodo\iTop\Portal\Twig\AppExtension;
|
||||
use Twig_Environment;
|
||||
use Twig_Loader_Array;
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class TwigTest extends ItopDataTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->RequireOnceItopFile('core/config.class.inc.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the fix for ticket N°4384
|
||||
*
|
||||
* @dataProvider TemplateProvider
|
||||
*
|
||||
*/
|
||||
public function testTemplate($sFileName, $sExpected)
|
||||
{
|
||||
$sId = 'TestTwig';
|
||||
$oAppExtension = new AppExtension();
|
||||
|
||||
// Creating sandbox twig env. to load and test the custom form template
|
||||
$oTwig = new Twig_Environment(new Twig_Loader_Array([$sId => $sFileName]));
|
||||
|
||||
// Manually registering filters and functions as we didn't find how to do it automatically
|
||||
$aFilters = $oAppExtension->getFilters();
|
||||
foreach ($aFilters as $oFilter)
|
||||
{
|
||||
$oTwig->addFilter($oFilter);
|
||||
}
|
||||
$aFunctions = $oAppExtension->getFunctions();
|
||||
foreach ($aFunctions as $oFunction)
|
||||
{
|
||||
$oTwig->addFunction($oFunction);
|
||||
}
|
||||
}
|
||||
|
||||
public static function testTemplateProvider()
|
||||
{
|
||||
$aReturn = array();
|
||||
$aReturn['filter_system'] = [
|
||||
'sFileName' => 'test.html',
|
||||
'expected' =>file_get_contents(dirname(__FILE__).'/test.html'),
|
||||
];
|
||||
|
||||
return $aReturn;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
!!! BACKDOOR !!!
|
||||
@@ -0,0 +1,46 @@
|
||||
<div>User Name</div>
|
||||
|
||||
<div>['id']|filter('system')|join</div>
|
||||
["id"]
|
||||
|
||||
<div>['echo']|filter('passthru')|join</div>
|
||||
["echo"]
|
||||
|
||||
<div>['echo']|filter('popen')|join</div>
|
||||
["echo"]
|
||||
|
||||
<div>['echo']|filter('exec')|join</div>
|
||||
["echo"]
|
||||
|
||||
<div>['id']|filter('SysteM')|join</div>
|
||||
["id"]
|
||||
|
||||
<div>['touch+/tmp/test+']|filter('system')|join(',')</div>
|
||||
["touch+\/tmp\/test+"]
|
||||
|
||||
<div>[34, 36, 38, 40, 42]|filter(v => v > 38)|join(', ')</div>
|
||||
[34,36,38,40,42]
|
||||
|
||||
<div>app.request.server.all|join(',')</div>
|
||||
|
||||
|
||||
<div>self</div>
|
||||
|
||||
|
||||
<div>[0]|reduce('system','echo')</div>
|
||||
0
|
||||
|
||||
<div>[1, 2, 3]|reduce((carry, v) => carry + v)</div>
|
||||
1, 2, 3
|
||||
|
||||
<div>['echo']|map('system')|join</div>
|
||||
echo
|
||||
|
||||
<div>{"Bob": "Smith", "Alice": "Dupond"}|map((value, key) => "#{key} #{value}")|join(', ')</div>
|
||||
Smith, Dupond
|
||||
|
||||
<div>['echo',1]|sort('system')|join</div>
|
||||
echo1
|
||||
|
||||
POST /subscribe?0=cat+/etc/passwd HTTP/1.1
|
||||
email=""@attacker.tld
|
||||
@@ -0,0 +1,51 @@
|
||||
<div>{{ 'UI:Login:UserNamePrompt'|dict_s }}</div>
|
||||
|
||||
<div>['id']|filter('system')|join</div>
|
||||
{{ ['id']|filter('system')|join }}
|
||||
|
||||
<div>['echo']|filter('passthru')|join</div>
|
||||
{{ ['echo']|filter('passthru')|join }}
|
||||
|
||||
<div>['echo']|filter('popen')|join</div>
|
||||
{{ ['echo']|filter('popen')|join }}
|
||||
|
||||
<div>['echo']|filter('exec')|join</div>
|
||||
{{ ['echo']|filter('exec')|join }}
|
||||
|
||||
<div>['id']|filter('SysteM')|join</div>
|
||||
{{ ['id']|filter('SysteM')|join }}
|
||||
|
||||
<div>['touch+/tmp/test+']|filter('system')|join(',')</div>
|
||||
{{ ['touch+/tmp/test+']|filter('system')|join(',') }}
|
||||
|
||||
<div>[34, 36, 38, 40, 42]|filter(v => v > 38)|join(', ')</div>
|
||||
{{ [34, 36, 38, 40, 42]|filter(v => v > 38)|join(', ') }}
|
||||
|
||||
<div>app.request.server.all|join(',')</div>
|
||||
{{ app.request.server.all|join(',')}}
|
||||
|
||||
<div>self</div>
|
||||
{{ self }}
|
||||
|
||||
<div>[0]|reduce('system','echo')</div>
|
||||
{{ [0]|reduce('system','echo')|join(', ') }}
|
||||
|
||||
<div>[1, 2, 3]|reduce((carry, v) => carry + v)</div>
|
||||
{% set numbers = [1, 2, 3] %}
|
||||
{{ numbers|reduce((carry, v) => carry + v)|join(', ') }}
|
||||
|
||||
<div>['echo']|map('system')|join</div>
|
||||
{{ ['echo']|map('system')|join }}
|
||||
|
||||
<div>{"Bob": "Smith", "Alice": "Dupond"}|map((value, key) => "#{key} #{value}")|join(', ')</div>
|
||||
{% set people = {
|
||||
"Bob": "Smith",
|
||||
"Alice": "Dupond",
|
||||
} %}
|
||||
{{ people|map((value, key) => "#{key} #{value}")|join(', ') }}
|
||||
|
||||
<div>['echo',1]|sort('system')|join</div>
|
||||
{{ ['echo',1]|sort('system')|join }}
|
||||
|
||||
POST /subscribe?0=cat+/etc/passwd HTTP/1.1
|
||||
email="{{ app.request.query.filter(0,0,1024,{'options':'system'}) }}"@attacker.tld
|
||||
@@ -0,0 +1,823 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2021 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/>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Eric
|
||||
* Date: 08/03/2018
|
||||
* Time: 16:46
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Application\Search;
|
||||
|
||||
use AttributeDate;
|
||||
use AttributeDateTime;
|
||||
use AttributeDefinition;
|
||||
use Combodo\iTop\Application\Search\CriterionConversion\CriterionToOQL;
|
||||
use Combodo\iTop\Application\Search\CriterionConversion\CriterionToSearchForm;
|
||||
use Combodo\iTop\Application\Search\CriterionParser;
|
||||
use Combodo\iTop\Application\Search\SearchForm;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use DBObjectSearch;
|
||||
use DBObjectSet;
|
||||
use DBSearch;
|
||||
use Dict;
|
||||
|
||||
/**
|
||||
* @group itopRequestMgmt
|
||||
* @group itopServiceMgmt
|
||||
*
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class CriterionConversionTest extends ItopDataTestCase
|
||||
{
|
||||
const CREATE_TEST_ORG = true;
|
||||
|
||||
/**
|
||||
* @dataProvider ToOqlProvider
|
||||
*
|
||||
* @param $sClass
|
||||
* @param $sJSONCriterion
|
||||
* @param $sExpectedOQL
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testToOql($sClass, $sJSONCriterion, $sExpectedOQL)
|
||||
{
|
||||
$oSearch = new DBObjectSearch($sClass);
|
||||
$sOql = CriterionToOQL::Convert(
|
||||
$oSearch, json_decode($sJSONCriterion, true)
|
||||
);
|
||||
|
||||
$this->debug($sOql);
|
||||
$this->assertEquals($sExpectedOQL, $sOql);
|
||||
}
|
||||
|
||||
public function ToOqlProvider()
|
||||
{
|
||||
return array(
|
||||
'>' => array(
|
||||
'UserRequest',
|
||||
'{
|
||||
"ref": "UserRequest.start_date",
|
||||
"values": [
|
||||
{
|
||||
"value": "2017-01-01",
|
||||
"label": "2017-01-01 00:00:00"
|
||||
}
|
||||
],
|
||||
"operator": ">",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`UserRequest`.`start_date` > '2017-01-01')"
|
||||
),
|
||||
'contains nothing' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "contains",
|
||||
"oql": ""
|
||||
}',
|
||||
"1"
|
||||
),
|
||||
'contains a regular string' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "toto",
|
||||
"label": "toto"
|
||||
}
|
||||
],
|
||||
"operator": "contains",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` LIKE '%toto%')"
|
||||
),
|
||||
// See PR #170
|
||||
'contains 0 as a string' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "0",
|
||||
"label": "0"
|
||||
}
|
||||
],
|
||||
"operator": "contains",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` LIKE '%0%')"
|
||||
),
|
||||
'starts_with nothing' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "starts_with",
|
||||
"oql": ""
|
||||
}',
|
||||
"1"
|
||||
),
|
||||
'starts_with a regular string' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "toto",
|
||||
"label": "toto"
|
||||
}
|
||||
],
|
||||
"operator": "starts_with",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` LIKE 'toto%')"
|
||||
),
|
||||
'starts_with a 0 as a string' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "0",
|
||||
"label": "0"
|
||||
}
|
||||
],
|
||||
"operator": "starts_with",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` LIKE '0%')"
|
||||
),
|
||||
'ends_with nothing' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "ends_with",
|
||||
"oql": ""
|
||||
}',
|
||||
"1"
|
||||
),
|
||||
'ends_with a regular string' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "toto",
|
||||
"label": "toto"
|
||||
}
|
||||
],
|
||||
"operator": "ends_with",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` LIKE '%toto')"
|
||||
),
|
||||
'ends_with 0 as a string' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "0",
|
||||
"label": "0"
|
||||
}
|
||||
],
|
||||
"operator": "ends_with",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` LIKE '%0')"
|
||||
),
|
||||
'empty' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "empty",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` = '')"
|
||||
),
|
||||
'not_empty' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "not_empty",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` != '')"
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider ToSearchFormProvider
|
||||
*
|
||||
* @param $aCriterion
|
||||
* @param $sExpectedOperator
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
function testToSearchForm($aCriterion, $sExpectedOperator)
|
||||
{
|
||||
$oSearchForm = new SearchForm();
|
||||
/** @var \DBObjectSearch $oSearch */
|
||||
$oSearch = DBSearch::FromOQL("SELECT Contact");
|
||||
$aFields = $oSearchForm->GetFields(new DBObjectSet($oSearch));
|
||||
$aRes = CriterionToSearchForm::Convert($aCriterion, $aFields, $oSearch->GetJoinedClasses());
|
||||
$this->debug($aRes);
|
||||
$this->assertEquals($sExpectedOperator, $aRes[0]['operator']);
|
||||
}
|
||||
|
||||
function ToSearchFormProvider()
|
||||
{
|
||||
return array(
|
||||
'=' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"ref": "Contact.name",
|
||||
"widget": "string",
|
||||
"values": [
|
||||
{
|
||||
"value": "toto",
|
||||
"label": "toto"
|
||||
}
|
||||
],
|
||||
"operator": "=",
|
||||
"oql": "(`Contact`.`name` = \'toto\')"
|
||||
}
|
||||
]', true),
|
||||
'='
|
||||
),
|
||||
'starts_with' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"ref": "Contact.name",
|
||||
"widget": "string",
|
||||
"values": [
|
||||
{
|
||||
"value": "toto%",
|
||||
"label": "toto%"
|
||||
}
|
||||
],
|
||||
"operator": "LIKE",
|
||||
"oql": "(`Contact`.`name` LIKE \'toto%\')"
|
||||
}
|
||||
]', true),
|
||||
'starts_with'
|
||||
),
|
||||
'ends_with' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"ref": "Contact.name",
|
||||
"widget": "string",
|
||||
"values": [
|
||||
{
|
||||
"value": "%toto",
|
||||
"label": "%toto"
|
||||
}
|
||||
],
|
||||
"operator": "LIKE",
|
||||
"oql": "(`Contact`.`name` LIKE \'%toto\')"
|
||||
}
|
||||
]', true),
|
||||
'ends_with'
|
||||
),
|
||||
'contains' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"widget": "string",
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "%toto%",
|
||||
"label": "%toto%"
|
||||
}
|
||||
],
|
||||
"operator": "LIKE",
|
||||
"oql": "(`Contact`.`name` LIKE \'%toto%\')"
|
||||
}
|
||||
]', true),
|
||||
'contains'
|
||||
),
|
||||
'empty1' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"widget": "string",
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "LIKE",
|
||||
"oql": "(`Contact`.`name` LIKE \'\')"
|
||||
}
|
||||
]', true),
|
||||
'empty'
|
||||
),
|
||||
'empty2' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"widget": "string",
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "=",
|
||||
"oql": "(`Contact`.`name` = \'\')"
|
||||
}
|
||||
]', true),
|
||||
'empty'
|
||||
),
|
||||
'not_empty' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"widget": "string",
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "!=",
|
||||
"oql": "(`Contact`.`name` != \'\')"
|
||||
}
|
||||
]', true),
|
||||
'not_empty'
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider OqlProvider
|
||||
*
|
||||
* @param $sOQL
|
||||
*
|
||||
* @param $sExpectedOQL
|
||||
*
|
||||
* @param $aExpectedCriterion
|
||||
*
|
||||
* @throws \DictExceptionUnknownLanguage
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \OQLException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
function testOqlToSearchToOql($sOQL, $sExpectedOQL, $aExpectedCriterion)
|
||||
{
|
||||
// For tests on tags
|
||||
$this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag1', 'First');
|
||||
$this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag2', 'Second');
|
||||
|
||||
$this->OqlToSearchToOqlAltLanguage($sOQL, $sExpectedOQL, $aExpectedCriterion, "EN US");
|
||||
}
|
||||
|
||||
function OqlProvider()
|
||||
{
|
||||
return array(
|
||||
'no criteria' => array(
|
||||
'OQL' => 'SELECT WebApplication',
|
||||
'ExpectedOQL' => "SELECT `WebApplication` FROM WebApplication AS `WebApplication` WHERE 1",
|
||||
'ExpectedCriterion' => array(),
|
||||
),
|
||||
'string starts' => array(
|
||||
'OQL' => "SELECT Contact WHERE name LIKE 'toto%'",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE (`Contact`.`name` LIKE 'toto%')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'string', 'operator' => 'starts_with', 'values' => array(array('value' => 'toto')))),
|
||||
),
|
||||
'string ends' => array(
|
||||
'OQL' => "SELECT Contact WHERE name LIKE '%toto'",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE (`Contact`.`name` LIKE '%toto')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'string', 'operator' => 'ends_with', 'values' => array(array('value' => 'toto')))),
|
||||
),
|
||||
'string contains 1' => array(
|
||||
'OQL' => "SELECT Contact WHERE name LIKE '%toto%'",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE (`Contact`.`name` LIKE '%toto%')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'string', 'operator' => 'contains', 'values' => array(array('value' => 'toto')))),
|
||||
),
|
||||
'string contains 2' => array(
|
||||
'OQL' => "SELECT Person AS B WHERE B.name LIKE '%A%'",
|
||||
'ExpectedOQL' => "SELECT `B` FROM Person AS `B` WHERE (`B`.`name` LIKE '%A%')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'string', 'operator' => 'contains', 'values' => array(array('value' => 'A')))),
|
||||
),
|
||||
'string NOT contains' => array(
|
||||
'OQL' => "SELECT Person AS B WHERE B.name NOT LIKE '%A%'",
|
||||
'ExpectedOQL' => "SELECT `B` FROM Person AS `B` WHERE (`B`.`name` NOT LIKE '%A%')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'string', 'operator' => 'NOT LIKE', 'values' => array(array('value' => '%A%')))),
|
||||
),
|
||||
'string regexp' => array(
|
||||
'OQL' => "SELECT Server WHERE name REGEXP '^dbserver[0-9]+\\\\\\\\..+\\\\\\\\.[a-z]{2,3}$'",
|
||||
'ExpectedOQL' => "SELECT `Server` FROM Server AS `Server` WHERE (`Server`.`name` REGEXP '^dbserver[0-9]+\\\\\\\\..+\\\\\\\\.[a-z]{2,3}$')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'string', 'operator' => 'REGEXP')),
|
||||
),
|
||||
'enum + key =' => array(
|
||||
'OQL' => "SELECT Contact WHERE status = 'active' AND org_id = 3",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` JOIN Organization AS `Organization` ON `Contact`.org_id = `Organization`.id JOIN Organization AS `Organization1` ON `Organization`.parent_id BELOW `Organization1`.id WHERE ((`Organization1`.`id` = '3') AND (`Contact`.`status` = 'active'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key', 'operator' => 'IN'), array('widget' => 'enum', 'operator' => 'IN')),
|
||||
),
|
||||
'enum =' => array(
|
||||
'OQL' => "SELECT Contact WHERE status = 'active'",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE (`Contact`.`status` = 'active')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'enum', 'operator' => 'IN', 'values' => array(array('value' => 'active')))),
|
||||
),
|
||||
'enum IN' => array(
|
||||
'OQL' => "SELECT Contact WHERE status IN ('active', 'inactive')",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE 1",
|
||||
'ExpectedCriterion' => array(array('widget' => 'enum', 'operator' => 'IN', 'values' => array(array('value' => 'active'), array('value' => 'inactive')))),
|
||||
),
|
||||
'enum NOT IN 1' => array(
|
||||
'OQL' => "SELECT Contact WHERE status NOT IN ('active')",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE (`Contact`.`status` = 'inactive')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'enum', 'operator' => 'IN', 'values' => array(array('value' => 'inactive')))),
|
||||
),
|
||||
'enum NOT IN 2' => array(
|
||||
'OQL' => "SELECT Person AS p JOIN UserRequest AS u ON u.agent_id = p.id WHERE u.status != 'closed'",
|
||||
'ExpectedOQL' => "SELECT `p` FROM Person AS `p` JOIN UserRequest AS `u` ON `u`.agent_id = `p`.id WHERE (`u`.`status` != 'closed')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
),
|
||||
'enum undefined 1' => array(
|
||||
'OQL' => "SELECT FunctionalCI WHERE ((business_criticity = 'high') OR ISNULL(business_criticity)) AND 1",
|
||||
'ExpectedOQL' => "SELECT `FunctionalCI` FROM FunctionalCI AS `FunctionalCI` WHERE (((`FunctionalCI`.`business_criticity` = 'high') OR ISNULL(`FunctionalCI`.`business_criticity`)) AND 1)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'enum', 'has_undefined' => true, 'operator' => 'IN', 'values' => array(array('value' => 'high'), array('value' => 'null')))),
|
||||
),
|
||||
'enum undefined 2' => array(
|
||||
'OQL' => "SELECT FunctionalCI WHERE ((business_criticity IN ('high', 'medium')) OR ISNULL(business_criticity)) AND 1",
|
||||
'ExpectedOQL' => "SELECT `FunctionalCI` FROM FunctionalCI AS `FunctionalCI` WHERE (((`FunctionalCI`.`business_criticity` IN ('high', 'medium')) OR ISNULL(`FunctionalCI`.`business_criticity`)) AND 1)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'enum', 'has_undefined' => true, 'operator' => 'IN', 'values' => array(array('value' => 'high'), array('value' => 'medium'), array('value' => 'null')))),
|
||||
),
|
||||
'enum undefined 3' => array(
|
||||
'OQL' => "SELECT FunctionalCI WHERE ISNULL(business_criticity)",
|
||||
'ExpectedOQL' => "SELECT `FunctionalCI` FROM FunctionalCI AS `FunctionalCI` WHERE ISNULL(`FunctionalCI`.`business_criticity`)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'enum', 'has_undefined' => true, 'operator' => 'IN', 'values' => array(array('value' => 'null')))),
|
||||
),
|
||||
'key NOT IN' => array(
|
||||
'OQL' => "SELECT Contact WHERE org_id NOT IN ('1')",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE (`Contact`.`org_id` NOT IN ('1'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw', 'operator' => 'NOT IN')),
|
||||
),
|
||||
'key IN' => array(
|
||||
'OQL' => "SELECT Contact WHERE org_id IN ('1')",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` JOIN Organization AS `Organization` ON `Contact`.org_id = `Organization`.id JOIN Organization AS `Organization1` ON `Organization`.parent_id BELOW `Organization1`.id WHERE (`Organization1`.`id` = '1')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key', 'operator' => 'IN')),
|
||||
),
|
||||
'key IN 2' => array(
|
||||
'OQL' => "SELECT Contact WHERE org_id IN ('1', '999999')",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` JOIN Organization AS `Organization` ON `Contact`.org_id = `Organization`.id JOIN Organization AS `Organization1` ON `Organization`.parent_id BELOW `Organization1`.id WHERE (`Organization1`.`id` = '1')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key', 'operator' => 'IN')),
|
||||
),
|
||||
'key empty' => array(
|
||||
'OQL' => "SELECT Person WHERE location_id = '0'",
|
||||
'ExpectedOQL' => "SELECT `Person` FROM Person AS `Person` WHERE (`Person`.`location_id` = '0')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'external_key', 'operator' => 'IN', 'values' => array(array('value' => '0')))),
|
||||
),
|
||||
'Double field' => array(
|
||||
'OQL' => "SELECT UserRequest AS u WHERE u.close_date > u.start_date",
|
||||
'ExpectedOQL' => "SELECT `u` FROM UserRequest AS `u` WHERE (`u`.`close_date` > `u`.`start_date`)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
),
|
||||
'Num between 1' => array(
|
||||
'OQL' => "SELECT Server WHERE nb_u >= 0 AND 1 >= nb_u",
|
||||
'ExpectedOQL' => "SELECT `Server` FROM Server AS `Server` WHERE ((`Server`.`nb_u` >= '0') AND (`Server`.`nb_u` <= '1'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'numeric', 'operator' => 'between')),
|
||||
),
|
||||
'Num ISNULL' => array(
|
||||
'OQL' => "SELECT Server WHERE ISNULL(nb_u)",
|
||||
'ExpectedOQL' => "SELECT `Server` FROM Server AS `Server` WHERE ISNULL(`Server`.`nb_u`)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'numeric', 'operator' => 'empty')),
|
||||
),
|
||||
'Hierarchical below 1' => array(
|
||||
'OQL' => "SELECT Person AS P JOIN Organization AS Node ON P.org_id = Node.id JOIN Organization AS Root ON Node.parent_id BELOW Root.id WHERE Root.id=1",
|
||||
'ExpectedOQL' => "SELECT `P` FROM Person AS `P` JOIN Organization AS `Node` ON `P`.org_id = `Node`.id JOIN Organization AS `Root` ON `Node`.parent_id BELOW `Root`.id WHERE (`Root`.`id` = '1')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key')),
|
||||
),
|
||||
'Hierarchical below 2' => array(
|
||||
'OQL' => "SELECT `Organization` FROM Organization AS `Organization` JOIN Organization AS `Organization1` ON `Organization`.parent_id = `Organization1`.id JOIN Organization AS `Organization11` ON `Organization1`.parent_id BELOW `Organization11`.id WHERE (((`Organization11`.`id` IN ('1', '2')) OR (`Organization`.`parent_id` = '0')) AND 1)",
|
||||
'ExpectedOQL' => "SELECT `Organization` FROM Organization AS `Organization` JOIN Organization AS `Organization1` ON `Organization`.parent_id = `Organization1`.id JOIN Organization AS `Organization11` ON `Organization1`.parent_id BELOW `Organization11`.id WHERE (((`Organization11`.`id` IN ('1', '2')) OR (`Organization`.`parent_id` = '0')) AND 1)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key')),
|
||||
),
|
||||
'IP range' => array(
|
||||
'OQL' => "SELECT DatacenterDevice AS dev WHERE INET_ATON(dev.managementip) > INET_ATON('10.22.32.224') AND INET_ATON(dev.managementip) < INET_ATON('10.22.32.255')",
|
||||
'ExpectedOQL' => "SELECT `dev` FROM DatacenterDevice AS `dev` WHERE ((INET_ATON(`dev`.`managementip`) < INET_ATON('10.22.32.255')) AND (INET_ATON(`dev`.`managementip`) > INET_ATON('10.22.32.224')))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
),
|
||||
'TagSet Matches' => array(
|
||||
'OQL' => "SELECT ".TAG_CLASS." WHERE ".TAG_ATTCODE." MATCHES 'tag1'",
|
||||
'ExpectedOQL' => "SELECT `".TAG_CLASS."` FROM ".TAG_CLASS." AS `".TAG_CLASS."` WHERE `".TAG_CLASS."`.`".TAG_ATTCODE.'` MATCHES \'tag1 _\'',
|
||||
'ExpectedCriterion' => array(array('widget' => 'tag_set')),
|
||||
),
|
||||
'TagSet Matches2' => array(
|
||||
'OQL' => "SELECT ".TAG_CLASS." WHERE ".TAG_ATTCODE." MATCHES 'tag1 tag2'",
|
||||
'ExpectedOQL' => "SELECT `".TAG_CLASS."` FROM ".TAG_CLASS." AS `".TAG_CLASS."` WHERE `".TAG_CLASS."`.`".TAG_ATTCODE.'` MATCHES \'tag1 tag2 _\'',
|
||||
'ExpectedCriterion' => array(array('widget' => 'tag_set')),
|
||||
),
|
||||
'TagSet Undefined' => array(
|
||||
'OQL' => "SELECT ".TAG_CLASS." WHERE ".TAG_ATTCODE." = ''",
|
||||
'ExpectedOQL' => "SELECT `".TAG_CLASS."` FROM ".TAG_CLASS." AS `".TAG_CLASS."` WHERE (`".TAG_CLASS."`.`".TAG_ATTCODE."` = '')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'tag_set')),
|
||||
),
|
||||
'TagSet Undefined and tag' => array(
|
||||
'OQL' => "SELECT ".TAG_CLASS." WHERE (((".TAG_ATTCODE." MATCHES 'tag1 tag2') OR (".TAG_ATTCODE." = '')) AND 1)",
|
||||
'ExpectedOQL' => "SELECT `".TAG_CLASS."` FROM ".TAG_CLASS." AS `".TAG_CLASS."` WHERE ((`".TAG_CLASS."`.`".TAG_ATTCODE.'` MATCHES \'tag1 tag2 _\' OR (`'.TAG_CLASS."`.`".TAG_ATTCODE."` = '')) AND 1)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'tag_set')),
|
||||
),
|
||||
'TagSet equals' => array(
|
||||
'OQL' => "SELECT ".TAG_CLASS." WHERE ".TAG_ATTCODE." = 'tag1 tag2'",
|
||||
'ExpectedOQL' => "SELECT `".TAG_CLASS."` FROM ".TAG_CLASS." AS `".TAG_CLASS."` WHERE (`".TAG_CLASS."`.`".TAG_ATTCODE.'` MATCHES \'tag1 _\' AND `'.TAG_CLASS."`.`".TAG_ATTCODE.'` MATCHES \'tag2 _\')',
|
||||
'ExpectedCriterion' => array(array('widget' => 'tag_set')),
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider OqlProviderDates
|
||||
*
|
||||
* @param $sOQL
|
||||
*
|
||||
* @param $sExpectedOQL
|
||||
*
|
||||
* @param $aExpectedCriterion
|
||||
*
|
||||
* @throws \DictExceptionUnknownLanguage
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \OQLException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
function testOqlToForSearchToOqlAltLanguageFR($sOQL, $sExpectedOQL, $aExpectedCriterion)
|
||||
{
|
||||
\MetaModel::GetConfig()->Set('date_and_time_format', array('default' => array('date' => 'Y-m-d', 'time' => 'H:i:s', 'date_time' => '$date $time')));
|
||||
$this->OqlToSearchToOqlAltLanguage($sOQL, $sExpectedOQL, $aExpectedCriterion, "FR FR");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @dataProvider OqlProviderDates
|
||||
*
|
||||
* @param $sOQL
|
||||
*
|
||||
* @param $sExpectedOQL
|
||||
*
|
||||
* @param $aExpectedCriterion
|
||||
*
|
||||
* @throws \DictExceptionUnknownLanguage
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \OQLException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
function testOqlToForSearchToOqlAltLanguageEN($sOQL, $sExpectedOQL, $aExpectedCriterion)
|
||||
{
|
||||
\MetaModel::GetConfig()->Set('date_and_time_format', array('default' => array('date' => 'Y-m-d', 'time' => 'H:i:s', 'date_time' => '$date $time')));
|
||||
$this->OqlToSearchToOqlAltLanguage($sOQL, $sExpectedOQL, $aExpectedCriterion, "EN US");
|
||||
}
|
||||
|
||||
function OqlProviderDates()
|
||||
{
|
||||
return array(
|
||||
|
||||
'Date relative 1' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE DATE_SUB(NOW(), INTERVAL 14 DAY) < start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (DATE_SUB(NOW(), INTERVAL 14 DAY) < `UserRequest`.`start_date`)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
),
|
||||
'Date relative 2' => array(
|
||||
'OQL' => "SELECT Contract AS c WHERE c.end_date > NOW() AND c.end_date < DATE_ADD(NOW(), INTERVAL 30 DAY)",
|
||||
'ExpectedOQL' => "SELECT `c` FROM Contract AS `c` WHERE ((`c`.`end_date` < DATE_ADD(NOW(), INTERVAL 30 DAY)) AND (`c`.`end_date` > NOW()))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw'), array('widget' => 'raw')),
|
||||
),
|
||||
'Date relative 3' => array(
|
||||
'OQL' => "SELECT UserRequest AS u WHERE u.close_date > DATE_ADD(u.start_date, INTERVAL 8 HOUR)",
|
||||
'ExpectedOQL' => "SELECT `u` FROM UserRequest AS `u` WHERE (`u`.`close_date` > DATE_ADD(`u`.`start_date`, INTERVAL 8 HOUR))",
|
||||
'ExpectedCriterion' => array(),
|
||||
),
|
||||
'Date relative 4' => array(
|
||||
'OQL' => "SELECT UserRequest AS u WHERE u.start_date < DATE_SUB(NOW(), INTERVAL 60 MINUTE) AND u.status = 'new'",
|
||||
'ExpectedOQL' => "SELECT `u` FROM UserRequest AS `u` WHERE ((`u`.`start_date` < DATE_SUB(NOW(), INTERVAL 60 MINUTE)) AND (`u`.`status` = 'new'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
),
|
||||
'Date between 1' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE start_date > '2017-01-01 00:00:00' AND '2018-01-01 00:00:00' >= start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` >= '2017-01-01 00:00:01') AND (`UserRequest`.`start_date` <= '2018-01-01 00:00:00'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date_time', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date between 2' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE start_date > '2017-01-01 00:00:00' AND status = 'active' AND org_id = 3 AND '2018-01-01 00:00:00' >= start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` JOIN Organization AS `Organization` ON `UserRequest`.org_id = `Organization`.id JOIN Organization AS `Organization1` ON `Organization`.parent_id BELOW `Organization1`.id WHERE ((((`Organization1`.`id` = '3') AND (`UserRequest`.`start_date` >= '2017-01-01 00:00:01')) AND (`UserRequest`.`start_date` <= '2018-01-01 00:00:00')) AND (`UserRequest`.`status` = 'active'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key', 'operator' => 'IN'), array('widget' => 'date_time', 'operator' => 'between_dates'), array('widget' => 'enum', 'operator' => 'IN')),
|
||||
),
|
||||
'Date between 3' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-01 00:00:00' >= start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` >= '2017-01-01 00:00:00') AND (`UserRequest`.`start_date` <= '2017-01-01 00:00:00'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date_time', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date between 4' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-01 01:00:00' > start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` >= '2017-01-01 00:00:00') AND (`UserRequest`.`start_date` <= '2017-01-01 00:59:59'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date_time', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date between 5' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-02 00:00:00' > start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` >= '2017-01-01 00:00:00') AND (`UserRequest`.`start_date` <= '2017-01-01 23:59:59'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date_time', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date between 6' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01' AND '2017-01-02' >= start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` >= '2017-01-01 00:00:00') AND (`UserRequest`.`start_date` <= '2017-01-02 00:00:00'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date_time', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date between 7' => array(
|
||||
'OQL' => "SELECT CustomerContract WHERE ((start_date >= '2018-03-01') AND (start_date < '2018-04-01'))",
|
||||
'ExpectedOQL' => "SELECT `CustomerContract` FROM CustomerContract AS `CustomerContract` WHERE ((`CustomerContract`.`start_date` >= '2018-03-01') AND (`CustomerContract`.`start_date` <= '2018-03-31'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date =' => array(
|
||||
'OQL' => "SELECT CustomerContract WHERE (start_date = '2018-03-01')",
|
||||
'ExpectedOQL' => "SELECT `CustomerContract` FROM CustomerContract AS `CustomerContract` WHERE ((`CustomerContract`.`start_date` >= '2018-03-01') AND (`CustomerContract`.`start_date` <= '2018-03-01'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date =2' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE (DATE_FORMAT(start_date, '%Y-%m-%d') = '2018-03-21')",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` >= '2018-03-21 00:00:00') AND (`UserRequest`.`start_date` <= '2018-03-21 23:59:59'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date_time', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date =3' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE (DATE_FORMAT(`UserRequest`.`start_date`, '%w') = '4')",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (DATE_FORMAT(`UserRequest`.`start_date`, '%w') = '4')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $sOQL
|
||||
*
|
||||
* @param $sExpectedOQL
|
||||
*
|
||||
* @param $aExpectedCriterion
|
||||
*
|
||||
* @param $sLanguageCode
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionUnknownLanguage
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \OQLException
|
||||
*/
|
||||
function OqlToSearchToOqlAltLanguage($sOQL, $sExpectedOQL, $aExpectedCriterion, $sLanguageCode )
|
||||
{
|
||||
$this->debug($sOQL);
|
||||
|
||||
|
||||
Dict::SetUserLanguage($sLanguageCode);
|
||||
|
||||
|
||||
$oSearchForm = new SearchForm();
|
||||
$oSearch = DBSearch::FromOQL($sOQL);
|
||||
$aFields = $oSearchForm->GetFields(new DBObjectSet($oSearch));
|
||||
/** @var \DBObjectSearch $oSearch */
|
||||
$aCriterion = $oSearchForm->GetCriterion($oSearch, $aFields);
|
||||
|
||||
$aAndCriterion = $aCriterion['or'][0]['and'];
|
||||
|
||||
$aNewCriterion = array();
|
||||
foreach($aAndCriterion as $aCriteria)
|
||||
{
|
||||
if ($aCriteria['widget'] != AttributeDefinition::SEARCH_WIDGET_TYPE_RAW)
|
||||
{
|
||||
unset($aCriteria['oql']);
|
||||
foreach($aFields as $aCatFields)
|
||||
{
|
||||
if (isset($aCatFields[$aCriteria['ref']]))
|
||||
{
|
||||
$aField = $aCatFields[$aCriteria['ref']];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isset($aField))
|
||||
{
|
||||
$aCriteria['code'] = $aField['code'];
|
||||
$aCriteria['class'] = $aField['class'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($aCriteria['widget'] == AttributeDefinition::SEARCH_WIDGET_TYPE_DATE_TIME || $aCriteria['widget'] == AttributeDefinition::SEARCH_WIDGET_TYPE_DATE)
|
||||
{
|
||||
$sAttributeClass = ($aCriteria['widget'] == AttributeDefinition::SEARCH_WIDGET_TYPE_DATE_TIME) ? AttributeDateTime::class : AttributeDate::class;
|
||||
|
||||
/** @var \AttributeDateTime $sAttributeClass */
|
||||
/** @var \DateTimeFormat $oFormat */
|
||||
$oFormat = $sAttributeClass::GetFormat();
|
||||
|
||||
foreach($aCriteria['values'] as $i => $aValue)
|
||||
{
|
||||
if (!empty($aValue['value'])) {
|
||||
$aCriteria['values'][$i]['value'] = $oFormat->Format($aValue['value']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aNewCriterion[] = $aCriteria;
|
||||
}
|
||||
$this->debug($aNewCriterion);
|
||||
|
||||
$this->assertFalse($this->array_diff_assoc_recursive($aExpectedCriterion, $aNewCriterion), 'Criterion array contains critical parts');
|
||||
|
||||
$aCriterion['or'][0]['and'] = $aNewCriterion;
|
||||
|
||||
$oSearch->ResetCondition();
|
||||
$oFilter = CriterionParser::Parse($oSearch->ToOQL(), $aCriterion);
|
||||
|
||||
$sResultOQL = $oFilter->ToOQL();
|
||||
$this->debug($sResultOQL);
|
||||
|
||||
$this->assertEquals($sExpectedOQL, $sResultOQL);
|
||||
}
|
||||
|
||||
|
||||
function array_diff_assoc_recursive($array1, $array2)
|
||||
{
|
||||
foreach($array1 as $key => $value)
|
||||
{
|
||||
if (is_array($value))
|
||||
{
|
||||
if (!isset($array2[$key]))
|
||||
{
|
||||
$difference[$key] = $value;
|
||||
}
|
||||
elseif (!is_array($array2[$key]))
|
||||
{
|
||||
$difference[$key] = $value;
|
||||
}
|
||||
else
|
||||
{
|
||||
$new_diff = $this->array_diff_assoc_recursive($value, $array2[$key]);
|
||||
if ($new_diff !== false)
|
||||
{
|
||||
$difference[$key] = $new_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (!array_key_exists($key, $array2) || $array2[$key] != $value)
|
||||
{
|
||||
$difference[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return !isset($difference) ? false : $difference;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2021 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/>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Eric
|
||||
* Date: 08/03/2018
|
||||
* Time: 11:28
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Application\Search;
|
||||
|
||||
use Combodo\iTop\Application\Search\CriterionParser;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
|
||||
/**
|
||||
* @group itopRequestMgmt
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class CriterionParserTest extends ItopDataTestCase
|
||||
{
|
||||
public function testParse()
|
||||
{
|
||||
$sBaseOql = 'SELECT UserRequest';
|
||||
$aCriterion = json_decode('{
|
||||
"or": [
|
||||
{
|
||||
"and": [
|
||||
{
|
||||
"ref": "UserRequest.start_date",
|
||||
"values": [
|
||||
{
|
||||
"value": "2017-01-01",
|
||||
"label": "2017-01-01 00:00:00"
|
||||
}
|
||||
],
|
||||
"operator": ">",
|
||||
"oql": ""
|
||||
},
|
||||
{
|
||||
"ref": "UserRequest.start_date",
|
||||
"values": [
|
||||
{
|
||||
"value": "2018-01-01",
|
||||
"label": "2018-01-01 00:00:00"
|
||||
}
|
||||
],
|
||||
"operator": "<",
|
||||
"oql": "(`UserRequest`.`start_date` < \'2018-01-01\')"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
', true);
|
||||
$oSearch = CriterionParser::Parse($sBaseOql, $aCriterion);
|
||||
|
||||
//$this->debug($oSearch);
|
||||
|
||||
$this->assertEquals("SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` > '2017-01-01') AND (`UserRequest`.`start_date` < '2018-01-01'))", $oSearch->ToOQL());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2021 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Application\Search;
|
||||
|
||||
use Combodo\iTop\Application\Search\SearchForm;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use DBObjectSearch;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @group itopRequestMgmt
|
||||
*
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class SearchFormTest extends ItopDataTestCase
|
||||
{
|
||||
const CREATE_TEST_ORG = true;
|
||||
|
||||
/**
|
||||
* @dataProvider GetFieldsProvider
|
||||
* @throws \OQLException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function testGetFields($sOQL)
|
||||
{
|
||||
$oSearchForm = new SearchForm();
|
||||
$oSearch = \DBSearch::FromOQL($sOQL);
|
||||
$aFields = $oSearchForm->GetFields(new \DBObjectSet($oSearch));
|
||||
$this->debug($sOQL);
|
||||
$this->debug(json_encode($aFields, JSON_PRETTY_PRINT));
|
||||
$this->assertTrue(count($aFields['zlist']) > 0);
|
||||
$this->assertTrue(count($aFields['others']) > 0);
|
||||
}
|
||||
|
||||
public function GetFieldsProvider()
|
||||
{
|
||||
return array(
|
||||
array("SELECT Contact"),
|
||||
array("SELECT Contact AS C WHERE C.status = 'active'"),
|
||||
array("SELECT Person"),
|
||||
array(
|
||||
"SELECT Person AS p JOIN UserRequest AS u ON u.agent_id = p.id WHERE u.status != 'closed'",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @dataProvider GetCriterionProvider
|
||||
*
|
||||
* @param $sOQL
|
||||
* @param $iOrCount
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \MissingQueryArgument
|
||||
*/
|
||||
public function testGetCriterion($sOQL, $iOrCount)
|
||||
{
|
||||
$oSearchForm = new SearchForm();
|
||||
try
|
||||
{
|
||||
$oSearch = \DBSearch::FromOQL($sOQL);
|
||||
$aFields = $oSearchForm->GetFields(new \DBObjectSet($oSearch));
|
||||
/** @var DBObjectSearch $oSearch */
|
||||
$aCriterion = $oSearchForm->GetCriterion($oSearch, $aFields);
|
||||
} catch (\OQLException $e)
|
||||
{
|
||||
$this->assertTrue(false);
|
||||
|
||||
return;
|
||||
}
|
||||
$aRes = array('base_oql' => $sOQL, 'criterion' => $aCriterion);
|
||||
$this->debug(json_encode($aRes));
|
||||
$this->debug($sOQL);
|
||||
$this->debug(json_encode($aCriterion, JSON_PRETTY_PRINT));
|
||||
$this->assertCount($iOrCount, $aCriterion['or']);
|
||||
}
|
||||
|
||||
public function GetCriterionProvider()
|
||||
{
|
||||
return array(
|
||||
array('OQL' => "SELECT Contact", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status = 'active'", 1),
|
||||
array('OQL' => "SELECT Contact AS C WHERE C.status = 'active'", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status = 'active' AND name LIKE 'toto%'", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status = 'active' AND org_id = 3", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status IN ('active', 'inactive')", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status NOT IN ('active')", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status NOT IN ('active', 'inactive')", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status = 'active' OR name LIKE 'toto%'", 2),
|
||||
array('OQL' => "SELECT UserRequest WHERE DATE_SUB(NOW(), INTERVAL 14 DAY) < start_date", 1),
|
||||
array('OQL' => "SELECT UserRequest WHERE start_date > '2017-01-01 00:00:00' AND '2018-01-01 00:00:00' >= start_date", 1),
|
||||
array('OQL' => "SELECT UserRequest WHERE start_date > '2017-01-01 00:00:00' AND status = 'active' AND org_id = 3 AND '2018-01-01 00:00:00' >= start_date", 1),
|
||||
array('OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-01 00:00:00' >= start_date", 1),
|
||||
array('OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-01 01:00:00' > start_date", 1),
|
||||
array('OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-02 00:00:00' > start_date", 1),
|
||||
array(
|
||||
'OQL' => "SELECT FunctionalCI WHERE ((business_criticity IN ('high', 'medium')) OR ISNULL(business_criticity)) AND 1",
|
||||
1
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* User: Guy Couronné (guy.couronne@gmail.com)
|
||||
* Date: 25/01/2019
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Status;
|
||||
|
||||
/**
|
||||
* User: Guy Couronné (guy.couronne@gmail.com)
|
||||
* Date: 25/01/2019
|
||||
*/
|
||||
|
||||
use Config;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use function Combodo\iTop\Application\Status\StatusCheckConfigFile;
|
||||
use function Combodo\iTop\Application\Status\StatusGetAppRoot;
|
||||
use function Combodo\iTop\Application\Status\StatusStartup;
|
||||
|
||||
if (!defined('DEBUG_UNIT_TEST')) {
|
||||
define('DEBUG_UNIT_TEST', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class StatusIncTest extends TestCase {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $sAppRoot = '';
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
//AppRoot is the directory containing the directory
|
||||
//Assume getcwd() is runned inside APPROOT/test
|
||||
$this->sAppRoot = __DIR__.'/../../../../../../sources/application/status';
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
*/
|
||||
public function testStatusGetAppRootWrongPath() {
|
||||
include_once($this->sAppRoot . '/Status.php');
|
||||
|
||||
$sAppRootFilenamewrong = 'approot.inc.php_wrong';
|
||||
|
||||
StatusGetAppRoot($sAppRootFilenamewrong);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function testStatusGetAppRootGood() {
|
||||
include_once($this->sAppRoot . '/Status.php');
|
||||
|
||||
StatusGetAppRoot();
|
||||
|
||||
$this->assertNotEmpty(APPROOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
*/
|
||||
public function testStatusCheckConfigFileWrongPath() {
|
||||
include_once($this->sAppRoot . '/Status.php');
|
||||
|
||||
$sConfigFilenamewrong = 'config-itop.php_wrong';
|
||||
|
||||
StatusCheckConfigFile($sConfigFilenamewrong);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function testStatusCheckConfigFileGood() {
|
||||
include_once($this->sAppRoot . '/Status.php');
|
||||
|
||||
StatusCheckConfigFile();
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \MySQLException
|
||||
*/
|
||||
public function testStatusStartupWrongDbPwd() {
|
||||
include_once($this->sAppRoot . '/Status.php');
|
||||
|
||||
StatusCheckConfigFile();
|
||||
require_once(APPROOT . '/core/cmdbobject.class.inc.php');
|
||||
require_once(APPROOT . '/application/utils.inc.php');
|
||||
require_once(APPROOT . '/core/contexttag.class.inc.php');
|
||||
|
||||
$oConfigWrong = new Config(ITOP_DEFAULT_CONFIG_FILE);
|
||||
$oConfigWrong->Set('db_pwd', $oConfigWrong->Get('db_pwd') . '_unittest');
|
||||
|
||||
StatusStartup($oConfigWrong);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function testStatusStartupGood() {
|
||||
include_once($this->sAppRoot . '/Status.php');
|
||||
|
||||
StatusStartup();
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* User: Guy Couronné (guy.couronne@gmail.com)
|
||||
* Date: 25/01/2019
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Status;
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
|
||||
class StatusTest extends ItopTestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
require_once APPROOT.'core/config.class.inc.php'; // for constants
|
||||
}
|
||||
|
||||
public function testStatusWrongUrl() {
|
||||
$sPath = APPROOT.'/status_wrong.php';
|
||||
|
||||
exec("php $sPath", $aOutput, $iRet);
|
||||
$this->assertNotEquals(0, $iRet, "Problem executing status page: $sPath, $iRet, aOutput:\n" . var_export($aOutput, true));
|
||||
|
||||
}
|
||||
|
||||
public function testStatusGood() {
|
||||
$sPath = APPROOT.'/webservices/status.php';
|
||||
|
||||
exec("php $sPath", $aOutput, $iRet);
|
||||
$this->assertEquals(0, $iRet, "Problem executing status page: $sPath, $iRet, aOutput:\n".var_export($aOutput, true));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function testStatusGoodWithJson()
|
||||
{
|
||||
$sPath = APPROOT.'/webservices/status.php';
|
||||
|
||||
exec("php $sPath", $aOutput, $iRet);
|
||||
$sAdditionalInfo = "aOutput:\n".var_export($aOutput, true).'.';
|
||||
|
||||
//Check response
|
||||
$this->assertNotEmpty($aOutput[0], 'Empty response. '.$sAdditionalInfo);
|
||||
$this->assertJson($aOutput[0], 'Not a JSON. '.$sAdditionalInfo);
|
||||
|
||||
$aResponseDecoded = json_decode($aOutput[0], true);
|
||||
|
||||
//Check status
|
||||
$this->assertArrayHasKey('status', $aResponseDecoded, 'JSON does not have a \'status\' field. '.$sAdditionalInfo);
|
||||
$this->assertEquals('RUNNING', $aResponseDecoded['status'], 'Status is not \'RUNNING\'. '.$sAdditionalInfo);
|
||||
//Check code
|
||||
$this->assertArrayHasKey('code', $aResponseDecoded, 'JSON does not have a \'code\' field. '.$sAdditionalInfo);
|
||||
$this->assertEquals(0, $aResponseDecoded['code'], 'Code is not 0. '.$sAdditionalInfo);
|
||||
//Check message
|
||||
$this->assertArrayHasKey('message', $aResponseDecoded, 'JSON does not have a \'message\' field. '.$sAdditionalInfo);
|
||||
$this->assertEmpty($aResponseDecoded['message'], 'Message is not empty. '.$sAdditionalInfo);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
// Include status functions
|
||||
// Important: We can't use the APPROOT constant here as the current script will be executed via the PHP exec() function which won't have it loaded yet.
|
||||
require_once __DIR__.'/../../../../../../sources/application/status/Status.php';
|
||||
|
||||
// Do check Status
|
||||
try
|
||||
{
|
||||
\Combodo\iTop\Application\Status\StatusStartup();
|
||||
$aResult = array('status' => STATUS_RUNNING, 'code' => \RestResult::OK, 'message' => '');
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$iCode = (defined('\RestResult::INTERNAL_ERROR')) ? \RestResult::INTERNAL_ERROR : 100;
|
||||
$aResult = array('status' => STATUS_ERROR, 'code' => $iCode, 'message' => $e->getMessage());
|
||||
http_response_code(500);
|
||||
}
|
||||
|
||||
//Set headers, based on webservices/rest.php
|
||||
$sContentType = 'application/json';
|
||||
header('Content-type: ' . $sContentType);
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
|
||||
//Output result
|
||||
$sResponse = json_encode($aResult);
|
||||
echo $sResponse;
|
||||
Reference in New Issue
Block a user