mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-19 16:48:42 +02:00
Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts: # .doc/itop-version-history.md
This commit is contained in:
@@ -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).
|
||||
|
||||
@@ -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],
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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%;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
36
css/backoffice/vendors/_ckeditor.scss
vendored
36
css/backoffice/vendors/_ckeditor.scss
vendored
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,7 @@
|
||||
|
||||
{% UIContentBlock Standard {'aContainerClasses':['ibo-update-core']} %}
|
||||
|
||||
{% UITitle ForPage {'sTitle':'iTopUpdate:UI:PageTitle'|dict_s} %}{% EndUITitle %}
|
||||
|
||||
<div class="ibo-v-spacer"> </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 %}
|
||||
2
js/ckeditor/build/ckeditor.js
vendored
2
js/ckeditor/build/ckeditor.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -178,10 +178,6 @@ class Editor extends ClassicEditor {
|
||||
'resizeImage:50',
|
||||
'resizeImage:original',
|
||||
'|',
|
||||
'imageStyle:alignLeft',
|
||||
'imageStyle:alignCenter',
|
||||
'imageStyle:alignRight',
|
||||
'|',
|
||||
'toggleImageCaption',
|
||||
],
|
||||
resizeOptions: [
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -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)
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user