Compare commits

...

60 Commits

Author SHA1 Message Date
rquetiez
1004dd9afb N°1649 - Support blobs and images as external fields 2020-07-03 22:11:11 +02:00
acognet
9628a1d028 N°2284 - Replace JQuery Autocompleter plugin by JQuery UI Autocomplete widget and start of bug 2390 - Auto-complete - Relevant results in first 2020-07-02 11:46:51 +02:00
acognet
5585385d08 N°2393 - API : Font Awesome remove v4 compatibility 2020-07-02 11:03:05 +02:00
acognet
98870b06e3 2548 - API : remove \DBObject::GetRelationQueries overrides in default datamodel 2020-07-01 16:28:20 +02:00
bruno DA SILVA
46d91322c1 n°2556 - fix errors in the merge of support/2.7 into develop
The cherry picks resulted in an out of order apply of the commits, the result was that the wrong code was keeped
2020-07-01 15:41:46 +02:00
acognet
ca28f8f3c4 2393 - API : Font Awesome remove v4 compatibility 2020-06-30 16:28:15 +02:00
acognet
0aaa55b35b 3009 - PHP Minimum version raised to 7.1 2020-06-30 10:10:00 +02:00
acognet
e9a1167da6 N°2363 - API : deprecate old linkedset update pattern 2020-06-30 09:02:42 +02:00
acognet
a67fce66fc N°2999 - Optimize OQL 2020-06-26 16:42:03 +02:00
acognet
491d1d7d53 N°API : remove CMDBSource::GetNextInsertId 2020-06-26 16:20:15 +02:00
acognet
54b48dc908 N°2372 - API : remove \MetaModel::EnumLinksClasses and \MetaModel::EnumLinkingClasses 2020-06-26 16:17:04 +02:00
acognet
dadeab58eb N°852 - Cleanup: remove deprecated impact analysis algorithm and clean up old broken test 2020-06-26 15:03:10 +02:00
acognet
0ecdc6620b N°852 - Cleanup: remove deprecated impact analysis algorithm 2020-06-26 15:02:30 +02:00
acognet
80161b909e N°2362 - API : remove DBInsertTracked / DBUpdateTracked 2020-06-26 14:16:14 +02:00
Pierre Goiffon
888232e8c3 Merge remote-tracking branch 'origin/support/2.7' into develop
# Conflicts:
#	test/core/HTMLDOMSanitizerTest.php
2020-06-26 10:53:49 +02:00
Pierre Goiffon
d904883bdd 📝 CONTRIBUTING : fix release branch naming 2020-06-23 17:48:42 +02:00
bruno DA SILVA
35d2c3afac uses the conventionnal host 2020-06-23 15:10:09 +02:00
Molkobain
7cee8c3cd0 Update README.md 2020-06-23 15:05:41 +02:00
Molkobain
27622bbcec Update readme.txt 2020-06-23 15:05:38 +02:00
bruno DA SILVA
219270ce81 Removes latest versions to ease maintenance 2020-06-23 14:59:11 +02:00
OИUЯd da silva
16dd47a3b9 simplify the readme (#143)
Removes latest versions to ease maintenance
2020-06-23 14:51:52 +02:00
Molkobain
70835984de Add "software requirements" section to README
At first I added a complete section with a table and all currently supported versions of iTop, then @bruno-ds pointed out that it would only be redundant with the wiki page and just another source of information to maintain (which is totally true, thanks!). So instead it's just a simple link in the "resources" section.
2020-06-23 14:23:15 +02:00
Pierre Goiffon
d9224f43f2 AttributeImage : remove useless override
The previous code was removed in d5b0bb02, and until then the method was just calling the parent doing nothing more
2020-06-23 11:39:51 +02:00
Molkobain
5b9643d6fb Update PHPDoc 2020-06-22 16:06:21 +02:00
bruno DA SILVA
d3525190d5 N°2556 - Html sanitization preserve content of removed tags (except for a forbidden list)
forbidden list: see $aTagsContentRemovableList

(cherry picked from commit 746b47bb0e)
(cherry picked from commit 79909fadc0)
2020-06-22 11:40:38 +02:00
Pierre Goiffon
f20808d929 Merge remote-tracking branch 'origin/support/2.7' into develop 2020-06-22 11:39:44 +02:00
Pierre Goiffon
aee80e41ca N°2214 Fix typo in method name
Introduced in b7136c0b7a
Many Thanks @jbostoen !
2020-06-19 13:47:15 +02:00
Pierre Goiffon
56ea6c8848 N°2214 fix @since after cherry-pick 2020-06-15 16:22:04 +02:00
Pierre Goiffon
b7136c0b7a N°2214 Add PHP check in CLI scripts
It is quite common that the PHP interpreter that is launched in CLI is different that the one used by the webserver. So iTop code launched by CLI could run in a context that doesn't meet iTop requirements !

This adds in the following scripts the same control that is done on the setup wizard first step :
* cron.php
* backup, check-backup
* export, exportv2
* bulk import
* synchro-exec, synchro-import

If the check throws at least one error then the script is stopped with an appropriate message, and a log is made (IssueLog, Error level, CLI channel)

(cherry picked from commit c768e18e2b : no risk taken for 2.7.1, so cherry picked for 2.8.0)
2020-06-15 15:20:17 +02:00
Pierre Goiffon
ea94986247 Merge remote-tracking branch 'origin/support/2.7' into develop 2020-06-15 15:19:12 +02:00
odain
d8363067e6 ci 2 new options: coverture + run only one test 💚
try to have coverture option
2020-06-15 10:32:47 +02:00
Thomas Casteleyn
b302569feb Update Dutch SynchroAttribute::update_policy translation 2020-06-08 13:02:57 +02:00
Pierre Goiffon
44008fc179 Merge remote-tracking branch 'origin/support/2.7' into develop 2020-05-26 12:26:44 +02:00
Thomas Casteleyn
c2f62a13e6 Fix duplicate version loading (#141) 2020-05-13 14:53:47 +02:00
Pierre Goiffon
accda04a37 Hierarchical selection popup : now collapsed by default, and collapse all / expand all buttons (#132)
The collapse all / expand all is not printed if no child exists
Combodo implementation of PR #87
2020-04-27 11:21:37 +02:00
Pierre Goiffon
f364e7b043 N°2923 Datatable : fix var name typo
Thanks @bruno-ds !
2020-04-24 18:28:50 +02:00
Pierre Goiffon
42afe033ef N°2923 Datatable : use container id instead of externally generated id 2020-04-24 17:16:47 +02:00
Pierre Goiffon
8de4c0360d Merge remote-tracking branch 'origin/support/2.7' into develop 2020-04-20 16:08:15 +02:00
Molkobain
24130dd94f Change version number to 2.8.0-dev 2020-04-14 18:01:30 +02:00
Pierre Goiffon
59cc6d3f76 📝 CONTRIBUTING : fix unecessary escape 2020-04-07 15:33:26 +02:00
Pierre Goiffon
ee37373cfa 📝 CONTRIBUTING : branch model paragraph small changes 2020-04-07 15:24:56 +02:00
Pierre Goiffon
56d9653f15 📝 CONTRIBUTING : modify branch model
We are renaming the master branch, so using a custom GitFlow branch model :)
2020-04-06 09:32:23 +02:00
Pierre Goiffon
d5670abdcc 📝 Fix PHPDoc for \MFElement::_FindNode
Introduced in 4688c92e
2020-04-06 08:57:23 +02:00
Pierre Goiffon
0360a3160d Merge remote-tracking branch 'origin/releases/germanium' into develop
# Conflicts:
#	setup/modelfactory.class.inc.php
2020-04-06 08:47:22 +02:00
Thomas Casteleyn
bcd21aefb4 📝 DBObject fix wrong PHPDoc (#133)
Thanks to @Hipska !
2020-04-06 08:32:31 +02:00
Pierre Goiffon
3cbcdd4f13 🎨 MFElement : fix access modifiers & PHPDoc 2020-03-31 08:53:22 +02:00
odain
c46d0f5662 N°2888 Impossibility to import iTop User with password policy 2020-03-30 17:48:01 +02:00
Pierre Goiffon
b2454d44ae 👥 Added @ousret to the contributor list
See #99
Thanks to him !
2020-03-30 08:39:35 +02:00
TAHRI Ahmed R
79cfb95f6e Support array for json_data posted in rest/json service (#99)
Previous syntax :
```
CURLOPT_POSTFIELDS => array(
	'auth_user' => 'admin',
	'auth_pwd' => 'admin',
	'json_data' => '{
	   "operation": "core/get",
	   "class": "Person",
	   "key": "SELECT Person", "limit": "10", "page": "1"
	}'
);
```

Now we can also use :
```
CURLOPT_POSTFIELDS => array(
	'auth_user' => 'admin',
	'auth_pwd' => 'admin',
	"json_data[operation]" => "core/get",
	"json_data[class]" => "Person",
	"json_data[key]" => "SELECT Person",
	"json_data[limit]" => 10,
	"json_data[page]" => 1
);
```
2020-03-27 18:11:09 +01:00
Pierre Goiffon
ff2e1a3507 Fix syntax error in core/email.class.inc.php
Missing ";" at the end of line :/
Introduced by 503afb98
2020-03-27 16:43:03 +01:00
Lars Hippler
503afb9831 Make it possible to add return path for mails (#95) 2020-03-27 16:20:59 +01:00
Pierre Goiffon
b6772917ae Merge branch 'release/2.7.0' into develop
# Conflicts:
#	.make/license/gen-community-license.sh
#	setup/licenses/community-licenses.xml
2020-03-27 15:20:08 +01:00
bruno DA SILVA
00971f9ec7 rollback on two composer options: adding them made no sense since this file is not meant to handle dependencies but just use the autoloader (dependencies are handled by the one a the root of the project) 2020-03-21 16:17:45 +01:00
bruno DA SILVA
a3a97fa228 added missing composer config for the portal's composer.json
- php 5.6+
 - dump the autoloader as optimized as possible
2020-03-21 16:13:28 +01:00
bruno DA SILVA
18c4ca9131 🐛 fix Cannot connect to the MySQL server for the CI's unattended_install 2020-03-20 15:15:29 +01:00
odain
466ddf768e Fix license generation tool 2020-03-17 18:59:29 +01:00
odain
76d26e8ef9 Fix license generation tool 2020-03-17 18:59:18 +01:00
odain
b526d6422b Adding a test to cover selectin/cmdb code
cleanup
2020-03-12 10:55:18 +01:00
Pierre Goiffon
63c02ff33d 📝 Fix PHPDoc typo 2020-03-09 16:00:15 +01:00
Molkobain
4688c92e7c Internal: PHPDoc and warnings suppression 2020-02-25 15:44:26 +01:00
52 changed files with 663 additions and 1542 deletions

View File

@@ -6,6 +6,8 @@ cd test
export DEBUG_UNIT_TEST=0
RUN_NONREG_TESTS=0
#USAGE ${debugMode} ${runNonRegOQLTests} "${coverture}" "${testFile}"
if [ $# -ge 1 -a "x$1" == "xtrue" ]
then
export DEBUG_UNIT_TEST=1
@@ -13,10 +15,27 @@ else
export DEBUG_UNIT_TEST=0
fi
set -x
OPTION=""
if [ $# -ge 3 -a "x$3" == "xtrue" ]
then
##coverture
OPTION="-dxdebug.coverage_enable=1 --coverage-clover ../var/test/coverage.xml"
fi
TESTFILE="$4"
if [ "x$TESTFILE" != "x" ]
then
# shellcheck disable=SC2001
TESTFILE=$(echo "$TESTFILE" | sed 's|test/||1')
php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml $OPTION $TESTFILE --teamcity
exit 0
fi
if [ $# -ge 2 -a "x$2" == "xtrue" ]
then
php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml --teamcity
php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml $OPTION --teamcity
else
#echo php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml --teamcity
php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml --exclude-group OQL --teamcity
php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml $OPTION --exclude-group OQL --teamcity
fi

View File

@@ -60,7 +60,7 @@ For example, if no version is currently prepared for shipping we could have:
In this example, when 2.8.0-beta is shipped that will become:
- `develop`: future 2.9.0 version
- `release/2.8`: 2.8.0-beta
- `release/2.8.0`: 2.8.0-beta
- `support/2.7`: 2.7.x maintenance version
- `support/2.6`: 2.6.x maintenance version
- `support/2.5`: 2.5.x maintenance version

5
Jenkinsfile vendored
View File

@@ -2,6 +2,8 @@ pipeline {
agent any
parameters {
booleanParam(name: 'debugMode', defaultValue: 'false', description: 'Debug mode?')
string(name: 'testFile', defaultValue: '', description: 'Provide test file to execute. Example: test/core/LogAPITest.php')
booleanParam(name: 'coverture', defaultValue: 'false', description: 'Test coverture?')
booleanParam(name: 'runNonRegOQLTests', defaultValue: 'false', description: 'Do You want to run legacy OQL regression tests?')
}
stages {
@@ -40,7 +42,7 @@ pipeline {
parallel {
stage('phpunit') {
steps {
sh './.jenkins/bin/tests/phpunit.sh ${debugMode} ${runNonRegOQLTests}'
sh './.jenkins/bin/tests/phpunit.sh ${debugMode} ${runNonRegOQLTests} "${coverture}" "${testFile}"'
}
}
}
@@ -50,6 +52,7 @@ pipeline {
post {
always {
archiveArtifacts allowEmptyArchive:true, excludes: '.gitkeep', artifacts: 'var/test/*.xml'
junit 'var/test/phpunit-log.junit.xml'
}
failure {

View File

@@ -21,21 +21,35 @@ iTop also offers mass import tools and web services to integrate with your IT
- [Data synchronization][18] (for data federation)
## Latest release
- [Changes since the previous version][62]
- [New features][63]
- [Installation notes][64]
- [Download][65]
[62]: https://www.itophub.io/wiki/page?id=latest:release:change_log
[63]: https://www.itophub.io/wiki/page?id=latest:release:start
[64]: https://www.itophub.io/wiki/page?id=latest:install:start
[65]: https://sourceforge.net/projects/itop/files/latest/download
## Resources
- [iTop Forums][1]: community support
- [iTop Tickets][2]: for feature requests and bug reports
- [Releases download][3]
- [Documentation][4] covering both iTop and its official extensions
- [iTop Hub][5] : discover and install extensions !
- [Software requirements][4]
- [Documentation][5] covering both iTop and its official extensions
- [iTop Hub][6] : discover and install extensions !
[1]: https://sourceforge.net/p/itop/discussion/
[2]: https://sourceforge.net/p/itop/tickets/
[3]: https://sourceforge.net/projects/itop/files/itop/
[4]: https://www.itophub.io/wiki
[5]: https://store.itophub.io/en_US/
[4]: https://www.itophub.io/wiki/page?id=latest:install:upgrading_itop
[5]: https://www.itophub.io/wiki
[6]: https://store.itophub.io/en_US/
[10]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#configuration_management_cmdb
[11]: https://www.itophub.io/wiki/page?id=latest%3Adatamodel%3Astart#ticketing
@@ -49,47 +63,6 @@ iTop also offers mass import tools and web services to integrate with your IT
## Last releases
### Versions 2.7.*
- 2.7.1 published on April 8, 2020
- [Changes since the previous version][62]
- [New features][63]
- [Migration notes][64]
- [Download iTop 2.7.0-2][65]
[62]: https://www.itophub.io/wiki/page?id=2_7_0:release:change_log
[63]: https://www.itophub.io/wiki/page?id=2_7_0:release:2_7_whats_new
[64]: https://www.itophub.io/wiki/page?id=2_7_0:install:260_to_270_migration_notes
[65]: https://sourceforge.net/projects/itop/files/itop/2.7.0-2
### Versions 2.6.*
- 2.6.0 published on January 9, 2019
- [Changes since the previous version][58]
- [New features][59]
- [Migration notes][60]
- [Download iTop 2.6.3][61]
[58]: https://www.itophub.io/wiki/page?id=2_6_0:release:change_log
[59]: https://www.itophub.io/wiki/page?id=2_6_0:release:2_6_whats_new
[60]: https://www.itophub.io/wiki/page?id=2_6_0:install:250_to_260_migration_notes
[61]: https://sourceforge.net/projects/itop/files/itop/2.6.3
### Versions 2.5.*
- 2.5.0 published on July 11, 2018
- [Changes since the previous version][54]
- [New features][55]
- [Migration notes][56]
- [Download iTop 2.5.1][57]
[54]: https://www.itophub.io/wiki/page?id=2_5_0:release:change_log
[55]: https://www.itophub.io/wiki/page?id=2_5_0:release:2_5_whats_new
[56]: https://www.itophub.io/wiki/page?id=2_5_0:install:240_to_250_migration_notes
[57]: https://sourceforge.net/projects/itop/files/itop/2.5.1
## About Us
iTop development is sponsored, led and supported by [Combodo][0].

View File

@@ -29,9 +29,13 @@ require_once(APPROOT."/application/webpage.class.inc.php");
class CLIPage implements Page
{
function __construct($s_title)
/** @var string */
public $s_title;
function __construct($s_title)
{
}
$this->s_title = $s_title;
}
public function output()
{
@@ -48,22 +52,22 @@ class CLIPage implements Page
public function add($sText)
{
echo $sText;
}
}
public function p($sText)
{
echo $sText."\n";
}
}
public function pre($sText)
{
echo $sText."\n";
}
}
public function add_comment($sText)
{
echo "#".$sText."\n";
}
}
public function table($aConfig, $aData, $aParams = array())
{
@@ -93,5 +97,3 @@ class CLIPage implements Page
}
}
}
?>

View File

@@ -73,19 +73,16 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
$this->add_header("Content-type: text/html; charset=".self::PAGES_CHARSET);
$this->add_header("Cache-control: no-cache");
$this->add_linked_stylesheet("../css/jquery.treeview.css");
$this->add_linked_stylesheet("../css/jquery.autocomplete.css");
$this->add_linked_stylesheet("../css/jquery-ui-timepicker-addon.css");
$this->add_linked_stylesheet("../css/jquery.multiselect.css");
$this->add_linked_stylesheet("../css/magnific-popup.css");
$this->add_linked_stylesheet("../css/c3.min.css");
$this->add_linked_stylesheet("../css/font-awesome/css/all.min.css");
$this->add_linked_stylesheet("../css/font-awesome/css/v4-shims.min.css");
$this->add_linked_stylesheet("../js/ckeditor/plugins/codesnippet/lib/highlight/styles/obsidian.css");
$this->add_linked_script('../js/jquery.layout.min.js');
$this->add_linked_script('../js/jquery.ba-bbq.min.js');
$this->add_linked_script("../js/jquery.treeview.js");
$this->add_linked_script("../js/jquery.autocomplete.js");
$this->add_linked_script("../js/date.js");
$this->add_linked_script("../js/jquery-ui-timepicker-addon.js");
$this->add_linked_script("../js/jquery-ui-timepicker-addon-i18n.min.js");

View File

@@ -92,7 +92,6 @@ class LoginWebPage extends NiceWebPage
{
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/login.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/v4-shims.min.css');
}
public static function SetLoginFailedMessage($sMessage)
@@ -100,6 +99,44 @@ class LoginWebPage extends NiceWebPage
self::$m_sLoginFailedMessage = $sMessage;
}
/**
* @param $oUser
* @param array $aProfiles
*
* @return array
* @throws \CoreException
* @throws \CoreUnexpectedValue
*/
public static function SynchroniseProfiles(&$oUser, array $aProfiles, $sOrigin)
{
$oProfilesSet = $oUser->Get(profile_list);
//delete old profiles
$aExistingProfiles = [];
while ($oProfile = $oProfilesSet->Fetch())
{
array_push($aExistingProfiles, $oProfile->Get('profileid'));
$iArrayKey = array_search($oProfile->Get('profileid'), $aProfiles);
if (!$iArrayKey)
{
$oProfilesSet->RemoveItem($oProfile->Get('profileid'));
}
else
{
unset($aProfiles[$iArrayKey]);
}
}
//add profiles not already linked with user
foreach ($aProfiles as $iProfileId)
{
$oLink = new URP_UserProfile();
$oLink->Set('profileid', $iProfileId);
$oLink->Set('reason', $sOrigin);
$oProfilesSet->AddItem(MetaModel::NewObject('URP_UserProfile', array('profileid' => $iProfileId, 'reason' => $sOrigin)));
}
$oUser->Set('profile_list', $oProfilesSet);
}
public function DisplayLoginHeader($bMainAppLogo = false)
{
$sLogo = 'itop-logo-external.png';
@@ -886,20 +923,12 @@ class LoginWebPage extends NiceWebPage
}
// Now synchronize the profiles
$oProfilesSet = DBObjectSet::FromScratch('URP_UserProfile');
$sOrigin = 'External User provisioning';
if (isset($_SESSION['login_mode']))
{
$sOrigin .= " ({$_SESSION['login_mode']})";
}
foreach ($aProfiles as $iProfileId)
{
$oLink = new URP_UserProfile();
$oLink->Set('profileid', $iProfileId);
$oLink->Set('reason', $sOrigin);
$oProfilesSet->AddObject($oLink);
}
$oUser->Set('profile_list', $oProfilesSet);
$aExistingProfiles = self::SynchroniseProfiles($oUser, $aProfiles, $sOrigin);
if ($oUser->IsModified())
{
$oUser->DBWrite();

View File

@@ -272,7 +272,7 @@ EOF
$iMinChars = isset($aArgs['iMinChars']) ? $aArgs['iMinChars'] : 3; //@@@ $this->oAttDef->GetMinAutoCompleteChars();
// the input for the auto-complete
$sHTMLValue .= "<input class=\"field_autocomplete\" type=\"text\" id=\"label_$this->iId\" value=\"$sDisplayValue\"/>";
$sHTMLValue .= "<input id=\"label_$this->iId\" value=\"$sDisplayValue\"/>";
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_search_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Search();\"><i class=\"fas fa-search\"></i></div></span>";
// another hidden input to store & pass the object's Id
@@ -281,18 +281,53 @@ EOF
$JSSearchMode = $this->bSearchMode ? 'true' : 'false';
// Scripts to start the autocomplete and bind some events to it
$oPage->add_ready_script(
<<<EOF
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', false, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode, $sJSDoSearch);
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
$('#label_$this->iId').autocomplete(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', { scroll:true, minChars:{$iMinChars}, autoFill:false, matchContains:true, mustMatch: true, keyHolder:'#{$this->iId}', extraParams:{operation:'ac_extkey', sTargetClass:'{$this->sTargetClass}',sFilter:'$sFilter',bSearchMode:$JSSearchMode, json: function() { return $sWizHelperJSON; } }});
$('#label_$this->iId').keyup(function() { if ($(this).val() == '') { $('#$this->iId').val(''); } } ); // Useful for search forms: empty value in the "label", means no value, immediatly !
$('#label_$this->iId').result( function(event, data, formatted) { OnAutoComplete('{$this->iId}', event, data, formatted); } );
$('#$this->iId').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
<<<JS
$('#label_$this->iId').autocomplete({
source: function( request, response ) {
$.post( {
url: GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
dataType: "json",
data: {
q:request.term,
operation:'ac_extkey',
sTargetClass:'{$this->sTargetClass}',
sFilter:'$sFilter',
bSearchMode:$JSSearchMode,
sOutputFormat:'json',
json: function() { return $sWizHelperJSON; }
},
success: function( data ) {
response( data );
}
} );
},
autoFocus: true,
minLength:{$iMinChars},
select: function( event, ui ) {
$('#$this->iId').val( ui.item.value );
$('#label_$this->iId').val( ui.item.label );
$('#$this->iId').trigger('validate');
$('#$this->iId').trigger('extkeychange');
$('#$this->iId').trigger('change');
return false;
}
})
.autocomplete( "instance" )._renderItem = function( ul, item ) {
var term = this.term.replace("/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi", "\\$1");
var val = item.label.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
if (item.obsolete == 'yes'){
val = val + ' <b>old</b>';
}
return $( "<li>" )
.append( val )
.appendTo( ul );
};
if ($('#ac_dlg_{$this->iId}').length == 0)
{
$('body').append('<div id="ac_dlg_{$this->iId}"></div>');
}
EOF
JS
);
}
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false)
@@ -441,10 +476,12 @@ EOF
$iMax = 150;
$oValuesSet->SetLimit($iMax);
$oValuesSet->SetSort(false);
$aOrder = array('friendlyname'=>true);
$oValuesSet->SetOrderBy($aOrder);
$oValuesSet->SetSort(true);
$oValuesSet->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
$oValuesSet->SetLimit($iMax);
$aValuesContains = $oValuesSet->GetValues(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'contains');
asort($aValuesContains);
$aValuesContains = $oValuesSet->GetValues(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'start_with');
$aValues = array();
foreach($aValuesContains as $sKey => $sFriendlyName)
{
@@ -453,6 +490,24 @@ EOF
$aValues[$sKey] = $sFriendlyName;
}
}
if (sizeof($aValuesContains) < $iMax)
{
$aValuesContains = $oValuesSet->GetValues(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains,
'contains');
//asort($aValuesContains);
$iSize=sizeof($aValuesContains);
foreach($aValuesContains as $sKey => $sFriendlyName)
{
if (!isset($aValues[$sKey]))
{
$aValues[$sKey] = $sFriendlyName;
if (++$iSize >= $iMax)
{
break;
}
}
}
}
switch($sOutputFormat)
{

View File

@@ -35,6 +35,10 @@ require_once(APPROOT.'/core/email.class.inc.php');
*/
abstract class Action extends cmdbAbstractObject
{
/**
* @throws \CoreException
* @throws \Exception
*/
public static function Init()
{
$aParams = array
@@ -57,15 +61,32 @@ abstract class Action extends cmdbAbstractObject
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("trigger_list", array("linked_class"=>"lnkTriggerAction", "ext_key_to_me"=>"action_id", "ext_key_to_remote"=>"trigger_id", "allowed_values"=>null, "count_min"=>0, "count_max"=>0, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'name', 'description', 'status')); // Attributes to be displayed for a list
// - Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list'));
// - Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('finalclass', 'name', 'description', 'status'));
// Search criteria
MetaModel::Init_SetZListItems('default_search', array('name', 'description', 'status')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// - Criteria of the std search form
MetaModel::Init_SetZListItems('default_search', array('name', 'description', 'status'));
// - Criteria of the advanced search form
// MetaModel::Init_SetZListItems('advanced_search', array('name'));
}
/**
* Encapsulate the execution of the action and handle failure & logging
*
* @param \Trigger $oTrigger
* @param array $aContextArgs
*
* @return mixed
*/
abstract public function DoExecute($oTrigger, $aContextArgs);
/**
* @return bool
* @throws \ArchivedObjectException
* @throws \CoreException
*/
public function IsActive()
{
switch($this->Get('status'))
@@ -79,6 +100,13 @@ abstract class Action extends cmdbAbstractObject
}
}
/**
* Return true if the current action status is set on "test"
*
* @return bool
* @throws \ArchivedObjectException
* @throws \CoreException
*/
public function IsBeingTested()
{
switch($this->Get('status'))
@@ -99,6 +127,10 @@ abstract class Action extends cmdbAbstractObject
*/
abstract class ActionNotification extends Action
{
/**
* @inheritDoc
* @throws \CoreException
*/
public static function Init()
{
$aParams = array
@@ -117,11 +149,15 @@ abstract class ActionNotification extends Action
MetaModel::Init_InheritAttributes();
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'name', 'description', 'status')); // Attributes to be displayed for a list
// - Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list'));
// - Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('finalclass', 'name', 'description', 'status'));
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// - Criteria of the std search form
// MetaModel::Init_SetZListItems('standard_search', array('name'));
// - Criteria of the advanced search form
// MetaModel::Init_SetZListItems('advanced_search', array('name'));
}
}
@@ -132,6 +168,9 @@ abstract class ActionNotification extends Action
*/
class ActionEmail extends ActionNotification
{
/**
* @inheritDoc
*/
public static function Init()
{
$aParams = array
@@ -161,11 +200,15 @@ class ActionEmail extends ActionNotification
MetaModel::Init_AddAttribute(new AttributeEnum("importance", array("allowed_values"=>new ValueSetEnum('low,normal,high'), "sql"=>"importance", "default_value"=>'normal', "is_null_allowed"=>false, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'test_recipient', 'from', 'reply_to', 'to', 'cc', 'bcc', 'subject', 'body', 'importance', 'trigger_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name', 'status', 'to', 'subject')); // Attributes to be displayed for a list
// - Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'test_recipient', 'from', 'reply_to', 'to', 'cc', 'bcc', 'subject', 'body', 'importance', 'trigger_list'));
// - Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('name', 'status', 'to', 'subject'));
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name','description', 'status', 'subject')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
// - Criteria of the std search form
MetaModel::Init_SetZListItems('standard_search', array('name','description', 'status', 'subject'));
// - Criteria of the advanced search form
// MetaModel::Init_SetZListItems('advanced_search', array('name'));
}
// count the recipients found
@@ -175,7 +218,18 @@ class ActionEmail extends ActionNotification
// executed in the background, while making sure that any issue would be reported clearly
protected $m_aMailErrors; //array of strings explaining the issue
// returns a the list of emails as a string, or a detailed error description
/**
* Return a the list of emails as a string, or a detailed error description
*
* @param string $sRecipAttCode
* @param array $aArgs
*
* @return string
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
protected function FindRecipients($sRecipAttCode, $aArgs)
{
$sOQL = $this->Get($sRecipAttCode);
@@ -224,9 +278,7 @@ class ActionEmail extends ActionNotification
}
/**
* @param \Trigger $oTrigger
* @param array $aContextArgs
*
* @inheritDoc
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
@@ -306,6 +358,7 @@ class ActionEmail extends ActionNotification
*
* @return string
* @throws \CoreException
* @throws \Exception
*/
protected function _DoExecute($oTrigger, $aContextArgs, &$oLog)
{
@@ -316,7 +369,7 @@ class ActionEmail extends ActionNotification
$this->m_aMailErrors = array();
$bRes = false; // until we do succeed in sending the email
// Determine recicipients
// Determine recipients
//
$sTo = $this->FindRecipients('to', $aContextArgs);
$sCC = $this->FindRecipients('cc', $aContextArgs);
@@ -439,4 +492,3 @@ class ActionEmail extends ActionNotification
}
}
}
?>

View File

@@ -65,6 +65,10 @@ class ExecAsyncTask implements iBackgroundProcess
*/
abstract class AsyncTask extends DBObject
{
/**
* @throws \CoreException
* @throws \Exception
*/
public static function Init()
{
$aParams = array
@@ -285,11 +289,13 @@ abstract class AsyncTask extends DBObject
/**
* Throws an exception (message and code)
*
* @return string
*/
abstract public function DoProcess();
/**
* Describes the error codes that DoProcess can return by the mean of exceptions
* Describes the error codes that DoProcess can return by the mean of exceptions
*/
static public function EnumErrorCodes()
{
@@ -352,6 +358,11 @@ class AsyncSendEmail extends AsyncTask
$oNew->DBInsert();
}
/**
* @inheritDoc
* @throws \ArchivedObjectException
* @throws \CoreException
*/
public function DoProcess()
{
$sMessage = $this->Get('message');

View File

@@ -742,7 +742,7 @@ abstract class AttributeDefinition
*
* @return mixed a value out of suffix/value pairs, for SELECT result interpretation
*/
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
return null;
}
@@ -2402,9 +2402,9 @@ class AttributeDBFieldVoid extends AttributeDefinition
return $aColumns;
}
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
$value = $this->MakeRealValue($aCols[$sPrefix.''], null);
$value = $this->MakeRealValue($aCols[$sPrefix.''], $oHostObject);
return $value;
}
@@ -3913,7 +3913,7 @@ class AttributeEncryptedString extends AttributeString
* @return string
* @throws \Exception
*/
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
$oSimpleCrypt = new SimpleCrypt(self::$sLibrary);
$sValue = $oSimpleCrypt->Decrypt(self::$sKey, $aCols[$sPrefix]);
@@ -4283,7 +4283,7 @@ class AttributeText extends AttributeString
*
* @return string
*/
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
$value = $aCols[$sPrefix.''];
if ($this->GetOptional('format', null) != null)
@@ -4577,7 +4577,7 @@ class AttributeCaseLog extends AttributeLongText
* @return \ormCaseLog
* @throws \MissingColumnException
*/
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
if (!array_key_exists($sPrefix, $aCols))
{
@@ -7378,18 +7378,18 @@ class AttributeExternalField extends AttributeDefinition
//public function GetSQLExpressions($sPrefix = '') {return array();}
// Here, we get the data...
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->FromSQLToValue($aCols, $sPrefix);
return $oExtAttDef->FromSQLToValue($aCols, $sPrefix, $oHostObject, $sHostAttCode);
}
public function GetAsHTML($value, $oHostObject = null, $bLocalize = true)
{
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->GetAsHTML($value, null, $bLocalize);
return $oExtAttDef->GetAsHTML($value, $oHostObject, $bLocalize);
}
public function GetAsXML($value, $oHostObject = null, $bLocalize = true)
@@ -7645,6 +7645,10 @@ class AttributeBlob extends AttributeDefinition
if (is_object($proposedValue))
{
if (!$proposedValue instanceof ormDocument)
{
throw new Exception(__METHOD__.": unexpected class ".get_class($proposedValue));
}
$proposedValue = clone $proposedValue;
}
else
@@ -7661,6 +7665,7 @@ class AttributeBlob extends AttributeDefinition
}
}
$proposedValue->SetHostObject($oHostObj, $this->GetCode());
return $proposedValue;
}
@@ -7679,7 +7684,7 @@ class AttributeBlob extends AttributeDefinition
return $aColumns;
}
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
if (!array_key_exists($sPrefix, $aCols))
{
@@ -7703,7 +7708,7 @@ class AttributeBlob extends AttributeDefinition
$sFileName = isset($aCols[$sPrefix.'_filename']) ? $aCols[$sPrefix.'_filename'] : '';
$value = new ormDocument($data, $sMimeType, $sFileName);
$value->SetHostObject($oHostObject, $sHostAttCode);
return $value;
}
@@ -7945,18 +7950,6 @@ class AttributeImage extends AttributeBlob
return "Image";
}
/**
* {@inheritDoc}
* @see AttributeBlob::MakeRealValue()
*/
public function MakeRealValue($proposedValue, $oHostObj)
{
$oDoc = parent::MakeRealValue($proposedValue, $oHostObj);
// The validation of the MIME Type is done by CheckFormat below
return $oDoc;
}
/**
* Check that the supplied ormDocument actually contains an image
* {@inheritDoc}
@@ -8231,7 +8224,7 @@ class AttributeStopWatch extends AttributeDefinition
return date("Y-m-d H:i:s", $iSeconds);
}
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
$aExpectedCols = array($sPrefix, $sPrefix.'_started', $sPrefix.'_laststart', $sPrefix.'_stopped');
foreach($this->ListThresholds() as $iThreshold => $aFoo)
@@ -9068,7 +9061,7 @@ class AttributeSubItem extends AttributeDefinition
//
// protected function ScalarToSQL($value) {return $value;} // format value as a valuable SQL literal (quoted outside)
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
}
@@ -9286,7 +9279,7 @@ class AttributeOneWayPassword extends AttributeDefinition
return $aColumns;
}
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
if (!array_key_exists($sPrefix, $aCols))
{
@@ -9483,7 +9476,7 @@ class AttributeTable extends AttributeDBField
return $proposedValue;
}
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
try
{
@@ -9498,11 +9491,11 @@ class AttributeTable extends AttributeDBField
}
if ($value === false)
{
$value = $this->MakeRealValue($aCols[$sPrefix.''], null);
$value = $this->MakeRealValue($aCols[$sPrefix.''], $oHostObject);
}
} catch (Exception $e)
{
$value = $this->MakeRealValue($aCols[$sPrefix.''], null);
$value = $this->MakeRealValue($aCols[$sPrefix.''], $oHostObject);
}
return $value;
@@ -9897,11 +9890,11 @@ abstract class AttributeSet extends AttributeDBFieldVoid
* @return mixed
* @throws \Exception
*/
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
$sValue = $aCols["$sPrefix"];
return $this->MakeRealValue($sValue, null, true);
return $this->MakeRealValue($sValue, $oHostObject, true);
}
/**
@@ -11046,7 +11039,7 @@ class AttributeTagSet extends AttributeSet
* @throws \CoreException
* @throws \Exception
*/
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
$sValue = $aCols["$sPrefix"];
@@ -11628,7 +11621,7 @@ class AttributeFriendlyName extends AttributeDefinition
return $sLabel;
}
public function FromSQLToValue($aCols, $sPrefix = '')
public function FromSQLToValue($aCols, $sPrefix = '', $oHostObject = null, $sHostAttCode = null)
{
$sValue = $aCols[$sPrefix];

View File

@@ -513,83 +513,6 @@ abstract class CMDBObject extends DBObject
}
}
/**
* @deprecated 2.7.0 N°2361 simply use {@link DBInsert} instead, that will automatically create and persist a CMDBChange object.
* If you need to persist your own, call {@link CMDBObject::SetCurrentChange} before.
*
* @param \CMDBChange $oChange
* @param null $bSkipStrongSecurity
*
* @return int|null
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
* @throws \SecurityException
*/
public function DBInsertTracked(CMDBChange $oChange, $bSkipStrongSecurity = null)
{
self::SetCurrentChange($oChange);
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
$ret = $this->DBInsertTracked_Internal();
return $ret;
}
/**
* @deprecated 2.7.0 N°2361 simply use {@link DBInsertNoReload} instead, that will automatically create and persist a CMDBChange object.
* If you need to persist your own, call {@link CMDBObject::SetCurrentChange} before.
*
* @param \CMDBChange $oChange
* @param null $bSkipStrongSecurity
*
* @return int
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
* @throws \SecurityException
*/
public function DBInsertTrackedNoReload(CMDBChange $oChange, $bSkipStrongSecurity = null)
{
self::SetCurrentChange($oChange);
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
$ret = $this->DBInsertTracked_Internal(true);
return $ret;
}
/**
* @deprecated 2.7.0 N°2361 simply use {@link DBInsert} or {@link DBInsertNoReload} instead
*
* @param bool $bDoNotReload
*
* @return integer Identifier of the created object
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*/
protected function DBInsertTracked_Internal($bDoNotReload = false)
{
if ($bDoNotReload)
{
$ret = $this->DBInsertNoReload();
}
else
{
$ret = $this->DBInsert();
}
return $ret;
}
public function DBClone($newKey = null)
{
return $this->DBCloneTracked_Internal();
@@ -622,24 +545,6 @@ abstract class CMDBObject extends DBObject
return $ret;
}
/**
* @deprecated 2.7.0 N°2361 simply use {@link DBUpdate} instead, that will automatically create and persist a CMDBChange object.
* If you need to persist your own, call {@link CMDBObject::SetCurrentChange} before.
*
* @param \CMDBChange $oChange
* @param null $bSkipStrongSecurity
*
* @return int|void
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \SecurityException
*/
public function DBUpdateTracked(CMDBChange $oChange, $bSkipStrongSecurity = null)
{
self::SetCurrentChange($oChange);
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
$this->DBUpdate();
}
/**
* @param null $oDeletionPlan
@@ -659,31 +564,6 @@ abstract class CMDBObject extends DBObject
return $this->DBDeleteTracked_Internal($oDeletionPlan);
}
/**
* @deprecated 2.7.0 N°2361 simply use {@link DBDelete} instead, that will automatically create and persist a CMDBChange object.
* If you need to persist your own, call {@link CMDBObject::SetCurrentChange} before.
*
* @param \CMDBChange $oChange
* @param null $bSkipStrongSecurity
* @param null $oDeletionPlan
*
* @throws \ArchivedObjectException
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DeleteException
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
* @throws \OQLException
* @throws \SecurityException
*/
public function DBDeleteTracked(CMDBChange $oChange, $bSkipStrongSecurity = null, &$oDeletionPlan = null)
{
self::SetCurrentChange($oChange);
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_DELETE);
$this->DBDeleteTracked_Internal($oDeletionPlan);
}
/**
* @param null $oDeletionPlan
*

View File

@@ -859,25 +859,6 @@ class CMDBSource
self::$m_iTransactionLevel = 0;
}
/**
*
* @deprecated 2.7.0 N°1627 use ItopCounter instead
*
* @param string $sTable
*
* @return int
* @throws \MySQLException
* @throws \MySQLHasGoneAwayException
*/
public static function GetNextInsertId($sTable)
{
$sSQL = "SHOW TABLE STATUS LIKE '$sTable'";
$oResult = self::Query($sSQL);
$aRow = $oResult->fetch_assoc();
return $aRow['Auto_increment'];
}
public static function GetInsertId()
{
$iRes = self::$m_oMysqli->insert_id;

View File

@@ -461,7 +461,7 @@ abstract class DBObject implements iDisplay
if (array_key_exists($sAttRef, $aRow))
{
$value = $oAttDef->FromSQLToValue($aRow, $sAttRef);
$value = $oAttDef->FromSQLToValue($aRow, $sAttRef, $this, $sAttCode);
$bIsDefined = true;
}
}
@@ -2947,46 +2947,6 @@ abstract class DBObject implements iDisplay
return $this->m_iKey;
}
/**
* @internal
*
* @deprecated 2.7.0 N°2361 simply use {@see DBObject::DBInsert()} instead, that will automatically create and persist a CMDBChange object.
* If you need to persist your own, call {@see CMDBObject::SetCurrentChange()} before.
*
* @param CMDBChange $oChange
*
* @return int|null
* @throws CoreException
*/
public function DBInsertTracked(CMDBChange $oChange)
{
CMDBObject::SetCurrentChange($oChange);
return $this->DBInsert();
}
/**
* @internal
*
* @deprecated 2.7.0 N°2361 simply use {@see DBObject::DBInsertNoReload()} instead, that will automatically create and persist a CMDBChange object.
* If you need to persist your own, call {@see CMDBObject::SetCurrentChange()} before.
*
* @param CMDBChange $oChange
*
* @return int
* @throws ArchivedObjectException
* @throws CoreCannotSaveObjectException
* @throws CoreException
* @throws CoreUnexpectedValue
* @throws CoreWarning
* @throws MySQLException
* @throws OQLException
*/
public function DBInsertTrackedNoReload(CMDBChange $oChange)
{
CMDBObject::SetCurrentChange($oChange);
return $this->DBInsertNoReload();
}
/**
* Creates a copy of the current object into the database
*
@@ -3338,25 +3298,6 @@ abstract class DBObject implements iDisplay
$this->m_aPreviousValuesForUpdatedAttributes = $aPreviousValuesForUpdatedAttributes;
}
/**
*
* @internal
*
* @deprecated 2.7.0 N°2361 simply use {@see DBObject::DBUpdate()} instead, that will automatically create and persist a CMDBChange object.
* If you need to persist your own, call {@see CMDBObject::SetCurrentChange()} before.
*
* @param CMDBChange $oChange
*
* @return int
* @throws CoreCannotSaveObjectException
* @throws CoreException
*/
public function DBUpdateTracked(CMDBChange $oChange)
{
CMDBObject::SetCurrentChange($oChange);
return $this->DBUpdate();
}
/**
* Make the current changes persistent - clever wrapper for Insert or Update
*
@@ -3611,32 +3552,7 @@ abstract class DBObject implements iDisplay
return $oDeletionPlan;
}
/**
* @internal
*
* @deprecated 2.7.0 N°2361 simply use {@see DBObject::DBDelete()} instead.
* If you need to persist your own, call {@see CMDBObject::SetCurrentChange()} before.
*
* @param CMDBChange $oChange
* @param boolean $bSkipStrongSecurity
* @param \DeletionPlan $oDeletionPlan
*
* @throws ArchivedObjectException
* @throws CoreCannotSaveObjectException
* @throws CoreException
* @throws CoreUnexpectedValue
* @throws DeleteException
* @throws MySQLException
* @throws MySQLHasGoneAwayException
* @throws OQLException
*/
public function DBDeleteTracked(CMDBChange $oChange, $bSkipStrongSecurity = null, &$oDeletionPlan = null)
{
CMDBObject::SetCurrentChange($oChange);
$this->DBDelete($oDeletionPlan);
}
/**
/**
* @internal
*
* @return array
@@ -4420,22 +4336,7 @@ abstract class DBObject implements iDisplay
}
/**
* implement relations
*
* Return an empty set for the parent of all
*
* this way of implementing the relations suffers limitations (not handling the redundancy)
* and you should consider defining those things in XML
*
* @internal
* @deprecated
*/
public static function GetRelationQueries($sRelCode)
{
return array();
}
/**
* Reserved: do not overload
*
@@ -4446,72 +4347,6 @@ abstract class DBObject implements iDisplay
return array();
}
/**
* Use GetRelatedObjectsDown/Up instead to take redundancy into account
*
* @internal
* @deprecated
*/
public function GetRelatedObjects($sRelCode, $iMaxDepth = 99, &$aResults = array())
{
// Temporary patch: until the impact analysis GUI gets rewritten,
// let's consider that "depends on" is equivalent to "impacts/up"
// The current patch has been implemented in DBObject and MetaModel
$sHackedRelCode = $sRelCode;
$bDown = true;
if ($sRelCode == 'depends on')
{
$sHackedRelCode = 'impacts';
$bDown = false;
}
foreach (MetaModel::EnumRelationQueries(get_class($this), $sHackedRelCode, $bDown) as $sDummy => $aQueryInfo)
{
$sQuery = $bDown ? $aQueryInfo['sQueryDown'] : $aQueryInfo['sQueryUp'];
//$bPropagate = $aQueryInfo["bPropagate"];
//$iDepth = $bPropagate ? $iMaxDepth - 1 : 0;
$iDepth = $iMaxDepth - 1;
// Note: the loop over the result set has been written in an unusual way for error reporting purposes
// In the case of a wrong query parameter name, the error occurs on the first call to Fetch,
// thus we need to have this first call into the try/catch, but
// we do NOT want to nest the try/catch for the error message to be clear
try
{
$oFlt = DBObjectSearch::FromOQL($sQuery);
$oObjSet = new DBObjectSet($oFlt, array(), $this->ToArgsForQuery());
$oObj = $oObjSet->Fetch();
}
catch (Exception $e)
{
$sClassOfDefinition = $aQueryInfo['_legacy_'] ? get_class($this).'(or a parent)::GetRelationQueries()' : $aQueryInfo['sDefinedInClass'];
throw new Exception("Wrong query for the relation $sRelCode/$sClassOfDefinition/{$aQueryInfo['sNeighbour']}: ".$e->getMessage());
}
if ($oObj)
{
do
{
$sRootClass = MetaModel::GetRootClass(get_class($oObj));
$sObjKey = $oObj->GetKey();
if (array_key_exists($sRootClass, $aResults))
{
if (array_key_exists($sObjKey, $aResults[$sRootClass]))
{
continue; // already visited, skip
}
}
$aResults[$sRootClass][$sObjKey] = $oObj;
if ($iDepth > 0)
{
$oObj->GetRelatedObjects($sRelCode, $iDepth, $aResults);
}
}
while ($oObj = $oObjSet->Fetch());
}
}
return $aResults;
}
/**
* Compute the "RelatedObjects" (forward or "down" direction) for the object
* for the specified relation

View File

@@ -1324,7 +1324,7 @@ class DBObjectSearch extends DBSearch
// Make the list of acceptable arguments... could be factorized with run_query, into oSearch->GetQueryParams($bExclude magic params)
$aNakedMagicArguments = array();
foreach (MetaModel::PrepareQueryArguments(array()) as $sArgName => $value)
foreach (MetaModel::PrepareQueryArguments(array(),array(), $this->GetExpectedArguments()) as $sArgName => $value)
{
$iPos = strpos($sArgName, '->object()');
if ($iPos === false)
@@ -1387,7 +1387,7 @@ class DBObjectSearch extends DBSearch
{
$aParams = array_merge($aContextParams, $this->m_aParams);
}
$aParams = MetaModel::PrepareQueryArguments($aParams);
$aParams = MetaModel::PrepareQueryArguments($aParams,array(), $this->GetExpectedArguments());
}
else
{
@@ -1580,7 +1580,7 @@ class DBObjectSearch extends DBSearch
$aRet = array('selects' => array(), 'joins' => array(), 'where' => array());
$aParams = array_merge($this->m_aParams);
$aParams = MetaModel::PrepareQueryArguments($aParams);
$aParams = MetaModel::PrepareQueryArguments($aParams, array(), $this->GetExpectedArguments());
foreach ($this->m_aSelectedClasses as $sAlias => $sClass)
{
@@ -1787,7 +1787,7 @@ class DBObjectSearch extends DBSearch
{
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($this);
$oSQLQuery = $oSQLObjectQueryBuilder->MakeSQLObjectDeleteQuery();
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams());
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams(), $this->GetExpectedArguments());
$sRet = $oSQLQuery->RenderDelete($aScalarArgs);
return $sRet;
}
@@ -1803,7 +1803,7 @@ class DBObjectSearch extends DBSearch
{
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($this);
$oSQLQuery = $oSQLObjectQueryBuilder->MakeSQLObjectUpdateQuery($aValues);
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams());
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams(), $this->GetExpectedArguments());
$sRet = $oSQLQuery->RenderUpdate($aScalarArgs);
return $sRet;
}
@@ -1822,7 +1822,7 @@ class DBObjectSearch extends DBSearch
{
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($this);
$oSQLQuery = $oSQLObjectQueryBuilder->MakeSQLObjectUpdateQuery($aValues);
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams());
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams(), $this->GetExpectedArguments());
$sRet = $oSQLQuery->RenderInsert($aScalarArgs);
return $sRet;
}

View File

@@ -1312,34 +1312,6 @@ class DBObjectSet implements iDBObjectSetIterator
return $oNewSet;
}
/**
* Will be deprecated soon - use MetaModel::GetRelatedObjectsDown/Up instead to take redundancy into account
*
* @throws \Exception
*/
public function GetRelatedObjects($sRelCode, $iMaxDepth = 99)
{
$aRelatedObjs = array();
$aVisited = array(); // optimization for consecutive calls of MetaModel::GetRelatedObjects
$this->Seek(0);
while ($oObject = $this->Fetch())
{
$aMore = $oObject->GetRelatedObjects($sRelCode, $iMaxDepth, $aVisited);
foreach ($aMore as $sClass => $aRelated)
{
foreach ($aRelated as $iObj => $oObj)
{
if (!isset($aRelatedObjs[$sClass][$iObj]))
{
$aRelatedObjs[$sClass][$iObj] = $oObj;
}
}
}
}
return $aRelatedObjs;
}
/**
* Compute the "RelatedObjects" (forward or "down" direction) for the set
* for the specified relation
@@ -1496,7 +1468,7 @@ class DBObjectSet implements iDBObjectSetIterator
public function ListConstantFields()
{
// The complete list of arguments will include magic arguments (e.g. current_user->attcode)
$aScalarArgs = MetaModel::PrepareQueryArguments($this->m_oFilter->GetInternalParams(), $this->m_aArgs);
$aScalarArgs = MetaModel::PrepareQueryArguments($this->m_oFilter->GetInternalParams(), $this->m_aArgs, $this->m_oFilter->ListParameters());
$aConst = $this->m_oFilter->ListConstantFields();
foreach($aConst as $sClassAlias => $aVals)
@@ -1515,7 +1487,7 @@ class DBObjectSet implements iDBObjectSetIterator
public function ApplyParameters()
{
$aAllArgs = MetaModel::PrepareQueryArguments($this->m_oFilter->GetInternalParams(), $this->m_aArgs);
$aAllArgs = MetaModel::PrepareQueryArguments($this->m_oFilter->GetInternalParams(), $this->m_aArgs, $this->m_oFilter->GetExpectedArguments());
$this->m_oFilter->ApplyParameters($aAllArgs);
}
}

View File

@@ -24,14 +24,14 @@ abstract class HTMLSanitizer
{
// Do nothing..
}
/**
* Sanitizes the given HTML document
* @param string $sHTML
* @return string
*/
abstract public function DoSanitize($sHTML);
/**
* Sanitize an HTML string with the configured sanitizer, falling back to HTMLDOMSanitizer in case of Exception or invalid configuration
* @param string $sHTML
@@ -50,7 +50,7 @@ abstract class HTMLSanitizer
IssueLog::Warning('The configured "html_sanitizer" class "'.$sSanitizerClass.'" is not a subclass of HTMLSanitizer. Will use HTMLDOMSanitizer as the default sanitizer.');
$sSanitizerClass = 'HTMLDOMSanitizer';
}
try
{
$oSanitizer = new $sSanitizerClass();
@@ -70,7 +70,7 @@ abstract class HTMLSanitizer
{
IssueLog::Error('Failed to sanitize an HTML string with "HTMLDOMSanitizer". The following exception occured: '.$e->getMessage());
IssueLog::Error('The HTML will NOT be sanitized.');
$sCleanHTML = $sHTML;
$sCleanHTML = $sHTML;
}
}
return $sCleanHTML;
@@ -97,7 +97,7 @@ class HTMLNullSanitizer extends HTMLSanitizer
{
return $sHTML;
}
}
/**
@@ -109,7 +109,7 @@ class HTMLNullSanitizer extends HTMLSanitizer
class HTMLPurifierSanitizer extends HTMLSanitizer
{
protected static $oPurifier = null;
public function __construct()
{
if (self::$oPurifier == null)
@@ -120,7 +120,7 @@ class HTMLPurifierSanitizer extends HTMLSanitizer
throw new Exception("Missing library '$sLibPath', cannot use HTMLPurifierSanitizer.");
}
require_once($sLibPath);
$oPurifierConfig = HTMLPurifier_Config::createDefault();
$oPurifierConfig->set('Core.Encoding', 'UTF-8'); // defaults to 'UTF-8'
$oPurifierConfig->set('HTML.Doctype', 'XHTML 1.0 Strict'); // defaults to 'XHTML 1.0 Transitional'
@@ -142,11 +142,11 @@ class HTMLPurifierSanitizer extends HTMLSanitizer
self::$oPurifier = new HTMLPurifier($oPurifierConfig);
}
}
public function DoSanitize($sHTML)
{
$sCleanHtml = self::$oPurifier->purify($sHTML);
return $sCleanHtml;
return $sCleanHtml;
}
}
*/
@@ -278,13 +278,13 @@ class HTMLDOMSanitizer extends HTMLSanitizer
$sHTML = preg_replace('~\xc2\xa0~', ' ', $sHTML);
@$this->oDoc->loadHTML('<?xml encoding="UTF-8"?>'.$sHTML); // For loading HTML chunks where the character set is not specified
$this->CleanNode($this->oDoc);
$oXPath = new DOMXPath($this->oDoc);
$sXPath = "//body";
$oNodesList = $oXPath->query($sXPath);
if ($oNodesList->length == 0)
{
// No body, save the whole document
@@ -297,10 +297,10 @@ class HTMLDOMSanitizer extends HTMLSanitizer
// remove the body tag itself
$sCleanHtml = str_replace( array('<body>', '</body>'), '', $sCleanHtml);
}
return $sCleanHtml;
}
protected function CleanNode(DOMNode $oElement)
{
$aAttrToRemove = array();
@@ -341,7 +341,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
$oElement->removeAttribute($sName);
}
}
if ($oElement->hasChildNodes())
{
$aChildElementsToRemove = array();
@@ -390,7 +390,7 @@ class HTMLDOMSanitizer extends HTMLSanitizer
}
return implode(';', $aAllowedStyles);
}
protected function IsValidAttributeContent($sAttributeName, $sValue)
{
if (array_key_exists($sAttributeName, self::$aAttrsWhiteList))

View File

@@ -2047,7 +2047,6 @@ abstract class MetaModel
*/
protected static function ComputeRelationQueries($sRelCode)
{
$bHasLegacy = false;
$aQueries = array();
foreach(self::GetClasses() as $sClass)
{
@@ -2133,158 +2132,8 @@ abstract class MetaModel
}
}
}
// Read legacy definitions
// The up/down queries have to be reconcilied, which can only be done later when all the classes have been browsed
//
// The keys used to store a query (up or down) into the array are built differently between the modern and legacy made data:
// Modern way: aQueries[sClass]['up'|'down'][sArrowId], where sArrowId is made of the source class + neighbour id (XML def)
// Legacy way: aQueries[sClass]['up'|'down'][sRemoteClass]
// The modern way does allow for several arrows between two classes
// The legacy way aims at simplifying the transformation (reconciliation between up and down)
if ($sRelCode == 'impacts')
{
$sRevertCode = 'depends on';
$aLegacy = call_user_func_array(array($sClass, 'GetRelationQueries'), array($sRelCode));
foreach($aLegacy as $sId => $aLegacyEntry)
{
$bHasLegacy = true;
$oFilter = DBObjectSearch::FromOQL($aLegacyEntry['sQuery']);
$sRemoteClass = $oFilter->GetClass();
// Determine wether the query is inherited from a parent or not
$bInherited = false;
foreach(self::EnumParentClasses($sClass) as $sParent)
{
if (!isset($aQueries[$sParent]['down'][$sRemoteClass]))
{
continue;
}
if ($aLegacyEntry['sQuery'] == $aQueries[$sParent]['down'][$sRemoteClass]['sQueryDown'])
{
$bInherited = true;
$aQueries[$sClass]['down'][$sRemoteClass] = $aQueries[$sParent]['down'][$sRemoteClass];
break;
}
}
if (!$bInherited)
{
$aQueries[$sClass]['down'][$sRemoteClass] = array(
'_legacy_' => true,
'sDefinedInClass' => $sClass,
'sFromClass' => $sClass,
'sToClass' => $sRemoteClass,
'sDirection' => 'down',
'sQueryDown' => $aLegacyEntry['sQuery'],
'sQueryUp' => null,
'sNeighbour' => $sRemoteClass // Normalize the neighbour id
);
}
}
$aLegacy = call_user_func_array(array($sClass, 'GetRelationQueries'), array($sRevertCode));
foreach($aLegacy as $sId => $aLegacyEntry)
{
$bHasLegacy = true;
$oFilter = DBObjectSearch::FromOQL($aLegacyEntry['sQuery']);
$sRemoteClass = $oFilter->GetClass();
// Determine wether the query is inherited from a parent or not
$bInherited = false;
foreach(self::EnumParentClasses($sClass) as $sParent)
{
if (!isset($aQueries[$sParent]['up'][$sRemoteClass]))
{
continue;
}
if ($aLegacyEntry['sQuery'] == $aQueries[$sParent]['up'][$sRemoteClass]['sQueryUp'])
{
$bInherited = true;
$aQueries[$sClass]['up'][$sRemoteClass] = $aQueries[$sParent]['up'][$sRemoteClass];
break;
}
}
if (!$bInherited)
{
$aQueries[$sClass]['up'][$sRemoteClass] = array(
'_legacy_' => true,
'sDefinedInClass' => $sRemoteClass,
'sFromClass' => $sRemoteClass,
'sToClass' => $sClass,
'sDirection' => 'both',
'sQueryDown' => null,
'sQueryUp' => $aLegacyEntry['sQuery'],
'sNeighbour' => $sClass// Normalize the neighbour id
);
}
}
}
//else
//{
// Cannot take the legacy system into account... simply ignore it
//}
} // foreach class
// Perform the up/down reconciliation for the legacy definitions
if ($bHasLegacy)
{
foreach(self::GetClasses() as $sClass)
{
// Foreach "up" legacy query, update its "down" counterpart
if (isset($aQueries[$sClass]['up']))
{
foreach($aQueries[$sClass]['up'] as $sNeighbourId => $aNeighbourData)
{
if (!array_key_exists('_legacy_', $aNeighbourData))
{
continue;
}
if (!$aNeighbourData['_legacy_'])
{
continue;
} // Skip modern definitions
$sLocalClass = $aNeighbourData['sToClass'];
foreach(self::EnumChildClasses($aNeighbourData['sFromClass'], ENUM_CHILD_CLASSES_ALL) as $sRemoteClass)
{
if (isset($aQueries[$sRemoteClass]['down'][$sLocalClass]))
{
$aQueries[$sRemoteClass]['down'][$sLocalClass]['sQueryUp'] = $aNeighbourData['sQueryUp'];
$aQueries[$sRemoteClass]['down'][$sLocalClass]['sDirection'] = 'both';
}
// Be silent in order to transparently support legacy data models where the counterpart query does not always exist
//else
//{
// throw new Exception("Legacy definition of the relation '$sRelCode/$sRevertCode', defined on $sLocalClass (relation: $sRevertCode, inherited to $sClass), missing the counterpart query on class $sRemoteClass ($sRelCode)");
//}
}
}
}
// Foreach "down" legacy query, update its "up" counterpart (if any)
foreach($aQueries[$sClass]['down'] as $sNeighbourId => $aNeighbourData)
{
if (!$aNeighbourData['_legacy_'])
{
continue;
} // Skip modern definitions
$sLocalClass = $aNeighbourData['sFromClass'];
foreach(self::EnumChildClasses($aNeighbourData['sToClass'], ENUM_CHILD_CLASSES_ALL) as $sRemoteClass)
{
if (isset($aQueries[$sRemoteClass]['up'][$sLocalClass]))
{
$aQueries[$sRemoteClass]['up'][$sLocalClass]['sQueryDown'] = $aNeighbourData['sQueryDown'];
}
}
}
}
}
return $aQueries;
}
@@ -3318,18 +3167,6 @@ abstract class MetaModel
// In fact it is an ABSTRACT function, but this is not compatible with the fact that it is STATIC (error in E_STRICT interpretation)
}
/**
* To be overloaded by biz model declarations
*
* @param string $sRelCode
*
* @return array
*/
public static function GetRelationQueries($sRelCode)
{
// In fact it is an ABSTRACT function, but this is not compatible with the fact that it is STATIC (error in E_STRICT interpretation)
return array();
}
/**
* @param array $aParams
@@ -7239,99 +7076,11 @@ abstract class MetaModel
return $aResult;
}
/**
* @deprecated 2.5.0 It is not recommended to use this function: call {@link MetaModel::GetLinkClasses} instead !
* The only difference with EnumLinkingClasses is the output format
*
* @see MetaModel::GetLinkClasses
* @return string[] classes having at least two external keys (thus too many classes as compared to GetLinkClasses)
*
*/
public static function EnumLinksClasses()
{
// Returns a flat array of classes having at least two external keys
$aResult = array();
foreach(self::$m_aAttribDefs as $sSomeClass => $aClassAttributes)
{
$iExtKeyCount = 0;
foreach($aClassAttributes as $sAttCode => $oAttDef)
{
if (self::$m_aAttribOrigins[$sSomeClass][$sAttCode] != $sSomeClass)
{
continue;
}
if ($oAttDef->IsExternalKey())
{
$iExtKeyCount++;
}
}
if ($iExtKeyCount >= 2)
{
$aResult[] = $sSomeClass;
}
}
return $aResult;
}
/**
* @deprecated 2.5.0 It is not recommended to use this function: call {@link MetaModel::GetLinkClasses} instead !
* The only difference with EnumLinksClasses is the output format
*
* @see MetaModel::GetLinkClasses
*
*@param string $sClass
*
* @return string[] classes having at least two external keys (thus too many classes as compared to GetLinkClasses)
* @throws \CoreException
*
*/
public static function EnumLinkingClasses($sClass = "")
{
// N-N links, array of sLinkClass => (array of sAttCode=>sClass)
$aResult = array();
foreach(self::EnumLinksClasses() as $sSomeClass)
{
$aTargets = array();
$bFoundClass = false;
foreach(self::ListAttributeDefs($sSomeClass) as $sAttCode => $oAttDef)
{
if (self::$m_aAttribOrigins[$sSomeClass][$sAttCode] != $sSomeClass)
{
continue;
}
if ($oAttDef->IsExternalKey())
{
$sRemoteClass = $oAttDef->GetTargetClass();
if (empty($sClass))
{
$aTargets[$sAttCode] = $sRemoteClass;
}
elseif ($sClass == $sRemoteClass)
{
$bFoundClass = true;
}
else
{
$aTargets[$sAttCode] = $sRemoteClass;
}
}
}
if (empty($sClass) || $bFoundClass)
{
$aResult[$sSomeClass] = $aTargets;
}
}
return $aResult;
}
/**
* Using GetLinkClasses is the recommended way to determine if a class is
* actually an N-N relation because it is based on the decision made by the
* designer the data model
*
* This function has two siblings that will be soon deprecated:
* {@link MetaModel::EnumLinkingClasses} and {@link MetaModel::EnumLinkClasses}
*
* @return array (target class => (external key code => target class))
* @throws \CoreException
*/

View File

@@ -1643,6 +1643,35 @@ class FieldExpression extends UnaryExpression
// Has been resolved into an SQL expression
class FieldExpressionResolved extends FieldExpression
{
protected $m_aAdditionalExpressions;
public function __construct($mExpression, $sParent = '')
{
$this->m_aAdditionalExpressions = array();
if (is_array($mExpression))
{
foreach ($mExpression as $sSuffix => $sExpression)
{
if ($sSuffix == '')
{
$sName = $sExpression;
}
$this->m_aAdditionalExpressions[$sSuffix] = new FieldExpressionResolved($sExpression, $sParent);
}
}
else
{
$sName = $mExpression;
}
parent::__construct($sName, $sParent);
}
public function AdditionalExpressions()
{
return $this->m_aAdditionalExpressions;
}
public function GetUnresolvedFields($sAlias, &$aUnresolved)
{
}

View File

@@ -38,6 +38,8 @@ class ormDocument
protected $m_data;
protected $m_sMimeType;
protected $m_sFileName;
protected $m_oHostObject;
protected $m_sHostObjectAttcode;
/**
* Constructor
@@ -47,6 +49,15 @@ class ormDocument
$this->m_data = $data;
$this->m_sMimeType = $sMimeType;
$this->m_sFileName = $sFileName;
$this->m_oHostObject = null;
$this->m_sHostObjectAttcode = null;
}
public function SetHostObject(DBObject $oHostObject, $sAttCode)
{
$this->m_oHostObject = $oHostObject;
$this->m_sHostObjectAttcode = $sAttCode;
}
public function __toString()
@@ -138,6 +149,12 @@ class ormDocument
*/
public function GetDownloadLink($sClass, $Id, $sAttCode)
{
if ($this->m_oHostObject)
{
$sClass = get_class($this->m_oHostObject);
$Id = $this->m_oHostObject->GetKey();
$sAttCode = $this->m_sHostObjectAttcode;
}
return "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/ajax.document.php?operation=download_document&class=$sClass&id=$Id&field=$sAttCode\">".htmlentities($this->GetFileName(), ENT_QUOTES, 'UTF-8')."</a>\n";
}
@@ -147,6 +164,12 @@ class ormDocument
*/
public function GetDisplayURL($sClass, $Id, $sAttCode)
{
if ($this->m_oHostObject)
{
$sClass = get_class($this->m_oHostObject);
$Id = $this->m_oHostObject->GetKey();
$sAttCode = $this->m_sHostObjectAttcode;
}
// TODO: When refactoring this with the URLMaker system, mind to also change calls in the portal (look for the "p_object_document_display" route)
return utils::GetAbsoluteUrlAppRoot() . "pages/ajax.render.php?operation=display_document&class=$sClass&id=$Id&field=$sAttCode";
}
@@ -157,6 +180,12 @@ class ormDocument
*/
public function GetDownloadURL($sClass, $Id, $sAttCode)
{
if ($this->m_oHostObject)
{
$sClass = get_class($this->m_oHostObject);
$Id = $this->m_oHostObject->GetKey();
$sAttCode = $this->m_sHostObjectAttcode;
}
// Compute a signature to reset the cache anytime the data changes (this is acceptable if used only with icon files)
$sSignature = md5($this->GetData());
// TODO: When refactoring this with the URLMaker system, mind to also change calls in the portal (look for the "p_object_document_display" route)

View File

@@ -178,6 +178,14 @@ class QueryBuilderExpressions
foreach ($this->m_aSelectExpr as $sColAlias => $oExpr)
{
$this->m_aSelectExpr[$sColAlias] = $oExpr->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
if ($this->m_aSelectExpr[$sColAlias] instanceof FieldExpressionResolved)
{
// Split the field with the relevant alias
foreach ($this->m_aSelectExpr[$sColAlias]->AdditionalExpressions() as $sSuffix => $oAdditionalExpr)
{
$this->m_aSelectExpr[$sColAlias.$sSuffix] = $oAdditionalExpr->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
}
}
}
if ($this->m_aGroupByExpr)
{

View File

@@ -239,24 +239,16 @@ class SQLObjectQueryBuilder
continue;
}
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
foreach ($oAttDef->GetSQLExpressions() as $sColId => $sSQLExpr)
$oFieldSQLExp = new FieldExpressionResolved($oAttDef->GetSQLExpressions(), $sClassAlias);
/**
* @var string $sPluginClass
* @var iQueryModifier $oQueryModifier
*/
foreach (MetaModel::EnumPlugins('iQueryModifier') as $sPluginClass => $oQueryModifier)
{
if (!empty($sColId))
{
// Multi column attributes
$oBuild->m_oQBExpressions->AddSelect($sSelectedClassAlias.$sAttCode.$sColId, new FieldExpression($sAttCode.$sColId, $sClassAlias));
}
$oFieldSQLExp = new FieldExpressionResolved($sSQLExpr, $sClassAlias);
/**
* @var string $sPluginClass
* @var iQueryModifier $oQueryModifier
*/
foreach (MetaModel::EnumPlugins('iQueryModifier') as $sPluginClass => $oQueryModifier)
{
$oFieldSQLExp = $oQueryModifier->GetFieldExpression($oBuild, $sClass, $sAttCode, $sColId, $oFieldSQLExp, $oBaseSQLQuery);
}
$aTranslation[$sClassAlias][$sAttCode.$sColId] = $oFieldSQLExp;
$oFieldSQLExp = $oQueryModifier->GetFieldExpression($oBuild, $sClass, $sAttCode, '', $oFieldSQLExp, $oBaseSQLQuery);
}
$aTranslation[$sClassAlias][$sAttCode] = $oFieldSQLExp;
}
// Translate the selected columns

View File

@@ -141,7 +141,10 @@ class ValueSetObjects extends ValueSetDefinition
$this->m_oExtraCondition = $oFilter;
$this->m_bIsLoaded = false;
}
public function SetOrderBy(array $aOrderBy)
{
$this->m_aOrderBy = $aOrderBy;
}
public function ToObjectSet($aArgs = array(), $sContains = '', $iAdditionalValue = null)
{
if ($this->m_bAllowAllData)
@@ -243,7 +246,7 @@ class ValueSetObjects extends ValueSetDefinition
$oExpression = DBObjectSearch::GetPolymorphicExpression($oFilter->GetClass(), 'friendlyname');
$aFields = $oExpression->ListRequiredFields();
$sClass = $oFilter->GetClass();
foreach($aFields as $sField)
/*foreach($aFields as $sField)
{
$aFieldItems = explode('.', $sField);
if ($aFieldItems[0] != $sClass)
@@ -251,7 +254,7 @@ class ValueSetObjects extends ValueSetDefinition
$sOperation = 'contains';
break;
}
}
}*/
switch ($sOperation)
{

View File

@@ -1,7 +0,0 @@
/**
This was the file containing the rules of Font Awesome v4. Kept for scripts that included it directly.
@deprecated 2.7.0 N°2269, use /css/font-awesome/css/all.min.css instead (Font Awesome v5)
*/
@import "all.min.css";
@import "v4-shims.min.css";

File diff suppressed because one or more lines are too long

View File

@@ -3903,4 +3903,52 @@ input:checked + .slider:before {
}
.ui-dialog .ui-dialog-content .treecontrol a {
font-size: small;
}
}
/*for autocomplete*/
.ui-autocomplete {
padding: 0px;
border: 1px solid black;
background-color: white;
overflow: hidden;
z-index: 99999;
ul {
width: 100%;
list-style-position: outside;
list-style: none;
padding: 0;
margin: 0;
}
li.ui-menu-item {
margin: 0px;
padding: 2px 5px;
white-space: nowrap;
padding-right: 20px; /* Space for the scrollbar */
cursor: default;
display: block;
/*
if width will be 100% horizontal scrollbar will apear
when scroll mode will be used
*/
/*width: 100%;*/
font: menu;
font-size: 12px;
/*
it is very important, if line-height not setted or setted
in relative units scroll will be broken in firefox
*/
line-height: 16px;
overflow: hidden;
&:nth-child(odd) {
background-color: #eee;
}
&.ui-state-focus {
background-color: #0A246A;
border-color: #0A246A;
color: white;
}
}
}

View File

@@ -156,7 +156,7 @@ class CASLoginExtension extends AbstractLoginFSMExtension implements iLogoutExte
{
phpCAS::setDebug(APPROOT.'log/cas.log');
}
// Initialize phpCAS
$sCASVersion = Config::Get('cas_version');
$sCASHost = Config::Get('cas_host');
@@ -500,15 +500,8 @@ class CASUserProvisioning
}
// Now synchronize the profiles
$oProfilesSet = DBObjectSet::FromScratch('URP_UserProfile');
foreach($aProfiles as $iProfileId)
{
$oLink = new URP_UserProfile();
$oLink->Set('profileid', $iProfileId);
$oLink->Set('reason', 'CAS/LDAP Synchro');
$oProfilesSet->AddObject($oLink);
}
$oUser->Set('profile_list', $oProfilesSet);
LoginWebPage::SynchroniseProfiles($oUser, $aProfiles, 'CAS/LDAP Synchro');
phpCAS::log("Info: the user '".$oUser->GetName()."' (id=".$oUser->GetKey().") now has the following profiles: '".implode("', '", $aProfiles)."'.");
if ($oUser->IsModified())
{

View File

@@ -134,6 +134,8 @@ set_time_limit(0);
if (utils::IsModeCLI())
{
$oP = new CLIPage("iTop - Database Backup");
SetupUtils::CheckPhpAndExtensionsForCli($oP);
}
else
{

View File

@@ -250,6 +250,8 @@ catch(Exception $e)
if (utils::IsModeCLI())
{
SetupUtils::CheckPhpAndExtensionsForCli(new CLIPage('Check backup utility'));
echo date('Y-m-d H:i:s')." - running check-backup utility\n";
try
{

View File

@@ -1684,16 +1684,6 @@
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
<method id="DisplayBareRelations">
<static>false</static>
<access>public</access>
@@ -2170,18 +2160,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
</class>
<class id="DatacenterDevice" _delta="define">
<parent>ConnectableCI</parent>
@@ -2732,18 +2711,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<relations>
<relation id="impacts">
<neighbours>
@@ -3060,18 +3028,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
</class>
<class id="ApplicationSolution" _delta="define">
<parent>FunctionalCI</parent>
@@ -3210,18 +3167,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<relations>
<relation id="impacts">
<neighbours>
@@ -3341,18 +3287,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
</class>
<class id="SoftwareInstance" _delta="define">
<parent>FunctionalCI</parent>
@@ -3533,18 +3468,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
</class>
<class id="Middleware" _delta="define">
<parent>SoftwareInstance</parent>
@@ -3669,18 +3593,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<relations>
<relation id="impacts">
<neighbours>
@@ -3814,18 +3727,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<relations>
<relation id="impacts">
<neighbours>
@@ -3959,18 +3861,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<relations>
<relation id="impacts">
<neighbours>
@@ -4329,18 +4220,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
</class>
<class id="DatabaseSchema" _delta="define">
<parent>FunctionalCI</parent>
@@ -4462,18 +4342,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
</class>
<class id="WebApplication" _delta="define">
<parent>FunctionalCI</parent>
@@ -4604,18 +4473,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
</class>
<class id="Software" _delta="define">
<parent>cmdbAbstractObject</parent>

View File

@@ -232,18 +232,7 @@
<count_max>0</count_max>
</field>
</fields>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<presentation>
<details>
<items>
@@ -411,18 +400,7 @@
</reconciliation>
</properties>
<fields/>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<presentation>
<details>
<items>
@@ -911,18 +889,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
</class>
</classes>
<menus>

View File

@@ -241,7 +241,6 @@ function DoInstall(WebPage $oPage)
$oPage->add_linked_stylesheet('../css/font-awesome/css/all.min.css');
$oPage->add_linked_stylesheet('../css/font-awesome/css/v4-shims.min.css');
$oPage->add('<div id="hub_installation_widget"></div>');

View File

@@ -10,7 +10,7 @@
id="brick-{{ oBrick.GetId }}"
data-brick-id="{{ oBrick.GetId }}">
<div>
<div class="tile_title"><span class="icon fa fa-{{ oBrick.GetTileMode }}"></span> {{ oBrick.GetTitle()|dict_s }}
<div class="tile_title"><span class="icon fas fa-{{ oBrick.GetTileMode }}"></span> {{ oBrick.GetTitle()|dict_s }}
({{ iCount }})</span> </div>
{% include 'itop-portal-base/portal/templates/bricks/manage/mode-' ~ oBrick.GetTileMode ~ '.html.twig' with {'oBrick': oBrick, 'aColumns': aColumns, 'aNames': aNames, 'aUrls': aUrls, 'aDisplayValues': aDisplayValues} %}
</div>

View File

@@ -43,7 +43,6 @@
<link href="{{ app['combodo.absolute_url'] ~ 'css/font-combodo/font-combodo.css'|add_itop_version }}" rel="stylesheet">
{# - Font awesome #}
<link href="{{ app['combodo.absolute_url'] ~ 'css/font-awesome/css/all.min.css'|add_itop_version }}" rel="stylesheet">
<link href="{{ app['combodo.absolute_url'] ~ 'css/font-awesome/css/v4-shims.min.css'|add_itop_version }}" rel="stylesheet">
{# - Misc libs #}
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/typeahead/css/typeaheadjs.bootstrap.css'|add_itop_version }}" rel="stylesheet">
<link href="{{ app['combodo.absolute_url'] ~ 'css/selectize.default.css'|add_itop_version }}" rel="stylesheet">

View File

@@ -240,18 +240,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<relations>
<relation id="impacts">
<neighbours>
@@ -498,18 +487,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<relations>
<relation id="impacts">
<neighbours>
@@ -756,18 +734,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<relations>
<relation id="impacts">
<neighbours>
@@ -1014,18 +981,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<relations>
<relation id="impacts">
<neighbours>
@@ -1127,18 +1083,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
</class>
<class id="NASFileSystem" _delta="define">
<parent>cmdbAbstractObject</parent>
@@ -1245,18 +1190,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
</class>
<class id="FiberChannelInterface" _delta="define">
<parent>NetworkInterface</parent>
@@ -1511,18 +1445,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<relations>
<relation id="impacts">
<neighbours>

View File

@@ -235,18 +235,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<relations>
<relation id="impacts">
<neighbours>
@@ -394,18 +383,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
<relations>
<relation id="impacts">
<neighbours>
@@ -540,18 +518,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
</class>
<class id="VirtualMachine" _delta="define">
<parent>VirtualDevice</parent>
@@ -783,18 +750,7 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<methods/>
</class>
<class id="LogicalInterface" _delta="define">
<parent>IPInterface</parent>

View File

@@ -820,9 +820,9 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Class:SynchroAttribute/Attribute:update' => 'Update',
'Class:SynchroAttribute/Attribute:reconcile' => 'Reconcile',
'Class:SynchroAttribute/Attribute:update_policy' => 'Update Policy',
'Class:SynchroAttribute/Attribute:update_policy/Value:master_locked' => 'Gesloten',
'Class:SynchroAttribute/Attribute:update_policy/Value:master_unlocked' => 'Open',
'Class:SynchroAttribute/Attribute:update_policy/Value:write_if_empty' => 'Begin indien leeg',
'Class:SynchroAttribute/Attribute:update_policy/Value:master_locked' => 'Geblokkeerd',
'Class:SynchroAttribute/Attribute:update_policy/Value:master_unlocked' => 'Vrij',
'Class:SynchroAttribute/Attribute:update_policy/Value:write_if_empty' => 'Vul in indien leeg',
'Class:SynchroAttribute/Attribute:finalclass' => 'Klasse',
'Class:SynchroAttExtKey' => 'Synchro Attribuut (ExtKey)',
'Class:SynchroAttExtKey/Attribute:reconciliation_attcode' => 'Reconciliation-attribuut',

View File

@@ -408,7 +408,7 @@ $(function()
var oFilterElem = $('<div></div>')
.addClass('sf_filter')
.addClass('sfm_filter')
.append('<span class="sff_input_wrapper"><input type="text" placeholder="' + Dict.S('UI:Search:Value:Filter:Placeholder') + '" /><span class="sff_picto sff_filter fas fa-filter"></span><span class="sff_picto sff_reset fa fa-times"></span></span>')
.append('<span class="sff_input_wrapper"><input type="text" placeholder="' + Dict.S('UI:Search:Value:Filter:Placeholder') + '" /><span class="sff_picto sff_filter fas fa-filter"></span><span class="sff_picto sff_reset fas fa-times"></span></span>')
.appendTo(oContentElem);
// - Lists container

View File

@@ -4,6 +4,7 @@ iTop stands for *IT Operations Portal*.
It is a complete open source, ITIL, web based service management tool including a fully customizable CMDB, a helpdesk system and a document management tool.
iTop also offers mass import tools and web services to integrate with your IT
## Features
- Fully configurable **CMDB**
- **HelpDesk** and Incident Management
@@ -17,34 +18,21 @@ iTop also offers mass import tools and web services to integrate with your IT
- **Data synchronization** (for data federation)
## Resources
## Latest release
- [Changes since the previous version](https://wiki.openitop.org/doku.php?id=latest:release:change_log)
- [New features](https://wiki.openitop.org/doku.php?id=latest:release:start)
- [Migration notes](https://wiki.openitop.org/doku.php?id=latest:install:start)
- [Download](https://sourceforge.net/projects/itop/files/latest/download)
## Resources
- [iTop Forums](https://sourceforge.net/p/itop/discussion/): for support request
- [iTop Tickets](https://sourceforge.net/p/itop/tickets/): for feature requests and bug reports
- [Releases download](https://sourceforge.net/projects/itop/files/itop/)
- [Software requirements](https://wiki.openitop.org/doku.php?id=latest:install:upgrading_itop)
- [iTop documentation](https://www.itophub.io/wiki/page) for iTop and official extensions
- [iTop extensions](https://store.itophub.io/en_US/) for discovering ans installing extensions
## Releases
### Version 2.7
- [Changes since the previous version](https://wiki.openitop.org/doku.php?id=2_7_0:release:change_log)
- [New features](https://wiki.openitop.org/doku.php?id=2_7_0:release:2_7_whats_new)
- [Migration notes](https://wiki.openitop.org/doku.php?id=2_7_0:install:260_to_270_migration_notes)
### Version 2.6
- [Changes since the previous version](https://wiki.openitop.org/doku.php?id=2_6_0:release:change_log)
- [New features](https://wiki.openitop.org/doku.php?id=2_6_0:release:2_6_whats_new)
- [Migration notes](https://wiki.openitop.org/doku.php?id=2_6_0:install:250_to_260_migration_notes)
### Version 2.5
- [Changes since the previous version](https://wiki.openitop.org/doku.php?id=2_5_0:release:change_log)
- [New features](https://wiki.openitop.org/doku.php?id=2_5_0:release:2_5_whats_new)
- [Migration notes](https://wiki.openitop.org/doku.php?id=2_5_0:install:240_to_250_migration_notes)
### Version 2.4
- [Changes since the previous version](https://wiki.openitop.org/doku.php?id=2_4_0:release:change_log)
- [New features](https://wiki.openitop.org/doku.php?id=2_4_0:release:2_4_whats_new)
- [Migration notes](https://wiki.openitop.org/doku.php?id=2_4_0:install:230_to_240_migration_notes)

View File

@@ -277,7 +277,6 @@ class iTopExtensionsMap
$oExtension->sVersion = $oXml->Get('version');
$oExtension->bMandatory = ($oXml->Get('mandatory') == 'true');
$oExtension->sMoreInfoUrl = $oXml->Get('more_info_url');
$oExtension->sVersion = $oXml->Get('version');
$oExtension->sSource = $sSource;
$oExtension->sSourceDir = $sSearchDir;

View File

@@ -39,6 +39,50 @@ class CheckResult
$this->sLabel = $sLabel;
$this->sDescription = $sDescription;
}
/**
* @return string
* @since 2.8.0 N°2214
*/
public function __toString()
{
$sPrintDesc = (empty($this->sDescription)) ? '' : " ({$this->sDescription})";
return "{$this->sLabel}$sPrintDesc";
}
/**
* @param \CheckResult[] $aResults
*
* @return \CheckResult[] only elements that are error (iSeverity===ERROR)
*
* @since 2.8.0 N°2214
*/
public static function KeepOnlyErrors($aResults)
{
return array_filter($aResults,
static function ($v)
{
if ($v->iSeverity === CheckResult::ERROR) {
return $v;
}
},
ARRAY_FILTER_USE_BOTH);
}
/**
* @param \CheckResult[] $aResults
*
* @return string[]
* @uses \CheckResult::__toString
*
* @since 2.8.0 N°2214
*/
public static function FromObjectsToStrings($aResults)
{
return array_map(function ($value) {
return $value->__toString();
}, $aResults);
}
}
/**
@@ -50,15 +94,15 @@ class CheckResult
class SetupUtils
{
// -- Minimum versions (requirements : forbids installation if not met)
const PHP_MIN_VERSION = '5.6.0'; // 5.6 will be supported until the end of 2018 (see http://php.net/supported-versions.php)
const PHP_MIN_VERSION = '7.1.3'; // 7 will be supported until the end of 2019 (see http://php.net/supported-versions.php)
const MYSQL_MIN_VERSION = '5.6.0'; // 5.6 to have fulltext on InnoDB for Tags fields (N°931)
const MYSQL_NOT_VALIDATED_VERSION = ''; // MySQL 8 is now OK (N°2010 in 2.7.0) but has no query cache so mind the perf on large volumes !
// -- versions that will be the minimum in next iTop major release (warning if not met)
const PHP_NEXT_MIN_VERSION = '7.1.3'; // we are aiming on switching to Symfony 4 in iTop 2.8
const PHP_NEXT_MIN_VERSION = ''; //
const MYSQL_NEXT_MIN_VERSION = ''; // no new MySQL requirement for next iTop version
// -- First recent version that is not yet validated by Combodo (warning)
const PHP_NOT_VALIDATED_VERSION = '7.5.0';
const PHP_NOT_VALIDATED_VERSION = '8.0.0';
const MIN_MEMORY_LIMIT = 33554432; // 32 * 1024 * 1024 - we can use expressions in const since PHP 5.6 but we are in the setup !
const SUHOSIN_GET_MAX_VALUE_LENGTH = 2048;
@@ -370,6 +414,37 @@ class SetupUtils
return $aResult;
}
/**
* @param \CLIPage $oCliPage
* @param int $iExitCode
*
* @since 2.8.0 N°2214
*/
public static function CheckPhpAndExtensionsForCli($oCliPage, $iExitCode = -1)
{
$aPhpCheckResults = self::CheckPhpAndExtensions();
$aPhpCheckErrors = CheckResult::KeepOnlyErrors($aPhpCheckResults);
if (empty($aPhpCheckErrors))
{
return;
}
$sMessageTitle = 'Error: PHP minimum requirements are not met !';
$oCliPage->p($sMessageTitle);
$aPhpCheckErrorsForPrint = CheckResult::FromObjectsToStrings($aPhpCheckErrors);
foreach ($aPhpCheckErrorsForPrint as $sError)
{
$oCliPage->p(' * '.$sError);
}
$oCliPage->output();
// some CLI scripts are launched automatically
// we need a log so that we don't miss errors after migration !
IssueLog::Error($oCliPage->s_title.' '.$sMessageTitle, 'CLI', $aPhpCheckErrorsForPrint);
exit($iExitCode);
}
/**
* @param CheckResult[] $aResult checks log
*/

View File

@@ -411,7 +411,7 @@ class CriterionToOQL extends CriterionConversionAbstract
// Use the 'below' operator by default
$oSearch->AddCondition_PointingTo($oHKFilter, $sAttCode);
$oCriteria = $oSearch->GetCriteria();
$aArgs = MetaModel::PrepareQueryArguments(array(), $oSearch->GetInternalParams());
$aArgs = MetaModel::PrepareQueryArguments(array(), $oSearch->GetInternalParams(), $oSearch->GetExpectedArguments() );
$oSearch->ResetCondition();
$sCondition = $oCriteria->Render($aArgs);
}

View File

@@ -530,7 +530,7 @@ class SearchForm
{
$aOrCriterion = array();
$bIsEmptyExpression = true;
$aArgs = MetaModel::PrepareQueryArguments($aArgs, $oSearch->GetInternalParams());
$aArgs = MetaModel::PrepareQueryArguments($aArgs, $oSearch->GetInternalParams(), $oSearch->GetExpectedArguments());
if ($oSearch instanceof DBObjectSearch)
{

View File

@@ -72,6 +72,7 @@ function ReadMandatoryParam($oP, $sParam, $sSanitizationFilter = 'parameter')
if (utils::IsModeCLI())
{
$oP = new CLIPage(Dict::S("TitleSynchroExecution"));
SetupUtils::CheckPhpAndExtensionsForCli($oP, -2);
}
else
{

View File

@@ -255,6 +255,7 @@ class CLILikeWebPage extends WebPage
if (utils::IsModeCLI())
{
$oP = new CLIPage(Dict::S('TitleSynchroExecution'));
SetupUtils::CheckPhpAndExtensionsForCli($oP, -2);
}
else
{

View File

@@ -277,5 +277,42 @@ class HTMLDOMSanitizerTest extends ItopTestCase
);
}
/**
* @dataProvider CallInlineImageProcessImageTagProvider
*/
public function testDoSanitizeCallInlineImageProcessImageTag($sHtml, $iExpectedCount)
{
require_once APPROOT.'test/core/sanitizer/InlineImageMock.php';
$oSanitizer = new HTMLDOMSanitizer();
$oSanitizer->DoSanitize($sHtml);
$iCalledCount = \InlineImage::GetCallCounter();
$this->assertEquals($iExpectedCount, $iCalledCount);
}
public function CallInlineImageProcessImageTagProvider()
{
return array(
'no image' => array(
'html' => '<p>bar</p>',
'expected' => 0,
),
'basic image' => array(
'html' => '<img />',
'expected' => 1,
),
'nested images within forbidden tags' => array(
'html' => '<html><body><img /><iframe baz="1"><div baz="baz"><article baz="1" biz="2">baz<img /><img /></article>rab</div> oof<img /></iframe><img /></body></html>',
'expected' => 2,
),
// This test will be restored with the ticket n°2556
// 'nested images within forbidden and removed tags' => array(
// 'html' => '<html><body><img /><iframe baz="1"><div baz="baz"><object baz="1" biz="2">baz<img /><img /></object>rab</div> oof<img /></iframe><img /></body></html>',
// 'expected' => 2,
// ),
);
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* Copyright (C) 2010-2020 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/>
*
*/
/**
* Mock class used by @see \Combodo\iTop\Test\UnitTest\Core\HTMLDOMSanitizerTest
*
*/
class InlineImage
{
private static $iCallCounter = 0;
public static function ProcessImageTag(DOMNode $oNode)
{
self::$iCallCounter++;
}
public static function GetCallCounter()
{
return self::$iCallCounter;
}
}

View File

@@ -485,7 +485,7 @@ class TestMyBizModel extends TestBizModel
echo "Max depth = $iMaxDepth</br>\n";
$oObj = MetaModel::GetObject("cmdbContact", 18);
$aRels = $oObj->GetRelatedObjects("Potes", $iMaxDepth);
$aRels = $oObj->GetRelatedObjectsDown("Potes", $iMaxDepth);
echo $oObj->Get('name')." has some 'Potes'...</br>\n";
foreach ($aRels as $sClass => $aObjs)
{
@@ -581,391 +581,6 @@ class TestMyBizModel extends TestBizModel
}
///////////////////////////////////////////////////////////////////////////
// Test a complex biz model on the fly
///////////////////////////////////////////////////////////////////////////
abstract class MyFarm extends TestBizModel
{
static public function GetConfigFile() {return '/config-test-farm.php';}
protected function DoPrepare()
{
parent::DoPrepare();
$this->ResetDB();
MetaModel::DBCheckIntegrity();
}
protected function InsertMammal($sSpecies, $sSex, $iSpeed, $iMotherid, $iFatherId, $sName, $iHeight, $sBirth)
{
$oNew = MetaModel::NewObject('Mammal');
$oNew->Set('species', $sSpecies);
$oNew->Set('sex', $sSex);
$oNew->Set('speed', $iSpeed);
$oNew->Set('mother', $iMotherid);
$oNew->Set('father', $iFatherId);
$oNew->Set('name', $sName);
$oNew->Set('height', $iHeight);
$oNew->Set('birth', $sBirth);
return $this->ObjectToDB($oNew);
}
protected function InsertBird($sSpecies, $sSex, $iSpeed, $iMotherid, $iFatherId)
{
$oNew = MetaModel::NewObject('Bird');
$oNew->Set('species', $sSpecies);
$oNew->Set('sex', $sSex);
$oNew->Set('speed', $iSpeed);
$oNew->Set('mother', $iMotherid);
$oNew->Set('father', $iFatherId);
return $this->ObjectToDB($oNew);
}
protected function InsertFlyingBird($sSpecies, $sSex, $iSpeed, $iMotherid, $iFatherId, $iFlyingSpeed)
{
$oNew = MetaModel::NewObject('FlyingBird');
$oNew->Set('species', $sSpecies);
$oNew->Set('sex', $sSex);
$oNew->Set('speed', $iSpeed);
$oNew->Set('mother', $iMotherid);
$oNew->Set('father', $iFatherId);
$oNew->Set('flyingspeed', $iFlyingSpeed);
return $this->ObjectToDB($oNew);
}
private function InsertGroup($sName, $iLeaderId)
{
$oNew = MetaModel::NewObject('Group');
$oNew->Set('name', $sName);
$oNew->Set('leader', $iLeaderId);
$iId = $oNew->DBInsertNoReload();
return $iId;
}
}
class TestQueriesOnFarm extends MyFarm
{
static public function GetName()
{
return 'Farm test';
}
static public function GetDescription()
{
return 'A series of tests on the farm business model (SQL generation)';
}
protected function CheckQuery($sQuery, $bIsCorrectQuery)
{
if ($bIsCorrectQuery)
{
echo "<h4 style=\"color:green;\">$sQuery</h4>\n";
}
else
{
echo "<h4 style=\"color:red;\">$sQuery</h3>\n";
}
try
{
//$oOql = new OqlInterpreter($sQuery);
//$oTrash = $oOql->ParseQuery();
//self::DumpVariable($oTrash, true);
$oMyFilter = DBObjectSearch::FromOQL($sQuery);
}
catch (OQLException $oOqlException)
{
if ($bIsCorrectQuery)
{
echo "<p>More info on this unexpected failure:<br/>".$oOqlException->getHtmlDesc()."</p>\n";
throw $oOqlException;
return false;
}
else
{
// Everything is fine :-)
echo "<p>More info on this expected failure:\n";
echo "<ul>\n";
echo "<li>".get_class($oOqlException)."</li>\n";
echo "<li>".$oOqlException->getMessage()."</li>\n";
echo "<li>".$oOqlException->getHtmlDesc()."</li>\n";
echo "</ul>\n";
echo "</p>\n";
return true;
}
}
// The query was correctly parsed, was it expected to be correct ?
if (!$bIsCorrectQuery)
{
throw new UnitTestException("The query '$sQuery' was parsed with success, while it shouldn't (?)");
return false;
}
echo "<p>To OQL: ".$oMyFilter->ToOQL()."</p>";
$this->search_and_show_list($oMyFilter);
//echo "<p>first pass<p>\n";
//self::DumpVariable($oMyFilter, true);
$sQuery1 = $oMyFilter->MakeSelectQuery();
//echo "<p>second pass<p>\n";
//self::DumpVariable($oMyFilter, true);
//$sQuery1 = $oMyFilter->MakeSelectQuery();
$sSerialize = $oMyFilter->serialize();
echo "<p>Serialized:$sSerialize</p>\n";
$oFilter2 = DBObjectSearch::unserialize($sSerialize);
try
{
$sQuery2 = $oFilter2->MakeSelectQuery();
}
catch (Exception $e)
{
echo "<p>Could not compute the query after unserialize</p>\n";
echo "<p>Query 1: $sQuery1</p>\n";
MyHelpers::var_cmp_html($oMyFilter, $oFilter2);
throw $e;
}
//if ($oFilter2 != $oMyFilter) no, they may differ while the resulting query is the same!
if ($sQuery1 != $sQuery2)
{
echo "<p>serialize/unserialize mismatch :-(</p>\n";
MyHelpers::var_cmp_html($sQuery1, $sQuery2);
MyHelpers::var_cmp_html($oMyFilter, $oFilter2);
return false;
}
return true;
}
protected function DoExecute()
{
// $this->ReportError("Found two different OQL expression out of the (same?) filter: <em>$sExpr1</em> != <em>$sExpr2</em>");
// $this->ReportSuccess('Found '.$oSet->Count()." objects of class $sClassName");
echo "<h3>Create protagonists...</h3>";
$iId1 = $this->InsertMammal('human', 'male', 10, 0, 0, 'romanoff', 192, '1971-07-19');
$iId2 = $this->InsertMammal('human', 'female', 9, 0, 0, 'rouanita', 165, '1983-01-23');
$this->InsertMammal('human', 'female', 3, $iId2, $iId1, 'pomme', 169, '2008-02-23');
$this->InsertMammal('pig', 'female', 3, 0, 0, 'grouinkette', 85, '2006-06-01');
$this->InsertMammal('donkey', 'female', 3, 0, 0, 'muleta', 124, '2003-11-11');
$this->InsertBird('rooster', 'male', 12, 0, 0);
$this->InsertFlyingBird('pie', 'female', 11, 0, 0, 35);
// Benchmarking
//
if (false)
{
define ('COUNT_BENCHMARK', 10);
echo "<h3>Parsing a long query, ".COUNT_BENCHMARK." times</h3>";
$sQuery = "SELECT Animal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.birth < DATE_SUB(CURRENT_DATE(), INTERVAL 10 YEAR) AND Dad.height * 2 <= ROUND(TO_DAYS(Dad.birth) / (3 + 1) * 5 - 3)";
$fStart = MyHelpers::getmicrotime();
for($i=0 ; $i < COUNT_BENCHMARK ; $i++)
{
$oMyFilter = DBObjectSearch::FromOQL($sQuery);
}
$fDuration = MyHelpers::getmicrotime() - $fStart;
$fParsingDuration = $fDuration / COUNT_BENCHMARK;
echo "<p>Mean time by op: $fParsingDuration</p>";
}
echo "<h3>Test queries...</h3>";
$aQueries = array(
'SELECT Animal' => true,
'SELECT Animal WHERE Animal.pkey = 1' => false,
'SELECT Animal WHERE Animal.id = 1' => true,
'SELECT Aniiimal' => false,
'SELECTe Animal' => false,
'SELECT * FROM Animal' => false,
'SELECT Animal AS zoo WHERE zoo.species = \'human\'' => true,
'SELECT Animal AS zoo WHERE species = \'human\'' => true,
'SELECT Animal AS zoo WHERE espece = \'human\'' => false,
'SELECT Animal AS zoo WHERE zoo.species IN (\'human\', "pig")' => true,
'SELECT Animal AS zoo WHERE CONCATENATION(zoo.species, zoo.sex) LIKE "hum%male"' => false,
'SELECT Animal AS zoo WHERE CONCAT(zoo.species, zoo.sex) LIKE "hum%male"' => true,
'SELECT Animal AS zoo WHERE zoo.species NOT IN (\'human\', "pig")' => true,
'SELECT Animal AS zoo WHERE zoo.kind = \'human\'' => false,
'SELECT Animal WHERE Animal.species = \'human\' AND Animal.sex = \'female\'' => true,
'SELECT Mammal AS x WHERE (x.species = \'human\' AND x.name LIKE \'ro%\') OR (x.species = \'donkey\' AND x.name LIKE \'po%\')' => true,
'SELECT Mammal AS x WHERE x.species = \'human\' AND x.name LIKE \'ro%\' OR x.species = \'donkey\' AND x.name LIKE \'po%\'' => true,
'SELECT Mammal AS m WHERE MONTH(m.birth) = 7' => true,
'SELECT Mammal AS m WHERE DAY(m.birth) = 19' => true,
'SELECT Mammal AS m WHERE YEAR(m.birth) = 1971' => true,
'SELECT Mammal AS m WHERE m.birth < DATE_SUB(CURRENT_DATE(), INTERVAL 10 YEAR)' => true,
'SELECT Mammal AS m WHERE m.birth > DATE_SUB(NOW(), INTERVAL 2000 DAY)' => true,
'SELECT Mammal AS m WHERE (TO_DAYS(NOW()) - TO_DAYS(m.birth)) > 2000' => true,
'SELECT Mammal AS m WHERE m.name = IF(FLOOR(ROUND(m.height)) > 2, "pomme", "romain")' => true,
'SELECT Mammal AS m WHERE (1 + 2' => false,
'SELECT Mammal AS m WHERE (1 + 2 * 4 / 23) > 0' => true,
'SELECT Mammal AS m WHERE (4 / 23 * 2 + 1) > 0' => true,
'SELECT Mammal AS m WHERE 1/0' => true,
'SELECT Mammal AS m WHERE MONTH(m.birth) = 7' => true,
'SELECT Animal JOIN Group ON Group.leader = Animal.id' => true,
'SELECT Group JOIN Animal ON Group.leader = Animal.id' => true,
'SELECT Animal AS A JOIN Group AS G1 ON G1.leader = A.id' => true,
'SELECT Animal AS A JOIN Group AS G ON FooClass.leader = A.id' => false,
'SELECT Animal AS A JOIN Group AS G ON G.leader = FooClass.id' => false,
'SELECT Animal AS A JOIN Group AS G ON G.masterchief = A.id' => false,
'SELECT Animal AS A JOIN Group AS G ON A.id = G.leader' => false,
'SELECT Animal AS A JOIN Group AS G ON G.leader = A.id WHERE A.sex=\'male\' OR G.qwerty = 123' => false,
'SELECT Animal AS A JOIN Group AS G ON G.leader = A.id WHERE A.sex=\'male\' OR G.name LIKE "a%"' => true,
'SELECT Animal AS A JOIN Group AS G ON G.leader = A.id WHERE A.id = 1' => true,
'SELECT Animal AS A JOIN Group AS G ON G.leader = A.id WHERE id = 1' => false,
'SELECT Animal AS A JOIN Group AS G ON A.member = G.id' => false,
'SELECT Mammal AS M JOIN Group AS G ON M.member = G.id' => true,
'SELECT Mammal AS M JOIN Group AS G ON A.member = G.id' => false,
'SELECT Mammal AS myAlias JOIN Group AS myAlias ON myAlias.member = myAlias.id' => false,
'SELECT Mammal AS Mammal JOIN Group AS Mammal ON Mammal.member = Mammal.id' => false,
'SELECT Group AS G WHERE G.leader_name LIKE "%"' => true,
'SELECT Group AS G WHERE G.leader_speed < 100000' => true,
'SELECT Mammal AS M JOIN Group AS G ON M.member = G.id WHERE G.leader_name LIKE "%"' => true,
'SELECT Mammal AS M JOIN Group AS G ON M.member = G.id WHERE G.leader_speed < 100000' => true,
'SELECT Mammal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id' => true,
'SELECT Mammal AS Child JOIN Animal AS Dad ON Child.father = Dad.id' => true,
'SELECT Animal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id' => true,
'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id' => true,
'SELECT Animal AS Dad JOIN Animal AS Child ON Child.father = Dad.id' => true,
'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id' => true,
'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.id = 1' => true,
'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.name = \'romanoff\'' => false,
'SELECT Animal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id' => true,
'SELECT Animal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.name = \'romanoff\' OR Mum.speed = 0' => true,
'SELECT Animal AS Dad JOIN Animal AS Child ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id' => true,
'SELECT Mammal AS Dad JOIN Mammal AS Child ON Child.father = Dad.id' => true,
'SELECT Mammal AS Dad JOIN Mammal AS Child ON Child.father = Dad.id JOIN Mammal AS Mum ON Child.mother = Mum.id WHERE Dad.name = \'romanoff\' OR Mum.name=\'chloe\' OR Child.name=\'bizounours\'' => true,
// Specifying multiple objects
'SELECT Animal FROM Animal' => true,
'SELECT yelele FROM Animal' => false,
'SELECT Animal FROM Animal AS A' => false,
'SELECT A FROM Animal AS A' => true,
);
//$aQueries = array(
// 'SELECT Mammal AS M JOIN Group AS G ON M.member = G.id WHERE G.leader_name LIKE "%"' => true,
//);
foreach($aQueries as $sQuery => $bIsCorrect)
{
$this->CheckQuery($sQuery, $bIsCorrect);
}
return true;
}
}
///////////////////////////////////////////////////////////////////////////
// Test data load
///////////////////////////////////////////////////////////////////////////
class TestBulkChangeOnFarm extends TestBizModel
{
static public function GetName()
{
return 'Farm test - data load';
}
static public function GetDescription()
{
return 'Bulk load';
}
static public function GetConfigFile() {return '/config-test-farm.php';}
protected function DoPrepare()
{
parent::DoPrepare();
$this->ResetDB();
MetaModel::DBCheckIntegrity();
}
protected function DoExecute()
{
// $this->ReportError("Found two different OQL expression out of the (same?) filter: <em>$sExpr1</em> != <em>$sExpr2</em>");
// $this->ReportSuccess('Found '.$oSet->Count()." objects of class $sClassName");
$oParser = new CSVParser("denomination,hauteur,age
suzy,123,2009-01-01
chita,456,
", ',', '"');
$aData = $oParser->ToArray(1, array('_name', '_height', '_birth'));
self::DumpVariable($aData);
$oBulk = new BulkChange(
'Mammal',
$aData,
// attributes
array('name' => '_name', 'height' => '_height', 'birth' => '_birth'),
// ext keys
array(),
// reconciliation
array('name')
);
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Testor");
$iChangeId = $oMyChange->DBInsert();
// echo "Created new change: $iChangeId</br>";
echo "<h3>Planned for loading...</h3>";
$aRes = $oBulk->Process();
self::DumpVariable($aRes);
echo "<h3>Go for loading...</h3>";
$aRes = $oBulk->Process($oMyChange);
self::DumpVariable($aRes);
return;
$oRawData = array(
'Mammal',
array('species', 'sex', 'speed', 'mother', 'father', 'name', 'height', 'birth'),
"human,male,23,0,0,romulus,192,1971
human,male,23,0,0,remus,154,-50
human,male,23,0,0,julius,160,-49
human,female,23,0,0,cleopatra,142,-50
pig,female,23,0,0,confucius,50,2003"
);
}
}
///////////////////////////////////////////////////////////////////////////
// Test data load
///////////////////////////////////////////////////////////////////////////
class TestFullTextSearchOnFarm extends MyFarm
{
static public function GetName()
{
return 'Farm test - full text search';
}
static public function GetDescription()
{
return 'Focus on the full text search feature';
}
protected function DoExecute()
{
echo "<h3>Create protagonists...</h3>";
$iId1 = $this->InsertMammal('human', 'male', 10, 0, 0, 'romanoff', 192, '1971-07-19');
$iId2 = $this->InsertMammal('human', 'female', 9, 0, 0, 'rouanita', 165, '1983-01-23');
$this->InsertMammal('human', 'female', 3, $iId2, $iId1, 'pomme', 169, '2008-02-23');
$this->InsertMammal('pig', 'female', 3, 0, 0, 'grouinkette', 85, '2006-06-01');
$this->InsertMammal('donkey', 'female', 3, 0, 0, 'muleta', 124, '2003-11-11');
$this->InsertBird('rooster', 'male', 12, 0, 0);
$this->InsertFlyingBird('pie', 'female', 11, 0, 0, 35);
echo "<h3>Search...</h3>";
$oSearch = new DBObjectSearch('Mammal');
$oSearch->AddCondition_FullText('manof');
//$oResultSet = new DBObjectSet($oSearch);
$this->search_and_show_list($oSearch);
}
}
///////////////////////////////////////////////////////////////////////////
// Test queries
///////////////////////////////////////////////////////////////////////////

View File

@@ -60,7 +60,7 @@ function ReadMandatoryParam($oP, $sParam, $sSanitizationFilter = 'parameter')
function UsageAndExit($oP)
{
$bModeCLI = utils::IsModeCLI();
$bModeCLI = ($oP instanceof CLIPage);
if ($bModeCLI)
{
@@ -477,9 +477,12 @@ function ReorderProcesses(&$aProcesses, $aTasks, $oNow, $bVerbose, &$oP)
set_time_limit(0); // Some background actions may really take long to finish (like backup)
if (utils::IsModeCLI())
$bIsModeCLI = utils::IsModeCLI();
if ($bIsModeCLI)
{
$oP = new CLIPage("iTop - cron");
SetupUtils::CheckPhpAndExtensionsForCli($oP, EXIT_CODE_FATAL);
}
else
{
@@ -497,7 +500,7 @@ catch (Exception $e)
exit(EXIT_CODE_FATAL);
}
if (utils::IsModeCLI())
if ($bIsModeCLI)
{
// Next steps:
// specific arguments: 'csvfile'

View File

@@ -32,6 +32,12 @@ require_once(APPROOT.'/core/bulkexport.class.inc.php');
require_once(APPROOT.'/application/startup.inc.php');
const EXIT_CODE_ERROR = -1;
const EXIT_CODE_FATAL = -2;
function ReportErrorAndExit($sErrorMessage)
{
if (utils::IsModeCLI())
@@ -39,14 +45,14 @@ function ReportErrorAndExit($sErrorMessage)
$oP = new CLIPage("iTop - Export");
$oP->p('ERROR: '.$sErrorMessage);
$oP->output();
exit(-1);
exit(EXIT_CODE_ERROR);
}
else
{
$oP = new WebPage("iTop - Export");
$oP->p('ERROR: '.$sErrorMessage);
$oP->output();
exit(-1);
exit(EXIT_CODE_ERROR);
}
}
@@ -58,7 +64,7 @@ function ReportErrorAndUsage($sErrorMessage)
$oP->p('ERROR: '.$sErrorMessage);
Usage($oP);
$oP->output();
exit(-1);
exit(EXIT_CODE_ERROR);
}
else
{
@@ -66,7 +72,7 @@ function ReportErrorAndUsage($sErrorMessage)
$oP->p('ERROR: '.$sErrorMessage);
Usage($oP);
$oP->output();
exit(-1);
exit(EXIT_CODE_ERROR);
}
}
@@ -565,6 +571,8 @@ function DoExport(WebPage $oP, BulkExport $oExporter, $bInteractive = false)
/////////////////////////////////////////////////////////////////////////////
if (utils::IsModeCLI())
{
SetupUtils::CheckPhpAndExtensionsForCli(new CLIPage('iTop - Export'));
try
{
// Do this before loging, in order to allow setting user credentials from within the file
@@ -573,7 +581,7 @@ if (utils::IsModeCLI())
catch(Exception $e)
{
echo "Error: ".$e->GetMessage()."<br/>\n";
exit(-2);
exit(EXIT_CODE_FATAL);
}
$sAuthUser = utils::ReadParam('auth_user', null, true /* Allow CLI */, 'raw_data');

View File

@@ -29,6 +29,11 @@ require_once(APPROOT.'/application/excelexporter.class.inc.php');
require_once(APPROOT.'/application/startup.inc.php');
const EXIT_CODE_ERROR = -1;
const EXIT_CODE_FATAL = -2;
try
{
// Do this before loging, in order to allow setting user credentials from within the file
@@ -37,12 +42,15 @@ try
catch(Exception $e)
{
echo "Error: ".$e->GetMessage()."<br/>\n";
exit -2;
exit(EXIT_CODE_FATAL);
}
if (utils::IsModeCLI())
{
$sAuthUser = utils::ReadParam('auth_user', null, true /* Allow CLI */, 'raw_data');
$oP = new CLIPage("iTop - Export");
SetupUtils::CheckPhpAndExtensionsForCli($oP, EXIT_CODE_FATAL);
$sAuthUser = utils::ReadParam('auth_user', null, true /* Allow CLI */, 'raw_data');
$sAuthPwd = utils::ReadParam('auth_pwd', null, true /* Allow CLI */, 'raw_data');
if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd))
@@ -51,10 +59,9 @@ if (utils::IsModeCLI())
}
else
{
$oP = new CLIPage("iTop - Export");
$oP->p("Access restricted or wrong credentials ('$sAuthUser')");
$oP->p("Access restricted or wrong credentials ('$sAuthUser')");
$oP->output();
exit -1;
exit(EXIT_CODE_ERROR);
}
}
else
@@ -74,7 +81,7 @@ if (utils::IsArchiveMode() && !UserRights::CanBrowseArchive())
$oP = new CLIPage("iTop - Export");
$oP->p("The user account is not authorized to access the archives");
$oP->output();
exit -1;
exit(EXIT_CODE_ERROR);
}
$bLocalize = (utils::ReadParam('no_localize', 0) != 1);

View File

@@ -212,6 +212,7 @@ function ReadMandatoryParam($oP, $sParam, $sSanitizationFilter)
if (utils::IsModeCLI())
{
$oP = new CLIPage("iTop - Bulk import");
SetupUtils::CheckPhpAndExtensionsForCli($oP, -2);
}
else
{