Merge remote-tracking branch 'origin/support/3.2' into develop

# Conflicts:
#	.doc/itop-version-history.md
This commit is contained in:
Molkobain
2024-06-28 15:08:31 +02:00
18 changed files with 152 additions and 238 deletions

View File

@@ -83,6 +83,8 @@ gitGraph
commit id: "2024-01-17a" tag: "2.7.10"
checkout support/3.0
commit id: "2024-01-17b" tag: "3.0.4"
checkout support/3.2
commit id: "2024-06-25" tag: "3.2.0-beta1"
```
To learn more, check the [iTop community versions history on the official wiki](https://www.itophub.io/wiki/page?id=latest:release:start).

View File

@@ -1686,19 +1686,16 @@ JS
$aRes = CMDBSource::QueryToArray($sSql);
$oContext = new ApplicationContext();
$sContextParam = $oContext->GetForLink();
/** @var AttributeDefinition $oGroupByAttDef */
$oGroupByAttDef = $aGroupBy["grouped_by_1"]->GetAttDef();
$iTotalCount = 0;
$aURLs = array();
foreach ($aRes as $iRow => $aRow) {
$sValue = $aRow['grouped_by_1'];
$sPlainTextValue = $oGroupByAttDef->GetValueLabel($sValue);
$sHtmlValue = utils::EscapeHtml($sPlainTextValue);
$sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
$iTotalCount += $aRow['_itop_count_'];
$aValues[] = array(
'label' => $sPlainTextValue,
'label' => html_entity_decode(strip_tags($sHtmlValue), ENT_QUOTES, 'UTF-8'),
'label_html' => $sHtmlValue,
'value' => (float)$aRow[$sFctVar],
);

View File

@@ -52,12 +52,13 @@ class LoginTwigContext
/**
* Set the absolute path on disk of the folder containing the twig templates
*
* @param string $sPath absolute path of twig templates directory
* @api
*
*@param string $sAbsPath Absolute path of twig templates directory
*/
public function SetLoaderPath($sPath)
public function SetLoaderPath($sAbsPath)
{
$this->sTwigLoaderPath = $sPath;
$this->sTwigLoaderPath = $sAbsPath;
}
/**
@@ -84,24 +85,27 @@ class LoginTwigContext
}
/**
* Add the URL of a CSS file to link to the login screen
* Add the absolute URL of a CSS file to link to the login screen
*
* @param string $sFile URL of the CSS file to link
* @api
*
* @param string $sFileAbsURL Absolute URL of the CSS file to link
*/
public function AddCSSFile($sFile)
public function AddCSSFile($sFileAbsURL)
{
$this->aCSSFiles[] = $sFile;
$this->aCSSFiles[] = $sFileAbsURL;
}
/**
* Add the URL of a javascript file to link to the login screen
* @param string $sFile URL of the javascript file to link
* Add the absolute URL of a javascript file to link to the login screen
*
* @api
*
* @param string $sFileAbsURL Absolute URL of the javascript file to link
*/
public function AddJsFile($sFile)
public function AddJsFile($sFileAbsURL)
{
$this->aJsFiles[] = $sFile;
$this->aJsFiles[] = $sFileAbsURL;
}
/**
@@ -133,7 +137,7 @@ class LoginTwigContext
}
/**
* @return array
* @return array Absolute URLs of the CSS files
*/
public function GetCSSFiles()
{
@@ -141,7 +145,7 @@ class LoginTwigContext
}
/**
* @return array
* @return array Absolute URLs of the JS files
*/
public function GetJsFiles()
{
@@ -274,12 +278,12 @@ class LoginTwigRenderer
$aCSSFiles = $oFormData->GetCSSFiles();
foreach ($aCSSFiles as $sCSSFile)
{
$oPage->add_linked_stylesheet($sCSSFile);
$oPage->LinkStylesheetFromURI($sCSSFile);
}
$aJsFiles = $oFormData->GetJsFiles();
foreach ($aJsFiles as $sJsFile)
{
$oPage->add_linked_script($sJsFile);
$oPage->LinkScriptFromURI($sJsFile);
}
}

View File

@@ -195,8 +195,6 @@ $ibo-field--enable-bulk--checkbox--margin-left: $ibo-spacing-300 !default;
/* Hack to force a table to fit its container without overflow (see N°2127) */
/* Note that along with with, we now display a "expand" icon on large fields so we can have a better view of its content */
.HTML {
@extend .ibo-vendors-ckeditor--display-content;
table {
table-layout: fixed;
width: 100%;

View File

@@ -18,7 +18,6 @@ $ibo-caselog-entry--main-information--decoration--width: 3px !default;
display: none;
}
.ibo-activity-entry--main-information-content{
@extend .ibo-vendors-ckeditor--display-content;
}
/* Highlight color */

View File

@@ -19,6 +19,9 @@ $ibo-hyperlink-text-decoration--on-hover: $ibo-hyperlink-text-decoration !defaul
$ibo-hyperlink-color--on-active: $ibo-color-primary-900 !default;
$ibo-hyperlink-text-decoration--on-active: $ibo-hyperlink-text-decoration !default;
$ibo-figure--spacing-x: 2em !default; /* Mind that this matches Bulma rule for figure */
$ibo-figure--spacing-y: 2em !default;
/* CSS variables */
:root{
--ibo-hyperlink-color: #{$ibo-hyperlink-color};
@@ -132,4 +135,22 @@ $ibo-hyperlink-text-decoration--on-active: $ibo-hyperlink-text-decoration !defau
code:not(.hljs) {
color: inherit;
}
p {
margin-top: 0.25em;
margin-bottom: 0.25em;
}
figure {
display: inline-block; /* So the figure doesn't take all width and can be aligned on the left */
margin-left: $ibo-figure--spacing-x !important; /* !important to overload the CKE inline style */
margin-right: $ibo-figure--spacing-x !important; /* !important to overload the CKE inline style */
&:not(:last-child) {
margin-bottom: $ibo-figure--spacing-y !important; /* !important to overload the CKE inline style */
}
&:not(:first-child) {
margin-top: $ibo-figure--spacing-y !important; /* !important to overload the CKE inline style */
}
}
}

View File

@@ -19,14 +19,17 @@ $ibo-vendors-ckeditor--autocomplete-item-image--border: 1px solid $ibo-color-gre
$ibo-vendors-ckeditor--autocomplete-item-title--text-color: #3A3A3A !default;
/* - Following SCSS variables are only there to overlaod the CSS3 variables of CKEditor (see `src/resources/styles/default-theme.css` in CKEditor) */
$ibo-vendors-ckeditor--ck-color-list-button-on-background: $ibo-color-grey-200;
$ibo-vendors-ckeditor--ck-color-list-button-on-background-focus: $ibo-color-grey-200;
$ibo-vendors-ckeditor--ck-color-list-button-hover-background: $ibo-color-grey-200;
$ibo-vendors-ckeditor--ck-color-list-button-on-text: $ibo-color-grey-900;
$ibo-vendors-ckeditor--ck-text-tiny-font-size: $ibo-font-size-20;
$ibo-vendors-ckeditor--ck-text-small-font-size: $ibo-font-size-50;
$ibo-vendors-ckeditor--ck-text-big-font-size: $ibo-font-size-200;
$ibo-vendors-ckeditor--ck-text-huge-font-size: $ibo-font-size-350;
$ibo-vendors-ckeditor--ck-color-list-button-on-background: $ibo-color-grey-200 !default;
$ibo-vendors-ckeditor--ck-color-list-button-on-background-focus: $ibo-color-grey-200 !default;
$ibo-vendors-ckeditor--ck-color-list-button-hover-background: $ibo-color-grey-200 !default;
$ibo-vendors-ckeditor--ck-color-list-button-on-text: $ibo-color-grey-900 !default;
$ibo-vendors-ckeditor--ck-text-tiny-font-size: $ibo-font-size-20 !default;
$ibo-vendors-ckeditor--ck-text-small-font-size: $ibo-font-size-50 !default;
$ibo-vendors-ckeditor--ck-text-big-font-size: $ibo-font-size-200 !default;
$ibo-vendors-ckeditor--ck-text-huge-font-size: $ibo-font-size-350 !default;
$ibo-vendors-ckeditor--ck-color-image-caption-text: $ibo-color-grey-900 !default;
/* CSS3 variables */
.ck {
@@ -34,10 +37,13 @@ $ibo-vendors-ckeditor--ck-text-huge-font-size: $ibo-font-size-350;
--ck-color-list-button-on-background-focus: #{$ibo-vendors-ckeditor--ck-color-list-button-on-background-focus};
--ck-color-list-button-hover-background: #{$ibo-vendors-ckeditor--ck-color-list-button-hover-background};
--ck-color-list-button-on-text: #{$ibo-vendors-ckeditor--ck-color-list-button-on-text};
--ck-text-tiny-font-size: #{$ibo-vendors-ckeditor--ck-text-tiny-font-size};
--ck-text-small-font-size: #{$ibo-vendors-ckeditor--ck-text-small-font-size};
--ck-text-big-font-size: #{$ibo-vendors-ckeditor--ck-text-big-font-size};
--ck-text-huge-font-size: #{$ibo-vendors-ckeditor--ck-text-huge-font-size};
--ck-color-image-caption-text: #{$ibo-vendors-ckeditor--ck-color-image-caption-text};
}
/* Base style */
@@ -132,17 +138,3 @@ ul.cke_autocomplete_panel{
@extend %ibo-font-weight-700;
}
}
.ibo-vendors-ckeditor--display-content{
.cke_editable{
line-height: 1.4;
}
figure{
border: solid 1px #ccc;
border-radius: 2px;
}
p{
margin-top: 0.25em;
margin-bottom: 0.25em;
}
}

View File

@@ -4,9 +4,7 @@
{% UIContentBlock Standard {'aContainerClasses':['ibo-update-core']} %}
{% UITitle ForPage {'sTitle':'iTopUpdate:UI:PageTitle'|dict_s} %}{% EndUITitle %}
<div class="ibo-v-spacer">&nbsp;</div>
{% UIPanel Neutral {sTitle:'iTopUpdate:UI:PageTitle'|dict_s} %}
{% UIContentBlock Standard {'aContainerClasses': ['display_block', 'display-files']} %}
{% UIFieldSet Standard {'sLegend':'iTopUpdate:UI:Status'|dict_s} %}
@@ -101,5 +99,7 @@
{% EndUIContentBlock %}
{% EndUIPanel %}
{% EndUIContentBlock %}
{% endapply %}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -178,10 +178,6 @@ class Editor extends ClassicEditor {
'resizeImage:50',
'resizeImage:original',
'|',
'imageStyle:alignLeft',
'imageStyle:alignCenter',
'imageStyle:alignRight',
'|',
'toggleImageCaption',
],
resizeOptions: [

View File

@@ -1,9 +0,0 @@
/* mention list ui customization */
:root {
--ck-color-list-button-on-background: #EFF0EF;
--ck-color-list-button-on-background-focus: #EFF0EF;
--ck-color-list-button-hover-background: #EFF0EF;
--ck-color-list-button-on-text: black;
--ck-z-default: 9999;
}

View File

@@ -1,9 +1,17 @@
/* mention list ui customization */
/**
* This file contains CKEditor 5 default theme styles.
* "Default theme" means common styles for all GUIs (backoffice, portal, ...)
*
* Any style specific for the backoffice should be in the backoffice theme (e.g. "css/backoffice/vendors/_ckeditor.scss)
* Any style specific for the portal should be in the portal theme (e.g. "datamodels/2.x/itop-portal-base/portal/public/css/portal.scss")
*/
:root {
--ck-color-list-button-on-background: #EFF0EF;
--ck-color-list-button-on-background-focus: #EFF0EF;
--ck-color-list-button-hover-background: #EFF0EF;
--ck-color-list-button-on-text: black;
--ck-color-image-caption-background: transparent;
/* Toolbar buttons / components downsize for better integration with UIs */
--ck-spacing-small: 0.35rem;
@@ -19,8 +27,7 @@
--ck-text-huge-font-size: 1.8rem;
}
/** text size classes */
/* Text size classes */
.text-tiny {
font-size: var(--ck-text-tiny-font-size);
}
@@ -37,8 +44,7 @@
font-size: var(--ck-text-huge-font-size);
}
/** marker classes */
/* Marker classes */
.marker-yellow {
background-color: var(--ck-highlight-marker-yellow);
}
@@ -53,4 +59,30 @@
.marker-blue {
background-color: var(--ck-highlight-marker-blue);
}
/* Editor base style */
/* - Fix editor base z-index to avoid its children (images, drop down buttons, ...) passing on top of other elements */
.ck-editor {
z-index: 0;
}
/* Figures / images */
/* - Avoid text being typed next to the image, only below */
.ck-content .image img {
min-width: inherit;
}
.ck-content .image-style-align-left,
.ck-content .image-style-align-right {
display: block;
float: unset;
}
.ck-content .image-style-align-left {
text-align: left;
margin-right: 0;
}
.ck-content .image-style-align-right {
text-align: right;
margin-left: 0;
}

View File

@@ -95,7 +95,14 @@ $(function()
value = $(oElem).val();
}
}
else if($(oElem).is(':checkbox') || $(oElem).is(':radio'))
else if( $(oElem).is(':radio'))
{
if($(oElem).is(':checked'))
{
value =$(oElem).val();
}
}
else if($(oElem).is(':checkbox'))
{
if(value === null)
{

View File

@@ -80,7 +80,7 @@ $(function() {
},
_bindEvents: async function () {
let me = this;
let CKEditorInstance = await this._GetCKEditorInstance();
let CKEditorInstance = this._GetCKEditorInstance();
// Handlers for the CKEditor itself
// Handle only the current CKEditor instance
// if (oEvent.editor.name !== me.options.text_input_id) {
@@ -91,7 +91,7 @@ $(function() {
// Note: That when images are uploaded, the "change" event is triggered before the image upload is complete, meaning that we don't have the <img> tag yet.
CKEditorInstance.model.document.on('change:data', async function () {
const bWasDraftBefore = me.is_draft;
const bIsDraftNow = !(await me._IsInputEmpty());
const bIsDraftNow = !(me._IsInputEmpty());
if (bWasDraftBefore !== bIsDraftNow) {
me.is_draft = bIsDraftNow;
me._UpdateEditingVisualHint();
@@ -198,12 +198,8 @@ $(function() {
this.element.trigger('requested_submission.caselog_entry_form.itop', oData);
},
// - Form
_GetCKEditorInstance: async function () {
// if(this.element.find('#' + this.options.text_input_id + ' ~ .ck .ck-editor__editable')[0] === undefined){
// return undefined;
// }
return await CombodoCKEditorHandler.GetInstance('#'+this.options.text_input_id);
//return this.element.find('#' + this.options.text_input_id + ' ~ .ck .ck-editor__editable')[0].ckeditorInstance;
_GetCKEditorInstance: function () {
return CombodoCKEditorHandler.GetInstanceSynchronous('#'+this.options.text_input_id);
},
_ShowEntryForm: function () {
this.element.closest(this.js_selectors.activity_panel).find(this.js_selectors.form).removeClass(this.css_classes.is_closed);
@@ -219,13 +215,13 @@ $(function() {
_EnableSubmission: function () {
this.element.find(this.js_selectors.save_button+', '+this.js_selectors.save_choices_picker).prop('disabled', false);
},
_EnterPendingSubmissionState: async function () {
(await this._GetCKEditorInstance()).enableReadOnlyMode('hi');
_EnterPendingSubmissionState: function () {
this._GetCKEditorInstance().enableReadOnlyMode('hi');
this.element.find(this.js_selectors.cancel_button).prop('disabled', true);
this._DisableSubmission();
},
_LeavePendingSubmissionState: async function () {
(await this._GetCKEditorInstance()).disableReadOnlyMode('hi');
_LeavePendingSubmissionState: function () {
this._GetCKEditorInstance().disableReadOnlyMode('hi');
this.element.find(this.js_selectors.cancel_button).prop('disabled', false);
this._EnableSubmission();
},
@@ -276,29 +272,27 @@ $(function() {
* @returns {void}
* @private
*/
_UpdateBridgeInput: async function () {
_UpdateBridgeInput: function () {
const sCaseLogAttCode = this.element.closest(this.js_selectors.activity_panel_toolbar).attr('data-caselog-attribute-code');
let oBridgeInputElem = this._GetGeneralFormElement().find('input[name="attr_'+sCaseLogAttCode+'"]');
oBridgeInputElem.val(await this._GetInputData());
oBridgeInputElem.val(this._GetInputData());
},
// - Input zone
_EmptyInput: function() {
this._GetCKEditorInstance().then((oEditor) => {
oEditor.setData('');
this._UpdateEditingVisualHint();
});
this._GetCKEditorInstance().setData('');
this._UpdateEditingVisualHint();
},
/**
* @returns {boolean} True if the input has no text
* @private
*/
_IsInputEmpty: async function () {
let sCKEditorValue = await this._GetInputData();
_IsInputEmpty: function () {
let sCKEditorValue = this._GetInputData();
return sCKEditorValue === '';
},
_GetInputData: async function () {
let oCKEditorInstance = await this._GetCKEditorInstance()
_GetInputData: function () {
let oCKEditorInstance = this._GetCKEditorInstance()
return (oCKEditorInstance === undefined) ? '' : oCKEditorInstance.getData();
},
_GetExtraInputs: function() {
@@ -334,20 +328,15 @@ $(function() {
this._UpdateSubmitButtonState();
},
_UpdateSubmitButtonState: function() {
this._IsInputEmpty().then((bIsEmpty) => {
if (bIsEmpty) {
this._DisableSubmission();
} else {
this._EnableSubmission();
}
});
if (this._IsInputEmpty()) {
this._DisableSubmission();
} else {
this._EnableSubmission();
}
},
_UpdateEditingVisualHint: function () {
this._IsInputEmpty().then((bIsEmpty) => {
const sEvent = bIsEmpty ? 'emptied' : 'draft';
this.element.trigger(sEvent+'.caselog_entry_form.itop', {attribute_code: this.options.attribute_code});
}
)
const sEvent = this._IsInputEmpty() ? 'emptied' : 'draft';
this.element.trigger(sEvent+'.caselog_entry_form.itop', {attribute_code: this.options.attribute_code});
}
});
});

View File

@@ -61,88 +61,6 @@ class TestBeSad extends TestHandler
}
}
class TestSQLQuery extends TestScenarioOnDB
{
static public function GetName() {return 'SQLQuery';}
static public function GetDescription() {return 'SQLQuery does not depend on the rest of the framework, therefore it makes sense to have a separate test framework for it';}
static public function GetDBHost() {return 'localhost';}
static public function GetDBUser() {return 'root';}
static public function GetDBPwd() {return '';}
static public function GetDBName() {return 'TestSQLQuery';}
static public function GetDBSubName() {return 'taratata';}
protected function DoPrepare()
{
parent::DoPrepare();
cmdbSource::CreateTable('CREATE TABLE `myTable` (myKey INT(11) NOT NULL auto_increment, column1 VARCHAR(255), column2 VARCHAR(255), PRIMARY KEY (`myKey`)) ENGINE = '.MYSQL_ENGINE);
cmdbSource::CreateTable('CREATE TABLE `myTable1` (myKey1 INT(11) NOT NULL auto_increment, column1_1 VARCHAR(255), column1_2 VARCHAR(255), PRIMARY KEY (`myKey1`)) ENGINE = '.MYSQL_ENGINE);
cmdbSource::CreateTable('CREATE TABLE `myTable2` (myKey2 INT(11) NOT NULL auto_increment, column2_1 VARCHAR(255), column2_2 VARCHAR(255), PRIMARY KEY (`myKey2`)) ENGINE = '.MYSQL_ENGINE);
}
protected function DoExecute()
{
$oQuery = new SQLObjectQuery(
$sTable = 'myTable',
$sTableAlias = 'myTableAlias',
$aFields = array('column1'=>new FieldExpression('column1', 'myTableAlias'), 'column2'=>new FieldExpression('column2', 'myTableAlias')),
// $aFullTextNeedles = array('column1'),
$bToDelete = false,
$aValues = array()
);
$oQuery->AddCondition(Expression::FromOQL('DATE(NOW() - 1200 * 2) > \'2008-07-31\''));
$oSubQuery1 = new SQLObjectQuery(
$sTable = 'myTable1',
$sTableAlias = 'myTable1Alias',
$aFields = array('column1_1'=>new FieldExpression('column1', 'myTableAlias'), 'column1_2'=>new FieldExpression('column1', 'myTableAlias')),
// $aFullTextNeedles = array(),
$bToDelete = false,
$aValues = array()
);
$oSubQuery2 = new SQLObjectQuery(
$sTable = 'myTable2',
$sTableAlias = 'myTable2Alias',
$aFields = array('column2_1'=>new FieldExpression('column2', 'myTableAlias'), 'column2_2'=>new FieldExpression('column2', 'myTableAlias')),
// $aFullTextNeedles = array(),
$bToDelete = false,
$aValues = array()
);
$oQuery->AddInnerJoin($oSubQuery1, 'column1', 'column1_1');
$oQuery->AddLeftJoin($oSubQuery2, 'column2', 'column2_2');
$oQuery->DisplayHtml();
$oQuery->RenderDelete();
$oQuery->RenderUpdate();
echo '<p>'.$oQuery->RenderSelect().'</p>';
$oQuery->RenderSelect(array('column1'));
$oQuery->RenderSelect(array('column1', 'column2'));
}
}
class TestGenericItoMyModel extends TestBizModelGeneric
{
static public function GetName()
{
return 'Generic RO test on '.self::GetConfigFile();
}
static public function GetConfigFile() {return '/config-test-mymodel.php';}
}
class TestGenericItopBigModel extends TestBizModelGeneric
{
static public function GetName()
{
return 'Generic RO test on '.self::GetConfigFile();
}
static public function GetConfigFile() {return '/config-test-itopv06.php';}
}
class TestUserRightsMatrixItop extends TestUserRights
{
static public function GetName()
@@ -2149,52 +2067,6 @@ class TestSetLinkset extends TestBizModel
}
}
class TestEmailAsynchronous extends TestBizModel
{
static public function GetName()
{
return 'Itop - Asynchronous email';
}
static public function GetDescription()
{
return 'Queues a request to send an email';
}
protected function DoExecute()
{
for ($i = 0 ; $i < 2 ; $i++)
{
$oMail = new Email();
$oMail->SetRecipientTO('romain.quetiez@combodo.com');
$oMail->SetRecipientFrom('romain.quetiez@combodo.com');
$oMail->SetRecipientCC('romainquetiez@yahoo.fr');
$oMail->SetSubject('automated test - '.$i);
$oMail->SetBody('this is one is entirely working fine '.time());
$iRes = $oMail->Send($aIssues, false);
switch ($iRes)
{
case EMAIL_SEND_OK:
echo "EMAIL_SEND_OK<br/>\n";
break;
case EMAIL_SEND_PENDING:
echo "EMAIL_SEND_PENDING<br/>\n";
break;
case EMAIL_SEND_ERROR:
echo "EMAIL_SEND_ERROR: <br/>\n";
foreach($aIssues as $sIssue)
{
echo "Issue: $sIssue<br/>\n";
}
break;
}
}
}
}
abstract class TestLinkSet extends TestBizModel
{
protected function StandardizedDump($oSet, $sAttPrefixToIgnore)

View File

@@ -57,6 +57,8 @@ class DisplayBlockTest extends ItopCustomDatamodelTestCase
*/
public function testRenderChartAjax(string $sClassToDisplay, string $sAttributeToDisplay, string $sRelatedClass, string $sRelatedClassAttributeToEdit, string $sExpected, string $sNonExpected): void
{
$this->markTestSkipped("Waiting for N°7313 to be fixed, this test was made during the first attempt to resolve N°7313, but as it broke N°7592, N°7594, N°7600 & N°7605, we reverted the change until we make a proper fix in Expression::MakeValueLabel()");
$oUserRequest = new UserRequest();
$oUserRequest->Set('title', 'MyTitle');
$oUserRequest->Set('org_id', $this->getTestOrgId());

View File

@@ -462,12 +462,13 @@ class MetaModelTest extends ItopDataTestCase
* @return void
* @throws CoreException
* @throws \OQLException
* @dataProvider PurgeDataProvider
*
*/
public function testPurgeData(){
// Set max_chunk_size to 2 (default 1000) to test chunk deletion with only 10 items
public function testPurgeData( $iMaxChunkSize, $iNbQueriesExpected){
// Set max_chunk_size to $iMaxChunkSize (default 1000) to test chunk deletion with only 10 items
$oConfig = MetaModel::GetConfig();
$oConfig->Set('purge_data.max_chunk_size', 2);
MetaModel::SetConfig($oConfig);
$oConfig->Set('purge_data.max_chunk_size', $iMaxChunkSize);
$aPkPerson = [];
for ($i=0; $i < 10; $i++) {
@@ -476,12 +477,23 @@ class MetaModelTest extends ItopDataTestCase
$aPkPerson[] = $oPerson->GetKey();
}
$sDeleteOQL = 'SELECT '.$sClass.' WHERE id IN ('.implode(',', $aPkPerson).')';
$oFilter = DBObjectSearch::FromOQL($sDeleteOQL);
$oFilter = DBObjectSearch::FromOQL('SELECT '.$sClass.' WHERE id IN ('.implode(',', $aPkPerson).')');
$iNbDelete = 0;
$this->assertDBQueryCount($iNbQueriesExpected, function() use ($oFilter, &$iNbDelete) {
$iNbDelete = MetaModel::PurgeData($oFilter);
} );
$iNbDelete = MetaModel::PurgeData($oFilter);
$this->assertEquals($iNbDelete, 10, 'MetaModel::PurgeData must delete 10 objects per batch of 2 items');
}
public function PurgeDataProvider(){
return [
'Purge 10 items with a max_chunk_size of 2 should be perfomed in 5 steps + an additional query to verify that the job is complete' => [2, 16],
'Purge 10 items with a max_chunk_size of 3 should be perfomed in 4 steps' => [3, 12],
'Purge 10 items with a max_chunk_size of 1000 (default value) should be perfomed in 1 step' => [1000, 3],
];
}
}
abstract class Wizzard