N°8796 - Add PHP code style validation in iTop and extensions - format whole code base

This commit is contained in:
odain
2025-11-07 15:39:53 +01:00
parent 12f23113f5
commit 890a2568c8
2110 changed files with 53099 additions and 63885 deletions

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Page:DefaultTitle' => 'Uživatelský portál %1$s',
'Page:PleaseWait' => 'Počkejte prosím',
'Page:Home' => 'Domů',
@@ -53,19 +54,19 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Otevřít</a> / <a href="%4$s" class="file_download_link">Stáhnout</a>',
'Portal:Calendar-FirstDayOfWeek' => 'cs', //work with moment.js locales
));
]);
// Object form
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Zavřít tento vstup',
'Portal:Form:Close:Warning' => 'Opravdu chcete opustit tento formulář? Data vložená do formuláře budou ztracena ',
'Portal:Error:ObjectCannotBeCreated' => 'Chyba: objekt nelze vytvořit. Před opětovným odesláním tohoto formuláře zkontrolujte související objekty a přílohy.',
'Portal:Error:ObjectCannotBeUpdated' => 'Chyba: objekt nelze vytvořit. Před opětovným odesláním tohoto formuláře zkontrolujte související objekty a přílohy.',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Brick:Portal:UserProfile:Name' => 'Uživatelský profil',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'Můj profil',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Odhlásit',
@@ -76,15 +77,15 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Nepodařilo se změnit heslo, kontaktujte prosím administrátora',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Osobní informace',
'Brick:Portal:UserProfile:Photo:Title' => 'Foto',
));
]);
// AggregatePageBrick
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Nástěnka',
));
]);
// BrowseBrick brick
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Brick:Portal:Browse:Name' => 'Procházet položky',
'Brick:Portal:Browse:Mode:List' => 'Seznam',
'Brick:Portal:Browse:Mode:Tree' => 'Strom',
@@ -97,10 +98,10 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Rozbalit vše',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Sbalit vše',
'Brick:Portal:Browse:Filter:NoData' => 'Žádná položka',
));
]);
// ManageBrick brick
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Brick:Portal:Manage:Name' => 'Spravovat položky',
'Brick:Portal:Manage:Table:NoData' => 'Žádná položka',
'Brick:Portal:Manage:Table:ItemActions' => 'Akce',
@@ -115,10 +116,10 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'Brick:Portal:Manage:fct:avg' => 'Průměr',
'Brick:Portal:Manage:fct:min' => 'Min',
'Brick:Portal:Manage:fct:max' => 'Max',
));
]);
// ObjectBrick brick
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Brick:Portal:Object:Name' => 'Objekt',
'Brick:Portal:Object:Form:Create:Title' => 'Nový %1$s',
'Brick:Portal:Object:Form:Edit:Title' => 'Aktualizace %2$s (%1$s)',
@@ -130,18 +131,18 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Vybrat %1$s (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%1$s: %2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Zkopíruj odkaz na objekt',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Zkopírováno'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Zkopírováno',
]);
// CreateBrick brick
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Brick:Portal:Create:Name' => 'Rychlé vytvoření',
'Brick:Portal:Create:ChooseType' => 'Vyberte typ',
));
]);
// Filter brick
Dict::Add('CS CZ', 'Czech', 'Čeština', array(
Dict::Add('CS CZ', 'Czech', 'Čeština', [
'Brick:Portal:Filter:Name' => 'Předfiltrování dlaždice',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'např. připojení k wifi',
'Brick:Portal:Filter:SearchInput:Submit' => 'Vyhledat',
));
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Page:DefaultTitle' => '%1$s User portal~~',
'Page:PleaseWait' => 'Please wait...~~',
'Page:Home' => 'Home~~',
@@ -53,19 +54,19 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>~~',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Download</a>~~',
'Portal:Calendar-FirstDayOfWeek' => 'da', //work with moment.js locales
));
]);
// Object form
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Close this entry~~',
'Portal:Form:Close:Warning' => 'Do you want to leave this form? Data entered may be lost~~',
'Portal:Error:ObjectCannotBeCreated' => 'Error: object cannot be created. Check associated objects and attachments before submitting this form again.~~',
'Portal:Error:ObjectCannotBeUpdated' => 'Error: object cannot be updated. Check associated objects and attachments before submitting this form again.~~',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Brick:Portal:UserProfile:Name' => 'User profile~~',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'My profile~~',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Logoff~~',
@@ -76,15 +77,15 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Can\'t change password, please contact your %1$s administrator~~',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Personal information~~',
'Brick:Portal:UserProfile:Photo:Title' => 'Photo~~',
));
]);
// AggregatePageBrick
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Dashboard~~',
));
]);
// BrowseBrick brick
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Brick:Portal:Browse:Name' => 'Browse throught items~~',
'Brick:Portal:Browse:Mode:List' => 'List~~',
'Brick:Portal:Browse:Mode:Tree' => 'Tree~~',
@@ -97,10 +98,10 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Expand all~~',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Collapse all~~',
'Brick:Portal:Browse:Filter:NoData' => 'No item~~',
));
]);
// ManageBrick brick
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Brick:Portal:Manage:Name' => 'Manage items~~',
'Brick:Portal:Manage:Table:NoData' => 'No item.~~',
'Brick:Portal:Manage:Table:ItemActions' => 'Actions~~',
@@ -115,10 +116,10 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'Brick:Portal:Manage:fct:avg' => 'Average~~',
'Brick:Portal:Manage:fct:min' => 'Min~~',
'Brick:Portal:Manage:fct:max' => 'Max~~',
));
]);
// ObjectBrick brick
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Brick:Portal:Object:Name' => 'Object~~',
'Brick:Portal:Object:Form:Create:Title' => 'New %1$s~~',
'Brick:Portal:Object:Form:Edit:Title' => 'Updating %2$s (%1$s)~~',
@@ -130,18 +131,18 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Select %1$s (%2$s)~~',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Copy object link~~',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied~~'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied~~',
]);
// CreateBrick brick
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Brick:Portal:Create:Name' => 'Quick creation~~',
'Brick:Portal:Create:ChooseType' => 'Please, choose a type~~',
));
]);
// Filter brick
Dict::Add('DA DA', 'Danish', 'Dansk', array(
Dict::Add('DA DA', 'Danish', 'Dansk', [
'Brick:Portal:Filter:Name' => 'Prefilter a brick~~',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'eg. connect wifi~~',
'Brick:Portal:Filter:SearchInput:Submit' => 'Search~~',
));
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Page:DefaultTitle' => '%1$s - Benutzer Portal',
'Page:PleaseWait' => 'Bitte warten...',
'Page:Home' => 'Start',
@@ -53,19 +54,19 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Öffnen</a> / <a href="%4$s" class="file_download_link">Download</a>',
'Portal:Calendar-FirstDayOfWeek' => 'de', //work with moment.js locales
));
]);
// Object form
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Dieses Objekt schließen',
'Portal:Form:Close:Warning' => 'Soll diese Eingabemaske verlassen werden? Eingegebene Daten werden nicht gespeichert.',
'Portal:Error:ObjectCannotBeCreated' => 'Error: Objekt kann nicht erzeugt werden. Prüfen Sie verknüpfte Objekte und Anhänge bevor Sie dieses Formular erneut abschicken.',
'Portal:Error:ObjectCannotBeUpdated' => 'Error: Objekt kann nicht geupdated werden. Prüfen Sie verknüpfte Objekte und Anhänge bevor Sie dieses Formular erneut abschicken.',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Brick:Portal:UserProfile:Name' => 'Benutzer Profil',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'Mein Profil',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Abmelden',
@@ -76,15 +77,15 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Passwort kann nicht geändert werden - bitte kontaktieren Sie Ihren %1$s Administrator',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Persönliche Informationen',
'Brick:Portal:UserProfile:Photo:Title' => 'Foto',
));
]);
// AggregatePageBrick
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Dashboard',
));
]);
// BrowseBrick brick
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Brick:Portal:Browse:Name' => 'Liste durchgehen',
'Brick:Portal:Browse:Mode:List' => 'Liste',
'Brick:Portal:Browse:Mode:Tree' => 'Baum',
@@ -97,10 +98,10 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Alle expandieren',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Alle kollabieren',
'Brick:Portal:Browse:Filter:NoData' => 'Kein Eintrag',
));
]);
// ManageBrick brick
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Brick:Portal:Manage:Name' => 'Einträge managen',
'Brick:Portal:Manage:Table:NoData' => 'Kein Eintrag.',
'Brick:Portal:Manage:Table:ItemActions' => 'Aktionen',
@@ -115,10 +116,10 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Brick:Portal:Manage:fct:avg' => 'Durchschnitt',
'Brick:Portal:Manage:fct:min' => 'Minimum',
'Brick:Portal:Manage:fct:max' => 'Maximum',
));
]);
// ObjectBrick brick
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Brick:Portal:Object:Name' => 'Object',
'Brick:Portal:Object:Form:Create:Title' => 'Neue %1$s',
'Brick:Portal:Object:Form:Edit:Title' => 'Wird aktualisiert %2$s (%1$s)',
@@ -130,18 +131,18 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Select %1$s (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Objektverknüpfung kopieren',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Kopiert'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Kopiert',
]);
// CreateBrick brick
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Brick:Portal:Create:Name' => 'Schnelles Erstellen',
'Brick:Portal:Create:ChooseType' => 'Bitte wählen Sie einen Typ',
));
]);
// Filter brick
Dict::Add('DE DE', 'German', 'Deutsch', array(
Dict::Add('DE DE', 'German', 'Deutsch', [
'Brick:Portal:Filter:Name' => 'Brick vorfiltern',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'z.B. connect wifi',
'Brick:Portal:Filter:SearchInput:Submit' => 'Suchen',
));
]);

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -18,7 +19,7 @@
*/
// Portal
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Page:DefaultTitle' => '%1$s User portal',
'Page:PleaseWait' => 'Please wait...',
'Page:Home' => 'Home',
@@ -62,19 +63,19 @@ Dict::Add('EN US', 'English', 'English', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Download</a>',
'Portal:Calendar-FirstDayOfWeek' => 'en-us', //work with moment.js locales
));
]);
// Object form
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Close this entry',
'Portal:Form:Close:Warning' => 'Do you want to leave this form? Data entered may be lost',
'Portal:Error:ObjectCannotBeCreated' => 'Error: object cannot be created. Check associated objects and attachments before submitting this form again.',
'Portal:Error:ObjectCannotBeUpdated' => 'Error: object cannot be updated. Check associated objects and attachments before submitting this form again.',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s',
]);
// UserProfile brick
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Brick:Portal:UserProfile:Name' => 'User profile',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'My profile',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Logoff',
@@ -85,15 +86,15 @@ Dict::Add('EN US', 'English', 'English', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Can\'t change password, please contact your %1$s administrator',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Personal information',
'Brick:Portal:UserProfile:Photo:Title' => 'Photo',
));
]);
// AggregatePageBrick
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Dashboard',
));
]);
// BrowseBrick brick
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Brick:Portal:Browse:Name' => 'Browse throught items',
'Brick:Portal:Browse:Mode:List' => 'List',
'Brick:Portal:Browse:Mode:Tree' => 'Tree',
@@ -106,10 +107,10 @@ Dict::Add('EN US', 'English', 'English', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Expand all',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Collapse all',
'Brick:Portal:Browse:Filter:NoData' => 'No item',
));
]);
// ManageBrick brick
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Brick:Portal:Manage:Name' => 'Manage items',
'Brick:Portal:Manage:Table:NoData' => 'No item.',
'Brick:Portal:Manage:Table:ItemActions' => 'Actions',
@@ -124,10 +125,10 @@ Dict::Add('EN US', 'English', 'English', array(
'Brick:Portal:Manage:fct:avg' => 'Average',
'Brick:Portal:Manage:fct:min' => 'Min',
'Brick:Portal:Manage:fct:max' => 'Max',
));
]);
// ObjectBrick brick
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Brick:Portal:Object:Name' => 'Object',
'Brick:Portal:Object:Form:Create:Title' => 'New %1$s',
'Brick:Portal:Object:Form:Edit:Title' => 'Updating %2$s (%1$s)',
@@ -139,18 +140,18 @@ Dict::Add('EN US', 'English', 'English', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Select %1$s (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Copy object link',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied',
]);
// CreateBrick brick
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Brick:Portal:Create:Name' => 'Quick creation',
'Brick:Portal:Create:ChooseType' => 'Please, choose a type',
));
]);
// Filter brick
Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', [
'Brick:Portal:Filter:Name' => 'Prefilter a brick',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'eg. connect wifi',
'Brick:Portal:Filter:SearchInput:Submit' => 'Search',
));
]);

View File

@@ -1,11 +1,12 @@
<?php
/**
* @copyright Copyright (C) 2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*/
// Portal
Dict::Add('EN GB', 'British English', 'British English', array(
Dict::Add('EN GB', 'British English', 'British English', [
'Page:DefaultTitle' => '%1$s User portal',
'Page:PleaseWait' => 'Please wait...',
'Page:Home' => 'Home',
@@ -49,19 +50,19 @@ Dict::Add('EN GB', 'British English', 'British English', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Download</a>',
'Portal:Calendar-FirstDayOfWeek' => 'en-gb',
));
]);
// Object form
Dict::Add('EN GB', 'British English', 'British English', array(
Dict::Add('EN GB', 'British English', 'British English', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Close this entry',
'Portal:Form:Close:Warning' => 'Do you want to leave this form? Data entered may be lost',
'Portal:Error:ObjectCannotBeCreated' => 'Error: object cannot be created. Check associated objects and attachments before submitting this form again.',
'Portal:Error:ObjectCannotBeUpdated' => 'Error: object cannot be updated. Check associated objects and attachments before submitting this form again.',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s',
]);
// UserProfile brick
Dict::Add('EN GB', 'British English', 'British English', array(
Dict::Add('EN GB', 'British English', 'British English', [
'Brick:Portal:UserProfile:Name' => 'User profile',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'My profile',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Log off',
@@ -72,15 +73,15 @@ Dict::Add('EN GB', 'British English', 'British English', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Can\'t change password, please contact your %1$s administrator',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Personal information',
'Brick:Portal:UserProfile:Photo:Title' => 'Photo',
));
]);
// AggregatePageBrick
Dict::Add('EN GB', 'British English', 'British English', array(
Dict::Add('EN GB', 'British English', 'British English', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Dashboard',
));
]);
// BrowseBrick brick
Dict::Add('EN GB', 'British English', 'British English', array(
Dict::Add('EN GB', 'British English', 'British English', [
'Brick:Portal:Browse:Name' => 'Browse through items',
'Brick:Portal:Browse:Mode:List' => 'List',
'Brick:Portal:Browse:Mode:Tree' => 'Tree',
@@ -93,10 +94,10 @@ Dict::Add('EN GB', 'British English', 'British English', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Expand all',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Collapse all',
'Brick:Portal:Browse:Filter:NoData' => 'No item',
));
]);
// ManageBrick brick
Dict::Add('EN GB', 'British English', 'British English', array(
Dict::Add('EN GB', 'British English', 'British English', [
'Brick:Portal:Manage:Name' => 'Manage items',
'Brick:Portal:Manage:Table:NoData' => 'No item.',
'Brick:Portal:Manage:Table:ItemActions' => 'Actions',
@@ -111,10 +112,10 @@ Dict::Add('EN GB', 'British English', 'British English', array(
'Brick:Portal:Manage:fct:avg' => 'Average',
'Brick:Portal:Manage:fct:min' => 'Min',
'Brick:Portal:Manage:fct:max' => 'Max',
));
]);
// ObjectBrick brick
Dict::Add('EN GB', 'British English', 'British English', array(
Dict::Add('EN GB', 'British English', 'British English', [
'Brick:Portal:Object:Name' => 'Object',
'Brick:Portal:Object:Form:Create:Title' => 'New %1$s',
'Brick:Portal:Object:Form:Edit:Title' => 'Updating %2$s (%1$s)',
@@ -126,18 +127,18 @@ Dict::Add('EN GB', 'British English', 'British English', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Select %1$s (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Copy object link',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied',
]);
// CreateBrick brick
Dict::Add('EN GB', 'British English', 'British English', array(
Dict::Add('EN GB', 'British English', 'British English', [
'Brick:Portal:Create:Name' => 'Quick creation',
'Brick:Portal:Create:ChooseType' => 'Please, choose a type',
));
]);
// Filter brick
Dict::Add('EN GB', 'British English', 'British English', array(
Dict::Add('EN GB', 'British English', 'British English', [
'Brick:Portal:Filter:Name' => 'Prefilter a brick',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'eg. connect wifi',
'Brick:Portal:Filter:SearchInput:Submit' => 'Search',
));
]);

View File

@@ -1,13 +1,14 @@
<?php
/**
* Spanish Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
* @author Miguel Turrubiates <miguel_tf@yahoo.com>
* @notas Utilizar codificación UTF-8 para mostrar acentos y otros caracteres especiales
* @notas Utilizar codificación UTF-8 para mostrar acentos y otros caracteres especiales
*/
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Page:DefaultTitle' => '%1$s - Portal de Usuario',
'Page:PleaseWait' => 'Por favor espere...',
'Page:Home' => 'Inicio',
@@ -51,19 +52,19 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Abierto</a> / <a href="%4$s" class="file_download_link">Descarga</a>',
'Portal:Calendar-FirstDayOfWeek' => 'es', //work with moment.js locales
));
]);
// Object form
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Cerrar este registro',
'Portal:Form:Close:Warning' => '¿Desea abandorar este formulario? Datos modificados se perderan',
'Portal:Error:ObjectCannotBeCreated' => 'Error: no se puede crear el objeto. Verifique los objetos asociados y archivos adjuntos antes de enviar nuevamente este formulario.',
'Portal:Error:ObjectCannotBeUpdated' => 'Error: no se puede actualizar el objeto. Verifique los objetos asociados y archivos adjuntos antes de enviar nuevamente este formulario.',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Brick:Portal:UserProfile:Name' => 'Perfil del usuario',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'Mi perfil',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Cerrar Sesión',
@@ -74,15 +75,15 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'No se puede cambiar la contraseña, póngase en contacto con el administrador de %1$s',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Información Personal',
'Brick:Portal:UserProfile:Photo:Title' => 'Foto',
));
]);
// AggregatePageBrick
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Tablero de Control',
));
]);
// BrowseBrick brick
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Brick:Portal:Browse:Name' => 'Buscar en todos los elementos',
'Brick:Portal:Browse:Mode:List' => 'Lista',
'Brick:Portal:Browse:Mode:Tree' => 'Árbol',
@@ -95,10 +96,10 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Expandir todo',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Desplegar todo',
'Brick:Portal:Browse:Filter:NoData' => 'Sin elementos',
));
]);
// ManageBrick brick
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Brick:Portal:Manage:Name' => 'Administrar elementos',
'Brick:Portal:Manage:Table:NoData' => 'Sin elementos',
'Brick:Portal:Manage:Table:ItemActions' => 'Acciones',
@@ -113,10 +114,10 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Brick:Portal:Manage:fct:avg' => 'Promedio',
'Brick:Portal:Manage:fct:min' => 'Mínimo',
'Brick:Portal:Manage:fct:max' => 'Máximo',
));
]);
// ObjectBrick brick
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Brick:Portal:Object:Name' => 'Objecto',
'Brick:Portal:Object:Form:Create:Title' => 'Nuevo %1$s',
'Brick:Portal:Object:Form:Edit:Title' => 'Actualizando %2$s (%1$s)',
@@ -128,18 +129,18 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Selección %1$s (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Copiar liga al objeto',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copiado'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copiado',
]);
// CreateBrick brick
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Brick:Portal:Create:Name' => 'Creación rápida',
'Brick:Portal:Create:ChooseType' => 'Por favor, seleccione un tipo',
));
]);
// Filter brick
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
'Brick:Portal:Filter:Name' => 'Prefiltrar bloque',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'Ej.:. Conectar a WiFi',
'Brick:Portal:Filter:SearchInput:Submit' => 'Buscar',
));
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Page:DefaultTitle' => 'Portail utilisateur %1$s',
'Page:PleaseWait' => 'Veuillez patienter...',
'Page:Home' => 'Accueil',
@@ -53,19 +54,19 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Ouvrir</a> / <a href="%4$s" class="file_download_link">Télécharger</a>',
'Portal:Calendar-FirstDayOfWeek' => 'fr', //work with moment.js locales
));
]);
// Object form
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Fermer cette entrée',
'Portal:Form:Close:Warning' => 'Voulez-vous quitter ce formulaire ? Les données saisies seront perdues',
'Portal:Error:ObjectCannotBeCreated' => 'Erreur: L\'objet n\'a pas été créé. Vérifiez les objets liés et les attachements avant de soumettre à nouveau le formulaire.',
'Portal:Error:ObjectCannotBeUpdated' => 'Erreur: L\'objet n\'a pas été modifié. Vérifiez les objets liés et les attachements avant de soumettre à nouveau le formulaire.',
'Portal:Error:CheckToWriteFailed' => 'Erreur durant la validation du champ \'%1$s\' : %2$s',
));
'Portal:Error:CheckToWriteFailed' => 'Erreur durant la validation du champ \'%1$s\' : %2$s',
]);
// UserProfile brick
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Brick:Portal:UserProfile:Name' => 'Profil utilisateur',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'Mon profil',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Déconnexion',
@@ -76,15 +77,15 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Impossible de modifier votre mot de passe, veuillez contacter votre administrateur %1$s',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Informations personnelles',
'Brick:Portal:UserProfile:Photo:Title' => 'Photo',
));
]);
// AggregatePageBrick
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Tableau de bord',
));
]);
// BrowseBrick brick
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Brick:Portal:Browse:Name' => 'Navigation dans les éléments',
'Brick:Portal:Browse:Mode:List' => 'Liste',
'Brick:Portal:Browse:Mode:Tree' => 'Hiérarchie',
@@ -97,10 +98,10 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Tout déplier',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Tout replier',
'Brick:Portal:Browse:Filter:NoData' => 'Aucun élément',
));
]);
// ManageBrick brick
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Brick:Portal:Manage:Name' => 'Gestion d\'éléments',
'Brick:Portal:Manage:Table:NoData' => 'Aucun élément',
'Brick:Portal:Manage:Table:ItemActions' => 'Actions',
@@ -115,10 +116,10 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Brick:Portal:Manage:fct:avg' => 'Moyenne',
'Brick:Portal:Manage:fct:min' => 'Min',
'Brick:Portal:Manage:fct:max' => 'Max',
));
]);
// ObjectBrick brick
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Brick:Portal:Object:Name' => 'Objet',
'Brick:Portal:Object:Form:Create:Title' => 'Création de %1$s',
'Brick:Portal:Object:Form:Edit:Title' => 'Modification de %2$s (%1$s)',
@@ -130,18 +131,18 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Sélection de %1$s (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Copier l\'url de l\'objet',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copié'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copié',
]);
// CreateBrick brick
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Brick:Portal:Create:Name' => 'Création rapide',
'Brick:Portal:Create:ChooseType' => 'Veuillez choisir le type',
));
]);
// Filter brick
Dict::Add('FR FR', 'French', 'Français', array(
Dict::Add('FR FR', 'French', 'Français', [
'Brick:Portal:Filter:Name' => 'Préfiltre une brique',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'ex : connecter wifi',
'Brick:Portal:Filter:SearchInput:Submit' => 'Rechercher',
));
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Page:DefaultTitle' => '%1$s Felhasználói portál',
'Page:PleaseWait' => 'Kérem várjon...',
'Page:Home' => 'Kezdőlap',
@@ -53,19 +54,19 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Megnyitás</a> / <a href="%4$s" class="file_download_link">Letöltés</a>',
'Portal:Calendar-FirstDayOfWeek' => 'hu', //work with moment.js locales
));
]);
// Object form
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Bejegyzés bezárása',
'Portal:Form:Close:Warning' => 'Szeretné elhagyni ezt az űrlapot? A megadott adatok elveszhetnek',
'Portal:Error:ObjectCannotBeCreated' => 'Hiba: az objektum nem hozható létre. Ellenőrizze a kapcsolódó objektumokat és mellékleteket, mielőtt újra elküldi ezt az űrlapot.',
'Portal:Error:ObjectCannotBeUpdated' => 'Hiba: az objektum nem frissíthető. Ellenőrizze a kapcsolódó objektumokat és mellékleteket, mielőtt újra elküldi ezt az űrlapot.',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Brick:Portal:UserProfile:Name' => 'Felhasználói profil',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'Saját profil',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Kijelentkezés',
@@ -76,15 +77,15 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Nem tudja megváltoztatni a jelszót, lépjen kapcsolatba a %1$s rendszergazdával',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Személyi adatok',
'Brick:Portal:UserProfile:Photo:Title' => 'Fénykép',
));
]);
// AggregatePageBrick
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Műszerfal',
));
]);
// BrowseBrick brick
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Brick:Portal:Browse:Name' => 'Böngésszen az elemek között',
'Brick:Portal:Browse:Mode:List' => 'Lista',
'Brick:Portal:Browse:Mode:Tree' => 'Fa',
@@ -97,10 +98,10 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Összes kinyitása',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Összecsukás',
'Brick:Portal:Browse:Filter:NoData' => 'Nincs elem',
));
]);
// ManageBrick brick
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Brick:Portal:Manage:Name' => 'Elemek kezelése',
'Brick:Portal:Manage:Table:NoData' => 'Nincs elem',
'Brick:Portal:Manage:Table:ItemActions' => 'Műveletek',
@@ -115,10 +116,10 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Brick:Portal:Manage:fct:avg' => 'Átlag',
'Brick:Portal:Manage:fct:min' => 'Minimum',
'Brick:Portal:Manage:fct:max' => 'Maximum',
));
]);
// ObjectBrick brick
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Brick:Portal:Object:Name' => 'Objektum',
'Brick:Portal:Object:Form:Create:Title' => 'Új %1$s',
'Brick:Portal:Object:Form:Edit:Title' => '%2$s frissítése (%1$s)',
@@ -130,18 +131,18 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => '%1$s kiválasztása (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Objektum hivatkozás másolása',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Másolva'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Másolva',
]);
// CreateBrick brick
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Brick:Portal:Create:Name' => 'Gyors létrehozás',
'Brick:Portal:Create:ChooseType' => 'Válasszon típust',
));
]);
// Filter brick
Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
'Brick:Portal:Filter:Name' => 'Tégla előszűrése',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'pl. wifi kapcsolat',
'Brick:Portal:Filter:SearchInput:Submit' => 'Keresés',
));
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Page:DefaultTitle' => '%1$s Portale Utente',
'Page:PleaseWait' => 'Attendere…',
'Page:Home' => 'Home',
@@ -53,19 +54,19 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Download</a>~~',
'Portal:Calendar-FirstDayOfWeek' => 'it', //work with moment.js locales
));
]);
// Object form
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Close this entry~~',
'Portal:Form:Close:Warning' => 'Do you want to leave this form? Data entered may be lost~~',
'Portal:Error:ObjectCannotBeCreated' => 'Error: object cannot be created. Check associated objects and attachments before submitting this form again.~~',
'Portal:Error:ObjectCannotBeUpdated' => 'Error: object cannot be updated. Check associated objects and attachments before submitting this form again.~~',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Brick:Portal:UserProfile:Name' => 'User profile~~',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'My profile~~',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Logoff~~',
@@ -76,15 +77,15 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Can\'t change password, please contact your %1$s administrator~~',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Personal information~~',
'Brick:Portal:UserProfile:Photo:Title' => 'Photo~~',
));
]);
// AggregatePageBrick
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Dashboard~~',
));
]);
// BrowseBrick brick
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Brick:Portal:Browse:Name' => 'Browse throught items~~',
'Brick:Portal:Browse:Mode:List' => 'List~~',
'Brick:Portal:Browse:Mode:Tree' => 'Tree~~',
@@ -97,10 +98,10 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Expand all~~',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Collapse all~~',
'Brick:Portal:Browse:Filter:NoData' => 'No item~~',
));
]);
// ManageBrick brick
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Brick:Portal:Manage:Name' => 'Manage items~~',
'Brick:Portal:Manage:Table:NoData' => 'No item.~~',
'Brick:Portal:Manage:Table:ItemActions' => 'Actions~~',
@@ -115,10 +116,10 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Brick:Portal:Manage:fct:avg' => 'Average~~',
'Brick:Portal:Manage:fct:min' => 'Min~~',
'Brick:Portal:Manage:fct:max' => 'Max~~',
));
]);
// ObjectBrick brick
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Brick:Portal:Object:Name' => 'Object~~',
'Brick:Portal:Object:Form:Create:Title' => 'New %1$s~~',
'Brick:Portal:Object:Form:Edit:Title' => 'Updating %2$s (%1$s)~~',
@@ -130,18 +131,18 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Select %1$s (%2$s)~~',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Copy object link~~',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied~~'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied~~',
]);
// CreateBrick brick
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Brick:Portal:Create:Name' => 'Quick creation~~',
'Brick:Portal:Create:ChooseType' => 'Please, choose a type~~',
));
]);
// Filter brick
Dict::Add('IT IT', 'Italian', 'Italiano', array(
Dict::Add('IT IT', 'Italian', 'Italiano', [
'Brick:Portal:Filter:Name' => 'Prefilter a brick~~',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'eg. connect wifi~~',
'Brick:Portal:Filter:SearchInput:Submit' => 'Search~~',
));
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Page:DefaultTitle' => '%1$s User portal~~',
'Page:PleaseWait' => 'Please wait...~~',
'Page:Home' => 'Home~~',
@@ -53,19 +54,19 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>~~',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Download</a>~~',
'Portal:Calendar-FirstDayOfWeek' => 'ja', //work with moment.js locales
));
]);
// Object form
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Close this entry~~',
'Portal:Form:Close:Warning' => 'Do you want to leave this form? Data entered may be lost~~',
'Portal:Error:ObjectCannotBeCreated' => 'Error: object cannot be created. Check associated objects and attachments before submitting this form again.~~',
'Portal:Error:ObjectCannotBeUpdated' => 'Error: object cannot be updated. Check associated objects and attachments before submitting this form again.~~',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Brick:Portal:UserProfile:Name' => 'User profile~~',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'My profile~~',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Logoff~~',
@@ -76,15 +77,15 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Can\'t change password, please contact your %1$s administrator~~',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Personal information~~',
'Brick:Portal:UserProfile:Photo:Title' => 'Photo~~',
));
]);
// AggregatePageBrick
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Dashboard~~',
));
]);
// BrowseBrick brick
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Brick:Portal:Browse:Name' => 'Browse throught items~~',
'Brick:Portal:Browse:Mode:List' => 'List~~',
'Brick:Portal:Browse:Mode:Tree' => 'Tree~~',
@@ -97,10 +98,10 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Expand all~~',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Collapse all~~',
'Brick:Portal:Browse:Filter:NoData' => 'No item~~',
));
]);
// ManageBrick brick
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Brick:Portal:Manage:Name' => 'Manage items~~',
'Brick:Portal:Manage:Table:NoData' => 'No item.~~',
'Brick:Portal:Manage:Table:ItemActions' => 'Actions~~',
@@ -115,10 +116,10 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'Brick:Portal:Manage:fct:avg' => 'Average~~',
'Brick:Portal:Manage:fct:min' => 'Min~~',
'Brick:Portal:Manage:fct:max' => 'Max~~',
));
]);
// ObjectBrick brick
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Brick:Portal:Object:Name' => 'Object~~',
'Brick:Portal:Object:Form:Create:Title' => 'New %1$s~~',
'Brick:Portal:Object:Form:Edit:Title' => 'Updating %2$s (%1$s)~~',
@@ -130,18 +131,18 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Select %1$s (%2$s)~~',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Copy object link~~',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied~~'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied~~',
]);
// CreateBrick brick
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Brick:Portal:Create:Name' => 'Quick creation~~',
'Brick:Portal:Create:ChooseType' => 'Please, choose a type~~',
));
]);
// Filter brick
Dict::Add('JA JP', 'Japanese', '日本語', array(
Dict::Add('JA JP', 'Japanese', '日本語', [
'Brick:Portal:Filter:Name' => 'Prefilter a brick~~',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'eg. connect wifi~~',
'Brick:Portal:Filter:SearchInput:Submit' => 'Search~~',
));
]);

View File

@@ -1,16 +1,17 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
* @author Jeffrey Bostoen <info@jeffreybostoen.be> (2018 - 2022)
*
*/
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Page:DefaultTitle' => '%1$s Gebruikersportaal',
'Page:PleaseWait' => 'Even geduld...',
'Page:Home' => 'Welkom',
@@ -54,19 +55,19 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Download</a>',
'Portal:Calendar-FirstDayOfWeek' => 'nl', //work with moment.js locales
));
]);
// Object form
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Sluit dit item.',
'Portal:Form:Close:Warning' => 'Ben je zeker dat je dit venster wil sluiten? Ingevoerde gegevens kunnen verloren gaan.',
'Portal:Error:ObjectCannotBeCreated' => 'Fout: object kan niet worden aangemaakt. Kijk verwante objecten en bijlagen na vooraleer dit formulier opnieuw te versturen.',
'Portal:Error:ObjectCannotBeUpdated' => 'Fout: object kan niet worden aangepast. Kijk verwante objecten en bijlagen na vooraleer dit formulier opnieuw te versturen.',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Brick:Portal:UserProfile:Name' => 'Gebruikersprofiel',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'Mijn profiel',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Uitloggen',
@@ -77,15 +78,15 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Jouw wachtwoord kan niet gewijzigd worden. Neem contact op met de beheerder',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Persoonlijke informatie',
'Brick:Portal:UserProfile:Photo:Title' => 'Foto',
));
]);
// AggregatePageBrick
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Dashboard',
));
]);
// BrowseBrick brick
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Brick:Portal:Browse:Name' => 'Bladeren',
'Brick:Portal:Browse:Mode:List' => 'Lijst',
'Brick:Portal:Browse:Mode:Tree' => 'Boomstructuur',
@@ -98,10 +99,10 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Toon alles',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Verberg alles',
'Brick:Portal:Browse:Filter:NoData' => 'Geen gegevens',
));
]);
// ManageBrick brick
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Brick:Portal:Manage:Name' => 'Beheer items',
'Brick:Portal:Manage:Table:NoData' => 'Geen gegevens',
'Brick:Portal:Manage:Table:ItemActions' => 'Acties',
@@ -116,10 +117,10 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Brick:Portal:Manage:fct:avg' => 'Gemiddelde',
'Brick:Portal:Manage:fct:min' => 'Min',
'Brick:Portal:Manage:fct:max' => 'Max',
));
]);
// ObjectBrick brick
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Brick:Portal:Object:Name' => 'Object',
'Brick:Portal:Object:Form:Create:Title' => 'Nieuw %1$s',
'Brick:Portal:Object:Form:Edit:Title' => 'Verwerken %2$s (%1$s)',
@@ -131,18 +132,18 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Selecteer %1$s (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Kopieer link naar object',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Gekopieerd'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Gekopieerd',
]);
// CreateBrick brick
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Brick:Portal:Create:Name' => 'Snel aanmaken',
'Brick:Portal:Create:ChooseType' => 'Geef een type op.',
));
]);
// Filter brick
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
'Brick:Portal:Filter:Name' => 'Voorfilteren van een bouwsteen',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'bv. wifi-verbinding',
'Brick:Portal:Filter:SearchInput:Submit' => 'Zoek',
));
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Page:DefaultTitle' => '%1$s portal użytkownika',
'Page:PleaseWait' => 'Proszę czekać...',
'Page:Home' => 'Start',
@@ -53,19 +54,19 @@ Dict::Add('PL PL', 'Polish', 'Polski', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Pobierz</a>',
'Portal:Calendar-FirstDayOfWeek' => 'en-us', //work with moment.js locales
));
]);
// Object form
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Zamknij ten wpis',
'Portal:Form:Close:Warning' => 'Chcesz opuścić ten formularz? Wprowadzone dane mogą zostać utracone',
'Portal:Error:ObjectCannotBeCreated' => 'Błąd: nie można utworzyć obiektu. Sprawdź powiązane obiekty i załączniki przed ponownym przesłaniem tego formularza.',
'Portal:Error:ObjectCannotBeUpdated' => 'Błąd: nie można zaktualizować obiektu. Sprawdź powiązane obiekty i załączniki przed ponownym przesłaniem tego formularza.',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Brick:Portal:UserProfile:Name' => 'Profil użytkownika',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'Mój profil',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Wyloguj',
@@ -76,15 +77,15 @@ Dict::Add('PL PL', 'Polish', 'Polski', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Nie można zmienić hasła. Skontaktuj się z administratorem %1$s',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Informacje osobiste',
'Brick:Portal:UserProfile:Photo:Title' => 'Zdjęcie',
));
]);
// AggregatePageBrick
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Pulpit',
));
]);
// BrowseBrick brick
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Brick:Portal:Browse:Name' => 'Przeglądaj elementy',
'Brick:Portal:Browse:Mode:List' => 'Lista',
'Brick:Portal:Browse:Mode:Tree' => 'Drzewo',
@@ -97,10 +98,10 @@ Dict::Add('PL PL', 'Polish', 'Polski', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Rozwiń wszystkie',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Zwiń wszystkie',
'Brick:Portal:Browse:Filter:NoData' => 'Brak elementu',
));
]);
// ManageBrick brick
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Brick:Portal:Manage:Name' => 'Zarządzaj elementami',
'Brick:Portal:Manage:Table:NoData' => 'Brak elementu.',
'Brick:Portal:Manage:Table:ItemActions' => 'Akcje',
@@ -115,10 +116,10 @@ Dict::Add('PL PL', 'Polish', 'Polski', array(
'Brick:Portal:Manage:fct:avg' => 'Średnia',
'Brick:Portal:Manage:fct:min' => 'Minimum',
'Brick:Portal:Manage:fct:max' => 'Maksimum',
));
]);
// ObjectBrick brick
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Brick:Portal:Object:Name' => 'Obiekty',
'Brick:Portal:Object:Form:Create:Title' => 'Nowy %1$s',
'Brick:Portal:Object:Form:Edit:Title' => 'Aktualizacja %2$s (%1$s)',
@@ -130,18 +131,18 @@ Dict::Add('PL PL', 'Polish', 'Polski', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Wybierz %1$s (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Skopiuj obiekt',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Skopiowano'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Skopiowano',
]);
// CreateBrick brick
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Brick:Portal:Create:Name' => 'Szybkie tworzenie',
'Brick:Portal:Create:ChooseType' => 'Proszę wybrać typ',
));
]);
// Filter brick
Dict::Add('PL PL', 'Polish', 'Polski', array(
Dict::Add('PL PL', 'Polish', 'Polski', [
'Brick:Portal:Filter:Name' => 'Wstępny filtr',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'na przykład. podłącz wifi',
'Brick:Portal:Filter:SearchInput:Submit' => 'Szukaj',
));
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Page:DefaultTitle' => 'Portal do Usuário do '.ITOP_APPLICATION_SHORT,
'Page:PleaseWait' => 'Aguarde...',
'Page:Home' => 'Página inicial',
@@ -53,19 +54,19 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Abrir</a> / <a href="%4$s" class="file_download_link">Download</a>',
'Portal:Calendar-FirstDayOfWeek' => 'pt-br', //work with moment.js locales
));
]);
// Object form
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Fechar esta solicitação',
'Portal:Form:Close:Warning' => 'Você deseja abandonar esta página? Os dados digitados podem ser perdidos',
'Portal:Error:ObjectCannotBeCreated' => 'Erro: objeto não pode ser criado. Verifique os objetos e anexos associados antes de enviar novamente este formulário',
'Portal:Error:ObjectCannotBeUpdated' => 'Erro: objeto não pode ser atualizado. Verifique os objetos e anexos associados antes de enviar novamente este formulário',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Brick:Portal:UserProfile:Name' => 'Perfil de Usuário',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'Meu Perfil',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Sair',
@@ -76,15 +77,15 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Não foi possível alterar sua senha, entre em contato com a T.I.',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Informações pessoais',
'Brick:Portal:UserProfile:Photo:Title' => 'Imagem',
));
]);
// AggregatePageBrick
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Painel do '.ITOP_APPLICATION_SHORT,
));
]);
// BrowseBrick brick
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Brick:Portal:Browse:Name' => 'Navegar por itens',
'Brick:Portal:Browse:Mode:List' => 'Lista',
'Brick:Portal:Browse:Mode:Tree' => 'Cascata',
@@ -97,10 +98,10 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Expandir todos',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Recolher todos',
'Brick:Portal:Browse:Filter:NoData' => 'Sem dados',
));
]);
// ManageBrick brick
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Brick:Portal:Manage:Name' => 'Gerenciar itens',
'Brick:Portal:Manage:Table:NoData' => 'Sem dados',
'Brick:Portal:Manage:Table:ItemActions' => 'Ações',
@@ -115,10 +116,10 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Brick:Portal:Manage:fct:avg' => 'Média',
'Brick:Portal:Manage:fct:min' => 'Min.',
'Brick:Portal:Manage:fct:max' => 'Máx.',
));
]);
// ObjectBrick brick
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Brick:Portal:Object:Name' => 'Objeto',
'Brick:Portal:Object:Form:Create:Title' => 'Novo %1$s',
'Brick:Portal:Object:Form:Edit:Title' => 'Alterar %2$s (%1$s)',
@@ -130,18 +131,18 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Selecinar %1$s (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Copiar',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copiado'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copiado',
]);
// CreateBrick brick
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Brick:Portal:Create:Name' => 'Criação rápida',
'Brick:Portal:Create:ChooseType' => 'Por favor, escolha um tipo:',
));
]);
// Filter brick
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
'Brick:Portal:Filter:Name' => 'Filtro ativado',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'ex. conectar ao WiFi',
'Brick:Portal:Filter:SearchInput:Submit' => 'Pesquisa',
));
]);

View File

@@ -1,16 +1,17 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
* @author Vladimir Kunin <v.b.kunin@gmail.com>
*
*/
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Page:DefaultTitle' => 'Пользовательский портал %1$s',
'Page:PleaseWait' => 'Пожалуйста, подождите...',
'Page:Home' => 'Домашняя страница',
@@ -54,19 +55,19 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Открыть</a> / <a href="%4$s" class="file_download_link">Скачать</a>',
'Portal:Calendar-FirstDayOfWeek' => 'ru', //work with moment.js locales
));
]);
// Object form
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Close this entry~~',
'Portal:Form:Close:Warning' => 'Вы действительно хотите закрыть эту форму? Введённые данные могут быть утеряны.',
'Portal:Error:ObjectCannotBeCreated' => 'Error: object cannot be created. Check associated objects and attachments before submitting this form again.~~',
'Portal:Error:ObjectCannotBeUpdated' => 'Error: object cannot be updated. Check associated objects and attachments before submitting this form again.~~',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Brick:Portal:UserProfile:Name' => 'Профиль пользователя',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'Мой профиль',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Выйти',
@@ -77,15 +78,15 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Не удалось изменить пароль, пожалуйста, свяжитесь с вашим администратором %1$s.',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Персональная информация',
'Brick:Portal:UserProfile:Photo:Title' => 'Фотография',
));
]);
// AggregatePageBrick
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Дашборд',
));
]);
// BrowseBrick brick
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Brick:Portal:Browse:Name' => 'Просмотр элементов',
'Brick:Portal:Browse:Mode:List' => 'Список',
'Brick:Portal:Browse:Mode:Tree' => 'Дерево',
@@ -98,10 +99,10 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Развернуть все',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Свернуть все',
'Brick:Portal:Browse:Filter:NoData' => 'Нет элементов',
));
]);
// ManageBrick brick
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Brick:Portal:Manage:Name' => 'Управление элементами',
'Brick:Portal:Manage:Table:NoData' => 'Нет элементов',
'Brick:Portal:Manage:Table:ItemActions' => 'Действия',
@@ -116,10 +117,10 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Brick:Portal:Manage:fct:avg' => 'Среднее',
'Brick:Portal:Manage:fct:min' => 'Минимум',
'Brick:Portal:Manage:fct:max' => 'Максимум',
));
]);
// ObjectBrick brick
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Brick:Portal:Object:Name' => 'Object',
'Brick:Portal:Object:Form:Create:Title' => 'Создать %1$s',
'Brick:Portal:Object:Form:Edit:Title' => 'Обновление %2$s (%1$s)',
@@ -131,18 +132,18 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Выбрать %1$s (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Скопировать ссылку на объект',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Ссылка скопирована'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Ссылка скопирована',
]);
// CreateBrick brick
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Brick:Portal:Create:Name' => 'Быстрое создание',
'Brick:Portal:Create:ChooseType' => 'Пожалуйста, выберите тип',
));
]);
// Filter brick
Dict::Add('RU RU', 'Russian', 'Русский', array(
Dict::Add('RU RU', 'Russian', 'Русский', [
'Brick:Portal:Filter:Name' => 'Фильтр',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'например, подключить wi-fi',
'Brick:Portal:Filter:SearchInput:Submit' => 'Искать',
));
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Page:DefaultTitle' => '%1$s User portal~~',
'Page:PleaseWait' => 'Please wait...~~',
'Page:Home' => 'Home~~',
@@ -53,19 +54,19 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>~~',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Download</a>~~',
'Portal:Calendar-FirstDayOfWeek' => 'en-us~~', //work with moment.js locales
));
]);
// Object form
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Close this entry~~',
'Portal:Form:Close:Warning' => 'Do you want to leave this form? Data entered may be lost~~',
'Portal:Error:ObjectCannotBeCreated' => 'Error: object cannot be created. Check associated objects and attachments before submitting this form again.~~',
'Portal:Error:ObjectCannotBeUpdated' => 'Error: object cannot be updated. Check associated objects and attachments before submitting this form again.~~',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Brick:Portal:UserProfile:Name' => 'User profile~~',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'My profile~~',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Logoff~~',
@@ -76,15 +77,15 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Can\'t change password, please contact your %1$s administrator~~',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Personal information~~',
'Brick:Portal:UserProfile:Photo:Title' => 'Photo~~',
));
]);
// AggregatePageBrick
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Dashboard~~',
));
]);
// BrowseBrick brick
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Brick:Portal:Browse:Name' => 'Browse throught items~~',
'Brick:Portal:Browse:Mode:List' => 'List~~',
'Brick:Portal:Browse:Mode:Tree' => 'Tree~~',
@@ -97,10 +98,10 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Expand all~~',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Collapse all~~',
'Brick:Portal:Browse:Filter:NoData' => 'No item~~',
));
]);
// ManageBrick brick
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Brick:Portal:Manage:Name' => 'Manage items~~',
'Brick:Portal:Manage:Table:NoData' => 'No item.~~',
'Brick:Portal:Manage:Table:ItemActions' => 'Actions~~',
@@ -115,10 +116,10 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
'Brick:Portal:Manage:fct:avg' => 'Average~~',
'Brick:Portal:Manage:fct:min' => 'Min~~',
'Brick:Portal:Manage:fct:max' => 'Max~~',
));
]);
// ObjectBrick brick
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Brick:Portal:Object:Name' => 'Object~~',
'Brick:Portal:Object:Form:Create:Title' => 'New %1$s~~',
'Brick:Portal:Object:Form:Edit:Title' => 'Updating %2$s (%1$s)~~',
@@ -130,18 +131,18 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Select %1$s (%2$s)~~',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Copy object link~~',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied~~'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied~~',
]);
// CreateBrick brick
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Brick:Portal:Create:Name' => 'Quick creation~~',
'Brick:Portal:Create:ChooseType' => 'Please, choose a type~~',
));
]);
// Filter brick
Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
'Brick:Portal:Filter:Name' => 'Prefilter a brick~~',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'eg. connect wifi~~',
'Brick:Portal:Filter:SearchInput:Submit' => 'Search~~',
));
]);

View File

@@ -1,15 +1,16 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*
*/
/**
*
*/
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
'Page:DefaultTitle' => '%1$s User portal~~',
'Page:PleaseWait' => 'Please wait...~~',
'Page:Home' => 'Home~~',
@@ -53,19 +54,19 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>~~',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Download</a>~~',
'Portal:Calendar-FirstDayOfWeek' => 'tr', //work with moment.js locales
));
]);
// Object form
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => 'Close this entry~~',
'Portal:Form:Close:Warning' => 'Do you want to leave this form? Data entered may be lost~~',
'Portal:Error:ObjectCannotBeCreated' => 'Error: object cannot be created. Check associated objects and attachments before submitting this form again.~~',
'Portal:Error:ObjectCannotBeUpdated' => 'Error: object cannot be updated. Check associated objects and attachments before submitting this form again.~~',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
'Brick:Portal:UserProfile:Name' => 'User profile~~',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => 'My profile~~',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => 'Logoff~~',
@@ -76,15 +77,15 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => 'Can\'t change password, please contact your %1$s administrator~~',
'Brick:Portal:UserProfile:PersonalInformations:Title' => 'Personal information~~',
'Brick:Portal:UserProfile:Photo:Title' => 'Photo~~',
));
]);
// AggregatePageBrick
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
'Brick:Portal:AggregatePage:DefaultTitle' => 'Dashboard~~',
));
]);
// BrowseBrick brick
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
'Brick:Portal:Browse:Name' => 'Browse throught items~~',
'Brick:Portal:Browse:Mode:List' => 'List~~',
'Brick:Portal:Browse:Mode:Tree' => 'Tree~~',
@@ -97,10 +98,10 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Brick:Portal:Browse:Tree:ExpandAll' => 'Expand all~~',
'Brick:Portal:Browse:Tree:CollapseAll' => 'Collapse all~~',
'Brick:Portal:Browse:Filter:NoData' => 'No item~~',
));
]);
// ManageBrick brick
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
'Brick:Portal:Manage:Name' => 'Manage items~~',
'Brick:Portal:Manage:Table:NoData' => 'No item.~~',
'Brick:Portal:Manage:Table:ItemActions' => 'Actions~~',
@@ -115,10 +116,10 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Brick:Portal:Manage:fct:avg' => 'Average~~',
'Brick:Portal:Manage:fct:min' => 'Min~~',
'Brick:Portal:Manage:fct:max' => 'Max~~',
));
]);
// ObjectBrick brick
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
'Brick:Portal:Object:Name' => 'Object~~',
'Brick:Portal:Object:Form:Create:Title' => 'New %1$s~~',
'Brick:Portal:Object:Form:Edit:Title' => 'Updating %2$s (%1$s)~~',
@@ -130,18 +131,18 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Select %1$s (%2$s)~~',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => 'Copy object link~~',
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied~~'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => 'Copied~~',
]);
// CreateBrick brick
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
'Brick:Portal:Create:Name' => 'Quick creation~~',
'Brick:Portal:Create:ChooseType' => 'Please, choose a type~~',
));
]);
// Filter brick
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
'Brick:Portal:Filter:Name' => 'Prefilter a brick~~',
'Brick:Portal:Filter:SearchInput:Placeholder' => 'eg. connect wifi~~',
'Brick:Portal:Filter:SearchInput:Submit' => 'Search~~',
));
]);

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
@@ -18,7 +19,7 @@
* You should have received a copy of the GNU Affero General Public License
*/
// Portal
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Page:DefaultTitle' => '%1$s 用户门户',
'Page:PleaseWait' => '请稍候...',
'Page:Home' => '主页',
@@ -62,19 +63,19 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Portal:File:DisplayInfo' => '<a href="%2$s" class="file_download_link">%1$s</a>',
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">打开</a> / <a href="%4$s" class="file_download_link">下载</a>',
'Portal:Calendar-FirstDayOfWeek' => 'zh-cn', //work with moment.js locales
));
]);
// Object form
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Portal:Form:Caselog:Entry:Close:Tooltip' => '关闭此条目',
'Portal:Form:Close:Warning' => '确定要离开表单吗? 已输入数据会丢失',
'Portal:Error:ObjectCannotBeCreated' => '错误: 无法创建对象. 请在再次提交表单前检查相关对象和附件.',
'Portal:Error:ObjectCannotBeUpdated' => '错误: 无法更新对象. 请在再次提交表单前检查相关对象和附件.',
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
));
'Portal:Error:CheckToWriteFailed' => 'Error during validation of field \'%1$s\': %2$s~~',
]);
// UserProfile brick
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Brick:Portal:UserProfile:Name' => '用户资料',
'Brick:Portal:UserProfile:Navigation:Dropdown:MyProfil' => '我的资料',
'Brick:Portal:UserProfile:Navigation:Dropdown:Logout' => '注销',
@@ -85,15 +86,15 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => '无法修改密码, 请联系管理员',
'Brick:Portal:UserProfile:PersonalInformations:Title' => '人员信息',
'Brick:Portal:UserProfile:Photo:Title' => '头像',
));
]);
// AggregatePageBrick
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Brick:Portal:AggregatePage:DefaultTitle' => '仪表盘',
));
]);
// BrowseBrick brick
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Brick:Portal:Browse:Name' => '浏览项目',
'Brick:Portal:Browse:Mode:List' => '列表',
'Brick:Portal:Browse:Mode:Tree' => '树形',
@@ -106,10 +107,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Brick:Portal:Browse:Tree:ExpandAll' => '全部展开',
'Brick:Portal:Browse:Tree:CollapseAll' => '全部收起',
'Brick:Portal:Browse:Filter:NoData' => '没有项目',
));
]);
// ManageBrick brick
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Brick:Portal:Manage:Name' => '管理项目',
'Brick:Portal:Manage:Table:NoData' => '没有项目.',
'Brick:Portal:Manage:Table:ItemActions' => '操作',
@@ -124,10 +125,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Brick:Portal:Manage:fct:avg' => '平均',
'Brick:Portal:Manage:fct:min' => '最小',
'Brick:Portal:Manage:fct:max' => '最大',
));
]);
// ObjectBrick brick
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Brick:Portal:Object:Name' => '对象',
'Brick:Portal:Object:Form:Create:Title' => '新建 %1$s',
'Brick:Portal:Object:Form:Edit:Title' => '正在更新 %2$s (%1$s)',
@@ -139,18 +140,18 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Brick:Portal:Object:Search:Hierarchy:Title' => '选择 %1$s (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%2$s',
'Brick:Portal:Object:Copy:Tooltip' => '复制对象链接',
'Brick:Portal:Object:Copy:CopiedTooltip' => '已复制'
));
'Brick:Portal:Object:Copy:CopiedTooltip' => '已复制',
]);
// CreateBrick brick
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Brick:Portal:Create:Name' => '快速创建',
'Brick:Portal:Create:ChooseType' => '请选择类型',
));
]);
// Filter brick
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Brick:Portal:Filter:Name' => '预筛选组件',
'Brick:Portal:Filter:SearchInput:Placeholder' => '例如. 连接wifi',
'Brick:Portal:Filter:SearchInput:Submit' => '搜索',
));
]);

View File

@@ -24,12 +24,9 @@
*/
// Load current environment
if (file_exists(__DIR__.'/../../approot.inc.php'))
{
if (file_exists(__DIR__.'/../../approot.inc.php')) {
require_once __DIR__.'/../../approot.inc.php'; // When in env-xxxx folder
}
else
{
} else {
require_once __DIR__.'/../../../approot.inc.php'; // When in datamodels/x.x folder
}
require_once APPROOT.'application/startup.inc.php';

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -20,37 +21,38 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-portal-base/3.2.1', array(
'itop-portal-base/3.2.1',
[
// Identification
'label' => 'Portal Development Library',
'category' => 'Portal',
// Setup
'dependencies' => array(
),
'dependencies' => [
],
'mandatory' => true,
'visible' => false,
// Components
'datamodel' => array(
'datamodel' => [
// Note: The autoloader is there instead of portal/config/bootstrap.php in order to be available for other modules with a dependency on this one.
// eg. If a module has a class extending \Combodo\iTop\Portal\Controller\AbstractController, it needs to find it even if the portal kernel is not loaded.
'portal/vendor/autoload.php',
),
'webservice' => array(
],
'webservice' => [
//'webservices.itop-portal-base.php',
),
'dictionary' => array(
),
'data.struct' => array(
],
'dictionary' => [
],
'data.struct' => [
//'data.struct.itop-portal-base.xml',
),
'data.sample' => array(
],
'data.sample' => [
//'data.sample.itop-portal-base.xml',
),
],
// Documentation
'doc.manual_setup' => '',
'doc.more_information' => '',
// Default settings
'settings' => array(
),
)
'settings' => [
],
]
);

View File

@@ -28,14 +28,10 @@ use Symfony\Component\Dotenv\Dotenv;
require_once APPROOT.'/lib/autoload.php';
// Load current environment if necessary (typically from CLI as the app is not started yet)
if (!defined('MODULESROOT'))
{
if (file_exists(__DIR__.'/../../../../approot.inc.php'))
{
if (!defined('MODULESROOT')) {
if (file_exists(__DIR__.'/../../../../approot.inc.php')) {
require_once __DIR__.'/../../../../approot.inc.php'; // When in env-xxxx folder
}
else
{
} else {
require_once __DIR__.'/../../../../../approot.inc.php'; // When in datamodels/x.x folder
}
require_once APPROOT.'/application/startup.inc.php';
@@ -62,7 +58,7 @@ if (!class_exists(Dotenv::class)) {
}
if (null === $sEnv = (isset($_SERVER['APP_ENV']) ? $_SERVER['APP_ENV'] : (isset($_ENV['APP_ENV']) ? $_ENV['APP_ENV'] : null))) {
$oDotenv->populate(array('APP_ENV' => $sEnv = 'prod'));
$oDotenv->populate(['APP_ENV' => $sEnv = 'prod']);
}
if ('test' !== $sEnv && file_exists($sPathDist = "$sPath.local")) {
@@ -83,31 +79,27 @@ if (!class_exists(Dotenv::class)) {
$_SERVER += $_ENV;
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = (isset($_SERVER['APP_ENV']) ? $_SERVER['APP_ENV'] : (isset($_ENV['APP_ENV']) ? $_ENV['APP_ENV'] : null)) ?: 'prod';
$_SERVER['APP_DEBUG'] = isset($_SERVER['APP_DEBUG']) ? $_SERVER['APP_DEBUG'] : (isset($_ENV['APP_DEBUG']) ? $_ENV['APP_DEBUG'] : ('prod' !== $_SERVER['APP_ENV']));
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int)$_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'],
FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int)$_SERVER['APP_DEBUG'] || filter_var(
$_SERVER['APP_DEBUG'],
FILTER_VALIDATE_BOOLEAN
) ? '1' : '0';
if ($_SERVER['APP_DEBUG'])
{
if ($_SERVER['APP_DEBUG']) {
umask(0000);
if (class_exists(Debug::class))
{
if (class_exists(Debug::class)) {
Debug::enable();
}
}
if (isset($_ENV['PORTAL_ID']))
{
if (isset($_ENV['PORTAL_ID'])) {
// Nothing to do
}
// Note: Default value is set to "false" to differentiate an empty value from a non given parameter
elseif ($sPortalId = utils::ReadParam('portal_id', false, true))
{
elseif ($sPortalId = utils::ReadParam('portal_id', false, true)) {
$_ENV['PORTAL_ID'] = $sPortalId;
}
elseif (defined('PORTAL_ID'))
{
} elseif (defined('PORTAL_ID')) {
$_ENV['PORTAL_ID'] = PORTAL_ID;
@trigger_error(
sprintf(
@@ -118,16 +110,14 @@ elseif (defined('PORTAL_ID'))
);
}
if (empty($_ENV['PORTAL_ID']))
{
if (empty($_ENV['PORTAL_ID'])) {
echo "Missing argument 'portal_id'";
exit;
}
// Make sure that the PORTAL_ID constant is also defined
// Note: This is widely used in extensions, snippets and all
if (!defined('PORTAL_ID'))
{
if (!defined('PORTAL_ID')) {
define('PORTAL_ID', $_ENV['PORTAL_ID']);
}
@@ -138,4 +128,4 @@ $_ENV['COMBODO_CONF_APP_ICON_URL'] = MetaModel::GetConfig()->Get('app_icon_url')
$_ENV['COMBODO_MODULES_ABSOLUTE_URL'] = utils::GetAbsoluteUrlModulesRoot();
$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_URL'] = utils::GetAbsoluteUrlModulesRoot().'itop-portal-base/portal/public/';
$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'] = MODULESROOT.'/itop-portal-base/portal/public/';
$_ENV['COMBODO_PORTAL_INSTANCE_ABSOLUTE_URL'] = utils::GetAbsoluteUrlModulesRoot().$_ENV['PORTAL_ID'].'/';
$_ENV['COMBODO_PORTAL_INSTANCE_ABSOLUTE_URL'] = utils::GetAbsoluteUrlModulesRoot().$_ENV['PORTAL_ID'].'/';

View File

@@ -7,4 +7,4 @@ return static function (ContainerConfigurator $container) {
// kernel.secret
$container->parameters()->set('kernel.secret', MetaModel::GetConfig()->Get('application.secret'));
};
};

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*

View File

@@ -58,26 +58,25 @@ $oKPI->ComputeAndReport('Load portal lists definition');
// A dedicated listener 'CssFromSassCompiler' exists to compile files again when by-passing HTTP cache.
// This is to keep developers comfort when tuning the SCSS files.
$oKPI = new ExecutionKPI();
$aImportPaths = array($_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'].'css/');
$aImportPaths = [$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'].'css/'];
$aPortalConf = $container->getParameter('combodo.portal.instance.conf');
foreach ($aPortalConf['properties']['themes'] as $sKey => $value)
{
if (!is_array($value))
{
$aPortalConf['properties']['themes'][$sKey] = utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$value,
$aImportPaths);
}
else
{
$aValues = array();
foreach ($value as $sSubValue)
{
$aValues[] = utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$sSubValue,
$aImportPaths);
foreach ($aPortalConf['properties']['themes'] as $sKey => $value) {
if (!is_array($value)) {
$aPortalConf['properties']['themes'][$sKey] = utils::GetCSSFromSASS(
'env-'.utils::GetCurrentEnvironment().'/'.$value,
$aImportPaths
);
} else {
$aValues = [];
foreach ($value as $sSubValue) {
$aValues[] = utils::GetCSSFromSASS(
'env-'.utils::GetCurrentEnvironment().'/'.$sSubValue,
$aImportPaths
);
}
$aPortalConf['properties']['themes'][$sKey] = $aValues;
}
}
$oKPI->ComputeAndReport('Generating CSS files');
$container->setParameter('combodo.portal.instance.conf', $aPortalConf);
$container->setParameter('combodo.portal.instance.conf', $aPortalConf);

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -24,8 +25,7 @@ use Symfony\Component\Routing\Route;
$oRouteCollection = new RouteCollection();
$aRoutes = ItopExtensionsExtraRoutes::GetRoutes();
foreach ($aRoutes as $aRoute)
{
foreach ($aRoutes as $aRoute) {
$aRoute['values'] = (isset($aRoute['values'])) ? $aRoute['values'] : [];
$aRoute['asserts'] = (isset($aRoute['asserts'])) ? $aRoute['asserts'] : [];
@@ -42,4 +42,4 @@ foreach ($aRoutes as $aRoute)
);
}
return $oRouteCollection;
return $oRouteCollection;

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -45,4 +46,4 @@ return static function (ContainerConfigurator $oContainer) {
->autoconfigure();
}
};
};

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -26,7 +27,6 @@ require_once MODULESROOT.'itop-portal-base/portal/config/bootstrap.php';
$oContext = new ContextTag(ContextTag::TAG_PORTAL);
$oContext2 = new ContextTag('Portal:'.$_ENV['PORTAL_ID']);
$oKPI = new ExecutionKPI();
// Note: Manually refactored ternary condition to be PHP 5.x compatible
@@ -52,10 +52,8 @@ $oResponse = $oKernel->handle($oRequest);
$oResponse->send();
$oKPI->ComputeAndReport('Page execution and rendering');
$oKPI = new ExecutionKPI();
$oKernel->terminate($oRequest, $oResponse);
$oKPI->ComputeAndReport('Symfony kernel termination');
ExecutionKPI::ReportStats();
ExecutionKPI::ReportStats();

View File

@@ -43,34 +43,34 @@ use ModuleDesign;
abstract class AbstractBrick implements TemplatesProviderInterface
{
/** @var string ENUM_DATA_LOADING_LAZY */
const ENUM_DATA_LOADING_LAZY = 'lazy';
public const ENUM_DATA_LOADING_LAZY = 'lazy';
/** @var string ENUM_DATA_LOADING_FULL */
const ENUM_DATA_LOADING_FULL = 'full';
public const ENUM_DATA_LOADING_FULL = 'full';
/** @var string ENUM_DATA_LOADING_AUTO */
const ENUM_DATA_LOADING_AUTO = 'auto';
public const ENUM_DATA_LOADING_AUTO = 'auto';
/** @var bool DEFAULT_MANDATORY */
const DEFAULT_MANDATORY = true;
public const DEFAULT_MANDATORY = true;
/** @var bool DEFAULT_ACTIVE */
const DEFAULT_ACTIVE = true;
public const DEFAULT_ACTIVE = true;
/** @var bool DEFAULT_VISIBLE */
const DEFAULT_VISIBLE = true;
public const DEFAULT_VISIBLE = true;
/** @var float DEFAULT_RANK */
const DEFAULT_RANK = 1.0;
public const DEFAULT_RANK = 1.0;
/** @var string|null DEFAULT_PAGE_TEMPLATE_PATH @deprecated since 3.2.1 */
const DEFAULT_PAGE_TEMPLATE_PATH = null;
public const DEFAULT_PAGE_TEMPLATE_PATH = null;
/** @var string DEFAULT_TITLE */
const DEFAULT_TITLE = '';
public const DEFAULT_TITLE = '';
/** @var string|null DEFAULT_DESCRIPTION */
const DEFAULT_DESCRIPTION = null;
public const DEFAULT_DESCRIPTION = null;
/** @var string DEFAULT_DATA_LOADING */
const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_AUTO;
public const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_AUTO;
/** @var string DEFAULT_ALLOWED_PROFILES_OQL */
const DEFAULT_ALLOWED_PROFILES_OQL = '';
public const DEFAULT_ALLOWED_PROFILES_OQL = '';
/** @var string DEFAULT_DENIED_PROFILES_OQL */
const DEFAULT_DENIED_PROFILES_OQL = '';
public const DEFAULT_DENIED_PROFILES_OQL = '';
/** @var string TEMPLATES_BASE_PATH */
const TEMPLATES_BASE_PATH = 'itop-portal-base/portal/templates/bricks/';
public const TEMPLATES_BASE_PATH = 'itop-portal-base/portal/templates/bricks/';
/** @var string $sId */
protected $sId;
@@ -105,8 +105,9 @@ abstract class AbstractBrick implements TemplatesProviderInterface
/** @inheritdoc */
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
{
$oTemplatesRegister->RegisterTemplates(self::class,
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'layout.html.twig'),
$oTemplatesRegister->RegisterTemplates(
self::class,
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH.'layout.html.twig'),
);
}
@@ -135,9 +136,9 @@ abstract class AbstractBrick implements TemplatesProviderInterface
*
* @return array
*/
static function GetEnumDataLoadingValues()
public static function GetEnumDataLoadingValues()
{
return array(self::ENUM_DATA_LOADING_LAZY, self::ENUM_DATA_LOADING_FULL, self::ENUM_DATA_LOADING_AUTO);
return [self::ENUM_DATA_LOADING_LAZY, self::ENUM_DATA_LOADING_FULL, self::ENUM_DATA_LOADING_AUTO];
}
/**
@@ -155,8 +156,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
$this->sTitle = static::DEFAULT_TITLE;
$this->sDescription = static::DEFAULT_DESCRIPTION;
$this->sDataLoading = static::DEFAULT_DATA_LOADING;
$this->aAllowedProfiles = array();
$this->aDeniedProfiles = array();
$this->aAllowedProfiles = [];
$this->aDeniedProfiles = [];
$this->sAllowedProfilesOql = static::DEFAULT_ALLOWED_PROFILES_OQL;
$this->sDeniedProfilesOql = static::DEFAULT_DENIED_PROFILES_OQL;
}
@@ -297,8 +298,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
* Sets the brick id
*
* @param string $sId
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*/
public function SetId($sId)
{
@@ -310,8 +311,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
* Sets if the brick is mandatory
*
* @param boolean $bMandatory
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*/
public function SetMandatory($bMandatory)
{
@@ -336,8 +337,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
* Sets if the brick is active
*
* @param boolean $bActive
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*/
public function SetActive($bActive)
{
@@ -349,8 +350,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
* Sets the rank of the brick
*
* @param float $fRank
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*/
public function SetRank($fRank)
{
@@ -362,15 +363,15 @@ abstract class AbstractBrick implements TemplatesProviderInterface
* Sets the page template path of the brick
*
* @param string $sPageTemplatePath
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*
* @deprecated since 3.2.1 use SetTemplatePath('page') instead
*/
public function SetPageTemplatePath($sPageTemplatePath)
{
$this->sPageTemplatePath = $sPageTemplatePath;
$this->SetTemplatePath( 'page', $sPageTemplatePath);
$this->SetTemplatePath('page', $sPageTemplatePath);
return $this;
}
@@ -378,8 +379,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
* Sets the title of the brick
*
* @param string $sTitle
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*/
public function SetTitle($sTitle)
{
@@ -391,8 +392,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
* Sets the description of the brick
*
* @param string $sDescription
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*/
public function SetDescription($sDescription)
{
@@ -404,8 +405,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
* Sets the data loading mode of the brick
*
* @param string $sDataLoading
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*/
public function SetDataLoading($sDataLoading)
{
@@ -444,8 +445,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
* Sets the allowed profiles oql query for the brick
*
* @param string $sAllowedProfilesOql
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*/
public function SetAllowedProfilesOql($sAllowedProfilesOql)
{
@@ -457,8 +458,8 @@ abstract class AbstractBrick implements TemplatesProviderInterface
* Sets the denied profiles oql query for the brick
*
* @param string $sDeniedProfilesOql
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*
* @return \Combodo\iTop\Portal\Brick\AbstractBrick
*/
public function SetDeniedProfilesOql($sDeniedProfilesOql)
{
@@ -489,8 +490,7 @@ abstract class AbstractBrick implements TemplatesProviderInterface
*/
public function RemoveAllowedProfile($sProfile)
{
if (isset($this->aAllowedProfiles[$sProfile]))
{
if (isset($this->aAllowedProfiles[$sProfile])) {
unset($this->aAllowedProfiles[$sProfile]);
}
@@ -530,8 +530,7 @@ abstract class AbstractBrick implements TemplatesProviderInterface
*/
public function RemoveDeniedProfile($sProfile)
{
if (isset($this->aDeniedProfiles[$sProfile]))
{
if (isset($this->aDeniedProfiles[$sProfile])) {
unset($this->aDeniedProfiles[$sProfile]);
}
@@ -560,7 +559,7 @@ abstract class AbstractBrick implements TemplatesProviderInterface
*/
public function IsGrantedForProfile($sProfile)
{
return $this->IsGrantedForProfiles(array($sProfile));
return $this->IsGrantedForProfiles([$sProfile]);
}
/**
@@ -577,27 +576,21 @@ abstract class AbstractBrick implements TemplatesProviderInterface
{
$bGranted = true;
if ($this->HasAllowedProfiles())
{
if ($this->HasAllowedProfiles()) {
// We set $bGranted to false as the user must explicitly have an allowed profile to be granted
$bGranted = false;
foreach ($aProfiles as $sProfile)
{
if (in_array($sProfile, $this->aAllowedProfiles))
{
foreach ($aProfiles as $sProfile) {
if (in_array($sProfile, $this->aAllowedProfiles)) {
$bGranted = true;
break;
}
}
}
if ($this->HasDeniedProfiles())
{
foreach ($aProfiles as $sProfile)
{
if (in_array($sProfile, $this->aDeniedProfiles))
{
if ($this->HasDeniedProfiles()) {
foreach ($aProfiles as $sProfile) {
if (in_array($sProfile, $this->aDeniedProfiles)) {
$bGranted = false;
break;
}
@@ -629,18 +622,15 @@ abstract class AbstractBrick implements TemplatesProviderInterface
public function LoadFromXml(DesignElement $oMDElement)
{
// Checking mandatory elements
if (!$oMDElement->hasAttribute('id'))
{
if (!$oMDElement->hasAttribute('id')) {
throw new DOMFormatException('Brick node must have both id and xsi:type attributes defined', 0, null, $oMDElement);
}
$this->SetId($oMDElement->getAttribute('id'));
// Checking others elements
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
{
switch ($oBrickSubNode->nodeName)
{
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode) {
switch ($oBrickSubNode->nodeName) {
case 'mandatory':
$this->SetMandatory(($oBrickSubNode->GetText() === 'no') ? false : true);
break;
@@ -649,15 +639,13 @@ abstract class AbstractBrick implements TemplatesProviderInterface
break;
case 'rank':
$oOptionalNode = $oBrickSubNode->GetOptionalElement('default');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$this->SetRank((float)$oOptionalNode->GetText(static::DEFAULT_RANK));
}
break;
case 'templates':
$oTemplateNodeList = $oBrickSubNode->GetNodes('template[@id='.ModuleDesign::XPathQuote('page').']');
if ($oTemplateNodeList->length > 0)
{
if ($oTemplateNodeList->length > 0) {
/** @var \Combodo\iTop\DesignElement $oTemplateNode */
$oTemplateNode = $oTemplateNodeList->item(0);
$this->SetTemplatePath('page', $oTemplateNode->GetText(static::DEFAULT_PAGE_TEMPLATE_PATH));
@@ -665,8 +653,7 @@ abstract class AbstractBrick implements TemplatesProviderInterface
break;
case 'title':
$oOptionalNode = $oBrickSubNode->GetOptionalElement('default');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$this->SetTitle($oOptionalNode->GetText(static::DEFAULT_TITLE));
}
break;
@@ -678,16 +665,17 @@ abstract class AbstractBrick implements TemplatesProviderInterface
break;
case 'security':
/** @var \Combodo\iTop\DesignElement $oSecurityNode */
foreach ($oBrickSubNode->GetNodes('*') as $oSecurityNode)
{
if ($oSecurityNode->nodeType === XML_TEXT_NODE && $oSecurityNode->GetText() === '')
{
throw new DOMFormatException('Brick security node "'.$oSecurityNode->nodeName.'" must contain an OQL query, it cannot be empty',
null, null, $oMDElement);
foreach ($oBrickSubNode->GetNodes('*') as $oSecurityNode) {
if ($oSecurityNode->nodeType === XML_TEXT_NODE && $oSecurityNode->GetText() === '') {
throw new DOMFormatException(
'Brick security node "'.$oSecurityNode->nodeName.'" must contain an OQL query, it cannot be empty',
null,
null,
$oMDElement
);
}
switch ($oSecurityNode->nodeName)
{
switch ($oSecurityNode->nodeName) {
case 'denied_profiles':
$this->SetDeniedProfilesOql($oSecurityNode->GetText());
break;

View File

@@ -38,11 +38,11 @@ use DOMFormatException;
class AggregatePageBrick extends PortalBrick
{
// Overloaded constants
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-tachometer-alt';
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-tachometer-alt fa-2x';
public const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-tachometer-alt';
public const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-tachometer-alt fa-2x';
/** @var string @deprecated since 3.2.1 */
const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/aggregate-page/layout.html.twig';
public const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/aggregate-page/layout.html.twig';
// Overloaded variables
public static $sRouteName = 'p_aggregatepage_brick';
@@ -50,21 +50,22 @@ class AggregatePageBrick extends PortalBrick
/**
* @var string[] list of bricks to use, ordered by rank (key=id, value=rank)
*/
private $aAggregatePageBricks = array();
private $aAggregatePageBricks = [];
/** @inheritdoc */
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
{
parent::RegisterTemplates($oTemplatesRegister);
$oTemplatesRegister->RegisterTemplates(self::class,
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'aggregate-page/layout.html.twig')
$oTemplatesRegister->RegisterTemplates(
self::class,
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH.'aggregate-page/layout.html.twig')
);
}
/**
* AggregatePageBrick constructor.
*/
function __construct()
public function __construct()
{
parent::__construct();
@@ -83,25 +84,24 @@ class AggregatePageBrick extends PortalBrick
parent::LoadFromXml($oMDElement);
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
{
switch ($oBrickSubNode->nodeName)
{
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode) {
switch ($oBrickSubNode->nodeName) {
case 'aggregate_page_bricks':
/** @var \Combodo\iTop\DesignElement $oAggregatePageBrickNode */
foreach ($oBrickSubNode->GetNodes('./aggregate_page_brick') as $oAggregatePageBrickNode)
{
if (!$oAggregatePageBrickNode->hasAttribute('id'))
{
throw new DOMFormatException('AggregatePageBrick : must have an id attribute', 0,
null, $oAggregatePageBrickNode);
foreach ($oBrickSubNode->GetNodes('./aggregate_page_brick') as $oAggregatePageBrickNode) {
if (!$oAggregatePageBrickNode->hasAttribute('id')) {
throw new DOMFormatException(
'AggregatePageBrick : must have an id attribute',
0,
null,
$oAggregatePageBrickNode
);
}
$sBrickName = $oAggregatePageBrickNode->getAttribute('id');
$iBrickRank = static::DEFAULT_RANK;
$oOptionalNode = $oAggregatePageBrickNode->GetOptionalElement('rank');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$iBrickRank = $oOptionalNode->GetText();
}
@@ -123,5 +123,4 @@ class AggregatePageBrick extends PortalBrick
return $this->aAggregatePageBricks;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -67,8 +68,8 @@ class BrickCollection
$this->aAllowedBricks = null;
$this->iDisplayedInHome = 0;
$this->iDisplayedInNavigationMenu = 0;
$this->aHomeOrdering = array();
$this->aNavigationMenuOrdering = array();
$this->aHomeOrdering = [];
$this->aNavigationMenuOrdering = [];
$this->Load();
}
@@ -84,8 +85,7 @@ class BrickCollection
public function __call($method, $arguments)
{
// Made for cleaner/easier access from twig (eg. app['brick_collection'].bricks)
switch ($method)
{
switch ($method) {
case 'bricks':
return $this->GetBricks();
break;
@@ -128,10 +128,8 @@ class BrickCollection
*/
public function GetBrickById($sId)
{
foreach ($this->GetBricks() as $oBrick)
{
if ($oBrick->GetId() === $sId)
{
foreach ($this->GetBricks() as $oBrick) {
if ($oBrick->GetId() === $sId) {
return $oBrick;
}
}
@@ -146,19 +144,15 @@ class BrickCollection
{
$aRawBrickList = $this->GetRawBrickList();
foreach ($aRawBrickList as $oBrick)
{
foreach ($aRawBrickList as $oBrick) {
ApplicationHelper::LoadBrickSecurity($oBrick);
if ($oBrick->GetActive() && $oBrick->IsGrantedForProfiles(UserRights::ListProfiles()))
{
if ($oBrick->GetActive() && $oBrick->IsGrantedForProfiles(UserRights::ListProfiles())) {
$this->aAllowedBricks[] = $oBrick;
if ($oBrick->GetVisibleHome())
{
if ($oBrick->GetVisibleHome()) {
$this->iDisplayedInHome++;
}
if ($oBrick->GetVisibleNavigationMenu())
{
if ($oBrick->GetVisibleNavigationMenu()) {
$this->iDisplayedInNavigationMenu++;
}
}
@@ -191,35 +185,30 @@ class BrickCollection
*/
private function GetRawBrickList()
{
$aBricks = array();
$aBricks = [];
/** @var \Combodo\iTop\DesignElement $oBrickNode */
foreach ($this->oModuleDesign->GetNodes('/module_design/bricks/brick') as $oBrickNode)
{
foreach ($this->oModuleDesign->GetNodes('/module_design/bricks/brick') as $oBrickNode) {
$sBrickClass = $oBrickNode->getAttribute('xsi:type');
try
{
if (class_exists($sBrickClass))
{
try {
if (class_exists($sBrickClass)) {
/** @var \Combodo\iTop\Portal\Brick\PortalBrick $oBrick */
$oBrick = new $sBrickClass();
// Load the brick specific properties from its XML definition
$oBrick->LoadFromXml($oBrickNode);
$aBricks[] = $oBrick;
} else {
throw new DOMFormatException(
'Unknown brick class "'.$sBrickClass.'" from xsi:type attribute',
null,
null,
$oBrickNode
);
}
else
{
throw new DOMFormatException('Unknown brick class "'.$sBrickClass.'" from xsi:type attribute', null,
null, $oBrickNode);
}
}
catch (DOMFormatException $e)
{
} catch (DOMFormatException $e) {
throw new Exception('Could not create brick ('.$sBrickClass.') from XML because of a DOM problem : '.$e->getMessage());
}
catch (Exception $e)
{
} catch (Exception $e) {
throw new Exception('Could not create brick ('.$sBrickClass.') from XML : '.$oBrickNode->Dump().' '.$e->getMessage());
}
}
@@ -227,4 +216,4 @@ class BrickCollection
return $aBricks;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -30,5 +31,4 @@ use Exception;
*/
class BrickNotFoundException extends Exception
{
}
}

View File

@@ -35,77 +35,76 @@ use DOMFormatException;
class BrowseBrick extends PortalBrick
{
/**
* @var string DEFAULT_PAGE_TEMPLATE_PATH
* @var string DEFAULT_PAGE_TEMPLATE_PATH
* @deprecated 3.2.1
*/
const DEFAULT_MODE_LIST_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_list.html.twig';
public const DEFAULT_MODE_LIST_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_list.html.twig';
/**
* @var string DEFAULT_MODE_MOSAIC_TEMPLATE_PATH
* @deprecated 3.2.1
*/
const DEFAULT_MODE_MOSAIC_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_mosaic.html.twig';
public const DEFAULT_MODE_MOSAIC_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_mosaic.html.twig';
/**
* @var string DEFAULT_MODE_TREE_TEMPLATE_PATH
* @deprecated 3.2.1
*/
const DEFAULT_MODE_TREE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_tree.html.twig';
public const DEFAULT_MODE_TREE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/browse/mode_tree.html.twig';
/** @var string ENUM_BROWSE_MODE_LIST */
const ENUM_BROWSE_MODE_LIST = 'list';
public const ENUM_BROWSE_MODE_LIST = 'list';
/** @var string ENUM_BROWSE_MODE_TREE */
const ENUM_BROWSE_MODE_TREE = 'tree';
public const ENUM_BROWSE_MODE_TREE = 'tree';
/** @var string ENUM_BROWSE_MODE_MOSAIC */
const ENUM_BROWSE_MODE_MOSAIC = 'mosaic';
public const ENUM_BROWSE_MODE_MOSAIC = 'mosaic';
/** @var string ENUM_ACTION_VIEW */
const ENUM_ACTION_VIEW = 'view';
public const ENUM_ACTION_VIEW = 'view';
/** @var string ENUM_ACTION_EDIT */
const ENUM_ACTION_EDIT = 'edit';
public const ENUM_ACTION_EDIT = 'edit';
/** @var string ENUM_ACTION_DRILLDOWN */
const ENUM_ACTION_DRILLDOWN = 'drilldown';
public const ENUM_ACTION_DRILLDOWN = 'drilldown';
/** @var string ENUM_ACTION_CREATE_FROM_THIS */
const ENUM_ACTION_CREATE_FROM_THIS = 'create_from_this';
public const ENUM_ACTION_CREATE_FROM_THIS = 'create_from_this';
/** @var string ENUM_ACTION_ICON_CLASS_VIEW */
const ENUM_ACTION_ICON_CLASS_VIEW = 'glyphicon glyphicon-list-alt';
public const ENUM_ACTION_ICON_CLASS_VIEW = 'glyphicon glyphicon-list-alt';
/** @var string ENUM_ACTION_ICON_CLASS_EDIT */
const ENUM_ACTION_ICON_CLASS_EDIT = 'glyphicon glyphicon-pencil';
public const ENUM_ACTION_ICON_CLASS_EDIT = 'glyphicon glyphicon-pencil';
/** @var string ENUM_ACTION_ICON_CLASS_DRILLDOWN */
const ENUM_ACTION_ICON_CLASS_DRILLDOWN = 'glyphicon glyphicon-menu-down';
public const ENUM_ACTION_ICON_CLASS_DRILLDOWN = 'glyphicon glyphicon-menu-down';
/** @var string ENUM_ACTION_ICON_CLASS_CREATE_FROM_THIS */
const ENUM_ACTION_ICON_CLASS_CREATE_FROM_THIS = 'glyphicon glyphicon-edit';
public const ENUM_ACTION_ICON_CLASS_CREATE_FROM_THIS = 'glyphicon glyphicon-edit';
/** @var string ENUM_FACTORY_TYPE_METHOD */
const ENUM_FACTORY_TYPE_METHOD = 'method';
public const ENUM_FACTORY_TYPE_METHOD = 'method';
/** @var string ENUM_FACTORY_TYPE_CLASS */
const ENUM_FACTORY_TYPE_CLASS = 'class';
public const ENUM_FACTORY_TYPE_CLASS = 'class';
// Overloaded constants
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-map';
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-map fa-2x';
const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_FULL;
public const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-map';
public const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-map fa-2x';
public const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_FULL;
/** @var string DEFAULT_LEVEL_NAME_ATT */
const DEFAULT_LEVEL_NAME_ATT = 'name';
public const DEFAULT_LEVEL_NAME_ATT = 'name';
/** @var string DEFAULT_BROWSE_MODE */
const DEFAULT_BROWSE_MODE = self::ENUM_BROWSE_MODE_LIST;
public const DEFAULT_BROWSE_MODE = self::ENUM_BROWSE_MODE_LIST;
/** @var string DEFAULT_ACTION */
const DEFAULT_ACTION = self::ENUM_ACTION_DRILLDOWN;
public const DEFAULT_ACTION = self::ENUM_ACTION_DRILLDOWN;
/** @var string DEFAULT_ACTION_OPENING_TARGET */
const DEFAULT_ACTION_OPENING_TARGET = self::ENUM_OPENING_TARGET_MODAL;
public const DEFAULT_ACTION_OPENING_TARGET = self::ENUM_OPENING_TARGET_MODAL;
/** @var int DEFAULT_LIST_LENGTH */
const DEFAULT_LIST_LENGTH = 20;
public const DEFAULT_LIST_LENGTH = 20;
// Overloaded variables
public static $sRouteName = 'p_browse_brick';
/** @var array $aBrowseModes */
public static $aBrowseModes = array(
public static $aBrowseModes = [
self::ENUM_BROWSE_MODE_LIST,
self::ENUM_BROWSE_MODE_TREE,
self::ENUM_BROWSE_MODE_MOSAIC,
);
];
/** @var array $aLevels */
protected $aLevels;
@@ -120,11 +119,12 @@ class BrowseBrick extends PortalBrick
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
{
parent::RegisterTemplates($oTemplatesRegister);
$oTemplatesRegister->RegisterTemplates(self::class,
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'browse/layout.html.twig'),
TemplateDefinitionDto::Create('page_list', static::TEMPLATES_BASE_PATH . 'browse/mode_list.html.twig'),
TemplateDefinitionDto::Create('page_tree', static::TEMPLATES_BASE_PATH . 'browse/mode_tree.html.twig'),
TemplateDefinitionDto::Create('page_mosaic', static::TEMPLATES_BASE_PATH . 'browse/mode_mosaic.html.twig'),
$oTemplatesRegister->RegisterTemplates(
self::class,
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH.'browse/layout.html.twig'),
TemplateDefinitionDto::Create('page_list', static::TEMPLATES_BASE_PATH.'browse/mode_list.html.twig'),
TemplateDefinitionDto::Create('page_tree', static::TEMPLATES_BASE_PATH.'browse/mode_tree.html.twig'),
TemplateDefinitionDto::Create('page_mosaic', static::TEMPLATES_BASE_PATH.'browse/mode_mosaic.html.twig'),
);
}
@@ -135,15 +135,15 @@ class BrowseBrick extends PortalBrick
{
parent::__construct();
$this->aLevels = array();
$this->aAvailablesBrowseModes = array();
$this->aLevels = [];
$this->aAvailablesBrowseModes = [];
$this->sDefaultBrowseMode = static::DEFAULT_BROWSE_MODE;
$this->iDefaultListLength = static::DEFAULT_LIST_LENGTH;
}
/**
* Compare function to sort actions by their rank attribute
*
*
* @param array $aAction1
* @param array $aAction2
*
@@ -154,13 +154,10 @@ class BrowseBrick extends PortalBrick
$bIsAction1RankSet = array_key_exists('rank', $aAction1);
$bIsAction2RankSet = array_key_exists('rank', $aAction2);
if($bIsAction1RankSet && $bIsAction2RankSet)
{
//If a1 == a2 return 0, if a1 > a2 return 1 else return -1
if ($bIsAction1RankSet && $bIsAction2RankSet) {
//If a1 == a2 return 0, if a1 > a2 return 1 else return -1
return ($aAction1['rank'] === $aAction2['rank'] ? $aAction1['default_rank'] - $aAction2['default_rank'] : $aAction1['rank'] - $aAction2['rank']);
}
else
{
} else {
//If a1 == a2 == null return 0, if a2 is null and not a1 return 1 else return -1
return ($bIsAction1RankSet === $bIsAction2RankSet ? $aAction1['default_rank'] - $aAction2['default_rank'] : ($bIsAction1RankSet ? 1 : -1));
}
@@ -255,7 +252,8 @@ class BrowseBrick extends PortalBrick
*
* @return $this
*/
public function SetDefaultListLength($iDefaultListLength) {
public function SetDefaultListLength($iDefaultListLength)
{
$this->iDefaultListLength = $iDefaultListLength;
return $this;
}
@@ -293,8 +291,7 @@ class BrowseBrick extends PortalBrick
*/
public function RemoveLevels($sLevel)
{
if (isset($this->aLevels[$sLevel]))
{
if (isset($this->aLevels[$sLevel])) {
unset($this->aLevels[$sLevel]);
}
@@ -309,7 +306,7 @@ class BrowseBrick extends PortalBrick
*
* @return \Combodo\iTop\Portal\Brick\BrowseBrick
*/
public function AddAvailableBrowseMode($sModeId, $aData = array())
public function AddAvailableBrowseMode($sModeId, $aData = [])
{
$this->aAvailablesBrowseModes[$sModeId] = $aData;
@@ -325,8 +322,7 @@ class BrowseBrick extends PortalBrick
*/
public function RemoveAvailableBrowseMode($sModeId)
{
if (isset($this->aAvailablesBrowseModes[$sModeId]))
{
if (isset($this->aAvailablesBrowseModes[$sModeId])) {
unset($this->aAvailablesBrowseModes[$sModeId]);
}
@@ -349,43 +345,38 @@ class BrowseBrick extends PortalBrick
// Checking specific elements
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
{
switch ($oBrickSubNode->nodeName)
{
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode) {
switch ($oBrickSubNode->nodeName) {
case 'levels':
/** @var \Combodo\iTop\DesignElement $oLevelNode */
foreach ($oBrickSubNode->GetNodes('*') as $oLevelNode)
{
if ($oLevelNode->nodeName === 'level')
{
foreach ($oBrickSubNode->GetNodes('*') as $oLevelNode) {
if ($oLevelNode->nodeName === 'level') {
$this->AddLevel($this->LoadLevelFromXml($oLevelNode));
}
}
break;
case 'browse_modes':
/** @var \Combodo\iTop\DesignElement $oBrowseModeNode */
foreach ($oBrickSubNode->GetNodes('*') as $oBrowseModeNode)
{
switch ($oBrowseModeNode->nodeName)
{
foreach ($oBrickSubNode->GetNodes('*') as $oBrowseModeNode) {
switch ($oBrowseModeNode->nodeName) {
case 'availables':
/** @var \Combodo\iTop\DesignElement $oModeNode */
foreach ($oBrowseModeNode->GetNodes('*') as $oModeNode)
{
if (!$oModeNode->hasAttribute('id'))
{
throw new DOMFormatException('BrowseBrick: Browse mode must have a unique ID attribute', 0,
null, $oModeNode);
foreach ($oBrowseModeNode->GetNodes('*') as $oModeNode) {
if (!$oModeNode->hasAttribute('id')) {
throw new DOMFormatException(
'BrowseBrick: Browse mode must have a unique ID attribute',
0,
null,
$oModeNode
);
}
$sModeId = $oModeNode->getAttribute('id');
$aModeData = array();
$aModeData = [];
// Checking if the browse mode has a specific template
$oTemplateNode = $oModeNode->GetOptionalElement('template');
if (($oTemplateNode !== null) && ($oTemplateNode->GetText() !== null))
{
if (($oTemplateNode !== null) && ($oTemplateNode->GetText() !== null)) {
$this->SetTemplatePath('page_'.$sModeId, $oTemplateNode->GetText());
}
@@ -400,12 +391,12 @@ class BrowseBrick extends PortalBrick
break;
case 'default_list_length':
$iNodeDefaultListLength = (int)$oBrickSubNode->GetText(static::DEFAULT_LIST_LENGTH);
if(!in_array($iNodeDefaultListLength, array(10, 20, 50, -1),true))
{
if (!in_array($iNodeDefaultListLength, [10, 20, 50, -1], true)) {
throw new DOMFormatException(
'BrowseBrick: Default list length must be contained in list length options. Expected -1/10/20/50, '.$iNodeDefaultListLength.' given.',
null,
null, $oBrickSubNode
null,
$oBrickSubNode
);
}
$this->SetDefaultListLength($iNodeDefaultListLength);
@@ -414,19 +405,18 @@ class BrowseBrick extends PortalBrick
}
// Checking that the brick has at least a browse mode
if (count($this->GetAvailablesBrowseModes()) === 0)
{
if (count($this->GetAvailablesBrowseModes()) === 0) {
throw new DOMFormatException('BrowseBrick : Must have at least one browse mode', 0, null, $oMDElement);
}
// Checking that default browse mode in among the available
if (!in_array($this->sDefaultBrowseMode, array_keys($this->aAvailablesBrowseModes)))
{
throw new DOMFormatException('BrowseBrick : Default browse mode "'.$this->sDefaultBrowseMode.'" must be one of the available browse modes ('.implode(', ',
$this->aAvailablesBrowseModes).')', null, null, $oMDElement);
if (!in_array($this->sDefaultBrowseMode, array_keys($this->aAvailablesBrowseModes))) {
throw new DOMFormatException('BrowseBrick : Default browse mode "'.$this->sDefaultBrowseMode.'" must be one of the available browse modes ('.implode(
', ',
$this->aAvailablesBrowseModes
).')', null, null, $oMDElement);
}
// Checking that the brick has at least a level
if (count($this->GetLevels()) === 0)
{
if (count($this->GetLevels()) === 0) {
throw new DOMFormatException('BrowseBrick : Must have at least one level', 0, null, $oMDElement);
}
@@ -444,39 +434,41 @@ class BrowseBrick extends PortalBrick
*/
protected function LoadLevelFromXml(DesignElement $oMDElement)
{
$aLevel = array(
$aLevel = [
'parent_att' => null,
'tooltip_att' => null,
'description_att' => null,
'image_att' => null,
'title' => null,
'name_att' => static::DEFAULT_LEVEL_NAME_ATT,
'fields' => array(),
'actions' => array('default' => array('type' => static::DEFAULT_ACTION, 'rules' => array())),
);
'fields' => [],
'actions' => ['default' => ['type' => static::DEFAULT_ACTION, 'rules' => []]],
];
// Getting level ID
if ($oMDElement->hasAttribute('id') && $oMDElement->getAttribute('id') !== '')
{
if ($oMDElement->hasAttribute('id') && $oMDElement->getAttribute('id') !== '') {
$aLevel['id'] = $oMDElement->getAttribute('id');
}
else
{
throw new DOMFormatException('BrowseBrick : level tag without "id" attribute. It must have one and it must not be empty', null,
null, $oMDElement);
} else {
throw new DOMFormatException(
'BrowseBrick : level tag without "id" attribute. It must have one and it must not be empty',
null,
null,
$oMDElement
);
}
// Getting level properties
/** @var \Combodo\iTop\DesignElement $oLevelPropertyNode */
foreach ($oMDElement->GetNodes('*') as $oLevelPropertyNode)
{
switch ($oLevelPropertyNode->nodeName)
{
foreach ($oMDElement->GetNodes('*') as $oLevelPropertyNode) {
switch ($oLevelPropertyNode->nodeName) {
case 'class':
$sClass = $oLevelPropertyNode->GetText();
if ($sClass === '')
{
throw new DOMFormatException('BrowseBrick : class tag is empty. Must contain Classname', null, null,
$oLevelPropertyNode);
if ($sClass === '') {
throw new DOMFormatException(
'BrowseBrick : class tag is empty. Must contain Classname',
null,
null,
$oLevelPropertyNode
);
}
$aLevel['oql'] = 'SELECT '.$sClass;
@@ -484,10 +476,13 @@ class BrowseBrick extends PortalBrick
case 'oql':
$sOql = $oLevelPropertyNode->GetText();
if ($sOql === '')
{
throw new DOMFormatException('BrowseBrick : oql tag is empty. Must contain OQL statement', null, null,
$oLevelPropertyNode);
if ($sOql === '') {
throw new DOMFormatException(
'BrowseBrick : oql tag is empty. Must contain OQL statement',
null,
null,
$oLevelPropertyNode
);
}
$aLevel['oql'] = $sOql;
@@ -508,25 +503,23 @@ class BrowseBrick extends PortalBrick
case 'fields':
$sTagName = $oLevelPropertyNode->nodeName;
if ($oLevelPropertyNode->hasChildNodes())
{
$aLevel[$sTagName] = array();
if ($oLevelPropertyNode->hasChildNodes()) {
$aLevel[$sTagName] = [];
/** @var \Combodo\iTop\DesignElement $oFieldNode */
foreach ($oLevelPropertyNode->GetNodes('*') as $oFieldNode)
{
if ($oFieldNode->hasAttribute('id') && $oFieldNode->getAttribute('id') !== '')
{
$aLevel[$sTagName][$oFieldNode->getAttribute('id')] = array('hidden' => false);
}
else
{
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/* tag must have an "id" attribute and it must not be empty',
null, null, $oFieldNode);
foreach ($oLevelPropertyNode->GetNodes('*') as $oFieldNode) {
if ($oFieldNode->hasAttribute('id') && $oFieldNode->getAttribute('id') !== '') {
$aLevel[$sTagName][$oFieldNode->getAttribute('id')] = ['hidden' => false];
} else {
throw new DOMFormatException(
'BrowseBrick : '.$sTagName.'/* tag must have an "id" attribute and it must not be empty',
null,
null,
$oFieldNode
);
}
$oFieldSubNode = $oFieldNode->GetOptionalElement('hidden');
if ($oFieldSubNode !== null)
{
if ($oFieldSubNode !== null) {
$aLevel[$sTagName][$oFieldNode->getAttribute('id')]['hidden'] = ($oFieldSubNode->GetText() === 'true') ? true : false;
}
}
@@ -536,94 +529,84 @@ class BrowseBrick extends PortalBrick
case 'actions':
$sTagName = $oLevelPropertyNode->nodeName;
if ($oLevelPropertyNode->hasChildNodes())
{
$aLevel[$sTagName] = array();
if ($oLevelPropertyNode->hasChildNodes()) {
$aLevel[$sTagName] = [];
$iActionDefaultRank = 0;
/** @var \Combodo\iTop\DesignElement $oActionNode */
foreach ($oLevelPropertyNode->GetNodes('*') as $oActionNode)
{
if ($oActionNode->hasAttribute('id') && $oActionNode->getAttribute('id') !== '')
{
$aTmpAction = array(
foreach ($oLevelPropertyNode->GetNodes('*') as $oActionNode) {
if ($oActionNode->hasAttribute('id') && $oActionNode->getAttribute('id') !== '') {
$aTmpAction = [
'type' => null,
'rules' => array(),
);
'rules' => [],
];
// Action type
$aTmpAction['type'] = ($oActionNode->hasAttribute('xsi:type') && $oActionNode->getAttribute('xsi:type') !== '') ? $oActionNode->getAttribute('xsi:type') : static::DEFAULT_ACTION;
// Action destination class
if ($aTmpAction['type'] === static::ENUM_ACTION_CREATE_FROM_THIS)
{
if ($oActionNode->GetOptionalElement('factory_method') !== null)
{
$aTmpAction['factory'] = array(
if ($aTmpAction['type'] === static::ENUM_ACTION_CREATE_FROM_THIS) {
if ($oActionNode->GetOptionalElement('factory_method') !== null) {
$aTmpAction['factory'] = [
'type' => static::ENUM_FACTORY_TYPE_METHOD,
'value' => $oActionNode->GetOptionalElement('factory_method')->GetText(),
);
}
else
{
$aTmpAction['factory'] = array(
];
} else {
$aTmpAction['factory'] = [
'type' => static::ENUM_FACTORY_TYPE_CLASS,
'value' => $oActionNode->GetUniqueElement('class')->GetText(),
);
];
}
}
// Action title
$oActionTitleNode = $oActionNode->GetOptionalElement('title');
if ($oActionTitleNode !== null)
{
if ($oActionTitleNode !== null) {
$aTmpAction['title'] = $oActionTitleNode->GetText();
}
// Action icon class
$oActionIconClassNode = $oActionNode->GetOptionalElement('icon_class');
if ($oActionIconClassNode !== null)
{
if ($oActionIconClassNode !== null) {
$aTmpAction['icon_class'] = $oActionIconClassNode->GetText();
}
// Action opening target
$oActionOpeningTargetNode = $oActionNode->GetOptionalElement('opening_target');
if ($oActionOpeningTargetNode !== null)
{
if ($oActionOpeningTargetNode !== null) {
$aTmpAction['opening_target'] = $oActionOpeningTargetNode->GetText(static::DEFAULT_ACTION_OPENING_TARGET);
}
else
{
} else {
$aTmpAction['opening_target'] = static::DEFAULT_ACTION_OPENING_TARGET;
}
// - Checking that opening target is among authorized modes
if (!in_array($aTmpAction['opening_target'], static::$aOpeningTargets))
{
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/action/opening_target has a wrong value. "'.$aTmpAction['opening_target'].'" given, '.implode('|',
static::$aOpeningTargets).' expected.', null, null, $oActionOpeningTargetNode);
if (!in_array($aTmpAction['opening_target'], static::$aOpeningTargets)) {
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/action/opening_target has a wrong value. "'.$aTmpAction['opening_target'].'" given, '.implode(
'|',
static::$aOpeningTargets
).' expected.', null, null, $oActionOpeningTargetNode);
}
$oActionRankNode = $oActionNode->GetOptionalElement('rank');
if ($oActionRankNode !== null)
{
if ($oActionRankNode !== null) {
$aTmpAction['rank'] = (int)$oActionRankNode->GetText();
}
// Action rules
/** @var \Combodo\iTop\DesignElement $oRuleNode */
foreach ($oActionNode->GetNodes('./rules/rule') as $oRuleNode)
{
if ($oRuleNode->hasAttribute('id') && $oRuleNode->getAttribute('id') !== '')
{
foreach ($oActionNode->GetNodes('./rules/rule') as $oRuleNode) {
if ($oRuleNode->hasAttribute('id') && $oRuleNode->getAttribute('id') !== '') {
$aTmpAction['rules'][] = $oRuleNode->getAttribute('id');
}
else
{
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/rules/rule tag must have an "id" attribute and it must not be empty',
null, null, $oRuleNode);
} else {
throw new DOMFormatException(
'BrowseBrick : '.$sTagName.'/rules/rule tag must have an "id" attribute and it must not be empty',
null,
null,
$oRuleNode
);
}
}
$aTmpAction['default_rank'] = $iActionDefaultRank++;
$aLevel[$sTagName][$oActionNode->getAttribute('id')] = $aTmpAction;
}
else
{
throw new DOMFormatException('BrowseBrick : '.$sTagName.'/* tag must have an "id" attribute and it must not be empty',
null, null, $oActionNode);
} else {
throw new DOMFormatException(
'BrowseBrick : '.$sTagName.'/* tag must have an "id" attribute and it must not be empty',
null,
null,
$oActionNode
);
}
}
uasort($aLevel[$sTagName], [$this, 'CompareActionsByRank']);
@@ -631,10 +614,8 @@ class BrowseBrick extends PortalBrick
break;
case 'levels':
foreach ($oLevelPropertyNode->GetNodes('*') as $oSubLevelNode)
{
if ($oSubLevelNode->nodeName === 'level')
{
foreach ($oLevelPropertyNode->GetNodes('*') as $oSubLevelNode) {
if ($oSubLevelNode->nodeName === 'level') {
$aLevel['levels'][] = $this->LoadLevelFromXml($oSubLevelNode);
}
}
@@ -644,8 +625,7 @@ class BrowseBrick extends PortalBrick
}
// Checking if level has an oql
if (!isset($aLevel['oql']) || $aLevel['oql'] === '')
{
if (!isset($aLevel['oql']) || $aLevel['oql'] === '') {
throw new DOMFormatException('BrowseBrick : must have a valid <class|oql> tag', null, null, $oMDElement);
}

View File

@@ -35,10 +35,10 @@ use DOMFormatException;
class CreateBrick extends PortalBrick
{
// Overloaded constants
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-plus';
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-plus fa-2x';
public const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-plus';
public const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-plus fa-2x';
/** @var string DEFAULT_CLASS */
const DEFAULT_CLASS = '';
public const DEFAULT_CLASS = '';
// Overloaded variables
public static $sRouteName = 'p_create_brick';
@@ -48,14 +48,15 @@ class CreateBrick extends PortalBrick
/** @var array $aRules */
protected $aRules;
const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/create/modal.html.twig';
public const DEFAULT_PAGE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/create/modal.html.twig';
/** @inheritdoc */
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
{
parent::RegisterTemplates($oTemplatesRegister);
$oTemplatesRegister->RegisterTemplates(self::class,
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'create/modal.html.twig')
$oTemplatesRegister->RegisterTemplates(
self::class,
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH.'create/modal.html.twig')
);
}
@@ -67,7 +68,7 @@ class CreateBrick extends PortalBrick
parent::__construct();
$this->sClass = static::DEFAULT_CLASS;
$this->aRules = array();
$this->aRules = [];
}
/**
@@ -134,26 +135,24 @@ class CreateBrick extends PortalBrick
// Checking specific elements
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
{
switch ($oBrickSubNode->nodeName)
{
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode) {
switch ($oBrickSubNode->nodeName) {
case 'class':
$this->SetClass($oBrickSubNode->GetText(self::DEFAULT_CLASS));
break;
case 'rules':
/** @var \Combodo\iTop\DesignElement $oRuleNode */
foreach ($oBrickSubNode->GetNodes('*') as $oRuleNode)
{
if ($oRuleNode->hasAttribute('id') && $oRuleNode->getAttribute('id') !== '')
{
foreach ($oBrickSubNode->GetNodes('*') as $oRuleNode) {
if ($oRuleNode->hasAttribute('id') && $oRuleNode->getAttribute('id') !== '') {
$this->aRules[] = $oRuleNode->getAttribute('id');
}
else
{
throw new DOMFormatException('CreateBrick: /rules/rule tag must have an "id" attribute and it must not be empty',
null, null, $oRuleNode);
} else {
throw new DOMFormatException(
'CreateBrick: /rules/rule tag must have an "id" attribute and it must not be empty',
null,
null,
$oRuleNode
);
}
}
break;

View File

@@ -35,21 +35,21 @@ use DOMFormatException;
class FilterBrick extends PortalBrick
{
// Overloaded constants
const DEFAULT_VISIBLE_NAVIGATION_MENU = false;
/**
* @deprecated 3.2.1
*/
const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/filter/tile.html.twig';
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-search';
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-search fa-2x';
/** @var string DEFAULT_TARGET_BRICK_CLASS */
const DEFAULT_TARGET_BRICK_CLASS = 'Combodo\\iTop\\Portal\\Brick\\BrowseBrick';
public const DEFAULT_VISIBLE_NAVIGATION_MENU = false;
/**
* @deprecated 3.2.1
*/
public const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/filter/tile.html.twig';
public const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-search';
public const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-search fa-2x';
/** @var string DEFAULT_TARGET_BRICK_CLASS */
public const DEFAULT_TARGET_BRICK_CLASS = 'Combodo\\iTop\\Portal\\Brick\\BrowseBrick';
/** @var string DEFAULT_SEARCH_PLACEHOLDER_VALUE */
const DEFAULT_SEARCH_PLACEHOLDER_VALUE = 'Brick:Portal:Filter:SearchInput:Placeholder';
public const DEFAULT_SEARCH_PLACEHOLDER_VALUE = 'Brick:Portal:Filter:SearchInput:Placeholder';
/** @var string DEFAULT_SEARCH_SUBMIT_LABEL */
const DEFAULT_SEARCH_SUBMIT_LABEL = 'Brick:Portal:Filter:SearchInput:Submit';
public const DEFAULT_SEARCH_SUBMIT_LABEL = 'Brick:Portal:Filter:SearchInput:Submit';
/** @var string DEFAULT_SEARCH_SUBMIT_CLASS */
const DEFAULT_SEARCH_SUBMIT_CLASS = '';
public const DEFAULT_SEARCH_SUBMIT_CLASS = '';
/** @var string $sTargetBrickId */
protected $sTargetBrickId;
@@ -68,8 +68,9 @@ class FilterBrick extends PortalBrick
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
{
parent::RegisterTemplates($oTemplatesRegister);
$oTemplatesRegister->RegisterTemplates(self::class,
TemplateDefinitionDto::Create('tile', static::TEMPLATES_BASE_PATH . 'filter/tile.html.twig')
$oTemplatesRegister->RegisterTemplates(
self::class,
TemplateDefinitionDto::Create('tile', static::TEMPLATES_BASE_PATH.'filter/tile.html.twig')
);
}
@@ -98,9 +99,9 @@ class FilterBrick extends PortalBrick
* @return string
*/
public function GetTargetBrickClass()
{
return $this->sTargetBrickClass;
}
{
return $this->sTargetBrickClass;
}
/**
* @return string
@@ -149,9 +150,9 @@ class FilterBrick extends PortalBrick
* @param string $sTargetBrickClass
*/
public function SetTargetBrickClass($sTargetBrickClass)
{
$this->sTargetBrickClass = $sTargetBrickClass;
}
{
$this->sTargetBrickClass = $sTargetBrickClass;
}
/**
* @param string $sTargetBrickTab
@@ -197,38 +198,34 @@ class FilterBrick extends PortalBrick
return $this;
}
/**
* Load the brick's data from the xml passed as a ModuleDesignElement.
* This is used to set all the brick attributes at once.
*
* @param \Combodo\iTop\DesignElement $oMDElement
*
* @return \Combodo\iTop\Portal\Brick\FilterBrick
*
* @throws \DOMFormatException
*/
/**
* Load the brick's data from the xml passed as a ModuleDesignElement.
* This is used to set all the brick attributes at once.
*
* @param \Combodo\iTop\DesignElement $oMDElement
*
* @return \Combodo\iTop\Portal\Brick\FilterBrick
*
* @throws \DOMFormatException
*/
public function LoadFromXml(DesignElement $oMDElement)
{
parent::LoadFromXml($oMDElement);
// Checking specific elements
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
{
switch ($oBrickSubNode->nodeName)
{
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode) {
switch ($oBrickSubNode->nodeName) {
case 'target_brick':
/** @var \Combodo\iTop\DesignElement $oTargetBrickNode */
foreach ($oBrickSubNode->GetNodes('*') as $oTargetBrickNode)
{
switch ($oTargetBrickNode->nodeName)
{
case 'id':
$this->SetTargetBrickId($oTargetBrickNode->GetText());
break;
case 'type':
$this->SetTargetBrickClass($oTargetBrickNode->GetText());
break;
foreach ($oBrickSubNode->GetNodes('*') as $oTargetBrickNode) {
switch ($oTargetBrickNode->nodeName) {
case 'id':
$this->SetTargetBrickId($oTargetBrickNode->GetText());
break;
case 'type':
$this->SetTargetBrickClass($oTargetBrickNode->GetText());
break;
case 'tab':
$this->SetTargetBrickTab($oTargetBrickNode->GetText());
break;
@@ -236,12 +233,12 @@ class FilterBrick extends PortalBrick
}
break;
case 'search_placeholder_value':
// Note: We don't put the default value constant if the node is empty because we might actually want this to be empty
// Note: We don't put the default value constant if the node is empty because we might actually want this to be empty
$this->SetSearchPlaceholderValue($oBrickSubNode->GetText(''));
break;
case 'search_submit_label':
// Note: We don't put the default value constant if the node is empty because we might actually want this to be empty
$this->SetSearchSubmitLabel($oBrickSubNode->GetText(''));
// Note: We don't put the default value constant if the node is empty because we might actually want this to be empty
$this->SetSearchSubmitLabel($oBrickSubNode->GetText(''));
break;
case 'search_submit_class':
$this->SetSearchSubmitClass($oBrickSubNode->GetText(static::DEFAULT_SEARCH_SUBMIT_CLASS));
@@ -250,8 +247,7 @@ class FilterBrick extends PortalBrick
}
// Checking that the brick has at least a target brick id
if (($this->GetTargetBrickId() === null) || ($this->GetTargetBrickId() === ''))
{
if (($this->GetTargetBrickId() === null) || ($this->GetTargetBrickId() === '')) {
throw new DOMFormatException('FilterBrick : Must have a target brick id', 0, null, $oMDElement);
}

View File

@@ -32,126 +32,126 @@ use ModuleDesign;
class ManageBrick extends PortalBrick
{
/** @var string ENUM_ACTION_VIEW */
const ENUM_ACTION_VIEW = 'view';
public const ENUM_ACTION_VIEW = 'view';
/** @var string ENUM_ACTION_EDIT */
const ENUM_ACTION_EDIT = 'edit';
public const ENUM_ACTION_EDIT = 'edit';
/** @var string ENUM_TILE_MODE_TEXT */
const ENUM_TILE_MODE_TEXT = 'text';
public const ENUM_TILE_MODE_TEXT = 'text';
/** @var string ENUM_TILE_MODE_BADGE */
const ENUM_TILE_MODE_BADGE = 'badge';
public const ENUM_TILE_MODE_BADGE = 'badge';
/** @var string ENUM_TILE_MODE_PIE */
const ENUM_TILE_MODE_PIE = 'pie-chart';
public const ENUM_TILE_MODE_PIE = 'pie-chart';
/** @var string ENUM_TILE_MODE_BAR */
const ENUM_TILE_MODE_BAR = 'bar-chart';
public const ENUM_TILE_MODE_BAR = 'bar-chart';
/** @var string ENUM_TILE_MODE_TOP */
const ENUM_TILE_MODE_TOP = 'top-list';
public const ENUM_TILE_MODE_TOP = 'top-list';
/** @var string ENUM_DISPLAY_MODE_LIST */
const ENUM_DISPLAY_MODE_LIST = 'list';
public const ENUM_DISPLAY_MODE_LIST = 'list';
/** @var string ENUM_DISPLAY_MODE_PIE */
const ENUM_DISPLAY_MODE_PIE = 'pie-chart';
public const ENUM_DISPLAY_MODE_PIE = 'pie-chart';
/** @var string ENUM_DISPLAY_MODE_BAR */
const ENUM_DISPLAY_MODE_BAR = 'bar-chart';
public const ENUM_DISPLAY_MODE_BAR = 'bar-chart';
/** @var string ENUM_PAGE_TEMPLATE_PATH_TABLE
* @deprecated since 3.2.1
* */
const ENUM_PAGE_TEMPLATE_PATH_TABLE = 'itop-portal-base/portal/templates/bricks/manage/layout-table.html.twig';
public const ENUM_PAGE_TEMPLATE_PATH_TABLE = 'itop-portal-base/portal/templates/bricks/manage/layout-table.html.twig';
/** @var string ENUM_PAGE_TEMPLATE_PATH_CHART
* @deprecated since 3.2.1
* */
const ENUM_PAGE_TEMPLATE_PATH_CHART = 'itop-portal-base/portal/templates/bricks/manage/layout-chart.html.twig';
public const ENUM_PAGE_TEMPLATE_PATH_CHART = 'itop-portal-base/portal/templates/bricks/manage/layout-chart.html.twig';
/** Overloaded constants */
const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-pen-square';
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-pen-square fa-2x';
public const DEFAULT_DECORATION_CLASS_HOME = 'fas fa-pen-square';
public const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'fas fa-pen-square fa-2x';
/**
* @deprecated 3.2.1
*/
const DEFAULT_PAGE_TEMPLATE_PATH = self::ENUM_PAGE_TEMPLATE_PATH_TABLE;
const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_LAZY;
public const DEFAULT_PAGE_TEMPLATE_PATH = self::ENUM_PAGE_TEMPLATE_PATH_TABLE;
public const DEFAULT_DATA_LOADING = self::ENUM_DATA_LOADING_LAZY;
/**
* @deprecated 3.2.1
*/
const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/manage/tile-default.html.twig';
const DEFAULT_TILE_CONTROLLER_ACTION = 'Combodo\\iTop\\Portal\\Controller\\ManageBrickController::TileAction';
public const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/manage/tile-default.html.twig';
public const DEFAULT_TILE_CONTROLLER_ACTION = 'Combodo\\iTop\\Portal\\Controller\\ManageBrickController::TileAction';
/** @var string DEFAULT_OQL */
const DEFAULT_OQL = '';
public const DEFAULT_OQL = '';
/** @var string DEFAULT_OPENING_MODE */
const DEFAULT_OPENING_MODE = self::ENUM_ACTION_EDIT;
public const DEFAULT_OPENING_MODE = self::ENUM_ACTION_EDIT;
/** @var int DEFAULT_LIST_LENGTH */
const DEFAULT_LIST_LENGTH = 20;
public const DEFAULT_LIST_LENGTH = 20;
/** @var string DEFAULT_ZLIST_FIELDS */
const DEFAULT_ZLIST_FIELDS = 'list';
public const DEFAULT_ZLIST_FIELDS = 'list';
/** @var bool DEFAULT_SHOW_TAB_COUNTS */
const DEFAULT_SHOW_TAB_COUNTS = false;
public const DEFAULT_SHOW_TAB_COUNTS = false;
/** @var string DEFAULT_DISPLAY_MODE */
const DEFAULT_DISPLAY_MODE = self::ENUM_DISPLAY_MODE_LIST;
public const DEFAULT_DISPLAY_MODE = self::ENUM_DISPLAY_MODE_LIST;
/** @var string DEFAULT_TILE_MODE */
const DEFAULT_TILE_MODE = self::ENUM_TILE_MODE_TEXT;
public const DEFAULT_TILE_MODE = self::ENUM_TILE_MODE_TEXT;
/** @var int DEFAULT_GROUP_LIMIT */
const DEFAULT_GROUP_LIMIT = 0;
public const DEFAULT_GROUP_LIMIT = 0;
/** @var bool DEFAULT_GROUP_SHOW_OTHERS */
const DEFAULT_GROUP_SHOW_OTHERS = true;
public const DEFAULT_GROUP_SHOW_OTHERS = true;
/** @var array $aDisplayModes */
public static array $aDisplayModes = array(
public static array $aDisplayModes = [
self::ENUM_DISPLAY_MODE_LIST,
self::ENUM_DISPLAY_MODE_PIE,
self::ENUM_DISPLAY_MODE_BAR,
);
];
/** @var array $aTileModes */
public static array $aTileModes = array(
public static array $aTileModes = [
self::ENUM_TILE_MODE_TEXT,
self::ENUM_TILE_MODE_BADGE,
self::ENUM_TILE_MODE_PIE,
self::ENUM_TILE_MODE_BAR,
self::ENUM_TILE_MODE_TOP,
);
];
/** @var array $aPresentationData
* @deprecated since 3.2.1
*/
public static $aPresentationData = array(
self::ENUM_TILE_MODE_BADGE => array(
public static $aPresentationData = [
self::ENUM_TILE_MODE_BADGE => [
'decorationCssClass' => 'fas fa-id-card fa-2x',
'tileTemplate' => 'itop-portal-base/portal/templates/bricks/manage/tile-badge.html.twig',
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_TABLE,
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_LIST,
'need_details' => true,
),
self::ENUM_TILE_MODE_TOP => array(
],
self::ENUM_TILE_MODE_TOP => [
'decorationCssClass' => 'fas fa-signal fa-rotate-270 fa-2x',
'tileTemplate' => 'itop-portal-base/portal/templates/bricks/manage/tile-top-list.html.twig',
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_TABLE,
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_LIST,
'need_details' => true,
),
self::ENUM_TILE_MODE_PIE => array(
],
self::ENUM_TILE_MODE_PIE => [
'decorationCssClass' => 'fas fa-chart-pie fa-2x',
'tileTemplate' => 'itop-portal-base/portal/templates/bricks/manage/tile-chart.html.twig',
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_CHART,
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_PIE,
'need_details' => false,
),
self::ENUM_TILE_MODE_BAR => array(
],
self::ENUM_TILE_MODE_BAR => [
'decorationCssClass' => 'fas fa-chart-bar fa-2x',
'tileTemplate' => 'itop-portal-base/portal/templates/bricks/manage/tile-chart.html.twig',
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_CHART,
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_BAR,
'need_details' => false,
),
self::ENUM_TILE_MODE_TEXT => array(
],
self::ENUM_TILE_MODE_TEXT => [
'decorationCssClass' => 'fas fa-pen-square fa-2x',
'tileTemplate' => self::DEFAULT_TILE_TEMPLATE_PATH,
'layoutTemplate' => self::ENUM_PAGE_TEMPLATE_PATH_TABLE,
'layoutDisplayMode' => self::ENUM_DISPLAY_MODE_LIST,
'need_details' => true,
),
);
],
];
/** @var array $aDefaultTileData */
private static array $aDefaultTileData = [
@@ -201,7 +201,7 @@ class ManageBrick extends PortalBrick
/** @var bool $bShowTabCounts */
protected $bShowTabCounts;
/** @var array $aAvailableDisplayModes */
protected $aAvailableDisplayModes = array();
protected $aAvailableDisplayModes = [];
/** @var string $sDefaultDisplayMode */
protected $sDefaultDisplayMode;
/** @var string $sTileMode */
@@ -217,16 +217,17 @@ class ManageBrick extends PortalBrick
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
{
parent::RegisterTemplates($oTemplatesRegister);
$oTemplatesRegister->RegisterTemplates(self::class,
TemplateDefinitionDto::Create('tile', static::TEMPLATES_BASE_PATH . 'manage/tile-default.html.twig'),
TemplateDefinitionDto::Create('tile_badge', static::TEMPLATES_BASE_PATH. 'manage/tile-badge.html.twig'),
TemplateDefinitionDto::Create('tile_chart', static::TEMPLATES_BASE_PATH . 'manage/tile-chart.html.twig'),
TemplateDefinitionDto::Create('tile_top_list', static::TEMPLATES_BASE_PATH . 'manage/tile-top-list.html.twig'),
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'manage/layout.html.twig'),
TemplateDefinitionDto::Create('page_table', static::TEMPLATES_BASE_PATH . 'manage/layout-table.html.twig'),
TemplateDefinitionDto::Create('page_chart', static::TEMPLATES_BASE_PATH . 'manage/layout-chart.html.twig'),
TemplateDefinitionDto::Create('mode_chart_bar', static::TEMPLATES_BASE_PATH . 'manage/mode-bar-chart.html.twig', true, self::ENUM_DISPLAY_MODE_BAR),
TemplateDefinitionDto::Create('mode_chart_pie', static::TEMPLATES_BASE_PATH . 'manage/mode-pie-chart.html.twig', true,self::ENUM_DISPLAY_MODE_PIE),
$oTemplatesRegister->RegisterTemplates(
self::class,
TemplateDefinitionDto::Create('tile', static::TEMPLATES_BASE_PATH.'manage/tile-default.html.twig'),
TemplateDefinitionDto::Create('tile_badge', static::TEMPLATES_BASE_PATH.'manage/tile-badge.html.twig'),
TemplateDefinitionDto::Create('tile_chart', static::TEMPLATES_BASE_PATH.'manage/tile-chart.html.twig'),
TemplateDefinitionDto::Create('tile_top_list', static::TEMPLATES_BASE_PATH.'manage/tile-top-list.html.twig'),
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH.'manage/layout.html.twig'),
TemplateDefinitionDto::Create('page_table', static::TEMPLATES_BASE_PATH.'manage/layout-table.html.twig'),
TemplateDefinitionDto::Create('page_chart', static::TEMPLATES_BASE_PATH.'manage/layout-chart.html.twig'),
TemplateDefinitionDto::Create('mode_chart_bar', static::TEMPLATES_BASE_PATH.'manage/mode-bar-chart.html.twig', true, self::ENUM_DISPLAY_MODE_BAR),
TemplateDefinitionDto::Create('mode_chart_pie', static::TEMPLATES_BASE_PATH.'manage/mode-pie-chart.html.twig', true, self::ENUM_DISPLAY_MODE_PIE),
);
}
@@ -239,9 +240,9 @@ class ManageBrick extends PortalBrick
$this->sOql = static::DEFAULT_OQL;
$this->sOpeningMode = static::DEFAULT_OPENING_MODE;
$this->aGrouping = array();
$this->aFields = array();
$this->aExportFields = array();
$this->aGrouping = [];
$this->aFields = [];
$this->aExportFields = [];
$this->bShowTabCounts = static::DEFAULT_SHOW_TAB_COUNTS;
$this->sDefaultDisplayMode = static::DEFAULT_DISPLAY_MODE;
@@ -251,7 +252,7 @@ class ManageBrick extends PortalBrick
$this->iDefaultListLength = static::DEFAULT_LIST_LENGTH;
// This is hardcoded for now, we might allow area grouping on another attribute in the future
$this->AddGrouping('areas', array('attribute' => 'finalclass'));
$this->AddGrouping('areas', ['attribute' => 'finalclass']);
}
/**
@@ -263,13 +264,11 @@ class ManageBrick extends PortalBrick
*
* @return bool
*/
static public function AreDetailsNeededForDisplayMode($sDisplayMode)
public static function AreDetailsNeededForDisplayMode($sDisplayMode)
{
$bNeedDetails = false;
foreach (static::$aPresentationData as $aData)
{
if ($aData['layoutDisplayMode'] === $sDisplayMode)
{
foreach (static::$aPresentationData as $aData) {
if ($aData['layoutDisplayMode'] === $sDisplayMode) {
$bNeedDetails = $aData['need_details'];
break;
}
@@ -278,7 +277,6 @@ class ManageBrick extends PortalBrick
return $bNeedDetails;
}
/**
* Returns if the $sLayoutMode need objects details for rendering.
*
@@ -301,13 +299,11 @@ class ManageBrick extends PortalBrick
* @param string $sDisplayMode
* @return string
*/
static public function GetPageTemplateFromDisplayMode($sDisplayMode)
public static function GetPageTemplateFromDisplayMode($sDisplayMode)
{
$sTemplate = static::DEFAULT_PAGE_TEMPLATE_PATH;
foreach (static::$aPresentationData as $aData)
{
if ($aData['layoutDisplayMode'] === $sDisplayMode)
{
foreach (static::$aPresentationData as $aData) {
if ($aData['layoutDisplayMode'] === $sDisplayMode) {
$sTemplate = $aData['layoutTemplate'];
break;
}
@@ -484,8 +480,7 @@ class ManageBrick extends PortalBrick
*/
public function GetPresentationDataForTileMode($sTileMode)
{
if (isset(static::$aPresentationData[$sTileMode]))
{
if (isset(static::$aPresentationData[$sTileMode])) {
return static::$aPresentationData[$sTileMode];
}
@@ -580,7 +575,7 @@ class ManageBrick extends PortalBrick
/**
* Returns the default lists length to display
*
*
* @return int
*/
public function GetDefaultListLength()
@@ -590,12 +585,13 @@ class ManageBrick extends PortalBrick
/**
* Sets the default lists length to display
*
*
* @param int $iDefaultListLength
*
*
* @return $this
*/
public function SetDefaultListLength($iDefaultListLength) {
public function SetDefaultListLength($iDefaultListLength)
{
$this->iDefaultListLength = $iDefaultListLength;
return $this;
}
@@ -615,8 +611,7 @@ class ManageBrick extends PortalBrick
$this->aGrouping[$sName] = $aGrouping;
// Sorting
if (!$this->IsGroupingByDistinctValues($sName))
{
if (!$this->IsGroupingByDistinctValues($sName)) {
usort($this->aGrouping[$sName]['groups'], function ($a, $b) {
if ($a['rank'] === $b['rank']) {
return 0;
@@ -638,8 +633,7 @@ class ManageBrick extends PortalBrick
*/
public function RemoveGrouping($sName)
{
if (isset($this->aGrouping[$sName]))
{
if (isset($this->aGrouping[$sName])) {
unset($this->aGrouping[$sName]);
}
@@ -655,8 +649,7 @@ class ManageBrick extends PortalBrick
*/
public function AddField($sAttCode)
{
if (!in_array($sAttCode, $this->aFields))
{
if (!in_array($sAttCode, $this->aFields)) {
$this->aFields[] = $sAttCode;
}
@@ -672,8 +665,7 @@ class ManageBrick extends PortalBrick
*/
public function RemoveField($sAttCode)
{
if (isset($this->aFields[$sAttCode]))
{
if (isset($this->aFields[$sAttCode])) {
unset($this->aFields[$sAttCode]);
}
@@ -682,8 +674,7 @@ class ManageBrick extends PortalBrick
public function AddExportField($sAttCode)
{
if (!in_array($sAttCode, $this->aExportFields))
{
if (!in_array($sAttCode, $this->aExportFields)) {
$this->aExportFields[] = $sAttCode;
}
@@ -692,8 +683,7 @@ class ManageBrick extends PortalBrick
public function RemoveExportField($sAttCode)
{
if (isset($this->aExportFields[$sAttCode]))
{
if (isset($this->aExportFields[$sAttCode])) {
unset($this->aExportFields[$sAttCode]);
}
@@ -749,10 +739,11 @@ class ManageBrick extends PortalBrick
*/
public function AddAvailableDisplayMode($sModeId)
{
if (!in_array($sModeId, static::$aDisplayModes))
{
throw new Exception('ManageBrick: Display mode "'.$sModeId.'" must be one of the allowed display modes ('.implode(', ',
static::$aDisplayModes).')');
if (!in_array($sModeId, static::$aDisplayModes)) {
throw new Exception('ManageBrick: Display mode "'.$sModeId.'" must be one of the allowed display modes ('.implode(
', ',
static::$aDisplayModes
).')');
}
$this->aAvailableDisplayModes[] = $sModeId;
@@ -769,8 +760,7 @@ class ManageBrick extends PortalBrick
*/
public function RemoveAvailableDisplayMode($sModeId)
{
if (isset($this->aAvailableDisplayModes[$sModeId]))
{
if (isset($this->aAvailableDisplayModes[$sModeId])) {
unset($this->aAvailableDisplayModes[$sModeId]);
}
@@ -843,16 +833,17 @@ class ManageBrick extends PortalBrick
// Checking specific elements
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
{
switch ($oBrickSubNode->nodeName)
{
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode) {
switch ($oBrickSubNode->nodeName) {
case 'class':
$sClass = $oBrickSubNode->GetText();
if ($sClass === '')
{
throw new DOMFormatException('ManageBrick: class tag is empty. Must contain Classname', null,
null, $oBrickSubNode);
if ($sClass === '') {
throw new DOMFormatException(
'ManageBrick: class tag is empty. Must contain Classname',
null,
null,
$oBrickSubNode
);
}
$this->SetOql('SELECT '.$sClass);
@@ -860,10 +851,13 @@ class ManageBrick extends PortalBrick
case 'oql':
$sOql = $oBrickSubNode->GetText();
if ($sOql === '')
{
throw new DOMFormatException('ManageBrick: oql tag is empty. Must contain OQL statement', null,
null, $oBrickSubNode);
if ($sOql === '') {
throw new DOMFormatException(
'ManageBrick: oql tag is empty. Must contain OQL statement',
null,
null,
$oBrickSubNode
);
}
$this->SetOql($sOql);
@@ -871,10 +865,13 @@ class ManageBrick extends PortalBrick
case 'opening_mode':
$sOpeningMode = $oBrickSubNode->GetText(static::DEFAULT_OPENING_MODE);
if (!in_array($sOpeningMode, array(static::ENUM_ACTION_VIEW, static::ENUM_ACTION_EDIT)))
{
throw new DOMFormatException('ManageBrick: opening_mode tag value must be edit|view ("'.$sOpeningMode.'" given)',
null, null, $oBrickSubNode);
if (!in_array($sOpeningMode, [static::ENUM_ACTION_VIEW, static::ENUM_ACTION_EDIT])) {
throw new DOMFormatException(
'ManageBrick: opening_mode tag value must be edit|view ("'.$sOpeningMode.'" given)',
null,
null,
$oBrickSubNode
);
}
$this->SetOpeningMode($sOpeningMode);
@@ -882,26 +879,31 @@ class ManageBrick extends PortalBrick
case 'display_modes':
/** @var \Combodo\iTop\DesignElement $oDisplayNode */
foreach ($oBrickSubNode->GetNodes('./*') as $oDisplayNode)
{
switch ($oDisplayNode->nodeName)
{
case 'availables';
foreach ($oBrickSubNode->GetNodes('./*') as $oDisplayNode) {
switch ($oDisplayNode->nodeName) {
case 'availables':
/** @var \Combodo\iTop\DesignElement $oModeNode */
foreach ($oDisplayNode->GetNodes('*') as $oModeNode)
{
if (!$oModeNode->hasAttribute('id'))
{
throw new DOMFormatException('ManageBrick: Display mode must have a unique ID attribute',
0, null, $oModeNode);
foreach ($oDisplayNode->GetNodes('*') as $oModeNode) {
if (!$oModeNode->hasAttribute('id')) {
throw new DOMFormatException(
'ManageBrick: Display mode must have a unique ID attribute',
0,
null,
$oModeNode
);
}
$sModeId = $oModeNode->getAttribute('id');
if (!in_array($sModeId, static::$aDisplayModes))
{
throw new DOMFormatException('ManageBrick: Display mode has an invalid value. Expected '.implode('/',
static::$aDisplayModes.', "'.$sModeId.'" given.'),
null, null, $oModeNode);
if (!in_array($sModeId, static::$aDisplayModes)) {
throw new DOMFormatException(
'ManageBrick: Display mode has an invalid value. Expected '.implode(
'/',
static::$aDisplayModes.', "'.$sModeId.'" given.'
),
null,
null,
$oModeNode
);
}
$this->AddAvailableDisplayMode($sModeId);
@@ -912,9 +914,9 @@ class ManageBrick extends PortalBrick
$this->SetDefaultDisplayMode($oDisplayNode->GetText(static::DEFAULT_DISPLAY_MODE));
break;
case 'tile';
case 'tile':
$this->SetTileMode($oDisplayNode->GetText(static::DEFAULT_TILE_MODE));
if($this->sDecorationClassHome === static::DEFAULT_DECORATION_CLASS_HOME){
if ($this->sDecorationClassHome === static::DEFAULT_DECORATION_CLASS_HOME) {
$this->sDecorationClassHome = static::$aDefaultTileData[$this->GetTileMode()]['decorationCssClass'];
$this->SetDecorationClassNavigationMenu(static::$aDefaultTileData[$this->GetTileMode()]['decorationCssClass']);
$this->SetDecorationClassHome(static::$aDefaultTileData[$this->GetTileMode()]['decorationCssClass']);
@@ -926,12 +928,14 @@ class ManageBrick extends PortalBrick
case 'fields':
/** @var \Combodo\iTop\DesignElement $oFieldNode */
foreach ($oBrickSubNode->GetNodes('./field') as $oFieldNode)
{
if (!$oFieldNode->hasAttribute('id'))
{
throw new DOMFormatException('ManageBrick : Field must have a unique ID attribute', 0,
null, $oFieldNode);
foreach ($oBrickSubNode->GetNodes('./field') as $oFieldNode) {
if (!$oFieldNode->hasAttribute('id')) {
throw new DOMFormatException(
'ManageBrick : Field must have a unique ID attribute',
0,
null,
$oFieldNode
);
}
$this->AddField($oFieldNode->getAttribute('id'));
}
@@ -939,19 +943,18 @@ class ManageBrick extends PortalBrick
case 'export':
/** @var \Combodo\iTop\DesignElement $oExportNode */
foreach ($oBrickSubNode->GetNodes('./*') as $oExportNode)
{
switch ($oExportNode->nodeName)
{
foreach ($oBrickSubNode->GetNodes('./*') as $oExportNode) {
switch ($oExportNode->nodeName) {
case 'fields':
/** @var \Combodo\iTop\DesignElement $oFieldNode */
foreach ($oExportNode->GetNodes('./field') as $oFieldNode)
{
if (!$oFieldNode->hasAttribute('id'))
{
throw new DOMFormatException('ManageBrick : Field must have a unique ID attribute',
foreach ($oExportNode->GetNodes('./field') as $oFieldNode) {
if (!$oFieldNode->hasAttribute('id')) {
throw new DOMFormatException(
'ManageBrick : Field must have a unique ID attribute',
0,
null, $oFieldNode);
null,
$oFieldNode
);
}
$this->AddExportField($oFieldNode->getAttribute('id'));
}
@@ -966,12 +969,12 @@ class ManageBrick extends PortalBrick
break;
case 'default_list_length':
$iNodeDefaultListLength = (int)$oBrickSubNode->GetText(static::DEFAULT_LIST_LENGTH);
if(!in_array($iNodeDefaultListLength, array(10, 20, 50, -1),true))
{
if (!in_array($iNodeDefaultListLength, [10, 20, 50, -1], true)) {
throw new DOMFormatException(
'ManageBrick : Default list length must be contained in list length options. Expected -1/10/20/50, '.$iNodeDefaultListLength.' given.',
null,
null, $oBrickSubNode
null,
$oBrickSubNode
);
}
$this->SetDefaultListLength($iNodeDefaultListLength);
@@ -979,25 +982,21 @@ class ManageBrick extends PortalBrick
case 'grouping':
// Tabs grouping
/** @var \Combodo\iTop\DesignElement $oGroupingNode */
foreach ($oBrickSubNode->GetNodes('./tabs/*') as $oGroupingNode)
{
switch ($oGroupingNode->nodeName)
{
case 'show_tab_counts';
foreach ($oBrickSubNode->GetNodes('./tabs/*') as $oGroupingNode) {
switch ($oGroupingNode->nodeName) {
case 'show_tab_counts':
$bShowTabCounts = ($oGroupingNode->GetText(static::DEFAULT_SHOW_TAB_COUNTS) === 'true') ? true : false;
$this->SetShowTabCounts($bShowTabCounts);
break;
case 'attribute':
$sAttribute = $oGroupingNode->GetText();
if ($sAttribute !== '')
{
$this->AddGrouping('tabs', array('attribute' => $sAttribute));
if ($sAttribute !== '') {
$this->AddGrouping('tabs', ['attribute' => $sAttribute]);
}
break;
case 'limit':
$iLimit = $oGroupingNode->GetText();
if (is_numeric($iLimit))
{
if (is_numeric($iLimit)) {
$this->iGroupLimit = $iLimit;
}
break;
@@ -1005,24 +1004,24 @@ class ManageBrick extends PortalBrick
$this->bGroupShowOthers = ($oGroupingNode->GetText() === 'true') ? true : false;
break;
case 'groups':
$aGroups = array();
$aGroups = [];
/** @var \Combodo\iTop\DesignElement $oGroupNode */
foreach ($oGroupingNode->GetNodes('./group') as $oGroupNode)
{
if (!$oGroupNode->hasAttribute('id'))
{
throw new DOMFormatException('ManageBrick : Group must have a unique ID attribute',
0, null, $oGroupNode);
foreach ($oGroupingNode->GetNodes('./group') as $oGroupNode) {
if (!$oGroupNode->hasAttribute('id')) {
throw new DOMFormatException(
'ManageBrick : Group must have a unique ID attribute',
0,
null,
$oGroupNode
);
}
$sGroupId = $oGroupNode->getAttribute('id');
$aGroup = array();
$aGroup = [];
$aGroup['id'] = $sGroupId; // We don't put the group id as the $aGroups key because the array will be sorted later in AddGrouping, which replace array keys by integer ordered keys
/** @var \Combodo\iTop\DesignElement $oGroupProperty */
foreach ($oGroupNode->GetNodes('*') as $oGroupProperty)
{
switch ($oGroupProperty->nodeName)
{
foreach ($oGroupNode->GetNodes('*') as $oGroupProperty) {
switch ($oGroupProperty->nodeName) {
case 'rank':
$aGroup[$oGroupProperty->nodeName] = (int)$oGroupProperty->GetText(0);
break;
@@ -1035,19 +1034,25 @@ class ManageBrick extends PortalBrick
}
// Checking constitancy
if (!isset($aGroup['title']) || $aGroup['title'] === '')
{
throw new DOMFormatException('ManageBrick : Group must have a title tag and it must not be empty',
0, null, $oGroupNode);
if (!isset($aGroup['title']) || $aGroup['title'] === '') {
throw new DOMFormatException(
'ManageBrick : Group must have a title tag and it must not be empty',
0,
null,
$oGroupNode
);
}
if (!isset($aGroup['condition']) || $aGroup['condition'] === '')
{
throw new DOMFormatException('ManageBrick : Group must have a condition tag and it must not be empty',
0, null, $oGroupNode);
if (!isset($aGroup['condition']) || $aGroup['condition'] === '') {
throw new DOMFormatException(
'ManageBrick : Group must have a condition tag and it must not be empty',
0,
null,
$oGroupNode
);
}
$aGroups[] = $aGroup;
}
$this->AddGrouping('tabs', array('groups' => $aGroups));
$this->AddGrouping('tabs', ['groups' => $aGroups]);
break;
}
}
@@ -1069,62 +1074,58 @@ class ManageBrick extends PortalBrick
}
// Checking if has an oql
if ($this->GetOql() === '')
{
if ($this->GetOql() === '') {
throw new DOMFormatException('ManageBrick: must have a valid <class|oql> tag', null, null, $oMDElement);
}
// Checking that the brick has at least a display mode
if (count($this->GetAvailablesDisplayModes()) === 0)
{
if (count($this->GetAvailablesDisplayModes()) === 0) {
$this->AddAvailableDisplayMode(static::DEFAULT_DISPLAY_MODE);
}
// Checking that default display mode in among the availables
if (!in_array($this->sDefaultDisplayMode, $this->aAvailableDisplayModes))
{
throw new DOMFormatException('ManageBrick: Default display mode "'.$this->sDefaultDisplayMode.'" must be one of the available display modes ('.implode(', ',
$this->aAvailableDisplayModes).')', null, null, $oMDElement);
if (!in_array($this->sDefaultDisplayMode, $this->aAvailableDisplayModes)) {
throw new DOMFormatException('ManageBrick: Default display mode "'.$this->sDefaultDisplayMode.'" must be one of the available display modes ('.implode(
', ',
$this->aAvailableDisplayModes
).')', null, null, $oMDElement);
}
// Checking that tile mode in among the availables
if (!in_array($this->sTileMode, static::$aTileModes))
{
throw new DOMFormatException('ManageBrick: Tile mode "'.$this->sTileMode.'" must be one of the allowed tile modes ('.implode(', ',
static::$aTileModes).')', null, null, $oMDElement);
if (!in_array($this->sTileMode, static::$aTileModes)) {
throw new DOMFormatException('ManageBrick: Tile mode "'.$this->sTileMode.'" must be one of the allowed tile modes ('.implode(
', ',
static::$aTileModes
).')', null, null, $oMDElement);
}
// Checking if specified fields, if not we put those from the details zlist
if (empty($this->aFields))
{
if (empty($this->aFields)) {
$sClass = DBSearch::FromOQL($this->GetOql());
$aFields = MetaModel::FlattenZList(MetaModel::GetZListItems($sClass->GetClass(),
static::DEFAULT_ZLIST_FIELDS));
$aFields = MetaModel::FlattenZList(MetaModel::GetZListItems(
$sClass->GetClass(),
static::DEFAULT_ZLIST_FIELDS
));
$this->SetFields($aFields);
}
// Default Export Fields
if ($bUseListFieldsForExport)
{
foreach ($this->GetFields() as $sAttCode)
{
if ($bUseListFieldsForExport) {
foreach ($this->GetFields() as $sAttCode) {
$this->AddExportField($sAttCode);
}
}
// Checking the navigation icon
$sDecorationClassNavigationMenu = $this->GetDecorationClassNavigationMenu();
if (empty($sDecorationClassNavigationMenu) && isset(static::$aDefaultTileData[$this->sTileMode]))
{
if (empty($sDecorationClassNavigationMenu) && isset(static::$aDefaultTileData[$this->sTileMode])) {
/** @var string $sDecorationClassNavigationMenu */
$sDecorationClassNavigationMenu = static::$aDefaultTileData[$this->sTileMode]['decorationCssClass'];
if (!empty($sDecorationClassNavigationMenu))
{
if (!empty($sDecorationClassNavigationMenu)) {
$this->SetDecorationClassNavigationMenu($sDecorationClassNavigationMenu);
}
}
$sTitle = $this->GetTitleHome();
if (empty($sTitle))
{
if (empty($sTitle)) {
$sOql = $this->GetOql();
$oSearch = DBSearch::FromOQL($sOql);
$sClassName = MetaModel::GetName($oSearch->GetClass());

View File

@@ -38,37 +38,37 @@ use ModuleDesign;
abstract class PortalBrick extends AbstractBrick
{
/** @var string ENUM_OPENING_TARGET_MODAL */
const ENUM_OPENING_TARGET_MODAL = 'modal';
public const ENUM_OPENING_TARGET_MODAL = 'modal';
/** @var string ENUM_OPENING_TARGET_SELF */
const ENUM_OPENING_TARGET_SELF = 'self';
public const ENUM_OPENING_TARGET_SELF = 'self';
/** @var string ENUM_OPENING_TARGET_NEW */
const ENUM_OPENING_TARGET_NEW = 'new';
public const ENUM_OPENING_TARGET_NEW = 'new';
/** @var int DEFAULT_WIDTH */
const DEFAULT_WIDTH = 6;
public const DEFAULT_WIDTH = 6;
/** @var int DEFAULT_HEIGHT */
const DEFAULT_HEIGHT = 1;
public const DEFAULT_HEIGHT = 1;
/** @var bool DEFAULT_MODAL */
const DEFAULT_MODAL = false;
public const DEFAULT_MODAL = false;
/** @var bool DEFAULT_VISIBLE_HOME */
const DEFAULT_VISIBLE_HOME = true;
public const DEFAULT_VISIBLE_HOME = true;
/** @var bool DEFAULT_VISIBLE_NAVIGATION_MENU */
const DEFAULT_VISIBLE_NAVIGATION_MENU = true;
public const DEFAULT_VISIBLE_NAVIGATION_MENU = true;
/** @var string DEFAULT_DECORATION_CLASS_HOME */
const DEFAULT_DECORATION_CLASS_HOME = '';
public const DEFAULT_DECORATION_CLASS_HOME = '';
/** @var string DEFAULT_DECORATION_CLASS_NAVIGATION_MENU */
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = '';
public const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = '';
/** @var string DEFAULT_TILE_TEMPLATE_PATH */
const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/tile.html.twig';
public const DEFAULT_TILE_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/tile.html.twig';
/** @var string|null DEFAULT_TILE_CONTROLLER_ACTION */
const DEFAULT_TILE_CONTROLLER_ACTION = null;
public const DEFAULT_TILE_CONTROLLER_ACTION = null;
/** @var string DEFAULT_OPENING_TARGET */
const DEFAULT_OPENING_TARGET = self::ENUM_OPENING_TARGET_MODAL;
public const DEFAULT_OPENING_TARGET = self::ENUM_OPENING_TARGET_MODAL;
/** @var string|null $sRouteName */
static $sRouteName = null;
public static $sRouteName = null;
/** @var array $aOpeningTargets */
static $aOpeningTargets = array(self::ENUM_OPENING_TARGET_MODAL, self::ENUM_OPENING_TARGET_SELF, self::ENUM_OPENING_TARGET_NEW);
public static $aOpeningTargets = [self::ENUM_OPENING_TARGET_MODAL, self::ENUM_OPENING_TARGET_SELF, self::ENUM_OPENING_TARGET_NEW];
/** @var int $iWidth */
protected $iWidth;
@@ -103,14 +103,13 @@ abstract class PortalBrick extends AbstractBrick
/** @var string $sTitleNavigationMenu */
protected $sTitleNavigationMenu;
/** @inheritdoc */
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
{
parent::RegisterTemplates($oTemplatesRegister);
$oTemplatesRegister->RegisterTemplates(self::class,
TemplateDefinitionDto::Create('tile', static::TEMPLATES_BASE_PATH . 'tile.html.twig'),
$oTemplatesRegister->RegisterTemplates(
self::class,
TemplateDefinitionDto::Create('tile', static::TEMPLATES_BASE_PATH.'tile.html.twig'),
);
}
@@ -500,10 +499,8 @@ abstract class PortalBrick extends AbstractBrick
// Checking specific elements
/** @var \Combodo\iTop\DesignElement $oBrickSubNode */
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode)
{
switch ($oBrickSubNode->nodeName)
{
foreach ($oMDElement->GetNodes('./*') as $oBrickSubNode) {
switch ($oBrickSubNode->nodeName) {
case 'width':
$sWidth = $oBrickSubNode->GetText(static::DEFAULT_WIDTH);
$this->bIsWidthPixel = str_contains($sWidth, 'px');
@@ -522,23 +519,20 @@ abstract class PortalBrick extends AbstractBrick
case 'visible':
// Default value
$oOptionalNode = $oBrickSubNode->GetOptionalElement('default');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$optionalNodeValue = ($oOptionalNode->GetText() === 'false') ? false : true;
$this->SetVisibleHome($optionalNodeValue);
$this->SetVisibleNavigationMenu($optionalNodeValue);
}
// Home value
$oOptionalNode = $oBrickSubNode->GetOptionalElement('home');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$optionalNodeValue = ($oOptionalNode->GetText() === 'false') ? false : true;
$this->SetVisibleHome($optionalNodeValue);
}
// Navigation menu value
$oOptionalNode = $oBrickSubNode->GetOptionalElement('navigation_menu');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$optionalNodeValue = ($oOptionalNode->GetText() === 'false') ? false : true;
$this->SetVisibleNavigationMenu($optionalNodeValue);
}
@@ -546,8 +540,7 @@ abstract class PortalBrick extends AbstractBrick
case 'templates':
$oTemplateNodeList = $oBrickSubNode->GetNodes('template[@id='.ModuleDesign::XPathQuote('tile').']');
if ($oTemplateNodeList->length > 0)
{
if ($oTemplateNodeList->length > 0) {
/** @var \Combodo\iTop\DesignElement $oTemplateNode */
$oTemplateNode = $oTemplateNodeList->item(0);
$this->SetTemplatePath('tile', $oTemplateNode->GetText(static::DEFAULT_TILE_TEMPLATE_PATH));
@@ -560,23 +553,20 @@ abstract class PortalBrick extends AbstractBrick
$this->SetRankNavigationMenu($this->fRank);
// Default value
$oOptionalNode = $oBrickSubNode->GetOptionalElement('default');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$optionalNodeValue = $oOptionalNode->GetText(static::DEFAULT_RANK);
$this->SetRankHome($optionalNodeValue);
$this->SetRankNavigationMenu($optionalNodeValue);
}
// Home value
$oOptionalNode = $oBrickSubNode->GetOptionalElement('home');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$optionalNodeValue = $oOptionalNode->GetText(static::DEFAULT_RANK);
$this->SetRankHome($optionalNodeValue);
}
// Navigation menu value
$oOptionalNode = $oBrickSubNode->GetOptionalElement('navigation_menu');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$optionalNodeValue = $oOptionalNode->GetText(static::DEFAULT_RANK);
$this->SetRankNavigationMenu($optionalNodeValue);
}
@@ -588,23 +578,20 @@ abstract class PortalBrick extends AbstractBrick
$this->SetTitleNavigationMenu($this->sTitle);
// Default value
$oOptionalNode = $oBrickSubNode->GetOptionalElement('default');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$optionalNodeValue = $oOptionalNode->GetText(static::DEFAULT_TITLE);
$this->SetTitleHome($optionalNodeValue);
$this->SetTitleNavigationMenu($optionalNodeValue);
}
// Home value
$oOptionalNode = $oBrickSubNode->GetOptionalElement('home');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$optionalNodeValue = $oOptionalNode->GetText(static::DEFAULT_TITLE);
$this->SetTitleHome($optionalNodeValue);
}
// Navigation menu value
$oOptionalNode = $oBrickSubNode->GetOptionalElement('navigation_menu');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$optionalNodeValue = $oOptionalNode->GetText(static::DEFAULT_TITLE);
$this->SetTitleNavigationMenu($optionalNodeValue);
$this->SetTitle($optionalNodeValue);
@@ -617,23 +604,20 @@ abstract class PortalBrick extends AbstractBrick
$this->SetDecorationClassNavigationMenu(static::DEFAULT_DECORATION_CLASS_NAVIGATION_MENU);
// Default value
$oOptionalNode = $oBrickSubNode->GetOptionalElement('default');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$optionalNodeValue = $oOptionalNode->GetText(static::DEFAULT_DECORATION_CLASS_NAVIGATION_MENU);
$this->SetDecorationClassHome($optionalNodeValue);
$this->SetDecorationClassNavigationMenu($optionalNodeValue);
}
// Home value
$oOptionalNode = $oBrickSubNode->GetOptionalElement('home');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$optionalNodeValue = $oOptionalNode->GetText(static::DEFAULT_DECORATION_CLASS_HOME);
$this->SetDecorationClassHome($optionalNodeValue);
}
// Navigation menu value
$oOptionalNode = $oBrickSubNode->GetOptionalElement('navigation_menu');
if ($oOptionalNode !== null)
{
if ($oOptionalNode !== null) {
$optionalNodeValue = $oOptionalNode->GetText(static::DEFAULT_DECORATION_CLASS_NAVIGATION_MENU);
$this->SetDecorationClassNavigationMenu($optionalNodeValue);
}
@@ -645,11 +629,16 @@ abstract class PortalBrick extends AbstractBrick
case 'opening_target':
$sOpeningTarget = $oBrickSubNode->GetText(static::DEFAULT_OPENING_TARGET);
if (!in_array($sOpeningTarget,
array(static::ENUM_OPENING_TARGET_MODAL, static::ENUM_OPENING_TARGET_NEW, static::ENUM_OPENING_TARGET_SELF)))
{
throw new DOMFormatException('PortalBrick : opening_target tag value must be modal|new|self ("'.$sOpeningTarget.'" given)',
null, null, $oBrickSubNode);
if (!in_array(
$sOpeningTarget,
[static::ENUM_OPENING_TARGET_MODAL, static::ENUM_OPENING_TARGET_NEW, static::ENUM_OPENING_TARGET_SELF]
)) {
throw new DOMFormatException(
'PortalBrick : opening_target tag value must be modal|new|self ("'.$sOpeningTarget.'" given)',
null,
null,
$oBrickSubNode
);
}
$this->SetOpeningTarget($sOpeningTarget);

View File

@@ -31,5 +31,4 @@ use Exception;
*/
class PropertyNotFoundException extends Exception
{
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -34,19 +35,19 @@ use DOMFormatException;
class UserProfileBrick extends PortalBrick
{
// Overloaded constants
const DEFAULT_VISIBLE_NAVIGATION_MENU = false;
const DEFAULT_VISIBLE_HOME = false;
const DEFAULT_DECORATION_CLASS_HOME = 'glyphicon glyphicon-user';
const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'glyphicon glyphicon-user';
public const DEFAULT_VISIBLE_NAVIGATION_MENU = false;
public const DEFAULT_VISIBLE_HOME = false;
public const DEFAULT_DECORATION_CLASS_HOME = 'glyphicon glyphicon-user';
public const DEFAULT_DECORATION_CLASS_NAVIGATION_MENU = 'glyphicon glyphicon-user';
/** @var bool DEFAULT_SHOW_PICTURE_FORM */
const DEFAULT_SHOW_PICTURE_FORM = true;
public const DEFAULT_SHOW_PICTURE_FORM = true;
/** @var bool DEFAULT_SHOW_PREFERENCES_FORM */
const DEFAULT_SHOW_PREFERENCES_FORM = true;
public const DEFAULT_SHOW_PREFERENCES_FORM = true;
/** @var bool DEFAULT_SHOW_PASSWORD_FORM */
const DEFAULT_SHOW_PASSWORD_FORM = true;
public const DEFAULT_SHOW_PASSWORD_FORM = true;
// Overloaded variables
static $sRouteName = 'p_user_profile_brick';
public static $sRouteName = 'p_user_profile_brick';
/** @var array $aForm */
protected $aForm;
@@ -61,8 +62,9 @@ class UserProfileBrick extends PortalBrick
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
{
parent::RegisterTemplates($oTemplatesRegister);
$oTemplatesRegister->RegisterTemplates(self::class,
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'user-profile/layout.html.twig'),
$oTemplatesRegister->RegisterTemplates(
self::class,
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH.'user-profile/layout.html.twig'),
TemplateDefinitionDto::Create('user_info', static::TEMPLATES_BASE_PATH.'user-profile/user_info.html.twig'),
TemplateDefinitionDto::Create('user_info_ready_js', static::TEMPLATES_BASE_PATH.'user-profile/user_info.ready.js.twig'),
);
@@ -75,12 +77,12 @@ class UserProfileBrick extends PortalBrick
{
parent::__construct();
$this->aForm = array(
$this->aForm = [
'id' => 'default-user-profile',
'type' => 'zlist',
'fields' => 'details',
'layout' => null,
);
];
$this->bShowPictureForm = static::DEFAULT_SHOW_PICTURE_FORM;
$this->bShowPreferencesForm = static::DEFAULT_SHOW_PREFERENCES_FORM;
$this->bShowPasswordForm = static::DEFAULT_SHOW_PASSWORD_FORM;
@@ -191,13 +193,13 @@ class UserProfileBrick extends PortalBrick
// Enumerating fields
if ($oBrickSubNode->GetOptionalElement('fields') !== null) {
$this->aForm['type'] = 'custom_list';
$this->aForm['fields'] = array();
$this->aForm['fields'] = [];
/** @var \Combodo\iTop\DesignElement $oFieldNode */
foreach ($oBrickSubNode->GetOptionalElement('fields')->GetNodes('field') as $oFieldNode) {
$sFieldId = $oFieldNode->getAttribute('id');
if ($sFieldId !== '') {
$aField = array();
$aField = [];
// Parsing field options like read_only, hidden and mandatory
if ($oFieldNode->GetOptionalElement('read_only')) {
$aField['readonly'] = ($oFieldNode->GetOptionalElement('read_only')->GetText('true') === 'true') ? true : false;
@@ -223,10 +225,10 @@ class UserProfileBrick extends PortalBrick
$sXml = preg_replace('/^.+\n/', '', $sXml);
$sXml = preg_replace('/\n.+$/', '', $sXml);
$this->aForm['layout'] = array(
$this->aForm['layout'] = [
'type' => (preg_match('/\{\{|\{\#|\{\%/', $sXml) === 1) ? 'twig' : 'xhtml',
'content' => $sXml,
);
];
}
break;

View File

@@ -37,14 +37,15 @@ use Symfony\Contracts\Service\Attribute\Required;
*/
abstract class AbstractController extends SymfonyAbstractController implements TemplatesProviderInterface
{
const TEMPLATES_BASE_PATH = 'itop-portal-base/portal/templates/';
public const TEMPLATES_BASE_PATH = 'itop-portal-base/portal/templates/';
/** @inheritdoc */
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
{
$oTemplatesRegister->RegisterTemplates(self::class,
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH . 'layout.html.twig'),
TemplateDefinitionDto::Create('modal', static::TEMPLATES_BASE_PATH . 'modal/layout.html.twig'),
$oTemplatesRegister->RegisterTemplates(
self::class,
TemplateDefinitionDto::Create('page', static::TEMPLATES_BASE_PATH.'layout.html.twig'),
TemplateDefinitionDto::Create('modal', static::TEMPLATES_BASE_PATH.'modal/layout.html.twig'),
TemplateDefinitionDto::Create('loader', static::TEMPLATES_BASE_PATH.'helpers/loader.html.twig'),
TemplateDefinitionDto::Create('tagset_clic_handler_js', static::TEMPLATES_BASE_PATH.'helpers/tagset_clic_handler.js.twig'),
TemplateDefinitionDto::Create('session_message', static::TEMPLATES_BASE_PATH.'helpers/session_messages/session_message.html.twig'),

View File

@@ -29,7 +29,6 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use UserRights;
/**
* Class AggregatePageBrickController
*
@@ -41,7 +40,6 @@ use UserRights;
*/
class AggregatePageBrickController extends BrickController
{
/**
* Constructor.
*
@@ -51,8 +49,7 @@ class AggregatePageBrickController extends BrickController
*/
public function __construct(
protected BrickCollection $oBrickCollection
)
{
) {
}
@@ -76,11 +73,11 @@ class AggregatePageBrickController extends BrickController
$aTilesRendering = $this->GetBricksTileRendering($oRequest, $aAggregatePageBricks);
$sLayoutTemplate = $oBrick->GetTemplatePath('page');
$aData = array(
$aData = [
'oBrick' => $oBrick,
'aggregatepage_bricks' => $aAggregatePageBricks,
'aTilesRendering' => $aTilesRendering,
);
];
$oResponse = $this->render($sLayoutTemplate, $aData);
return $oResponse;
@@ -94,15 +91,11 @@ class AggregatePageBrickController extends BrickController
*/
private function GetOrderedAggregatePageBricksObjectsById($aAggregatePageBricksConf)
{
$aAggregatePageBricks = array();
foreach ($aAggregatePageBricksConf as $sBrickId => $iBrickRank)
{
try
{
$aAggregatePageBricks = [];
foreach ($aAggregatePageBricksConf as $sBrickId => $iBrickRank) {
try {
$oPortalBrick = $this->oBrickCollection->GetBrickById($sBrickId);
}
catch (BrickNotFoundException $oException)
{
} catch (BrickNotFoundException $oException) {
IssueLog::Debug('AggregatePageBrick: Could not display brick, either wrong id or user profile not allowed', LogChannels::PORTAL, [
'brick_id' => $sBrickId,
'user_profiles' => UserRights::ListProfiles(),
@@ -124,21 +117,17 @@ class AggregatePageBrickController extends BrickController
*/
private function GetBricksTileRendering(Request $oRequest, $aBricks)
{
$aTilesRendering = array();
foreach ($aBricks as $oBrick)
{
if ($oBrick->GetTileControllerAction() !== null)
{
$aTilesRendering = [];
foreach ($aBricks as $oBrick) {
if ($oBrick->GetTileControllerAction() !== null) {
$aControllerActionParts = explode('::', $oBrick->GetTileControllerAction());
if (count($aControllerActionParts) !== 2)
{
if (count($aControllerActionParts) !== 2) {
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Tile controller action must be of form "\Namespace\ControllerClass::FunctionName" for brick "'.$oBrick->GetId().'"');
}
$aRouteParams = array();
$aRouteParams = [];
// Add sBrickId in the route params as it is necessary for each brick actions
if (is_a($aControllerActionParts[0], BrickController::class, true))
{
if (is_a($aControllerActionParts[0], BrickController::class, true)) {
$aRouteParams['sBrickId'] = $oBrick->GetId();
}
@@ -150,4 +139,4 @@ class AggregatePageBrickController extends BrickController
return $aTilesRendering;
}
}
}

View File

@@ -29,5 +29,4 @@ namespace Combodo\iTop\Portal\Controller;
*/
abstract class BrickController extends AbstractController
{
}

View File

@@ -51,7 +51,6 @@ use VariableExpression;
*/
class BrowseBrickController extends BrickController
{
/**
* Constructor.
*
@@ -67,12 +66,10 @@ class BrowseBrickController extends BrickController
protected RequestManipulatorHelper $oRequestManipulatorHelper,
protected BrickControllerHelper $oBrickControllerHelper,
protected BrickCollection $oBrickCollection
)
{
) {
}
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
* @param string $sBrickId
@@ -103,85 +100,92 @@ class BrowseBrickController extends BrickController
// Getting current browse mode (First from router parameter, then default brick value)
$sBrowseMode = (!empty($sBrowseMode)) ? $sBrowseMode : $oBrick->GetDefaultBrowseMode();
// Getting current dataloading mode (First from router parameter, then query parameter, then default brick value)
$sDataLoading = ($sDataLoading !== null) ? $sDataLoading : $this->oRequestManipulatorHelper->ReadParam('sDataLoading',
$oBrick->GetDataLoading());
$sDataLoading = ($sDataLoading !== null) ? $sDataLoading : $this->oRequestManipulatorHelper->ReadParam(
'sDataLoading',
$oBrick->GetDataLoading()
);
// Getting search value
$sRawSearchValue = $this->oRequestManipulatorHelper->ReadParam('sSearchValue', '');
$sSearchValue = html_entity_decode($sRawSearchValue);
if (strlen($sSearchValue) > 0)
{
if (strlen($sSearchValue) > 0) {
$sDataLoading = AbstractBrick::ENUM_DATA_LOADING_LAZY;
}
$aData = array();
$aLevelsProperties = array();
$aLevelsClasses = array();
$aData = [];
$aLevelsProperties = [];
$aLevelsClasses = [];
$this->oBrowseBrickHelper->TreeToFlatLevelsProperties($oBrick->GetLevels(), $aLevelsProperties);
// Consistency checks
if (!in_array($sBrowseMode, array_keys($aBrowseModes)))
{
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR,
'Browse brick "'.$sBrickId.'" : Unknown browse mode "'.$sBrowseMode.'", availables are '.implode(' / ',
array_keys($aBrowseModes)));
if (!in_array($sBrowseMode, array_keys($aBrowseModes))) {
throw new HttpException(
Response::HTTP_INTERNAL_SERVER_ERROR,
'Browse brick "'.$sBrickId.'" : Unknown browse mode "'.$sBrowseMode.'", availables are '.implode(
' / ',
array_keys($aBrowseModes)
)
);
}
if (empty($aLevelsProperties))
{
if (empty($aLevelsProperties)) {
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Browse brick "'.$sBrickId.'" : No levels to display.');
}
// Building DBObjectSearch
$oQuery = null;
// ... In this case only we have to build a specific query for the current level only
if (in_array($sBrowseMode, array(
if (in_array($sBrowseMode, [
BrowseBrick::ENUM_BROWSE_MODE_TREE,
BrowseBrick::ENUM_BROWSE_MODE_MOSAIC,
)) && ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY))
{
]) && ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY)) {
// Will be handled later in the pagination part
}
// .. Otherwise
else
{
else {
// We iterate (in reverse mode /!\) over the levels to build the whole query, starting from the bottom
$aLevelsPropertiesKeys = array_keys($aLevelsProperties);
$iLoopMax = count($aLevelsPropertiesKeys) - 1;
$oFullBinExpr = null;
for ($i = $iLoopMax; $i >= 0; $i--)
{
for ($i = $iLoopMax; $i >= 0; $i--) {
// Retrieving class alias for all depth
array_unshift($aLevelsClasses, $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->GetClassAlias());
// Joining queries from bottom-up
if ($i < $iLoopMax)
{
$aRealiasingMap = array();
if ($i < $iLoopMax) {
$aRealiasingMap = [];
$oParentAtt = MetaModel::GetAttributeDef($aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['search']->GetClass(), $aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['parent_att']);
// If we work on a n:n link
if($oParentAtt instanceof AttributeLinkedSetIndirect)
{
if ($oParentAtt instanceof AttributeLinkedSetIndirect) {
// Create a DBSearch from Link class
$oSubSearch = new DBObjectSearch($oParentAtt->GetLinkedClass());
// Join it to the bottom query
$oSubSearch = $oSubSearch->Join($aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['search'],
DBSearch::JOIN_POINTING_TO, $oParentAtt->GetExtKeyToMe(), TREE_OPERATOR_EQUALS, $aRealiasingMap);
$oSubSearch = $oSubSearch->Join(
$aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['search'],
DBSearch::JOIN_POINTING_TO,
$oParentAtt->GetExtKeyToMe(),
TREE_OPERATOR_EQUALS,
$aRealiasingMap
);
// Join our Link class + bottom query to the up query
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] ->Join($oSubSearch, DBSearch::JOIN_REFERENCED_BY,
$oParentAtt->GetExtKeyToRemote(), TREE_OPERATOR_EQUALS, $aRealiasingMap);
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] ->Join(
$oSubSearch,
DBSearch::JOIN_REFERENCED_BY,
$oParentAtt->GetExtKeyToRemote(),
TREE_OPERATOR_EQUALS,
$aRealiasingMap
);
} else {
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->Join(
$aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['search'],
DBSearch::JOIN_REFERENCED_BY,
$aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['parent_att'],
TREE_OPERATOR_EQUALS,
$aRealiasingMap
);
}
else
{
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search'] = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->Join($aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['search'],
DBSearch::JOIN_REFERENCED_BY, $aLevelsProperties[$aLevelsPropertiesKeys[$i + 1]]['parent_att'],
TREE_OPERATOR_EQUALS, $aRealiasingMap);
}
foreach ($aLevelsPropertiesKeys as $sLevelAlias)
{
if (array_key_exists($sLevelAlias, $aRealiasingMap))
{
foreach ($aLevelsPropertiesKeys as $sLevelAlias) {
if (array_key_exists($sLevelAlias, $aRealiasingMap)) {
/** @since 2.7.2 */
foreach ($aRealiasingMap[$sLevelAlias] as $sAliasToChange)
{
foreach ($aRealiasingMap[$sLevelAlias] as $sAliasToChange) {
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->RenameAlias($sAliasToChange, $sLevelAlias);
}
}
@@ -190,8 +194,7 @@ class BrowseBrickController extends BrickController
// Adding search clause
// Note : For know the search is naive and looks only for the exact match. It doesn't search for words separately
if (strlen($sSearchValue) > 0)
{
if (strlen($sSearchValue) > 0) {
// - Cleaning the search value by exploding and trimming spaces
$aExplodedSearchValues = explode(' ', $sSearchValue);
$aSearchValues = [];
@@ -202,25 +205,21 @@ class BrowseBrickController extends BrickController
}
// - Retrieving fields to search
$aSearchFields = array($aLevelsProperties[$aLevelsPropertiesKeys[$i]]['name_att']);
if (!empty($aLevelsProperties[$aLevelsPropertiesKeys[$i]]['fields']))
{
$aSearchFields = [$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['name_att']];
if (!empty($aLevelsProperties[$aLevelsPropertiesKeys[$i]]['fields'])) {
$sTmpFieldClass = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->GetClass();
foreach ($aLevelsProperties[$aLevelsPropertiesKeys[$i]]['fields'] as $aTmpField)
{
foreach ($aLevelsProperties[$aLevelsPropertiesKeys[$i]]['fields'] as $aTmpField) {
$sTmpFieldAttCode = $aTmpField['code'];
// Skip invalid attcodes
if(!MetaModel::IsValidAttCode($sTmpFieldClass, $sTmpFieldAttCode))
{
if (!MetaModel::IsValidAttCode($sTmpFieldClass, $sTmpFieldAttCode)) {
continue;
}
// For external key, force search on the friendlyname instead of the ID.
// This should be addressed more globally with the bigger issue, see N°1970
$oTmpFieldAttDef = MetaModel::GetAttributeDef($sTmpFieldClass, $sTmpFieldAttCode);
if($oTmpFieldAttDef instanceof AttributeExternalKey)
{
if ($oTmpFieldAttDef instanceof AttributeExternalKey) {
$sTmpFieldAttCode .= '_friendlyname';
}
@@ -231,60 +230,49 @@ class BrowseBrickController extends BrickController
$oLevelBinExpr = null;
$iFieldLoopMax = count($aSearchFields) - 1;
$iSearchLoopMax = count($aSearchValues) - 1;
for ($j = 0; $j <= $iFieldLoopMax; $j++)
{
for ($j = 0; $j <= $iFieldLoopMax; $j++) {
$sTmpFieldAttCode = $aSearchFields[$j];
$oFieldBinExpr = null;
//$oFieldBinExpr = new BinaryExpression(new FieldExpression($aSearchFields[$j], $aLevelsPropertiesKeys[$i]), )
for ($k = 0; $k <= $iSearchLoopMax; $k++)
{
$oSearchBinExpr = new BinaryExpression(new FieldExpression($sTmpFieldAttCode, $aLevelsPropertiesKeys[$i]),
'LIKE', new VariableExpression('search_value_'.$k));
if ($k === 0)
{
for ($k = 0; $k <= $iSearchLoopMax; $k++) {
$oSearchBinExpr = new BinaryExpression(
new FieldExpression($sTmpFieldAttCode, $aLevelsPropertiesKeys[$i]),
'LIKE',
new VariableExpression('search_value_'.$k)
);
if ($k === 0) {
$oFieldBinExpr = $oSearchBinExpr;
}
else
{
} else {
$oFieldBinExpr = new BinaryExpression($oFieldBinExpr, 'AND', $oSearchBinExpr);
}
}
if ($j === 0)
{
if ($j === 0) {
$oLevelBinExpr = $oFieldBinExpr;
}
else
{
} else {
$oLevelBinExpr = new BinaryExpression($oLevelBinExpr, 'OR', $oFieldBinExpr);
}
}
// - Building query for the level
if ($i === $iLoopMax)
{
if ($i === $iLoopMax) {
$oFullBinExpr = $oLevelBinExpr;
}
else
{
} else {
$oFullBinExpr = new BinaryExpression($oFullBinExpr, 'OR', $oLevelBinExpr);
}
// - Adding it to the query when complete
if ($i === 0)
{
if ($i === 0) {
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->AddConditionExpression($oFullBinExpr);
}
}
// Setting selected classes and binding parameters
if ($i === 0)
{
if ($i === 0) {
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->SetSelectedClasses($aLevelsClasses);
if (strlen($sSearchValue) > 0)
{
if (strlen($sSearchValue) > 0) {
// Note : This could be way more simpler if we had a SetInternalParam($sParam, $value) verb
$aQueryParams = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->GetInternalParams();
// Note : $iSearchloopMax was initialized on the previous loop
@@ -302,23 +290,26 @@ class BrowseBrickController extends BrickController
// - Check how many records there is.
// - Update $sDataLoading with its new value regarding the number of record and the threshold
$oCountSet = new DBObjectSet($oQuery);
$fThreshold = (float)MetaModel::GetModuleSetting($sPortalId,
'lazy_loading_threshold');
$fThreshold = (float)MetaModel::GetModuleSetting(
$sPortalId,
'lazy_loading_threshold'
);
$sDataLoading = ($oCountSet->Count() > $fThreshold) ? AbstractBrick::ENUM_DATA_LOADING_LAZY : AbstractBrick::ENUM_DATA_LOADING_FULL;
unset($oCountSet);
}
}
// Setting query pagination if needed
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY)
{
switch ($sBrowseMode)
{
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY) {
switch ($sBrowseMode) {
case BrowseBrick::ENUM_BROWSE_MODE_LIST:
// Retrieving parameters
$iPageNumber = (int)$this->oRequestManipulatorHelper->ReadParam('iPageNumber', 1, FILTER_SANITIZE_NUMBER_INT);
$iListLength = (int)$this->oRequestManipulatorHelper->ReadParam('iListLength', BrowseBrick::DEFAULT_LIST_LENGTH,
FILTER_SANITIZE_NUMBER_INT);
$iListLength = (int)$this->oRequestManipulatorHelper->ReadParam(
'iListLength',
BrowseBrick::DEFAULT_LIST_LENGTH,
FILTER_SANITIZE_NUMBER_INT
);
// Getting total records number
$oCountSet = new DBObjectSet($oQuery);
@@ -337,36 +328,26 @@ class BrowseBrickController extends BrickController
$sNodeId = $this->oRequestManipulatorHelper->ReadParam('sNodeId', '');
// If no values for those parameters, we might be loading page in lazy mode for the first time, therefore the URL doesn't have those information.
if (empty($sLevelAlias))
{
if (empty($sLevelAlias)) {
reset($aLevelsProperties);
$oQuery = $aLevelsProperties[key($aLevelsProperties)]['search'];
if (!empty($sNodeId))
{
if (!empty($sNodeId)) {
$oQuery->AddCondition('id', $sNodeId);
}
}
// Else we need to find the OQL for that particular level
else
{
else {
$bFoundLevel = false;
foreach ($aLevelsProperties as $aLevelProperties)
{
if ($aLevelProperties['alias'] === $sLevelAlias)
{
if (isset($aLevelProperties['levels']) && !empty($aLevelProperties['levels']) && isset($aLevelsProperties[$aLevelProperties['levels'][0]]))
{
foreach ($aLevelsProperties as $aLevelProperties) {
if ($aLevelProperties['alias'] === $sLevelAlias) {
if (isset($aLevelProperties['levels']) && !empty($aLevelProperties['levels']) && isset($aLevelsProperties[$aLevelProperties['levels'][0]])) {
$oQuery = $aLevelsProperties[$aLevelProperties['levels'][0]]['search'];
if (!empty($sNodeId))
{
if (!empty($sNodeId)) {
$sParentAttCode = $aLevelsProperties[$aLevelProperties['levels'][0]]['parent_att'];
$oParentAtt = MetaModel::GetAttributeDef($oQuery->GetClass(), $sParentAttCode);
if($oParentAtt instanceof AttributeLinkedSetIndirect)
{
if ($oParentAtt instanceof AttributeLinkedSetIndirect) {
$oQuery->AddConditionAdvanced($sParentAttCode.'->'.$oParentAtt->GetExtKeyToRemote(), $sNodeId);
}
else
{
} else {
$oQuery->AddCondition($sParentAttCode, $sNodeId);
}
}
@@ -376,10 +357,11 @@ class BrowseBrickController extends BrickController
}
}
if (!$bFoundLevel)
{
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR,
'Browse brick "'.$sBrickId.'" : Level alias "'.$sLevelAlias.'" is not defined for that brick.');
if (!$bFoundLevel) {
throw new HttpException(
Response::HTTP_INTERNAL_SERVER_ERROR,
'Browse brick "'.$sBrickId.'" : Level alias "'.$sLevelAlias.'" is not defined for that brick.'
);
}
}
@@ -394,34 +376,26 @@ class BrowseBrickController extends BrickController
$oSet = new DBObjectSet($oQuery);
break;
}
}
else
{
} else {
$oSet = new DBObjectSet($oQuery);
}
// Optimizing the ObjectSet to retrieve only necessary columns
$aColumnAttrs = array();
foreach ($oSet->GetFilter()->GetSelectedClasses() as $sTmpClassAlias => $sTmpClassName)
{
if (isset($aLevelsProperties[$sTmpClassAlias]))
{
$aColumnAttrs = [];
foreach ($oSet->GetFilter()->GetSelectedClasses() as $sTmpClassAlias => $sTmpClassName) {
if (isset($aLevelsProperties[$sTmpClassAlias])) {
$aTmpLevelProperties = $aLevelsProperties[$sTmpClassAlias];
// Mandatory main attribute
$aTmpColumnAttrs = array($aTmpLevelProperties['name_att']);
$aTmpColumnAttrs = [$aTmpLevelProperties['name_att']];
// Optional attributes, only if in list mode
if ($sBrowseMode === BrowseBrick::ENUM_BROWSE_MODE_LIST)
{
foreach ($aTmpLevelProperties['fields'] as $aTmpField)
{
if ($sBrowseMode === BrowseBrick::ENUM_BROWSE_MODE_LIST) {
foreach ($aTmpLevelProperties['fields'] as $aTmpField) {
$aTmpColumnAttrs[] = $aTmpField['code'];
}
}
// Optional attributes
foreach (BrowseBrickHelper::OPTIONAL_ATTRIBUTES as $sOptionalAttribute)
{
if ($aTmpLevelProperties[$sOptionalAttribute] !== null)
{
foreach (BrowseBrickHelper::OPTIONAL_ATTRIBUTES as $sOptionalAttribute) {
if ($aTmpLevelProperties[$sOptionalAttribute] !== null) {
$aTmpColumnAttrs[] = $aTmpLevelProperties[$sOptionalAttribute];
}
}
@@ -434,20 +408,15 @@ class BrowseBrickController extends BrickController
// Setting specified column sort, setting default datamodel one otherwise
$aSortedParams = $this->oBrickControllerHelper->ExtractSortParams();
if (!empty($aSortedParams))
{
if (!empty($aSortedParams)) {
$oSet->SetOrderBy($aSortedParams);
}
else
{
} else {
$oSet->SetOrderByClasses();
}
// Retrieving results and organizing them for templating
$aItems = array();
while ($aCurrentRow = $oSet->FetchAssoc())
{
switch ($sBrowseMode)
{
$aItems = [];
while ($aCurrentRow = $oSet->FetchAssoc()) {
switch ($sBrowseMode) {
case BrowseBrick::ENUM_BROWSE_MODE_TREE:
case BrowseBrick::ENUM_BROWSE_MODE_MOSAIC:
$this->oBrowseBrickHelper->AddToTreeItems($aItems, $aCurrentRow, $aLevelsProperties, null);
@@ -460,22 +429,21 @@ class BrowseBrickController extends BrickController
}
}
IssueLog::Debug('Portal BrowseBrick query', LogChannels::PORTAL, array(
IssueLog::Debug('Portal BrowseBrick query', LogChannels::PORTAL, [
'sPortalId' => $sPortalId,
'sBrickId' => $sBrickId,
'oql' => $oSet->GetFilter()->ToOQL(),
));
]);
// Preparing response
if ($oRequest->isXmlHttpRequest()) {
$aData = $aData + array(
$aData = $aData + [
'data' => $aItems,
'levelsProperties' => $aLevelsProperties,
);
];
$oResponse = new JsonResponse($aData);
} else {
$aData = $aData + array(
$aData = $aData + [
'oBrick' => $oBrick,
'sBrickId' => $sBrickId,
'sBrowseMode' => $sBrowseMode,
@@ -486,7 +454,7 @@ class BrowseBrickController extends BrickController
'iItemsCount' => count($aItems),
'aLevelsProperties' => json_encode($aLevelsProperties),
'iDefaultLengthList' => $oBrick->GetDefaultListLength(),
);
];
// Note : To extend this brick's template, depending on what you want to do :
// a) Modify the whole template :
@@ -495,13 +463,10 @@ class BrowseBrickController extends BrickController
// - Create a template for that browse mode,
// - Add the mode to those available in the brick configuration,
// - Create a router and add a route for the new browse mode
if ($oBrick->HasInstanceOverriddenTemplate('page'))
{
if ($oBrick->HasInstanceOverriddenTemplate('page')) {
$sTemplatePath = $oBrick->GetTemplatePath('page');
}
else
{
$sTemplatePath = $oBrick->GetTemplatePath('page_' .$sBrowseMode);
} else {
$sTemplatePath = $oBrick->GetTemplatePath('page_'.$sBrowseMode);
}
$oResponse = $this->render($sTemplatePath, $aData);
}

View File

@@ -33,7 +33,6 @@ use Symfony\Component\HttpFoundation\Request;
*/
class CreateBrickController extends BrickController
{
/**
* Constructor.
*
@@ -43,8 +42,7 @@ class CreateBrickController extends BrickController
*/
public function __construct(
protected BrickCollection $oBrickCollection
)
{
) {
}
/**
@@ -60,16 +58,15 @@ class CreateBrickController extends BrickController
/** @var \Combodo\iTop\Portal\Brick\CreateBrick $oBrick */
$oBrick = $this->oBrickCollection->GetBrickById($sBrickId);
$aRouteParams = array(
$aRouteParams = [
'sBrickId' => $sBrickId,
'sObjectClass' => $oBrick->GetClass(),
'ar_token' => null,
);
];
// Checking for actions rules
$aRules = $oBrick->GetRules();
if (!empty($aRules))
{
if (!empty($aRules)) {
$aRouteParams['ar_token'] = ContextManipulatorHelper::PrepareAndEncodeRulesToken($aRules);
}

View File

@@ -39,8 +39,9 @@ class DefaultController extends AbstractController
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
{
parent::RegisterTemplates($oTemplatesRegister);
$oTemplatesRegister->RegisterTemplates(self::class,
TemplateDefinitionDto::Create('home', static::TEMPLATES_BASE_PATH . 'home/layout.html.twig'),
$oTemplatesRegister->RegisterTemplates(
self::class,
TemplateDefinitionDto::Create('home', static::TEMPLATES_BASE_PATH.'home/layout.html.twig'),
);
}
@@ -53,26 +54,24 @@ class DefaultController extends AbstractController
*/
public function HomeAction(Request $oRequest, BrickCollection $oBricksCollection)
{
$aData = array();
$aData = [];
// Rendering tiles
$aData['aTilesRendering'] = array();
foreach ($oBricksCollection->GetBricks() as $oBrick)
{
$aData['aTilesRendering'] = [];
foreach ($oBricksCollection->GetBricks() as $oBrick) {
// Doing it only for tile visible on home page to avoid unnecessary rendering
if (($oBrick->GetVisibleHome() === true) && ($oBrick->GetTileControllerAction() !== null))
{
if (($oBrick->GetVisibleHome() === true) && ($oBrick->GetTileControllerAction() !== null)) {
$aControllerActionParts = explode('::', $oBrick->GetTileControllerAction());
if (count($aControllerActionParts) !== 2)
{
return new Response('Tile controller action must be of form "\Namespace\ControllerClass::FunctionName" for brick "'.$oBrick->GetId().'"',
500);
if (count($aControllerActionParts) !== 2) {
return new Response(
'Tile controller action must be of form "\Namespace\ControllerClass::FunctionName" for brick "'.$oBrick->GetId().'"',
500
);
}
$aRouteParams = array();
$aRouteParams = [];
// Add sBrickId in the route params as it is necessary for each brick actions
if (is_a($aControllerActionParts[0], BrickController::class, true))
{
if (is_a($aControllerActionParts[0], BrickController::class, true)) {
$aRouteParams['sBrickId'] = $oBrick->GetId();
}

View File

@@ -72,18 +72,19 @@ use utils;
*/
class ManageBrickController extends BrickController
{
/**
* @var string EXCEL_EXPORT_TEMPLATE_PATH
/**
* @var string EXCEL_EXPORT_TEMPLATE_PATH
* @deprecated since 3.2.1
*/
const EXCEL_EXPORT_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig';
public const EXCEL_EXPORT_TEMPLATE_PATH = 'itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig';
/** @inheritdoc */
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void
{
parent::RegisterTemplates($oTemplatesRegister);
$oTemplatesRegister->RegisterTemplates(self::class,
TemplateDefinitionDto::Create('modal_export_excel', static::TEMPLATES_BASE_PATH . 'bricks/manage/popup-export-excel.html.twig'),
$oTemplatesRegister->RegisterTemplates(
self::class,
TemplateDefinitionDto::Create('modal_export_excel', static::TEMPLATES_BASE_PATH.'bricks/manage/popup-export-excel.html.twig'),
);
}
@@ -104,8 +105,7 @@ class ManageBrickController extends BrickController
protected RequestManipulatorHelper $oRequestManipulatorHelper,
protected SecurityHelper $oSecurityHelper,
protected BrickControllerHelper $oBrickControllerHelper
)
{
) {
}
@@ -138,17 +138,15 @@ class ManageBrickController extends BrickController
$aData = $this->GetData($oRequest, $sBrickId, $sGroupingTab, $oBrick->IsDetailsNeeded($sDisplayMode));
$aExportFields = $oBrick->GetExportFields();
$aData = $aData + array(
$aData = $aData + [
'sDisplayMode' => $sDisplayMode,
'bCanExport' => !empty($aExportFields),
'iDefaultListLength' => $oBrick->GetDefaultListLength(),
);
];
// Preparing response
if ($oRequest->isXmlHttpRequest()) {
$oResponse = new JsonResponse($aData);
}
else
{
} else {
$sLayoutTemplate = $oBrick->GetPageTemplate($sDisplayMode);
$oResponse = $this->render($sLayoutTemplate, $aData);
}
@@ -171,14 +169,11 @@ class ManageBrickController extends BrickController
/** @var \Combodo\iTop\Portal\Brick\ManageBrick $oBrick */
$oBrick = $this->oBrickCollection->GetBrickById($sBrickId);
try
{
try {
$aData = $this->GetData($oRequest, $sBrickId, null);
}
catch (Exception $e)
{
} catch (Exception $e) {
// TODO Default values
$aData = array();
$aData = [];
}
return $this->render($oBrick->GetTileTemplate(), $aData);
@@ -210,37 +205,28 @@ class ManageBrickController extends BrickController
$sClass = $oQuery->GetClass();
$aData = $this->GetData($oRequest, $sBrickId, $sGroupingTab, true);
if (isset($aData['aQueries']) && count($aData['aQueries']) === 1)
{
if (isset($aData['aQueries']) && count($aData['aQueries']) === 1) {
$aQueries = $aData['aQueries'];
reset($aQueries);
$sKey = key($aQueries);
$oSearch = $aData['aQueries'][$sKey];
}
else
{
} else {
$this->oScopeValidatorHelper->AddScopeToQuery($oQuery, $sClass);
$aData = array();
$aData = [];
$this->ManageSearchValue($aData, $oQuery, $sClass);
// Grouping tab
if ($oBrick->HasGroupingTabs())
{
if ($oBrick->HasGroupingTabs()) {
$aGroupingTabs = $oBrick->GetGroupingTabs();
// If tabs are made of the distinct values of an attribute, we have a find them via a query
if ($oBrick->IsGroupingTabsByDistinctValues())
{
if ($oBrick->IsGroupingTabsByDistinctValues()) {
$sGroupingTabAttCode = $aGroupingTabs['attribute'];
$aGroupingTabsValues = $this->GroupByAttribute($oQuery, $sGroupingTabAttCode, $oBrick);
$oQuery = $oQuery->Intersect($aGroupingTabsValues[$sGroupingTab]['condition']);
}
else
{
foreach ($aGroupingTabs['groups'] as $aGroup)
{
if ($aGroup['id'] === $sGroupingTab)
{
} else {
foreach ($aGroupingTabs['groups'] as $aGroup) {
if ($aGroup['id'] === $sGroupingTab) {
$oConditionQuery = $oQuery->Intersect(DBSearch::FromOQL($aGroup['condition']));
$oQuery = $oQuery->Intersect($oConditionQuery);
break;
@@ -251,29 +237,27 @@ class ManageBrickController extends BrickController
// Finalclass
$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GARE');
$oExpression = new BinaryExpression(new FieldExpression('finalclass', 'GARE'), '=',
new UnaryExpression($sGroupingArea));
$oExpression = new BinaryExpression(
new FieldExpression('finalclass', 'GARE'),
'=',
new UnaryExpression($sGroupingArea)
);
$oConditionQuery->AddConditionExpression($oExpression);
/** @var DBSearch $oSearch */
$oSearch = $oQuery->Intersect($oConditionQuery);
}
$aColumnsAttrs = $oBrick->GetExportFields();
$aFields = array();
$aFields = [];
$sTitleAttrCode = 'friendlyname';
if (!in_array($sTitleAttrCode, $aColumnsAttrs))
{
if (!in_array($sTitleAttrCode, $aColumnsAttrs)) {
$aFields[] = $sTitleAttrCode;
}
foreach ($aColumnsAttrs as $sAttCode)
{
foreach ($aColumnsAttrs as $sAttCode) {
$oAttributeDef = MetaModel::GetAttributeDef($sGroupingArea, $sAttCode);
if ($oAttributeDef->IsExternalKey(EXTKEY_ABSOLUTE))
{
if ($oAttributeDef->IsExternalKey(EXTKEY_ABSOLUTE)) {
$aFields[] = $sAttCode.'_friendlyname';
}
else
{
} else {
$aFields[] = $sAttCode;
}
}
@@ -288,12 +272,12 @@ class ManageBrickController extends BrickController
$oExporter->SetLocalizeOutput(true);
$oExporter->SetFields($sFields);
$aData = array(
$aData = [
'oBrick' => $oBrick,
'sBrickId' => $sBrickId,
'sToken' => $oExporter->SaveState(),
'sWikiUrl' => 'https://www.itophub.io/wiki/page?id='.utils::GetItopVersionWikiSyntax().'%3Auser%3Alists#excel_export',
);
'sWikiUrl' => 'https://www.itophub.io/wiki/page?id='.utils::GetItopVersionWikiSyntax().'%3Auser%3Alists#excel_export',
];
return $this->render($this->GetTemplatePath('modal_export_excel'), $aData);
}
@@ -323,10 +307,10 @@ class ManageBrickController extends BrickController
/** @var \Combodo\iTop\Portal\Brick\ManageBrick $oBrick */
$oBrick = $this->oBrickCollection->GetBrickById($sBrickId);
$aData = array();
$aGroupingTabsValues = array();
$aGroupingAreasValues = array();
$aQueries = array();
$aData = [];
$aGroupingTabsValues = [];
$aGroupingAreasValues = [];
$aQueries = [];
$bHasScope = true;
// Getting current data loading mode (First from router parameter, then query parameter, then default brick value)
@@ -334,8 +318,7 @@ class ManageBrickController extends BrickController
// - Retrieving the grouping areas to display
$sGroupingArea = $this->oRequestManipulatorHelper->ReadParam('sGroupingArea', '');
if (!empty($sGroupingArea))
{
if (!empty($sGroupingArea)) {
$bNeedDetails = true;
}
@@ -343,9 +326,8 @@ class ManageBrickController extends BrickController
$aColumnsAttrs = $oBrick->GetFields();
// Adding friendlyname attribute to the list if not already in it
$sTitleAttrCode = 'friendlyname';
if (($sTitleAttrCode !== null) && !in_array($sTitleAttrCode, $aColumnsAttrs))
{
$aColumnsAttrs = array_merge(array($sTitleAttrCode), $aColumnsAttrs);
if (($sTitleAttrCode !== null) && !in_array($sTitleAttrCode, $aColumnsAttrs)) {
$aColumnsAttrs = array_merge([$sTitleAttrCode], $aColumnsAttrs);
}
// Starting to build query
@@ -356,100 +338,78 @@ class ManageBrickController extends BrickController
// Preparing tabs
// - We need to retrieve distinct values for the grouping attribute
$iCount = 0;
if ($oBrick->HasGroupingTabs())
{
if ($oBrick->HasGroupingTabs()) {
$aGroupingTabs = $oBrick->GetGroupingTabs();
// If tabs are made of the distinct values of an attribute, we have a find them via a query
if ($oBrick->IsGroupingTabsByDistinctValues())
{
if ($oBrick->IsGroupingTabsByDistinctValues()) {
$sGroupingTabAttCode = $aGroupingTabs['attribute'];
$aGroupingTabsValues = $this->GroupByAttribute($oQuery, $sGroupingTabAttCode, $oBrick);
foreach ($aGroupingTabsValues as $aResult)
{
foreach ($aGroupingTabsValues as $aResult) {
$iCount += $aResult['count'];
}
}
// Otherwise we create the tabs from the SQL expressions
else
{
$aConditionQueryGrouping = array();
foreach ($aGroupingTabs['groups'] as $aGroup)
{
else {
$aConditionQueryGrouping = [];
foreach ($aGroupingTabs['groups'] as $aGroup) {
$oDBSearch = DBSearch::FromOQL($aGroup['condition']);
$oConditionQuery = $oQuery->Intersect($oDBSearch);
// - Restricting query to scope
array_push($aConditionQueryGrouping,$oDBSearch);
array_push($aConditionQueryGrouping, $oDBSearch);
$bHasScope = $this->oScopeValidatorHelper->AddScopeToQuery($oConditionQuery, $oConditionQuery->GetClass());
if ($bHasScope)
{
if ($bHasScope) {
// - Building ObjectSet
$oConditionSet = new DBObjectSet($oConditionQuery);
$iGroupCount = $oConditionSet->Count();
}
else
{
} else {
$oConditionSet = null;
$iGroupCount = 0;
}
$aGroupingTabsValues[$aGroup['id']] = array(
$aGroupingTabsValues[$aGroup['id']] = [
'value' => $aGroup['id'],
'label' => Dict::S($aGroup['title']),
'label_html' => Dict::S($aGroup['title']),
'description' => array_key_exists('description',$aGroup) ? Dict::S($aGroup['description']) : null,
'description' => array_key_exists('description', $aGroup) ? Dict::S($aGroup['description']) : null,
'condition' => $oConditionQuery,
'count' => $iGroupCount,
);
];
}
try
{
try {
$oConditionQuery = $oQuery->Intersect(new DBUnionSearch($aConditionQueryGrouping));
$bHasScope = $this->oScopeValidatorHelper->AddScopeToQuery($oConditionQuery, $oConditionQuery->GetClass());
if ($bHasScope)
{
if ($bHasScope) {
// - Building ObjectSet
$oConditionSet = new DBObjectSet($oConditionQuery);
$iCount = $oConditionSet->Count();
}
else
{
} else {
$oConditionSet = null;
$iCount = 0;
}
}
catch (Exception $e){
} catch (Exception $e) {
$oConditionSet = null;
$iCount = -1;
}
}
}
else
{
} else {
$oConditionQuery = $this->GetScopedQuery($oBrick, $sClass);
if (!is_null($oConditionQuery))
{
if (!is_null($oConditionQuery)) {
$oSet = new DBObjectSet($oConditionQuery);
$iCount = $oSet->Count();
}
}
// - Retrieving the current grouping tab to display if necessary and altering the query to do so
if (empty($sGroupingTab))
{
if ($oBrick->HasGroupingTabs())
{
if (empty($sGroupingTab)) {
if ($oBrick->HasGroupingTabs()) {
reset($aGroupingTabsValues);
$sGroupingTab = key($aGroupingTabsValues);
if ($aGroupingTabsValues[$sGroupingTab]['condition'] !== null)
{
if ($aGroupingTabsValues[$sGroupingTab]['condition'] !== null) {
$oQuery = $aGroupingTabsValues[$sGroupingTab]['condition']->DeepClone();
}
}
}
else
{
if ($aGroupingTabsValues[$sGroupingTab]['condition'] !== null)
{
} else {
if ($aGroupingTabsValues[$sGroupingTab]['condition'] !== null) {
$oQuery = $aGroupingTabsValues[$sGroupingTab]['condition']->DeepClone();
}
}
@@ -464,60 +424,56 @@ class ManageBrickController extends BrickController
// - We need to retrieve distinct values for the grouping attribute
// Note : Will have to be changed when we consider grouping on something else than the finalclass
$sParentAlias = $oQuery->GetClassAlias();
if ($bNeedDetails)
{
if ($bNeedDetails) {
$sGroupingAreaAttCode = 'finalclass';
// For root classes
if (MetaModel::IsValidAttCode($sClass, $sGroupingAreaAttCode))
{
if (MetaModel::IsValidAttCode($sClass, $sGroupingAreaAttCode)) {
$oDistinctQuery = $this->GetScopedQuery($oBrick, $sClass);
// Adding grouping conditions
$oFieldExp = new FieldExpression($sGroupingAreaAttCode, $oDistinctQuery->GetClassAlias());
$sDistinctSql = $oDistinctQuery->MakeGroupByQuery(array(), array('grouped_by_1' => $oFieldExp), true);
$sDistinctSql = $oDistinctQuery->MakeGroupByQuery([], ['grouped_by_1' => $oFieldExp], true);
$aDistinctResults = CMDBSource::QueryToArray($sDistinctSql);
foreach ($aDistinctResults as $aDistinctResult)
{
foreach ($aDistinctResults as $aDistinctResult) {
$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GARE');
$oExpression = new BinaryExpression(new FieldExpression($sGroupingAreaAttCode, 'GARE'), '=',
new UnaryExpression($aDistinctResult['grouped_by_1']));
$oExpression = new BinaryExpression(
new FieldExpression($sGroupingAreaAttCode, 'GARE'),
'=',
new UnaryExpression($aDistinctResult['grouped_by_1'])
);
$oConditionQuery->AddConditionExpression($oExpression);
$aGroupingAreasValues[$aDistinctResult['grouped_by_1']] = array(
$aGroupingAreasValues[$aDistinctResult['grouped_by_1']] = [
'value' => $aDistinctResult['grouped_by_1'],
'label' => MetaModel::GetName($aDistinctResult['grouped_by_1']),
// Caution : This works only because we froze the grouping areas on the finalclass attribute.
'condition' => $oConditionQuery,
'count' => $aDistinctResult['_itop_count_'],
);
];
unset($oConditionQuery);
}
unset($aDistinctResults);
}
// For leaf classes
else
{
$aGroupingAreasValues[$sClass] = array(
else {
$aGroupingAreasValues[$sClass] = [
'value' => $sClass,
'label' => MetaModel::GetName($sClass),
// Caution : This works only because we froze the grouping areas on the finalclass attribute.
'condition' => null,
'count' => 0,
);
];
}
// - If specified or lazy loading, we truncate the $aGroupingAreasValues to keep only this one
if (!empty($sGroupingArea))
{
$aGroupingAreasValues = array($sGroupingArea => $aGroupingAreasValues[$sGroupingArea]);
if (!empty($sGroupingArea)) {
$aGroupingAreasValues = [$sGroupingArea => $aGroupingAreasValues[$sGroupingArea]];
}
// - Preparing the queries
foreach ($aGroupingAreasValues as $sKey => $aGroupingAreasValue)
{
foreach ($aGroupingAreasValues as $sKey => $aGroupingAreasValue) {
$oAreaQuery = DBSearch::CloneWithAlias($oQuery, $sParentAlias);
if ($aGroupingAreasValue['condition'] !== null)
{
if ($aGroupingAreasValue['condition'] !== null) {
$oAreaQuery = $aGroupingAreasValue['condition']->DeepClone();
}
@@ -525,8 +481,7 @@ class ManageBrickController extends BrickController
// Note: Will need to moved the scope restriction on queries elsewhere when we consider grouping on something else than finalclass
// Note: We now get view scope instead of edit scope as we allowed users to view/edit objects in the brick regarding their rights
$bHasScope = $this->oScopeValidatorHelper->AddScopeToQuery($oAreaQuery, $aGroupingAreasValue['value']);
if (!$bHasScope)
{
if (!$bHasScope) {
// if no scope apply does not allow any data
$oAreaQuery = null;
}
@@ -538,71 +493,64 @@ class ManageBrickController extends BrickController
// Testing appropriate data loading mode if we are in auto
// - For all (html) tables, this doesn't care for the grouping ares (finalclass)
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_AUTO)
{
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_AUTO) {
// - Check how many records there is.
// - Update $sDataLoading with its new value regarding the number of record and the threshold
$oCountSet = new DBObjectSet($oQuery);
$oCountSet->OptimizeColumnLoad(array($oQuery->GetClassAlias() => array()));
$fThreshold = (float)MetaModel::GetModuleSetting($sPortalId,
'lazy_loading_threshold');
$oCountSet->OptimizeColumnLoad([$oQuery->GetClassAlias() => []]);
$fThreshold = (float)MetaModel::GetModuleSetting(
$sPortalId,
'lazy_loading_threshold'
);
$sDataLoading = ($oCountSet->Count() > $fThreshold) ? AbstractBrick::ENUM_DATA_LOADING_LAZY : AbstractBrick::ENUM_DATA_LOADING_FULL;
unset($oCountSet);
}
// Preparing data sets
$aSets = array();
$aSets = [];
/** @var DBSearch $oQuery */
foreach ($aQueries as $sKey => $oQuery)
{
foreach ($aQueries as $sKey => $oQuery) {
// Checking if we have a valid query
if ($oQuery !== null)
{
if ($oQuery !== null) {
// - Adding search clause if necessary
$this->ManageSearchValue($aData, $oQuery, $sKey, $aColumnsAttrs);
// Setting query pagination if needed
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY)
{
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_LAZY) {
// Retrieving parameters
$iPageNumber = (int)$this->oRequestManipulatorHelper->ReadParam('iPageNumber', 1, FILTER_SANITIZE_NUMBER_INT);
$iListLength = (int)$this->oRequestManipulatorHelper->ReadParam('iListLength', ManageBrick::DEFAULT_LIST_LENGTH,
FILTER_SANITIZE_NUMBER_INT);
$iListLength = (int)$this->oRequestManipulatorHelper->ReadParam(
'iListLength',
ManageBrick::DEFAULT_LIST_LENGTH,
FILTER_SANITIZE_NUMBER_INT
);
// Getting total records number
$oCountSet = new DBObjectSet($oQuery);
$oCountSet->OptimizeColumnLoad(array($oQuery->GetClassAlias() => $aColumnsAttrs));
$oCountSet->OptimizeColumnLoad([$oQuery->GetClassAlias() => $aColumnsAttrs]);
$aData['recordsTotal'] = $oCountSet->Count();
$aData['recordsFiltered'] = $oCountSet->Count();
unset($oCountSet);
$oSet = new DBObjectSet($oQuery);
$oSet->SetLimit($iListLength, $iListLength * ($iPageNumber - 1));
}
else
{
} else {
$oSet = new DBObjectSet($oQuery);
}
// Setting specified column sort, setting default datamodel one otherwise
if (!empty($aSortedParams))
{
if (!empty($aSortedParams)) {
$oSet->SetOrderBy($aSortedParams);
}
else
{
} else {
$oSet->SetOrderByClasses();
}
// Adding always_in_tables attributes
$aColumnsToLoad = array($oQuery->GetClassAlias() => $aColumnsAttrs);
foreach ($oQuery->GetSelectedClasses() as $sAlias => $sClassSelected)
{
$aColumnsToLoad = [$oQuery->GetClassAlias() => $aColumnsAttrs];
foreach ($oQuery->GetSelectedClasses() as $sAlias => $sClassSelected) {
/** @var AttributeDefinition $oAttDef */
foreach (MetaModel::ListAttributeDefs($sClassSelected) as $sAttCode => $oAttDef)
{
if ($oAttDef->AlwaysLoadInTables())
{
foreach (MetaModel::ListAttributeDefs($sClassSelected) as $sAttCode => $oAttDef) {
if ($oAttDef->AlwaysLoadInTables()) {
$aColumnsToLoad[$sAlias][] = $sAttCode;
}
}
@@ -610,17 +558,18 @@ class ManageBrickController extends BrickController
// Note: $aColumnToLoad already contains array of aliases => attcodes
$oSet->OptimizeColumnLoad($aColumnsToLoad);
$this->oSecurityHelper->PreloadForCache($oSet->GetFilter(),
$aColumnsToLoad[$oQuery->GetClassAlias()] /* preloading only extkeys from the main class */);
$this->oSecurityHelper->PreloadForCache(
$oSet->GetFilter(),
$aColumnsToLoad[$oQuery->GetClassAlias()] /* preloading only extkeys from the main class */
);
$aSets[$sKey] = $oSet;
}
}
// Retrieving and preparing data for rendering
$aGroupingAreasData = array();
$aGroupingAreasData = [];
$bHasObjectListItemExtension = false;
foreach ($aSets as $sKey => $oSet)
{
foreach ($aSets as $sKey => $oSet) {
// Set properties
$sCurrentClass = $sKey;
@@ -628,94 +577,88 @@ class ManageBrickController extends BrickController
$sMainActionAttrCode = $aColumnsAttrs[0];
// Loading columns definition
$aColumnsDefinition = array();
foreach ($aColumnsAttrs as $sColumnAttr)
{
$aColumnsDefinition = [];
foreach ($aColumnsAttrs as $sColumnAttr) {
$oAttDef = MetaModel::GetAttributeDef($sKey, $sColumnAttr);
$aColumnsDefinition[$sColumnAttr] = array(
$aColumnsDefinition[$sColumnAttr] = [
'title' => $oAttDef->GetLabel(),
'type' => ($oAttDef instanceof AttributeDateTime) ? 'moment-'.$oAttDef->GetFormat()->ToMomentJS() : 'html',
// Special sorting for Date & Time
);
];
}
// Getting items
$aItems = array();
$aItems = [];
// ... For each item
/** @var DBObject $oCurrentRow */
while ($oCurrentRow = $oSet->Fetch())
{
while ($oCurrentRow = $oSet->Fetch()) {
$sCurrentObjectClass = get_class($oCurrentRow);
$sCurrentObjectId = $oCurrentRow->GetKey();
// ... Retrieving item's attributes values
$aItemAttrs = array();
foreach ($aColumnsAttrs as $sItemAttr)
{
$aActions = array();
$aItemAttrs = [];
foreach ($aColumnsAttrs as $sItemAttr) {
$aActions = [];
// Set the edit action to the main (first) attribute only
//if ($sItemAttr === $sTitleAttrCode)
if ($sItemAttr === $sMainActionAttrCode)
{
if ($sItemAttr === $sMainActionAttrCode) {
// Checking if we can edit the object
if (($oBrick->GetOpeningMode() === ManageBrick::ENUM_ACTION_EDIT) && $this->oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY,
$sCurrentClass, $oCurrentRow->GetKey()))
{
if (($oBrick->GetOpeningMode() === ManageBrick::ENUM_ACTION_EDIT) && $this->oSecurityHelper->IsActionAllowed(
UR_ACTION_MODIFY,
$sCurrentClass,
$oCurrentRow->GetKey()
)) {
$sActionType = ManageBrick::ENUM_ACTION_EDIT;
}
// - Otherwise, check if view is allowed
elseif ($this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sCurrentClass,
$oCurrentRow->GetKey()))
{
elseif ($this->oSecurityHelper->IsActionAllowed(
UR_ACTION_READ,
$sCurrentClass,
$oCurrentRow->GetKey()
)) {
$sActionType = ManageBrick::ENUM_ACTION_VIEW;
}
else
{
} else {
$sActionType = null;
}
// - Then set allowed action
if ($sActionType !== null)
{
$aActions[] = array(
if ($sActionType !== null) {
$aActions[] = [
'type' => $sActionType,
'class' => $sCurrentClass,
'id' => $oCurrentRow->GetKey(),
'opening_target' => $oBrick->GetOpeningTarget(),
);
];
}
}
/** @var \AttributeDefinition $oAttDef */
$oAttDef = MetaModel::GetAttributeDef($sCurrentClass, $sItemAttr);
$sAttDefClass = get_class($oAttDef);
if ($oAttDef->IsExternalKey())
{
if ($oAttDef->IsExternalKey()) {
/** @var \AttributeExternalKey $oAttDef */
$sValue = $oCurrentRow->GetAsHTML($sItemAttr.'_friendlyname');
$sSortValue = $oCurrentRow->Get($sItemAttr.'_friendlyname');
// Adding a view action on the external keys
if ($oCurrentRow->Get($sItemAttr) !== $oAttDef->GetNullValue())
{
if ($oCurrentRow->Get($sItemAttr) !== $oAttDef->GetNullValue()) {
// Checking if we can view the object
if (($this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $oAttDef->GetTargetClass(),
$oCurrentRow->Get($sItemAttr))))
{
$aActions[] = array(
if (($this->oSecurityHelper->IsActionAllowed(
UR_ACTION_READ,
$oAttDef->GetTargetClass(),
$oCurrentRow->Get($sItemAttr)
))) {
$aActions[] = [
'type' => ManageBrick::ENUM_ACTION_VIEW,
'class' => $oAttDef->GetTargetClass(),
'id' => $oCurrentRow->Get($sItemAttr),
'opening_target' => $oBrick->GetOpeningTarget(),
);
];
}
}
}
elseif ($oAttDef instanceof AttributeImage)
{
} elseif ($oAttDef instanceof AttributeImage) {
/** @var \ormDocument $oOrmDoc */
$oOrmDoc = $oCurrentRow->Get($sItemAttr);
if (is_object($oOrmDoc) && !$oOrmDoc->IsEmpty())
{
if (is_object($oOrmDoc) && !$oOrmDoc->IsEmpty()) {
$sUrl = $this->oUrlGenerator->generate('p_object_document_display', [
'sObjectClass' => get_class($oCurrentRow),
'sObjectId' => $oCurrentRow->GetKey(),
@@ -723,16 +666,12 @@ class ManageBrickController extends BrickController
'cache' => 86400,
's' => $oOrmDoc->GetSignature(),
]);
}
else
{
} else {
$sUrl = $oAttDef->Get('default_image');
}
$sValue = '<img src="'.$sUrl.'" />';
$sSortValue = null;
}
elseif ($oAttDef instanceof AttributeTagSet)
{
} elseif ($oAttDef instanceof AttributeTagSet) {
/** @var \ormTagSet $oSetValues */
$oSetValues = $oCurrentRow->Get($sItemAttr);
$aCodes = $oSetValues->GetTags();
@@ -754,17 +693,15 @@ class ManageBrickController extends BrickController
// For simple fields, we get the raw (stored) value as well
$bExcludeRawValue = false;
foreach (ApplicationHelper::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude)
{
if (is_a($sAttDefClass, $sAttDefClassToExclude, true))
{
foreach (ApplicationHelper::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude) {
if (is_a($sAttDefClass, $sAttDefClassToExclude, true)) {
$bExcludeRawValue = true;
break;
}
}
$attValueRaw = ($bExcludeRawValue === false) ? $oCurrentRow->Get($sItemAttr) : null;
$aItemAttrs[$sItemAttr] = array(
$aItemAttrs[$sItemAttr] = [
'object_class' => $sCurrentObjectClass,
'object_id' => $sCurrentObjectId,
'attribute_code' => $sItemAttr,
@@ -773,114 +710,105 @@ class ManageBrickController extends BrickController
'value_html' => $sValue,
'sort_value' => $sSortValue,
'actions' => $aActions,
);
];
}
// ... Checking menu extensions
$aItemButtons = array();
$aItemButtons = [];
/** @var iPopupMenuExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance)
{
foreach ($oExtensionInstance->EnumItems(iPopupMenuExtension::PORTAL_OBJLISTITEM_ACTIONS, array(
foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance) {
foreach ($oExtensionInstance->EnumItems(iPopupMenuExtension::PORTAL_OBJLISTITEM_ACTIONS, [
'portal_id' => $sPortalId,
'object' => $oCurrentRow,
)) as $oMenuItem)
{
if (is_object($oMenuItem))
{
if ($oMenuItem instanceof JSButtonItem)
{
$aItemButtons[] = $oMenuItem->GetMenuItem() + array(
]) as $oMenuItem) {
if (is_object($oMenuItem)) {
if ($oMenuItem instanceof JSButtonItem) {
$aItemButtons[] = $oMenuItem->GetMenuItem() + [
'js_files' => $oMenuItem->GetLinkedScripts(),
'type' => 'button',
);
}
elseif ($oMenuItem instanceof URLButtonItem)
{
$aItemButtons[] = $oMenuItem->GetMenuItem() + array('type' => 'link');
];
} elseif ($oMenuItem instanceof URLButtonItem) {
$aItemButtons[] = $oMenuItem->GetMenuItem() + ['type' => 'link'];
}
}
}
}
// ... And item's properties
$aItems[] = array(
$aItems[] = [
'id' => $oCurrentRow->GetKey(),
'class' => $sCurrentClass,
'attributes' => $aItemAttrs,
'highlight_class' => $oCurrentRow->GetHilightClass(),
'actions' => $aItemButtons,
);
];
if (!empty($aItemButtons))
{
if (!empty($aItemButtons)) {
$bHasObjectListItemExtension = true;
}
}
// Adding an extra column for object list item extensions
if ($bHasObjectListItemExtension === true)
{
$aColumnsDefinition['_ui_extensions'] = array(
if ($bHasObjectListItemExtension === true) {
$aColumnsDefinition['_ui_extensions'] = [
'title' => Dict::S('Brick:Portal:Manage:Table:ItemActions'),
'type' => 'html',
);
];
}
$aGroupingAreasData[$sKey] = array(
$aGroupingAreasData[$sKey] = [
'sId' => $sKey,
'sTitle' => $aGroupingAreasValues[$sKey]['label'],
'aItems' => $aItems,
'iItemsCount' => $oSet->Count(),
'aColumnsDefinition' => $aColumnsDefinition,
);
];
IssueLog::Debug('Portal ManageBrick query', LogChannels::PORTAL, array(
IssueLog::Debug('Portal ManageBrick query', LogChannels::PORTAL, [
'sPortalId' => $sPortalId,
'sBrickId' => $sBrickId,
'sGroupingTab' => $sGroupingTab,
'oql' => $oSet->GetFilter()->ToOQL(),
'aGroupingTabs' => $aGroupingTabs,
));
]);
}
} else {
$aGroupingAreasData = array();
$aGroupingAreasData = [];
$sGroupingArea = null;
}
// Preparing response
if ($oRequest->isXmlHttpRequest()) {
$aData = $aData + array(
$aData = $aData + [
'data' => $aGroupingAreasData[$sGroupingArea]['aItems'],
);
];
} else {
$aDisplayValues = array();
$aUrls = array();
$aColumns = array();
$aNames = array();
$aDisplayValues = [];
$aUrls = [];
$aColumns = [];
$aNames = [];
if ($bHasScope) {
foreach ($aGroupingTabsValues as $aValues) {
$aDisplayValues[] = array(
$aDisplayValues[] = [
'value' => $aValues['count'],
'label' => $aValues['label'],
'label_html' => $aValues['label_html'],
);
$aUrls[] = $this->oUrlGenerator->generate('p_manage_brick_display_as', array(
];
$aUrls[] = $this->oUrlGenerator->generate('p_manage_brick_display_as', [
'sBrickId' => $sBrickId,
'sDisplayMode' => 'list',
'sGroupingTab' => $aValues['value'],
));
]);
}
foreach ($aDisplayValues as $idx => $aValue)
{
$aColumns[] = array('series_'.$idx, (int)$aValue['value']);
foreach ($aDisplayValues as $idx => $aValue) {
$aColumns[] = ['series_'.$idx, (int)$aValue['value']];
$aNames['series_'.$idx] = $aValue['label'];
}
}
// Preparing data to pass to the templating service
$aData = $aData + array(
$aData = $aData + [
'sFct' => 'count',
'sIconURL' => $sIconURL,
'aColumns' => $aColumns,
@@ -896,7 +824,7 @@ class ManageBrickController extends BrickController
'sDateFormat' => AttributeDate::GetFormat()->ToMomentJS(),
'sDateTimeFormat' => AttributeDateTime::GetFormat()->ToMomentJS(),
'iCount' => $iCount,
);
];
}
return $aData;
@@ -911,7 +839,7 @@ class ManageBrickController extends BrickController
* @throws \CoreException
* @throws \Exception
*/
protected function ManageSearchValue(&$aData, DBSearch &$oQuery, $sClass, $aColumnsAttrs = array())
protected function ManageSearchValue(&$aData, DBSearch &$oQuery, $sClass, $aColumnsAttrs = [])
{
// Getting search value
$sRawSearchValue = trim($this->oRequestManipulatorHelper->ReadParam('sSearchValue', ''));
@@ -975,24 +903,22 @@ class ManageBrickController extends BrickController
* @throws \OQLException
* @throws \Exception
*/
protected function GroupByAttribute(DBSearch $oQuery, $sGroupingTabAttCode, ManageBrick $oBrick) {
protected function GroupByAttribute(DBSearch $oQuery, $sGroupingTabAttCode, ManageBrick $oBrick)
{
$aGroupingTabsValues = array();
$aDistinctResults = array();
$aGroupingTabsValues = [];
$aDistinctResults = [];
$oDistinctQuery = DBSearch::FromOQL($oBrick->GetOql());
$bHasScope = $this->oScopeValidatorHelper->AddScopeToQuery($oDistinctQuery, $oDistinctQuery->GetClass());
if ($bHasScope)
{
if ($bHasScope) {
// - Adding field condition
$oFieldExp = new FieldExpression($sGroupingTabAttCode, $oDistinctQuery->GetClassAlias());
$sDistinctSql = $oDistinctQuery->MakeGroupByQuery(array(), array('grouped_by_1' => $oFieldExp), true);
$sDistinctSql = $oDistinctQuery->MakeGroupByQuery([], ['grouped_by_1' => $oFieldExp], true);
$aDistinctResults = CMDBSource::QueryToArray($sDistinctSql);
if (!empty($aDistinctResults))
{
if (!empty($aDistinctResults)) {
$iLimit = $oBrick->GetGroupLimit();
$aOthers = array();
if ($iLimit > 0)
{
$aOthers = [];
if ($iLimit > 0) {
uasort($aDistinctResults, function ($a, $b) {
$v1 = $a['_itop_count_'];
$v2 = $b['_itop_count_'];
@@ -1000,77 +926,72 @@ class ManageBrickController extends BrickController
return ($v1 == $v2) ? 0 : (($v1 > $v2) ? -1 : 1);
});
if (count($aDistinctResults) > $iLimit)
{
if ($oBrick->ShowGroupOthers())
{
if (count($aDistinctResults) > $iLimit) {
if ($oBrick->ShowGroupOthers()) {
$aOthers = array_slice($aDistinctResults, $iLimit);
}
$aDistinctResults = array_slice($aDistinctResults, 0, $iLimit);
}
}
foreach ($aDistinctResults as $aDistinctResult)
{
foreach ($aDistinctResults as $aDistinctResult) {
$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GTAB');
$oExpression = new BinaryExpression(new FieldExpression($sGroupingTabAttCode,
$oConditionQuery->GetClassAlias()), '=', new UnaryExpression($aDistinctResult['grouped_by_1']));
$oExpression = new BinaryExpression(new FieldExpression(
$sGroupingTabAttCode,
$oConditionQuery->GetClassAlias()
), '=', new UnaryExpression($aDistinctResult['grouped_by_1']));
$oConditionQuery->AddConditionExpression($oExpression);
$sHtmlLabel = $oFieldExp->MakeValueLabel($oDistinctQuery, $aDistinctResult['grouped_by_1'], '');
$aGroupingTabsValues[$aDistinctResult['grouped_by_1']] = array(
$aGroupingTabsValues[$aDistinctResult['grouped_by_1']] = [
'value' => $aDistinctResult['grouped_by_1'],
'label_html' => $sHtmlLabel,
'label' => strip_tags(html_entity_decode($sHtmlLabel, ENT_QUOTES, 'UTF-8')),
'condition' => $oConditionQuery,
'count' => $aDistinctResult['_itop_count_'],
);
];
unset($oConditionQuery);
}
if (!empty($aOthers))
{
if (!empty($aOthers)) {
// Aggregate others
$oConditionQuery = DBSearch::CloneWithAlias($oQuery, 'GTAB');
$oExpression = null;
$iOtherCount = 0;
foreach ($aOthers as $aResult)
{
foreach ($aOthers as $aResult) {
$iOtherCount += $aResult['_itop_count_'];
$oExpr = new BinaryExpression(new FieldExpression($sGroupingTabAttCode,
$oConditionQuery->GetClassAlias()), '=', new UnaryExpression($aResult['grouped_by_1']));
if (is_null($oExpression))
{
$oExpr = new BinaryExpression(new FieldExpression(
$sGroupingTabAttCode,
$oConditionQuery->GetClassAlias()
), '=', new UnaryExpression($aResult['grouped_by_1']));
if (is_null($oExpression)) {
$oExpression = $oExpr;
}
else
{
} else {
$oExpression = new BinaryExpression($oExpression, 'OR', $oExpr);
}
}
$oConditionQuery->AddConditionExpression($oExpression);
$sLabel = Dict::S('Brick:Portal:Manage:Others');
$aGroupingTabsValues['Others'] = array(
$aGroupingTabsValues['Others'] = [
'value' => 'Others',
'label_html' => $sLabel,
'label' => $sLabel,
'condition' => $oConditionQuery,
'count' => $iOtherCount,
);
];
unset($oConditionQuery);
}
}
}
if (empty($aDistinctResults))
{
if (empty($aDistinctResults)) {
$sLabel = Dict::S('Brick:Portal:Manage:All');
$aGroupingTabsValues['undefined'] = array(
$aGroupingTabsValues['undefined'] = [
'value' => 'All',
'label_html' => $sLabel,
'label' => $sLabel,
'condition' => null,
'count' => 0,
);
];
}
return $aGroupingTabsValues;

View File

@@ -36,7 +36,6 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
*/
class SessionMessageController extends AbstractController
{
/**
* @param \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulatorHelper
* @param \Combodo\iTop\Portal\Helper\SessionMessageHelper $oSessionMessageHelper
@@ -46,8 +45,7 @@ class SessionMessageController extends AbstractController
public function __construct(
protected RequestManipulatorHelper $oRequestManipulatorHelper,
protected SessionMessageHelper $oSessionMessageHelper
)
{
) {
}
/**
@@ -57,15 +55,14 @@ class SessionMessageController extends AbstractController
*/
public function AddMessageAction(Request $oRequest)
{
$aData = array();
$aData = [];
// Retrieve parameters
$sMessageSeverity = $this->oRequestManipulatorHelper->ReadParam('sSeverity');
$sMessageContent = $this->oRequestManipulatorHelper->ReadParam('sContent');
// Check parameters consistency
if (empty($sMessageSeverity) || empty($sMessageContent))
{
if (empty($sMessageSeverity) || empty($sMessageContent)) {
throw new HttpException(Response::HTTP_BAD_REQUEST, 'Message must have a severity and a content, make sure both sSeverity & sContent parameters are sent.');
}

View File

@@ -45,6 +45,7 @@ use Symfony\Component\HttpKernel\Exception\HttpException;
use UserRights;
use utils;
use Dict;
/**
* Class UserProfileBrickController
*
@@ -60,7 +61,7 @@ class UserProfileBrickController extends BrickController
* @param \Combodo\iTop\Portal\Brick\BrickCollection $oBrickCollection
* @param \Combodo\iTop\Portal\Routing\UrlGenerator $oUrlGenerator
* @param \Combodo\iTop\Portal\Helper\SecurityHelper $oSecurityHelper
*
* @since 3.2.0 N°6933
*/
@@ -70,12 +71,11 @@ class UserProfileBrickController extends BrickController
protected BrickCollection $oBrickCollection,
protected UrlGenerator $oUrlGenerator,
protected SecurityHelper $oSecurityHelper
)
{
) {
}
/** @var string ENUM_FORM_TYPE_PICTURE */
const ENUM_FORM_TYPE_PICTURE = 'picture';
public const ENUM_FORM_TYPE_PICTURE = 'picture';
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
@@ -92,26 +92,20 @@ class UserProfileBrickController extends BrickController
public function DisplayAction(Request $oRequest, $sBrickId)
{
// If the brick id was not specified, we get the first one registered that is an instance of UserProfileBrick as default
if ($sBrickId === null)
{
if ($sBrickId === null) {
/** @var \Combodo\iTop\Portal\Brick\PortalBrick $oTmpBrick */
foreach ($this->oBrickCollection->GetBricks() as $oTmpBrick)
{
if ($oTmpBrick instanceof UserProfileBrick)
{
foreach ($this->oBrickCollection->GetBricks() as $oTmpBrick) {
if ($oTmpBrick instanceof UserProfileBrick) {
$oBrick = $oTmpBrick;
}
}
// We make sure a UserProfileBrick was found
if (!isset($oBrick) || $oBrick === null)
{
if (!isset($oBrick) || $oBrick === null) {
$oBrick = new UserProfileBrick();
//throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'UserProfileBrick : Brick could not be loaded as there was no UserProfileBrick loaded in the application.');
}
}
else
{
} else {
$oBrick = $this->oBrickCollection->GetBrickById($sBrickId);
}
@@ -124,11 +118,14 @@ class UserProfileBrickController extends BrickController
$sTab = $this->oRequestManipulatorHelper->ReadParam('sTab', 'user-info', FILTER_UNSAFE_RAW, FILTER_FLAG_EMPTY_STRING_NULL);
// If this is ajax call, we are just submitting preferences or password forms
if ($oRequest->isXmlHttpRequest())
{
if ($oRequest->isXmlHttpRequest()) {
if ($sTab === "user-info") {
$aCurrentValues = $this->oRequestManipulatorHelper->ReadParam('current_values', array(), FILTER_UNSAFE_RAW,
FILTER_REQUIRE_ARRAY);
$aCurrentValues = $this->oRequestManipulatorHelper->ReadParam(
'current_values',
[],
FILTER_UNSAFE_RAW,
FILTER_REQUIRE_ARRAY
);
$sFormType = $aCurrentValues['form_type'];
if ($sFormType === PreferencesFormManager::FORM_TYPE) {
$aData['form'] = $this->HandlePreferencesForm($oRequest, $sFormMode);
@@ -143,8 +140,7 @@ class UserProfileBrickController extends BrickController
$oResponse = new JsonResponse($aData);
}
// Else, we are displaying page for first time
else
{
else {
if ($sTab === "user-info") {
// Retrieving current contact
/** @var \DBObject $oCurContact */
@@ -175,7 +171,6 @@ class UserProfileBrickController extends BrickController
return $oResponse;
}
private function ManageUserProfileBrickExtensibility(string $sTab, array &$aData): void
{
$aData['sTab'] = $sTab;
@@ -193,7 +188,7 @@ class UserProfileBrickController extends BrickController
// Read the current tab content From iPortalTabSectionExtension
$aTabSectionExtensions = ExtensibilityHelper::GetInstance()->GetPortalTabContentExtensions(iUserProfileTabContentExtension::class, $sTab);
if (count($aTabSectionExtensions) !== 0 && count($_POST) !== 0){
if (count($aTabSectionExtensions) !== 0 && count($_POST) !== 0) {
$sTransactionId = utils::ReadPostedParam('transaction_id', null, utils::ENUM_SANITIZATION_FILTER_TRANSACTION_ID);
IssueLog::Debug(__FUNCTION__.": transaction [$sTransactionId]");
if (utils::IsNullOrEmptyString($sTransactionId) || !utils::IsTransactionValid($sTransactionId, false)) {
@@ -214,30 +209,28 @@ class UserProfileBrickController extends BrickController
}
}
public function EditPerson(Request $oRequest)
{
$oCurContact = UserRights::GetContactObject();
$sObjectClass = get_class($oCurContact);
$sObjectId = $oCurContact->GetKey();
public function EditPerson(Request $oRequest)
{
$oCurContact = UserRights::GetContactObject();
$sObjectClass = get_class($oCurContact);
$sObjectId = $oCurContact->GetKey();
// Checking security layers
// Warning : This is a dirty quick fix to allow editing its own contact information
$bAllowWrite = ($sObjectClass === 'Person' && $sObjectId == UserRights::GetContactId());
if (!$this->oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY, $sObjectClass, $sObjectId) && !$bAllowWrite) {
IssueLog::Warning(__METHOD__.' at line '.__LINE__.' : User #'.UserRights::GetUserId().' not allowed to modify '.$sObjectClass.'::'.$sObjectId.' object.');
throw new HttpException(Response::HTTP_NOT_FOUND, Dict::S('UI:ObjectDoesNotExist'));
}
// Checking security layers
// Warning : This is a dirty quick fix to allow editing its own contact information
$bAllowWrite = ($sObjectClass === 'Person' && $sObjectId == UserRights::GetContactId());
if (!$this->oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY, $sObjectClass, $sObjectId) && !$bAllowWrite) {
IssueLog::Warning(__METHOD__ . ' at line ' . __LINE__ . ' : User #' . UserRights::GetUserId() . ' not allowed to modify ' . $sObjectClass . '::' . $sObjectId . ' object.');
throw new HttpException(Response::HTTP_NOT_FOUND, Dict::S('UI:ObjectDoesNotExist'));
}
$aForm = $this->GetBrick()->GetForm();
$aForm['submit_endpoint'] = $this->generateUrl('p_user_profile_brick_edit_person');
$aForm = $this->GetBrick()->GetForm();
$aForm['submit_endpoint'] = $this->generateUrl('p_user_profile_brick_edit_person');
$aData = ['sMode' => 'edit'];
$aData['form'] = $this->ObjectFormHandlerHelper->HandleForm($oRequest, $aData['sMode'], $sObjectClass, $sObjectId, $aForm);
return new JsonResponse($aData);
}
$aData = ['sMode' => 'edit'];
$aData['form'] = $this->ObjectFormHandlerHelper->HandleForm($oRequest, $aData['sMode'], $sObjectClass, $sObjectId, $aForm);
return new JsonResponse($aData);
}
/**
* @param \Symfony\Component\HttpFoundation\Request $oRequest
@@ -249,13 +242,12 @@ class UserProfileBrickController extends BrickController
*/
public function HandlePreferencesForm(Request $oRequest, $sFormMode)
{
$aFormData = array();
$aFormData = [];
// Handling form
$sOperation = $this->oRequestManipulatorHelper->ReadParam('operation', null);
// - Create
if ($sOperation === null)
{
if ($sOperation === null) {
// - Creating renderer
$oFormRenderer = new BsFormRenderer();
$oFormRenderer->SetEndpoint($this->oUrlGenerator->generate('p_user_profile_brick'));
@@ -264,50 +256,47 @@ class UserProfileBrickController extends BrickController
$oFormManager->SetRenderer($oFormRenderer)
->Build();
// - Checking if we have to make the form read only
if ($sFormMode === ObjectFormHandlerHelper::ENUM_MODE_VIEW)
{
if ($sFormMode === ObjectFormHandlerHelper::ENUM_MODE_VIEW) {
$oFormManager->GetForm()->MakeReadOnly();
}
}
// - Submit
else
{
if ($sOperation === 'submit')
{
else {
if ($sOperation === 'submit') {
$sFormManagerClass = $this->oRequestManipulatorHelper->ReadParam('formmanager_class', null, FILTER_UNSAFE_RAW);
$sFormManagerData = $this->oRequestManipulatorHelper->ReadParam('formmanager_data', null, FILTER_UNSAFE_RAW);
if ($sFormManagerClass === null || $sFormManagerData === null)
{
if ($sFormManagerClass === null || $sFormManagerData === null) {
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Parameters formmanager_class and formmanager_data must be defined.');
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR,
'Parameters formmanager_class and formmanager_data must be defined.');
throw new HttpException(
Response::HTTP_INTERNAL_SERVER_ERROR,
'Parameters formmanager_class and formmanager_data must be defined.'
);
}
// Rebuilding manager from json
/** @var \Combodo\iTop\Form\FormManager $oFormManager */
$oFormManager = $sFormManagerClass::FromJSON($sFormManagerData);
// Applying modification to object
$aFormData['validation'] = $oFormManager->OnSubmit(array(
'currentValues' => $this->oRequestManipulatorHelper->ReadParam('current_values', array(), FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
));
$aFormData['validation'] = $oFormManager->OnSubmit([
'currentValues' => $this->oRequestManipulatorHelper->ReadParam('current_values', [], FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
]);
// Reloading page only if preferences were changed
if (($aFormData['validation']['valid'] === true) && !empty($aFormData['validation']['messages']['success']))
{
$aFormData['validation']['redirection'] = array(
if (($aFormData['validation']['valid'] === true) && !empty($aFormData['validation']['messages']['success'])) {
$aFormData['validation']['redirection'] = [
'url' => $this->oUrlGenerator->generate('p_user_profile_brick'),
'timeout_duration' => 1000, //since there are several ajax request, we use a longer timeout in hope that they will all be finished in time. A promise would have been more reliable, but since this change is made in a minor version, this approach is less error prone.
);
];
}
}
}
// Else, submit from another form
// Preparing field_set data
$aFieldSetData = array(
$aFieldSetData = [
'fields_list' => $oFormManager->GetRenderer()->Render(),
'fields_impacts' => $oFormManager->GetForm()->GetFieldsImpacts(),
'form_path' => $oFormManager->GetForm()->GetId(),
);
];
// Preparing form data
$aFormData['id'] = $oFormManager->GetForm()->GetId();
@@ -329,14 +318,13 @@ class UserProfileBrickController extends BrickController
*/
public function HandlePasswordForm(Request $oRequest, $sFormMode)
{
$aFormData = array();
$aFormData = [];
// Handling form
$sOperation = /** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
$this->oRequestManipulatorHelper->ReadParam('operation', null);
// - Create
if ($sOperation === null)
{
if ($sOperation === null) {
// - Creating renderer
$oFormRenderer = new BsFormRenderer();
$oFormRenderer->SetEndpoint($this->oUrlGenerator->generate('p_user_profile_brick'));
@@ -345,41 +333,40 @@ class UserProfileBrickController extends BrickController
$oFormManager->SetRenderer($oFormRenderer)
->Build();
// - Checking if we have to make the form read only
if ($sFormMode === ObjectFormHandlerHelper::ENUM_MODE_VIEW)
{
if ($sFormMode === ObjectFormHandlerHelper::ENUM_MODE_VIEW) {
$oFormManager->GetForm()->MakeReadOnly();
}
}
// - Submit
else
{
if ($sOperation === 'submit')
{
else {
if ($sOperation === 'submit') {
$sFormManagerClass = $this->oRequestManipulatorHelper->ReadParam('formmanager_class', null, FILTER_UNSAFE_RAW);
$sFormManagerData = $this->oRequestManipulatorHelper->ReadParam('formmanager_data', null, FILTER_UNSAFE_RAW);
if ($sFormManagerClass === null || $sFormManagerData === null) {
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Parameters formmanager_class and formmanager_data must be defined.');
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR,
'Parameters formmanager_class and formmanager_data must be defined.');
throw new HttpException(
Response::HTTP_INTERNAL_SERVER_ERROR,
'Parameters formmanager_class and formmanager_data must be defined.'
);
}
// Rebuilding manager from json
/** @var \Combodo\iTop\Form\FormManager $oFormManager */
$oFormManager = $sFormManagerClass::FromJSON($sFormManagerData);
// Applying modification to object
$aFormData['validation'] = $oFormManager->OnSubmit(array(
'currentValues' => $this->oRequestManipulatorHelper->ReadParam('current_values', array(), FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
));
$aFormData['validation'] = $oFormManager->OnSubmit([
'currentValues' => $this->oRequestManipulatorHelper->ReadParam('current_values', [], FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
]);
}
}
// Else, submit from another form
// Preparing field_set data
$aFieldSetData = array(
$aFieldSetData = [
'fields_list' => $oFormManager->GetRenderer()->Render(),
'fields_impacts' => $oFormManager->GetForm()->GetFieldsImpacts(),
'form_path' => $oFormManager->GetForm()->GetId(),
);
];
// Preparing form data
$aFormData['id'] = $oFormManager->GetForm()->GetId();
@@ -400,32 +387,27 @@ class UserProfileBrickController extends BrickController
*/
public function HandlePictureForm(Request $oRequest)
{
$aFormData = array();
$aFormData = [];
$sPictureAttCode = 'picture';
// Handling form
$sOperation = $this->oRequestManipulatorHelper->ReadParam('operation', null);
// - No operation specified
if ($sOperation === null)
{
if ($sOperation === null) {
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Operation parameter must be specified.');
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Operation parameter must be specified.');
}
// - Submit
else
{
if ($sOperation === 'submit')
{
else {
if ($sOperation === 'submit') {
$oRequestFiles = $oRequest->files;
$oPictureFile = $oRequestFiles->get($sPictureAttCode);
if ($oPictureFile === null)
{
if ($oPictureFile === null) {
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Parameter picture must be defined.');
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Parameter picture must be defined.');
}
try
{
try {
// Retrieving image as an ORMDocument
$oImage = utils::ReadPostedDocument($sPictureAttCode);
// Retrieving current contact
@@ -434,16 +416,19 @@ class UserProfileBrickController extends BrickController
// Resizing image
$oAttDef = MetaModel::GetAttributeDef(get_class($oCurContact), $sPictureAttCode);
$aSize = utils::GetImageSize($oImage->GetData());
$oImage = utils::ResizeImageToFit($oImage, $aSize[0], $aSize[1], $oAttDef->Get('storage_max_width'),
$oAttDef->Get('storage_max_height'));
$oImage = utils::ResizeImageToFit(
$oImage,
$aSize[0],
$aSize[1],
$oAttDef->Get('storage_max_width'),
$oAttDef->Get('storage_max_height')
);
// Setting it to the contact
$oCurContact->Set($sPictureAttCode, $oImage);
// Forcing allowed writing on the object if necessary.
$oCurContact->AllowWrite(true);
$oCurContact->DBUpdate();
}
catch (FileUploadException $e)
{
} catch (FileUploadException $e) {
$aFormData['error'] = $e->GetMessage();
}
@@ -456,10 +441,10 @@ class UserProfileBrickController extends BrickController
'cache' => 86400,
's' => $oOrmDoc->GetSignature(),
]);
$aFormData['validation'] = array(
$aFormData['validation'] = [
'valid' => true,
'messages' => array(),
);
'messages' => [],
];
}
}
@@ -468,30 +453,30 @@ class UserProfileBrickController extends BrickController
return $aFormData;
}
/**
* @param $sBrickId
* @return \Combodo\iTop\Portal\Brick\PortalBrick|UserProfileBrick
* @throws \Combodo\iTop\Portal\Brick\BrickNotFoundException
*/
public function GetBrick($sBrickId = null)
{
// If the brick id was not specified, we get the first one registered that is an instance of UserProfileBrick as default
if ($sBrickId === null) {
/** @var \Combodo\iTop\Portal\Brick\PortalBrick $oTmpBrick */
foreach ($this->oBrickCollection->GetBricks() as $oTmpBrick) {
if ($oTmpBrick instanceof UserProfileBrick) {
$oBrick = $oTmpBrick;
}
}
/**
* @param $sBrickId
* @return \Combodo\iTop\Portal\Brick\PortalBrick|UserProfileBrick
* @throws \Combodo\iTop\Portal\Brick\BrickNotFoundException
*/
public function GetBrick($sBrickId = null)
{
// If the brick id was not specified, we get the first one registered that is an instance of UserProfileBrick as default
if ($sBrickId === null) {
/** @var \Combodo\iTop\Portal\Brick\PortalBrick $oTmpBrick */
foreach ($this->oBrickCollection->GetBricks() as $oTmpBrick) {
if ($oTmpBrick instanceof UserProfileBrick) {
$oBrick = $oTmpBrick;
}
}
// We make sure a UserProfileBrick was found
if (!isset($oBrick) || $oBrick === null) {
$oBrick = new UserProfileBrick();
//throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'UserProfileBrick : Brick could not be loaded as there was no UserProfileBrick loaded in the application.');
}
} else {
$oBrick = $this->oBrickCollection->GetBrickById($sBrickId);
}
return $oBrick;
}
// We make sure a UserProfileBrick was found
if (!isset($oBrick) || $oBrick === null) {
$oBrick = new UserProfileBrick();
//throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'UserProfileBrick : Brick could not be loaded as there was no UserProfileBrick loaded in the application.');
}
} else {
$oBrick = $this->oBrickCollection->GetBrickById($sBrickId);
}
return $oBrick;
}
}

View File

@@ -16,7 +16,6 @@ use Throwable;
*/
class PortalCollector extends AbstractDataCollector
{
/**
* Constructor.
*
@@ -90,13 +89,13 @@ class PortalCollector extends AbstractDataCollector
$iOverridesCount = 0;
$aExtensions = [];
foreach($aTemplatesDefinitions as $templates){
foreach ($aTemplatesDefinitions as $templates) {
foreach ($templates as $template) {
$aMatches = [];
preg_match('#([\w-]+)/#', $template->GetPath(), $aMatches);
if(!in_array($aMatches[1], $aExtensions)){
if (!in_array($aMatches[1], $aExtensions)) {
$aExtensions[] = $aMatches[1];
}
@@ -124,4 +123,4 @@ class PortalCollector extends AbstractDataCollector
return 'portal';
}
}
}

View File

@@ -52,4 +52,4 @@ class AbstractConfiguration
return $this->oModuleDesign;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -44,8 +45,7 @@ class Basic extends AbstractConfiguration
*/
public function Process(Container $oContainer)
{
try
{
try {
// Parsing file
// - Default values
$aPortalConf = $this->GetInitialPortalConf();
@@ -55,9 +55,7 @@ class Basic extends AbstractConfiguration
$aPortalConf = $this->AppendLogoUri($aPortalConf);
// - Rectifying portal favicon url
$aPortalConf = $this->AppendFavIconUri($aPortalConf);
}
catch (Exception $oException)
{
} catch (Exception $oException) {
throw new Exception('Error while parsing portal configuration file : '.$oException->getMessage());
}
@@ -72,35 +70,35 @@ class Basic extends AbstractConfiguration
*/
private function GetInitialPortalConf()
{
$aPortalConf = array(
'properties' => array(
$aPortalConf = [
'properties' => [
'id' => $_ENV['PORTAL_ID'],
'ui_version' => '2017',
'name' => 'Page:DefaultTitle',
'logo' => Branding::GetPortalLogoAbsoluteUrl(),
'favicon' => Branding::GetPortalFavIconAbsoluteUrl(),
'themes' => array(
'themes' => [
'bootstrap' => 'itop-portal-base/portal/public/css/bootstrap-theme-combodo.scss',
'portal' => 'itop-portal-base/portal/public/css/portal.scss',
'others' => array(),
),
'templates' => array(
'others' => [],
],
'templates' => [
'layout' => 'itop-portal-base/portal/templates/layout.html.twig',
'home' => 'itop-portal-base/portal/templates/home/layout.html.twig',
),
],
'urlmaker_class' => null,
'triggers_query' => null,
'attachments' => array(
'attachments' => [
'allow_delete' => true,
),
'allowed_portals' => array(
],
'allowed_portals' => [
'opening_mode' => null,
),
),
'forms' => array(),
'bricks' => array(),
],
],
'forms' => [],
'bricks' => [],
'bricks_total_width' => 0,
);
];
return $aPortalConf;
}
@@ -114,10 +112,8 @@ class Basic extends AbstractConfiguration
private function ParseGlobalProperties(array $aPortalConf)
{
/** @var \MFElement $oPropertyNode */
foreach ($this->GetModuleDesign()->GetNodes('/module_design/properties/*') as $oPropertyNode)
{
switch ($oPropertyNode->nodeName)
{
foreach ($this->GetModuleDesign()->GetNodes('/module_design/properties/*') as $oPropertyNode) {
switch ($oPropertyNode->nodeName) {
case 'ui_version':
case 'name':
case 'urlmaker_class':
@@ -154,22 +150,20 @@ class Basic extends AbstractConfiguration
private function ParseTemplateAndTheme(array $aPortalConf, DesignElement $oPropertyNode)
{
/** @var \MFElement $oSubNode */
foreach ($oPropertyNode->GetNodes('template|theme') as $oSubNode)
{
if (!$oSubNode->hasAttribute('id') || $oSubNode->GetText(null) === null)
{
foreach ($oPropertyNode->GetNodes('template|theme') as $oSubNode) {
if (!$oSubNode->hasAttribute('id') || $oSubNode->GetText(null) === null) {
throw new DOMFormatException(
'Tag '.$oSubNode->nodeName.' must have a "id" attribute as well as a value',
null, null, $oSubNode
null,
null,
$oSubNode
);
}
$sNodeId = $oSubNode->getAttribute('id');
switch ($oSubNode->nodeName)
{
switch ($oSubNode->nodeName) {
case 'theme':
switch ($sNodeId)
{
switch ($sNodeId) {
case 'bootstrap':
case 'portal':
case 'custom':
@@ -181,8 +175,7 @@ class Basic extends AbstractConfiguration
}
break;
case 'template':
switch ($sNodeId)
{
switch ($sNodeId) {
case 'layout':
case 'home':
$aPortalConf['properties']['templates'][$sNodeId] = $oSubNode->GetText(null);
@@ -190,19 +183,21 @@ class Basic extends AbstractConfiguration
default:
$aMatches = [];
// allowed format is: <class implementing TemplatesProviderInterface>:<template_id>
if(preg_match('#([\w\\\d_]+):(\w+)#', $sNodeId, $aMatches)){
try{
if (preg_match('#([\w\\\d_]+):(\w+)#', $sNodeId, $aMatches)) {
try {
$oClass = new ReflectionClass($aMatches[1]);
if($oClass->implementsInterface(TemplatesProviderInterface::class)){
if ($oClass->implementsInterface(TemplatesProviderInterface::class)) {
$aPortalConf['properties']['templates'][$aMatches[1]][$aMatches[2]] = $oSubNode->GetText(null);
break;
}
} catch (Exception) {
}
catch(Exception){}
}
throw new DOMFormatException(
'Template ID "'.$sNodeId.'" is not handled in module design templates property',
null, null, $oSubNode
null,
null,
$oSubNode
);
}
break;
@@ -221,16 +216,13 @@ class Basic extends AbstractConfiguration
private function ParseAttachments(array $aPortalConf, DesignElement $oPropertyNode)
{
/** @var \MFElement $oSubNode */
foreach ($oPropertyNode->GetNodes('*') as $oSubNode)
{
switch ($oSubNode->nodeName)
{
foreach ($oPropertyNode->GetNodes('*') as $oSubNode) {
switch ($oSubNode->nodeName) {
case 'allow_delete':
$sValue = $oSubNode->GetText();
// If the text is null, we keep the default value
// Else we set it
if ($sValue !== null)
{
if ($sValue !== null) {
$aPortalConf['properties']['attachments'][$oSubNode->nodeName] = ($sValue === 'true') ? true : false;
}
break;
@@ -249,16 +241,13 @@ class Basic extends AbstractConfiguration
private function ParseAllowedPortalsOptions(array $aPortalConf, DesignElement $oPropertyNode)
{
/** @var \MFElement $oSubNode */
foreach ($oPropertyNode->GetNodes('*') as $oSubNode)
{
switch ($oSubNode->nodeName)
{
foreach ($oPropertyNode->GetNodes('*') as $oSubNode) {
switch ($oSubNode->nodeName) {
case 'opening_mode':
$sValue = $oSubNode->GetText();
// If the text is null, we keep the default value
// Else we set it
if ($sValue !== null)
{
if ($sValue !== null) {
$aPortalConf['properties']['allowed_portals'][$oSubNode->nodeName] = ($sValue === 'self') ? 'self' : 'tab';
}
break;
@@ -304,4 +293,4 @@ class Basic extends AbstractConfiguration
return $aPortalConf;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -42,23 +43,19 @@ class Forms extends AbstractConfiguration
*/
public function Process(Container $oContainer)
{
$aForms = array();
$aForms = [];
/** @var \MFElement $oFormNode */
foreach ($this->GetModuleDesign()->GetNodes('/module_design/forms/form') as $oFormNode)
{
try
{
foreach ($this->GetModuleDesign()->GetNodes('/module_design/forms/form') as $oFormNode) {
try {
// Parsing form id
$sFormId = $oFormNode->getAttribute('id');
if ($oFormNode->getAttribute('id') === '')
{
if ($oFormNode->getAttribute('id') === '') {
throw new DOMFormatException('form tag must have an id attribute', 0, null, $oFormNode);
}
// Parsing form object class
if ($oFormNode->GetUniqueElement('class')->GetText() === null)
{
if ($oFormNode->GetUniqueElement('class')->GetText() === null) {
throw new DOMFormatException('Class tag must be defined', 0, null, $oFormNode);
}
@@ -66,29 +63,26 @@ class Forms extends AbstractConfiguration
$sFormClass = $oFormNode->GetUniqueElement('class')->GetText();
// Parsing properties
$aFormProperties = array(
$aFormProperties = [
'display_mode' => ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE,
'always_show_submit' => ApplicationHelper::FORM_DEFAULT_ALWAYS_SHOW_SUBMIT,
'navigation_rules' => array(
'submit' => array(
'navigation_rules' => [
'submit' => [
NavigationRuleHelper::ENUM_ORIGIN_PAGE => null,
NavigationRuleHelper::ENUM_ORIGIN_MODAL => null,
),
'cancel' => array(
],
'cancel' => [
NavigationRuleHelper::ENUM_ORIGIN_PAGE => null,
NavigationRuleHelper::ENUM_ORIGIN_MODAL => null,
),
),
);
],
],
];
$aAllowedNavRulesButtonCodes = array_keys($aFormProperties['navigation_rules']);
if ($oFormNode->GetOptionalElement('properties') !== null)
{
if ($oFormNode->GetOptionalElement('properties') !== null) {
/** @var \MFElement $oPropertyNode */
foreach ($oFormNode->GetOptionalElement('properties')->GetNodes('*') as $oPropertyNode)
{
switch ($oPropertyNode->nodeName)
{
foreach ($oFormNode->GetOptionalElement('properties')->GetNodes('*') as $oPropertyNode) {
switch ($oPropertyNode->nodeName) {
case 'display_mode':
$aFormProperties['display_mode'] = $oPropertyNode->GetText(ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE);
break;
@@ -99,28 +93,23 @@ class Forms extends AbstractConfiguration
case 'navigation_rules':
/** @var \MFElement $oNavRuleButtonNode */
foreach($oPropertyNode->GetNodes('*') as $oNavRuleButtonNode)
{
foreach ($oPropertyNode->GetNodes('*') as $oNavRuleButtonNode) {
$sNavRuleButtonCode = $oNavRuleButtonNode->nodeName;
if(!in_array($sNavRuleButtonCode, $aAllowedNavRulesButtonCodes))
{
if (!in_array($sNavRuleButtonCode, $aAllowedNavRulesButtonCodes)) {
throw new DOMFormatException('navigation_rules tag must only contain '.implode('|', $aAllowedNavRulesButtonCodes).' tags, "'.$sNavRuleButtonCode.'" given.', null, null, $oPropertyNode);
}
/** @var \MFElement $oNavRuleOriginNode */
foreach($oNavRuleButtonNode->GetNodes('*') as $oNavRuleOriginNode)
{
foreach ($oNavRuleButtonNode->GetNodes('*') as $oNavRuleOriginNode) {
$sNavRuleOrigin = $oNavRuleOriginNode->nodeName;
if(!in_array($sNavRuleOrigin, NavigationRuleHelper::GetAllowedOrigins()))
{
throw new DOMFormatException($sNavRuleButtonCode. ' tag must only contain '.implode('|', NavigationRuleHelper::GetAllowedOrigins()).' tags, "'.$sNavRuleOrigin.'" given.', null, null, $oPropertyNode);
if (!in_array($sNavRuleOrigin, NavigationRuleHelper::GetAllowedOrigins())) {
throw new DOMFormatException($sNavRuleButtonCode.' tag must only contain '.implode('|', NavigationRuleHelper::GetAllowedOrigins()).' tags, "'.$sNavRuleOrigin.'" given.', null, null, $oPropertyNode);
}
$sNavRuleId = $oNavRuleOriginNode->GetText();
// Note: We don't check is rule exists as it would introduce a dependency to the NavigationRuleHelper service.
// Maybe we will consider it later.
if(empty($sNavRuleId))
{
if (empty($sNavRuleId)) {
throw new DOMFormatException($sNavRuleButtonCode.' tag cannot be empty.', null, null, $oPropertyNode);
}
@@ -129,8 +118,7 @@ class Forms extends AbstractConfiguration
// Set modal rule as the same as default is not present.
// We preset it so we don't have to make checks elsewhere in the code when using it.
if(empty($aFormProperties['navigation_rules'][$sNavRuleButtonCode][NavigationRuleHelper::ENUM_ORIGIN_MODAL]))
{
if (empty($aFormProperties['navigation_rules'][$sNavRuleButtonCode][NavigationRuleHelper::ENUM_ORIGIN_MODAL])) {
$aFormProperties['navigation_rules'][$sNavRuleButtonCode][NavigationRuleHelper::ENUM_ORIGIN_MODAL] = $aFormProperties['navigation_rules'][$sNavRuleButtonCode][NavigationRuleHelper::ENUM_ORIGIN_PAGE];
}
}
@@ -139,36 +127,33 @@ class Forms extends AbstractConfiguration
}
// Parsing available modes for that form (view, edit, create, apply_stimulus)
$aFormStimuli = array();
if (($oFormNode->GetOptionalElement('modes') !== null) && ($oFormNode->GetOptionalElement('modes')->GetNodes('mode')->length > 0))
{
$aModes = array();
$aFormStimuli = [];
if (($oFormNode->GetOptionalElement('modes') !== null) && ($oFormNode->GetOptionalElement('modes')->GetNodes('mode')->length > 0)) {
$aModes = [];
/** @var \MFElement $oModeNode */
foreach ($oFormNode->GetOptionalElement('modes')->GetNodes('mode') as $oModeNode)
{
foreach ($oFormNode->GetOptionalElement('modes')->GetNodes('mode') as $oModeNode) {
$sModeId = $oModeNode->getAttribute('id');
if ($sModeId === '')
{
throw new DOMFormatException('mode tag must have an id attribute', 0, null,
$oFormNode);
if ($sModeId === '') {
throw new DOMFormatException(
'mode tag must have an id attribute',
0,
null,
$oFormNode
);
}
$aModes[] = $sModeId;
// If apply_stimulus mode, checking if stimuli are defined
if ($sModeId === 'apply_stimulus')
{
if ($sModeId === 'apply_stimulus') {
$oStimuliNode = $oModeNode->GetOptionalElement('stimuli');
// If stimuli are defined, we overwrite the form that could have been set by the generic form
if ($oStimuliNode !== null)
{
if ($oStimuliNode !== null) {
/** @var \MFElement $oStimulusNode */
foreach ($oStimuliNode->GetNodes('stimulus') as $oStimulusNode)
{
foreach ($oStimuliNode->GetNodes('stimulus') as $oStimulusNode) {
$sStimulusCode = $oStimulusNode->getAttribute('id');
// Removing default form if present (in case the default forms were parsed before the current one (from current or parent class))
if (isset($aForms[$sFormClass]['apply_stimulus'][$sStimulusCode]))
{
if (isset($aForms[$sFormClass]['apply_stimulus'][$sStimulusCode])) {
unset($aForms[$sFormClass]['apply_stimulus'][$sStimulusCode]);
}
@@ -177,111 +162,95 @@ class Forms extends AbstractConfiguration
}
}
}
}
else
{
} else {
// If no mode was specified, we set it all but stimuli as it would have no sense that every transition forms
// have as many fields displayed as a regular edit form for example.
$aModes = array('view', 'edit', 'create');
$aModes = ['view', 'edit', 'create'];
}
// Parsing fields
$aFields = array(
$aFields = [
'_brought_by' => $sFormClass,
'id' => $sFormId,
'type' => null,
'properties' => $aFormProperties,
'fields' => null,
'layout' => null,
);
];
// ... either enumerated fields ...
if ($oFormNode->GetOptionalElement('fields') !== null)
{
if ($oFormNode->GetOptionalElement('fields') !== null) {
$aFields['type'] = 'custom_list';
$aFields['fields'] = array();
$aFields['fields'] = [];
/** @var \MFElement $oFieldNode */
foreach ($oFormNode->GetOptionalElement('fields')->GetNodes('field') as $oFieldNode)
{
foreach ($oFormNode->GetOptionalElement('fields')->GetNodes('field') as $oFieldNode) {
$sFieldId = $oFieldNode->getAttribute('id');
if ($sFieldId !== '')
{
$aField = array();
if ($sFieldId !== '') {
$aField = [];
// Parsing field options like read_only, hidden and mandatory
if ($oFieldNode->GetOptionalElement('read_only'))
{
if ($oFieldNode->GetOptionalElement('read_only')) {
$aField['readonly'] = ($oFieldNode->GetOptionalElement('read_only')->GetText('true') === 'true') ? true : false;
}
if ($oFieldNode->GetOptionalElement('mandatory'))
{
if ($oFieldNode->GetOptionalElement('mandatory')) {
$aField['mandatory'] = ($oFieldNode->GetOptionalElement('mandatory')->GetText('true') === 'true') ? true : false;
}
if ($oFieldNode->GetOptionalElement('hidden'))
{
if ($oFieldNode->GetOptionalElement('hidden')) {
$aField['hidden'] = ($oFieldNode->GetOptionalElement('hidden')->GetText('true') === 'true') ? true : false;
}
$aFields['fields'][$sFieldId] = $aField;
}
else
{
throw new DOMFormatException('Field tag must have an id attribute', 0, null,
$oFormNode);
} else {
throw new DOMFormatException(
'Field tag must have an id attribute',
0,
null,
$oFormNode
);
}
}
}
// ... or the default zlist
else
{
else {
$aFields['type'] = 'zlist';
$aFields['fields'] = 'details';
}
// Parsing presentation
if ($oFormNode->GetOptionalElement('twig') !== null)
{
if ($oFormNode->GetOptionalElement('twig') !== null) {
// Extracting the twig template and removing the first and last lines (twig tags)
$sXml = $this->GetModuleDesign()->saveXML($oFormNode->GetOptionalElement('twig'));
$sXml = preg_replace('/^.+\n/', '', $sXml);
$sXml = preg_replace('/\n.+$/', '', $sXml);
$aFields['layout'] = array(
$aFields['layout'] = [
'type' => (preg_match('/{{|{#|{%/', $sXml) === 1) ? 'twig' : 'xhtml',
'content' => $sXml,
);
];
}
// Adding form for each class / mode
foreach ($aModes as $sMode)
{
foreach ($aModes as $sMode) {
// Initializing current class if necessary
if (!isset($aForms[$sFormClass]))
{
$aForms[$sFormClass] = array();
if (!isset($aForms[$sFormClass])) {
$aForms[$sFormClass] = [];
}
// For stimuli we need to fill the matrix as only some stimuli might have been given
if ($sMode === 'apply_stimulus')
{
if ($sMode === 'apply_stimulus') {
// Iterating over current class and child classes
foreach (MetaModel::EnumChildClasses($sFormClass, ENUM_CHILD_CLASSES_ALL) as $sChildClass)
{
foreach (MetaModel::EnumChildClasses($sFormClass, ENUM_CHILD_CLASSES_ALL) as $sChildClass) {
// Initializing child class if necessary
if (!isset($aForms[$sChildClass][$sMode]))
{
$aForms[$sChildClass][$sMode] = array();
if (!isset($aForms[$sChildClass][$sMode])) {
$aForms[$sChildClass][$sMode] = [];
}
// If no explicit stimulus defined in this form, than it's the generic stimulus form
// we need to find which stimulus are missing
if(empty($aFormStimuli))
{
$aExistingStimuli = array();
if (empty($aFormStimuli)) {
$aExistingStimuli = [];
// Keep only stimuli brought by the class itself
foreach($aForms[$sChildClass][$sMode] as $sExistingStimulus => $aExistingForm)
{
if(!in_array($aExistingForm['_brought_by'], MetaModel::EnumParentClasses($sFormClass, ENUM_PARENT_CLASSES_EXCLUDELEAF)))
{
foreach ($aForms[$sChildClass][$sMode] as $sExistingStimulus => $aExistingForm) {
if (!in_array($aExistingForm['_brought_by'], MetaModel::EnumParentClasses($sFormClass, ENUM_PARENT_CLASSES_EXCLUDELEAF))) {
//continue;
$aExistingStimuli[] = $sExistingStimulus;
}
@@ -290,51 +259,43 @@ class Forms extends AbstractConfiguration
$aMissingStimulusForms = array_diff($aDatamodelStimuli, $aExistingStimuli);
}
// Otherwise, we process only the ones for this form
else
{
else {
$aMissingStimulusForms = $aFormStimuli;
}
// Retrieve missing stimuli of the child class to fill the matrix
foreach ($aMissingStimulusForms as $sDatamodelStimulus)
{
foreach ($aMissingStimulusForms as $sDatamodelStimulus) {
// Check some facts about the target form
$bFormExists = isset($aForms[$sChildClass][$sMode][$sDatamodelStimulus]);
$bWasFormBroughtByParent = $bFormExists && in_array($aForms[$sChildClass][$sMode][$sDatamodelStimulus]['_brought_by'], MetaModel::EnumParentClasses($sFormClass, ENUM_PARENT_CLASSES_EXCLUDELEAF));
// Check if we need to overwrite (form created by parent)
$bOverwriteNecessary = false;
if($bWasFormBroughtByParent || in_array($sDatamodelStimulus, $aFormStimuli))
{
if ($bWasFormBroughtByParent || in_array($sDatamodelStimulus, $aFormStimuli)) {
$bOverwriteNecessary = true;
}
// Setting form if not defined OR if it was defined by a parent (abstract) class
if (!$bFormExists || $bOverwriteNecessary)
{
if (!$bFormExists || $bOverwriteNecessary) {
$aForms[$sChildClass][$sMode][$sDatamodelStimulus] = $aFields;
$aForms[$sChildClass][$sMode][$sDatamodelStimulus]['id'] = 'apply_stimulus-'.$sChildClass.'-'.$sDatamodelStimulus;
}
}
}
}
elseif (!isset($aForms[$sFormClass][$sMode]))
{
} elseif (!isset($aForms[$sFormClass][$sMode])) {
$aForms[$sFormClass][$sMode] = $aFields;
}
else
{
throw new DOMFormatException('There is already a form for the class "'.$sFormClass.'" in "'.$sMode.'"',
null, null, $oFormNode);
} else {
throw new DOMFormatException(
'There is already a form for the class "'.$sFormClass.'" in "'.$sMode.'"',
null,
null,
$oFormNode
);
}
}
}
catch (DOMFormatException $e)
{
} catch (DOMFormatException $e) {
throw new Exception('Could not create from [id="'.$oFormNode->getAttribute('id').'"] from XML because of a DOM problem : '.$e->getMessage());
}
catch (Exception $e)
{
} catch (Exception $e) {
throw new Exception('Could not create from from XML : '.$oFormNode->Dump().' '.$e->getMessage());
}
}
@@ -343,4 +304,4 @@ class Forms extends AbstractConfiguration
$aPortalConf['forms'] = $aForms;
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -39,51 +40,52 @@ class Lists extends AbstractConfiguration
public function Process(Container $oContainer)
{
$iDefaultItemRank = 0;
$aClassesLists = array();
$aClassesLists = [];
// Parsing XML file
// - Each classes
/** @var \MFElement $oClassNode */
foreach ($this->GetModuleDesign()->GetNodes('/module_design/classes/class') as $oClassNode)
{
$aClassLists = array();
foreach ($this->GetModuleDesign()->GetNodes('/module_design/classes/class') as $oClassNode) {
$aClassLists = [];
$sClassId = $oClassNode->getAttribute('id');
if ($sClassId === null)
{
if ($sClassId === null) {
throw new DOMFormatException('Class tag must have an id attribute', 0, null, $oClassNode);
}
// - Each lists
/** @var \MFElement $oListNode */
foreach ($oClassNode->GetNodes('./lists/list') as $oListNode)
{
$aListItems = array();
foreach ($oClassNode->GetNodes('./lists/list') as $oListNode) {
$aListItems = [];
$sListId = $oListNode->getAttribute('id');
if ($sListId === null)
{
throw new DOMFormatException('List tag of "'.$sClassId.'" class must have an id attribute', null,
null, $oListNode);
if ($sListId === null) {
throw new DOMFormatException(
'List tag of "'.$sClassId.'" class must have an id attribute',
null,
null,
$oListNode
);
}
// - Each items
/** @var \MFElement $oItemNode */
foreach ($oListNode->GetNodes('./items/item') as $oItemNode)
{
foreach ($oListNode->GetNodes('./items/item') as $oItemNode) {
$sItemId = $oItemNode->getAttribute('id');
if ($sItemId === null)
{
throw new DOMFormatException('Item tag of "'.$sItemId.'" list must have an id attribute', null,
null, $oItemNode);
if ($sItemId === null) {
throw new DOMFormatException(
'Item tag of "'.$sItemId.'" list must have an id attribute',
null,
null,
$oItemNode
);
}
$aItem = array(
$aItem = [
'att_code' => $sItemId,
'rank' => $iDefaultItemRank,
);
];
$oRankNode = $oItemNode->GetOptionalElement('rank');
if ($oRankNode !== null)
{
if ($oRankNode !== null) {
$aItem['rank'] = $oRankNode->GetText($iDefaultItemRank);
}
@@ -100,8 +102,7 @@ class Lists extends AbstractConfiguration
}
// - Adding class only if it has at least one list
if (!empty($aClassLists))
{
if (!empty($aClassLists)) {
$aClassesLists[$sClassId] = $aClassLists;
}
}
@@ -110,4 +111,4 @@ class Lists extends AbstractConfiguration
$oContainer->setParameter('combodo.portal.instance.conf', $aPortalConf);
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -46,4 +47,4 @@ class ApplicationContextSetPluginPropertyClass
ApplicationContext::SetPluginProperty('QueryLocalizerPlugin', 'language_code', UserRights::GetUserLanguage());
}
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -31,16 +32,16 @@ use Symfony\Component\HttpKernel\Event\RequestEvent;
*/
class ApplicationContextSetUrlMakerClass
{
/** @var array $aCombodoPortalInstanceConf */
private $aCombodoPortalInstanceConf;
/** @var array $aCombodoPortalInstanceConf */
private $aCombodoPortalInstanceConf;
/**
* @param array $aCombodoPortalInstanceConf
*/
public function __construct($aCombodoPortalInstanceConf)
{
$this->aCombodoPortalInstanceConf = $aCombodoPortalInstanceConf;
}
/**
* @param array $aCombodoPortalInstanceConf
*/
public function __construct($aCombodoPortalInstanceConf)
{
$this->aCombodoPortalInstanceConf = $aCombodoPortalInstanceConf;
}
/**
* @param RequestEvent $oRequestEvent
@@ -51,4 +52,4 @@ class ApplicationContextSetUrlMakerClass
ApplicationContext::SetUrlMakerClass($this->aCombodoPortalInstanceConf['properties']['urlmaker_class']);
}
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -56,19 +57,15 @@ class CssFromSassCompiler
return;
}
$aImportPaths = array($_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'].'css/');
$aImportPaths = [$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'].'css/'];
foreach ($this->aCombodoPortalInstanceConf['properties']['themes'] as $sKey => $value) {
if (!is_array($value))
{
if (!is_array($value)) {
utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$value, $aImportPaths);
}
else
{
foreach ($value as $sSubValue)
{
} else {
foreach ($value as $sSubValue) {
utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$sSubValue, $aImportPaths);
}
}
}
}
}
}

View File

@@ -18,10 +18,8 @@
* You should have received a copy of the GNU Affero General Public License
*/
namespace Combodo\iTop\Portal\EventListener;
use Dict;
use ExceptionLog;
use Symfony\Component\ErrorHandler\Exception\FlattenException;
@@ -40,7 +38,6 @@ use Twig\Environment;
*/
class ExceptionListener
{
/**
* Constructor.
*
@@ -48,8 +45,7 @@ class ExceptionListener
*/
public function __construct(
protected Environment $oTwig
)
{
) {
}
/**
@@ -59,7 +55,7 @@ class ExceptionListener
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
*/
public function onKernelException(ExceptionEvent $oEvent) : void
public function onKernelException(ExceptionEvent $oEvent): void
{
// Get the exception object from the received event
$oException = $oEvent->getThrowable();
@@ -87,13 +83,11 @@ class ExceptionListener
// Prepare flatten exception
$oFlattenException = ($_SERVER['APP_DEBUG'] == 1) ? FlattenException::createFromThrowable($oException) : null;
// Remove APPROOT from file paths if in production (SF context)
if (!is_null($oFlattenException) && ($_SERVER['APP_ENV'] === 'prod'))
{
if (!is_null($oFlattenException) && ($_SERVER['APP_ENV'] === 'prod')) {
$oFlattenException->setFile($this->removeAppRootFromPath($oFlattenException->getFile()));
$aTrace = $oFlattenException->getTrace();
foreach ($aTrace as $iIdx => $aEntry)
{
foreach ($aTrace as $iIdx => $aEntry) {
$aTrace[$iIdx]['file'] = $this->removeAppRootFromPath($aEntry['file']);
}
$oFlattenException->setTrace($aTrace, $oFlattenException->getFile(), $oFlattenException->getLine());
@@ -105,20 +99,17 @@ class ExceptionListener
]);
// Prepare data for template
$aData = array(
$aData = [
'exception' => $oFlattenException,
'code' => $iStatusCode,
'error_title' => $sErrorTitle,
'error_message' => $sErrorMessage,
);
];
// Generate the response
if ($oEvent->getRequest()->isXmlHttpRequest())
{
if ($oEvent->getRequest()->isXmlHttpRequest()) {
$oResponse = new JsonResponse($aData);
}
else
{
} else {
$oResponse = new Response();
$oResponse->setContent($this->oTwig->render('itop-portal-base/portal/templates/errors/layout.html.twig', $aData));
}
@@ -164,5 +155,4 @@ class ExceptionListener
return str_replace($sNormalizedAppRoot, '', $sNormalizedInputPath);
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -78,7 +79,7 @@ class UserProvider
// - Checking user rights and prompt if needed (401 HTTP code returned if XHR request)
$iExitMethod = ($oRequestEvent->getRequest()->isXmlHttpRequest()) ? LoginWebPage::EXIT_RETURN : LoginWebPage::EXIT_PROMPT;
$iLogonRes = LoginWebPage::DoLoginEx($this->sPortalId, false, $iExitMethod);
if( ($iExitMethod === LoginWebPage::EXIT_RETURN) && ($iLogonRes != 0) ) {
if (($iExitMethod === LoginWebPage::EXIT_RETURN) && ($iLogonRes != 0)) {
die(Dict::S('Portal:ErrorUserLoggedOut'));
}
// - User must be associated with a Contact
@@ -92,8 +93,8 @@ class UserProvider
throw new Exception('Could not load connected user.');
}
// User allowed to log off or not
$this->bUserCanLogOff = utils::CanLogOff();
// User allowed to log off or not
$this->bUserCanLogOff = utils::CanLogOff();
// Allowed portals
$aAllowedPortals = UserRights::GetAllowedPortals();
@@ -146,5 +147,4 @@ class UserProvider
return $this->aAllowedPortals;
}
}
}

View File

@@ -51,6 +51,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use UserRights;
use utils;
use const UR_ACTION_READ;
/**
@@ -62,13 +63,13 @@ use const UR_ACTION_READ;
class ObjectFormManager extends FormManager
{
/** @var string ENUM_MODE_VIEW */
const ENUM_MODE_VIEW = 'view';
public const ENUM_MODE_VIEW = 'view';
/** @var string ENUM_MODE_EDIT */
const ENUM_MODE_EDIT = 'edit';
public const ENUM_MODE_EDIT = 'edit';
/** @var string ENUM_MODE_CREATE */
const ENUM_MODE_CREATE = 'create';
public const ENUM_MODE_CREATE = 'create';
/** @var string ENUM_MODE_APPLY_STIMULUS */
const ENUM_MODE_APPLY_STIMULUS = 'apply_stimulus';
public const ENUM_MODE_APPLY_STIMULUS = 'apply_stimulus';
/** @var \cmdbAbstractObject $oObject */
protected $oObject;
@@ -79,14 +80,14 @@ class ObjectFormManager extends FormManager
/** @var array $aFormProperties */
protected $aFormProperties;
/** @var array $aCallbackUrls */
protected $aCallbackUrls = array();
protected $aCallbackUrls = [];
/**
* List of hidden fields, used for form update (eg. remove them from the form regarding they dependencies)
*
* @var array $aHiddenFieldsId
* @since 2.7.5
*/
protected $aHiddenFieldsId = array();
protected $aHiddenFieldsId = [];
/**
* @var ObjectFormHandlerHelper $oFormHandlerHelper
@@ -95,7 +96,7 @@ class ObjectFormManager extends FormManager
private $oFormHandlerHelper;
/** @var array $aPlugins plugins data */
private array $aPlugins = array();
private array $aPlugins = [];
private array $aFieldsAtts = [];
private array $aExtraData = [];
private DOMDocument $oHtmlDocument;
@@ -143,27 +144,22 @@ class ObjectFormManager extends FormManager
}
$sObjectClass = $aJson['formobject_class'];
if (!isset($aJson['formobject_id']))
{
if (!isset($aJson['formobject_id'])) {
$oObject = MetaModel::NewObject($sObjectClass);
}
else
{
} else {
// Note : AllowAllData set to true here instead of checking scope's flag because we are displaying a value that has been set and validated
$oObject = MetaModel::GetObject($sObjectClass, $aJson['formobject_id'], true, true);
}
$oFormManager->SetObject($oObject);
// Retrieving form mode
if (!isset($aJson['formmode']))
{
if (!isset($aJson['formmode'])) {
throw new Exception('Form mode must be defined in order to generate the form');
}
$oFormManager->SetMode($aJson['formmode']);
// Retrieving actions rules
if (isset($aJson['formactionrulestoken']))
{
if (isset($aJson['formactionrulestoken'])) {
$oFormManager->SetActionRulesToken($aJson['formactionrulestoken']);
}
@@ -316,8 +312,7 @@ class ObjectFormManager extends FormManager
{
$aJson = parent::ToJSON();
$aJson['formobject_class'] = get_class($this->oObject);
if ($this->oObject->GetKey() > 0)
{
if ($this->oObject->GetKey() > 0) {
$aJson['formobject_id'] = $this->oObject->GetKey();
}
$aJson['formmode'] = $this->sMode;
@@ -338,11 +333,9 @@ class ObjectFormManager extends FormManager
// Building form from its properties
// - Consistency checks for stimulus form
if (isset($this->aFormProperties['stimulus_code']))
{
if (isset($this->aFormProperties['stimulus_code'])) {
$aTransitions = MetaModel::EnumTransitions($sObjectClass, $this->oObject->GetState());
if (!isset($aTransitions[$this->aFormProperties['stimulus_code']]))
{
if (!isset($aTransitions[$this->aFormProperties['stimulus_code']])) {
$aStimuli = Metamodel::EnumStimuli($sObjectClass);
$sStimulusLabel = $aStimuli[$this->aFormProperties['stimulus_code']]->GetLabel();
@@ -351,24 +344,22 @@ class ObjectFormManager extends FormManager
}
}
// Adding rendered template to the form renderer as the base layout
$this->oRenderer->SetBaseLayout($this->oHtmlDocument->saveHTML());
// Building the form
foreach ($this->aFieldsAtts as $sAttCode => $iFieldFlags)
{
foreach ($this->aFieldsAtts as $sAttCode => $iFieldFlags) {
// handle plugins fields
if($this->sMode !== 'apply_stimulus'
if ($this->sMode !== 'apply_stimulus'
&& array_key_exists($sAttCode, $this->aExtraData)
&& array_key_exists('plugin', $this->aExtraData[$sAttCode])){
&& array_key_exists('plugin', $this->aExtraData[$sAttCode])) {
$sPluginName = $this->aExtraData[$sAttCode]['plugin'];
switch($sPluginName){
switch ($sPluginName) {
case AttachmentPlugIn::class:
$this->AddAttachmentField($this->oForm, $sAttCode, $this->aExtraData);
break;
default:
throw new Exception('Unknown plugin ' . $sPluginName);
throw new Exception('Unknown plugin '.$sPluginName);
}
continue;
}
@@ -377,57 +368,44 @@ class ObjectFormManager extends FormManager
/** @var Field $oField */
$oField = null;
if (is_callable([$oAttDef, 'MakeFormField']))
{
if (is_callable([$oAttDef, 'MakeFormField'])) {
$oField = $oAttDef->MakeFormField($this->oObject);
}
// Failsafe for AttributeType that would not have MakeFormField and therefore could not be used in a form
if ($oField !== null)
{
if ($this->sMode !== static::ENUM_MODE_VIEW)
{
if ($oField !== null) {
if ($this->sMode !== static::ENUM_MODE_VIEW) {
// Field dependencies
$aFieldDependencies = $oAttDef->GetPrerequisiteAttributes();
if (!empty($aFieldDependencies))
{
if (!empty($aFieldDependencies)) {
$this->oForm->AddFieldDependencies($oField->GetId(), $aFieldDependencies);
}
// Setting the field flags
// - If it's locked because slave, we force it as read only
if (($iFieldFlags & OPT_ATT_SLAVE) === OPT_ATT_SLAVE)
{
if (($iFieldFlags & OPT_ATT_SLAVE) === OPT_ATT_SLAVE) {
$oField->SetReadOnly(true);
}
// - Else if it's must change (transition), we force it as mustchange, not readonly and not hidden
elseif (($iFieldFlags & OPT_ATT_MUSTCHANGE) === OPT_ATT_MUSTCHANGE && $this->IsTransitionForm())
{
elseif (($iFieldFlags & OPT_ATT_MUSTCHANGE) === OPT_ATT_MUSTCHANGE && $this->IsTransitionForm()) {
$oField->SetMustChange(true);
$oField->SetReadOnly(false);
$oField->SetHidden(false);
}
// - Else if it's must prompt (transition), we force it as not readonly and not hidden
elseif (($iFieldFlags & OPT_ATT_MUSTPROMPT) === OPT_ATT_MUSTPROMPT && $this->IsTransitionForm())
{
elseif (($iFieldFlags & OPT_ATT_MUSTPROMPT) === OPT_ATT_MUSTPROMPT && $this->IsTransitionForm()) {
$oField->SetReadOnly(false);
$oField->SetHidden(false);
}
// - Else if it wasn't mandatory or already had a value, and it's hidden, we force it as hidden
elseif (($iFieldFlags & OPT_ATT_HIDDEN) === OPT_ATT_HIDDEN)
{
elseif (($iFieldFlags & OPT_ATT_HIDDEN) === OPT_ATT_HIDDEN) {
$oField->SetHidden(true);
}
elseif (($iFieldFlags & OPT_ATT_READONLY) === OPT_ATT_READONLY)
{
} elseif (($iFieldFlags & OPT_ATT_READONLY) === OPT_ATT_READONLY) {
$oField->SetReadOnly(true);
}
else
{
} else {
// Normal field, use "flags" set by AttDef::MakeFormField()
// Except if we are in a transition be cause $oAttDef doesn't know if the form is for a transition
if ($this->IsTransitionForm())
{
if ($this->IsTransitionForm()) {
$oField->SetReadOnly(false);
$oField->SetHidden(false);
$oField->SetMandatory(false);
@@ -435,114 +413,110 @@ class ObjectFormManager extends FormManager
}
// Finally, if it's mandatory ...
if (($iFieldFlags & OPT_ATT_MANDATORY) === OPT_ATT_MANDATORY)
{
if (($iFieldFlags & OPT_ATT_MANDATORY) === OPT_ATT_MANDATORY) {
// ... and when in a transition, we force it as mandatory
if ($this->IsTransitionForm() && $oAttDef->IsNull($this->oObject->Get($sAttCode)))
{
if ($this->IsTransitionForm() && $oAttDef->IsNull($this->oObject->Get($sAttCode))) {
$oField->SetMandatory(true);
}
// .. and has no value, we force it as mandatory
elseif ($oAttDef->IsNull($this->oObject->Get($sAttCode)))
{
elseif ($oAttDef->IsNull($this->oObject->Get($sAttCode))) {
$oField->SetMandatory(true);
}
}
// Specific operation on field
// - Field that require a transaction id
if (in_array(get_class($oField),
array('Combodo\\iTop\\Form\\Field\\TextAreaField', 'Combodo\\iTop\\Form\\Field\\CaseLogField')))
{
if (in_array(
get_class($oField),
['Combodo\\iTop\\Form\\Field\\TextAreaField', 'Combodo\\iTop\\Form\\Field\\CaseLogField']
)) {
/** @var \Combodo\iTop\Form\Field\TextAreaField|\Combodo\iTop\Form\Field\CaseLogField $oField */
$oField->SetTransactionId($this->oForm->GetTransactionId());
}
// - Field that require a search endpoint
if (in_array(get_class($oField),
array('Combodo\\iTop\\Form\\Field\\SelectObjectField', 'Combodo\\iTop\\Form\\Field\\LinkedSetField'))) {
if (in_array(
get_class($oField),
['Combodo\\iTop\\Form\\Field\\SelectObjectField', 'Combodo\\iTop\\Form\\Field\\LinkedSetField']
)) {
/** @var \Combodo\iTop\Form\Field\SelectObjectField|\Combodo\iTop\Form\Field\LinkedSetField $oField */
if ($this->oFormHandlerHelper !== null) {
$sSearchEndpoint = $this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_search_generic', array(
$sSearchEndpoint = $this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_search_generic', [
'sTargetAttCode' => $oAttDef->GetCode(),
'sHostObjectClass' => get_class($this->oObject),
'sHostObjectId' => ($this->oObject->IsNew()) ? null : $this->oObject->GetKey(),
'ar_token' => $this->GetActionRulesToken(),
));
]);
$oField->SetSearchEndpoint($sSearchEndpoint);
}
}
// - Field that require an information endpoint
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\LinkedSetField'))) {
if (in_array(get_class($oField), ['Combodo\\iTop\\Form\\Field\\LinkedSetField'])) {
/** @var \Combodo\iTop\Form\Field\LinkedSetField $oField */
if ($this->oFormHandlerHelper !== null) {
$oField->SetInformationEndpoint($this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_get_information_for_linked_set_json'));
}
}
// - Field that require to apply scope on its DM OQL
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\SelectObjectField')))
{
if (in_array(get_class($oField), ['Combodo\\iTop\\Form\\Field\\SelectObjectField'])) {
/** @var \Combodo\iTop\Form\Field\SelectObjectField $oField */
if ($this->oFormHandlerHelper !== null) {
$oScopeOriginal = ($oField->GetSearch() !== null) ? $oField->GetSearch() : DBSearch::FromOQL($oAttDef->GetValuesDef()->GetFilterExpression());
/** @var \DBSearch $oScopeSearch */
$oScopeSearch = $this->oFormHandlerHelper->GetScopeValidator()->GetScopeFilterForProfiles(UserRights::ListProfiles(),
$oScopeOriginal->GetClass(), UR_ACTION_READ);
$oScopeSearch = $this->oFormHandlerHelper->GetScopeValidator()->GetScopeFilterForProfiles(
UserRights::ListProfiles(),
$oScopeOriginal->GetClass(),
UR_ACTION_READ
);
if ($oScopeSearch === null) {
IssueLog::Info(__METHOD__.' at line '.__LINE__.' : User #'.UserRights::GetUserId().' has no scope query for '.$oScopeOriginal->GetClass().' class.');
throw new HttpException(Response::HTTP_NOT_FOUND, Dict::S('UI:ObjectDoesNotExist'));
}
$oScopeOriginal = $oScopeOriginal->Intersect($oScopeSearch);
// Note : This is to skip the silo restriction on the final query
if ($oScopeSearch->IsAllDataAllowed())
{
if ($oScopeSearch->IsAllDataAllowed()) {
$oScopeOriginal->AllowAllData();
}
$oScopeOriginal->SetInternalParams(array('this' => $this->oObject));
$oScopeOriginal->SetInternalParams(['this' => $this->oObject]);
$oField->SetSearch($oScopeOriginal);
}
}
// - Field that require to check if the current value is among allowed ones
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\SelectObjectField')))
{
if (in_array(get_class($oField), ['Combodo\\iTop\\Form\\Field\\SelectObjectField'])) {
// Note: We can't do this in AttributeExternalKey::MakeFormField() in the Field::SetOnFinalizeCallback() because at this point we have no information about the portal scope and ignore_silos flag, hence it always applies silos.
// As a workaround we have to manually check if the field's current value is among the scope
$oField->ResetCurrentValueIfNotAmongAllowedValues();
}
// - Field that require processing on their subfields
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\SubFormField')))
{
if (in_array(get_class($oField), ['Combodo\\iTop\\Form\\Field\\SubFormField'])) {
/** @var \Combodo\iTop\Form\Field\SubFormField $oField */
$oSubForm = $oField->GetForm();
if ($oAttDef->GetEditClass() === 'CustomFields')
{
if ($oAttDef->GetEditClass() === 'CustomFields') {
// Retrieving only user data fields (not the metadata fields of the template)
if ($oSubForm->HasField('user_data'))
{
if ($oSubForm->HasField('user_data')) {
/** @var \Combodo\iTop\Form\Field\SubFormField $oUserDataField */
$oUserDataField = $oSubForm->GetField('user_data');
$oUserDataForm = $oUserDataField->GetForm();
foreach ($oUserDataForm->GetFields() as $oCustomField)
{
foreach ($oUserDataForm->GetFields() as $oCustomField) {
// - Field that require a search endpoint (OQL based dropdown list fields)
if (in_array(get_class($oCustomField), array('Combodo\\iTop\\Form\\Field\\SelectObjectField')))
{
if (in_array(get_class($oCustomField), ['Combodo\\iTop\\Form\\Field\\SelectObjectField'])) {
/** @var \Combodo\iTop\Form\Field\SelectObjectField $oCustomField */
if ($this->oFormHandlerHelper->GetUrlGenerator() !== null) {
$sSearchEndpoint = $this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_search_generic',
array(
$sSearchEndpoint = $this->oFormHandlerHelper->GetUrlGenerator()->generate(
'p_object_search_generic',
[
'sTargetAttCode' => $oAttDef->GetCode(),
'sHostObjectClass' => get_class($this->oObject),
'sHostObjectId' => ($this->oObject->IsNew()) ? null : $this->oObject->GetKey(),
'ar_token' => $this->GetActionRulesToken(),
));
]
);
$oCustomField->SetSearchEndpoint($sSearchEndpoint);
}
}
// - Field that require to check if the current value is among allowed ones
if (in_array(get_class($oCustomField), array('Combodo\\iTop\\Form\\Field\\SelectObjectField')))
{
if (in_array(get_class($oCustomField), ['Combodo\\iTop\\Form\\Field\\SelectObjectField'])) {
/** @var \Combodo\iTop\Form\Field\SelectObjectField $oCustomField */
$oCustomField->ResetCurrentValueIfNotAmongAllowedValues();
}
@@ -550,37 +524,34 @@ class ObjectFormManager extends FormManager
}
}
}
}
else
{
if (($iFieldFlags & OPT_ATT_HIDDEN) === OPT_ATT_HIDDEN)
{
} else {
if (($iFieldFlags & OPT_ATT_HIDDEN) === OPT_ATT_HIDDEN) {
$oField->SetHidden(true);
}
else
{
} else {
$oField->SetReadOnly(true);
}
}
// Specific operation on field
// - LinkedSet
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\LinkedSetField')))
{
if (in_array(get_class($oField), ['Combodo\\iTop\\Form\\Field\\LinkedSetField'])) {
/** @var \Combodo\iTop\Form\Field\LinkedSetField $oField */
/** @var \AttributeLinkedSetIndirect $oAttDef */
// - Overriding attributes to display
if ($this->oFormHandlerHelper !== null) {
// Note : This snippet is inspired from AttributeLinkedSet::MakeFormField()
$aAttCodesToDisplay = ApplicationHelper::GetLoadedListFromClass($this->oFormHandlerHelper->getCombodoPortalConf()['lists'],
$oField->GetTargetClass(), 'list');
$aAttCodesToDisplay = ApplicationHelper::GetLoadedListFromClass(
$this->oFormHandlerHelper->getCombodoPortalConf()['lists'],
$oField->GetTargetClass(),
'list'
);
// - Adding friendlyname attribute to the list is not already in it
$sTitleAttCode = 'friendlyname';
if (($sTitleAttCode !== null) && !in_array($sTitleAttCode, $aAttCodesToDisplay)) {
$aAttCodesToDisplay = array_merge(array($sTitleAttCode), $aAttCodesToDisplay);
$aAttCodesToDisplay = array_merge([$sTitleAttCode], $aAttCodesToDisplay);
}
// - Adding attribute labels
$aAttributesToDisplay = array();
$aAttributesToDisplay = [];
foreach ($aAttCodesToDisplay as $sAttCodeToDisplay) {
$oAttDefToDisplay = MetaModel::GetAttributeDef($oField->GetTargetClass(), $sAttCodeToDisplay);
$aAttributesToDisplay[$sAttCodeToDisplay] = [
@@ -598,7 +569,7 @@ class ObjectFormManager extends FormManager
}
// - Filtering links regarding scopes
if ($this->oFormHandlerHelper !== null) {
$aLimitedAccessItemIDs = array();
$aLimitedAccessItemIDs = [];
/** @var \ormLinkSet $oFieldOriginalSet */
$oFieldOriginalSet = $oField->GetCurrentValue();
@@ -617,19 +588,16 @@ class ObjectFormManager extends FormManager
$oField->SetLimitedAccessItemIDs($aLimitedAccessItemIDs);
}
// - Displaying as opened
if (array_key_exists($sAttCode, $this->aExtraData) && array_key_exists('opened', $this->aExtraData[$sAttCode]))
{
if (array_key_exists($sAttCode, $this->aExtraData) && array_key_exists('opened', $this->aExtraData[$sAttCode])) {
$oField->SetDisplayOpened(true);
}
// - Displaying out of scopes items
if (array_key_exists($sAttCode, $this->aExtraData) && array_key_exists('ignore_scopes', $this->aExtraData[$sAttCode]))
{
if (array_key_exists($sAttCode, $this->aExtraData) && array_key_exists('ignore_scopes', $this->aExtraData[$sAttCode])) {
$oField->SetDisplayLimitedAccessItems(true);
}
}
// - BlobField
if (in_array(get_class($oField), array('Combodo\\iTop\\Form\\Field\\BlobField', 'Combodo\\iTop\\Form\\Field\\ImageField')))
{
if (in_array(get_class($oField), ['Combodo\\iTop\\Form\\Field\\BlobField', 'Combodo\\iTop\\Form\\Field\\ImageField'])) {
// - Overriding attributes to display
if ($this->oFormHandlerHelper !== null) {
// Override hardcoded URLs in ormDocument pointing to back office console
@@ -654,9 +622,7 @@ class ObjectFormManager extends FormManager
}
}
}
else
{
} else {
$oField = new LabelField($sAttCode);
$oField->SetReadOnly(true)
->SetHidden(false)
@@ -665,8 +631,7 @@ class ObjectFormManager extends FormManager
}
// Setting field display mode
if (array_key_exists($sAttCode, $this->aExtraData) && array_key_exists('display_mode', $this->aExtraData[$sAttCode]))
{
if (array_key_exists($sAttCode, $this->aExtraData) && array_key_exists('display_mode', $this->aExtraData[$sAttCode])) {
$oField->SetDisplayMode($this->aExtraData[$sAttCode]['display_mode']);
}
@@ -678,32 +643,25 @@ class ObjectFormManager extends FormManager
// Do not add hidden fields as they are of no use, if one is necessary because another depends on it, it will be automatically added.
// Note: We do this at the end because during the process an hidden field could have become writable if mandatory and empty for example.
if($oField->GetHidden() === false)
{
if ($oField->GetHidden() === false) {
$this->oForm->AddField($oField);
} else {
$this->aHiddenFieldsId[]=$oField->GetId();
$this->aHiddenFieldsId[] = $oField->GetId();
}
}
// Checking dependencies to ensure that all needed fields are in the form
// (This is kind of a garbage collector for dependencies)
foreach ($this->oForm->GetDependencies() as $sImpactedFieldId => $aDependencies)
{
foreach ($aDependencies as $sDependencyFieldId)
{
if (!$this->oForm->HasField($sDependencyFieldId))
{
try
{
foreach ($this->oForm->GetDependencies() as $sImpactedFieldId => $aDependencies) {
foreach ($aDependencies as $sDependencyFieldId) {
if (!$this->oForm->HasField($sDependencyFieldId)) {
try {
$oAttDef = MetaModel::GetAttributeDef(get_class($this->oObject), $sDependencyFieldId);
$oField = $oAttDef->MakeFormField($this->oObject);
$oField->SetHidden(true);
$this->oForm->AddField($oField);
}
catch (Exception $e)
{
} catch (Exception $e) {
// Avoid blocking a form if a RequestTemplate reference a bad attribute (e.g. :this->id)
IssueLog::Error('May be a bad OQL (referencing :this->id) in a RequestTemplate causes the following error');
IssueLog::Error($e);
@@ -717,7 +675,7 @@ class ObjectFormManager extends FormManager
if ($this->sMode !== 'apply_stimulus'
&& class_exists('Attachment') && class_exists('AttachmentPlugIn')
&& !$this->IsPluginInitialized(AttachmentPlugIn::class)
&& AttachmentPlugIn::IsAttachmentAllowedForObject($this->oObject)){
&& AttachmentPlugIn::IsAttachmentAllowedForObject($this->oObject)) {
$this->AddAttachmentField($this->oForm, 'attachments_plugin', $this->aExtraData);
}
@@ -732,7 +690,7 @@ class ObjectFormManager extends FormManager
*
* @return bool
*/
private function IsPluginInitialized(string $sPluginName) : bool
private function IsPluginInitialized(string $sPluginName): bool
{
return array_key_exists($sPluginName, $this->aPlugins);
}
@@ -746,48 +704,54 @@ class ObjectFormManager extends FormManager
*
* @throws \Exception
*/
private function AddAttachmentField($oForm, $sId, $aFieldsExtraData) : void
private function AddAttachmentField($oForm, $sId, $aFieldsExtraData): void
{
// only one instance allowed
if($this->IsPluginInitialized(AttachmentPlugIn::class)){
throw new Exception("Unable to process field `$sId`, AttachmentPlugIn has already been initialized with field `" . $this->aPlugins[AttachmentPlugIn::class]['field']->GetId() . '`');
if ($this->IsPluginInitialized(AttachmentPlugIn::class)) {
throw new Exception("Unable to process field `$sId`, AttachmentPlugIn has already been initialized with field `".$this->aPlugins[AttachmentPlugIn::class]['field']->GetId().'`');
}
// not allowed for object class
if(!AttachmentPlugIn::IsAttachmentAllowedForObject($this->oObject)){
throw new Exception("Unable to process field `$sId`, AttachmentPlugIn is not allowed for class `" . $this->oObject::class . '`');
if (!AttachmentPlugIn::IsAttachmentAllowedForObject($this->oObject)) {
throw new Exception("Unable to process field `$sId`, AttachmentPlugIn is not allowed for class `".$this->oObject::class.'`');
}
// set id to a unique key - avoid collisions with another attribute that could exist with the name 'attachments'
$oField = new FileUploadField($sId);
$oField->SetLabel(Dict::S('Portal:Attachments'))
->SetUploadEndpoint($this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_attachment_add'))
->SetDownloadEndpoint($this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_attachment_download',
array('sAttachmentId' => '-sAttachmentId-')))
->SetDisplayEndpoint($this->oFormHandlerHelper->GetUrlGenerator()->generate('p_object_attachment_display',
array('sAttachmentId' => '-sAttachmentId-')))
->SetDownloadEndpoint($this->oFormHandlerHelper->GetUrlGenerator()->generate(
'p_object_attachment_download',
['sAttachmentId' => '-sAttachmentId-']
))
->SetDisplayEndpoint($this->oFormHandlerHelper->GetUrlGenerator()->generate(
'p_object_attachment_display',
['sAttachmentId' => '-sAttachmentId-']
))
->SetTransactionId($oForm->GetTransactionId())
->SetAllowDelete($this->oFormHandlerHelper->getCombodoPortalConf()['properties']['attachments']['allow_delete'])
->SetObject($this->oObject);
// Checking if we can edit attachments in the current state
$oObjectFormManager = $this;
$oField->SetOnFinalizeCallback(function() use ($oObjectFormManager, $oForm, $oField){
$oField->SetOnFinalizeCallback(function () use ($oObjectFormManager, $oForm, $oField) {
if (($oObjectFormManager->sMode === static::ENUM_MODE_VIEW)
|| AttachmentPlugIn::IsReadonlyState($oObjectFormManager->oObject, $oObjectFormManager->oObject->GetState(),
AttachmentPlugIn::ENUM_GUI_PORTALS) === true
|| $oForm->GetEditableFieldCount(true) === 0)
{
|| AttachmentPlugIn::IsReadonlyState(
$oObjectFormManager->oObject,
$oObjectFormManager->oObject->GetState(),
AttachmentPlugIn::ENUM_GUI_PORTALS
) === true
|| $oForm->GetEditableFieldCount(true) === 0) {
$oField->SetReadOnly(true);
}
});
if (array_key_exists($sId, $aFieldsExtraData) && array_key_exists('opened', $aFieldsExtraData[$sId])){
if (array_key_exists($sId, $aFieldsExtraData) && array_key_exists('opened', $aFieldsExtraData[$sId])) {
$oField->SetDisplayOpened(true);
}
// Adding attachments field in transition only if it is editable
if (!$this->IsTransitionForm() || !$oField->GetReadOnly()){
if (!$this->IsTransitionForm() || !$oField->GetReadOnly()) {
$oForm->AddField($oField);
}
@@ -810,8 +774,7 @@ class ObjectFormManager extends FormManager
{
// Ask to each field to clean itself
/** @var \Combodo\iTop\Form\Field\Field $oField */
foreach ($this->oForm->GetFields() as $oField)
{
foreach ($this->oForm->GetFields() as $oField) {
$oField->OnCancel();
}
// Then clean inline images from rich text editor such as TextareaField
@@ -837,7 +800,7 @@ class ObjectFormManager extends FormManager
}
$aData['messages']['error'] += [
'_main' => [$sError]
'_main' => [$sError],
];
$aData['valid'] = false;
}
@@ -875,8 +838,7 @@ class ObjectFormManager extends FormManager
$this->OnUpdate($aArgs);
// Check if form valid
if (! $this->oForm->Validate())
{
if (! $this->oForm->Validate()) {
// Handle errors
$aData['valid'] = false;
$aData['messages']['error'] += $this->oForm->GetErrorMessages();
@@ -901,8 +863,7 @@ class ObjectFormManager extends FormManager
}
// Writing object to DB
try
{
try {
$this->oObject->DBWrite();
} catch (CoreCannotSaveObjectException $e) {
throw new Exception($e->getTextMessage());
@@ -929,34 +890,29 @@ class ObjectFormManager extends FormManager
InlineImage::FinalizeInlineImages($this->oObject);
// Finalizing attachments link to object
// TODO : This has to be refactored when the function from itop-attachments has been migrated into the core
if (isset($aArgs['attachmentIds']))
{
if (isset($aArgs['attachmentIds'])) {
$this->FinalizeAttachments($aArgs['attachmentIds']);
}
// Checking if we have to apply a stimulus
if (isset($aArgs['applyStimulus']))
{
if (isset($aArgs['applyStimulus'])) {
$this->oObject->ApplyStimulus($aArgs['applyStimulus']['code']);
}
// Activating triggers only on update
if ($bActivateTriggers)
{
if ($bActivateTriggers) {
$sTriggersQuery = $this->oFormHandlerHelper->getCombodoPortalConf()['properties']['triggers_query'];
if ($sTriggersQuery !== null)
{
if ($sTriggersQuery !== null) {
$aParentClasses = MetaModel::EnumParentClasses($sObjectClass, ENUM_PARENT_CLASSES_ALL);
$oTriggerSet = new DBObjectSet(DBObjectSearch::FromOQL($sTriggersQuery), array(),
array('parent_classes' => $aParentClasses));
$oTriggerSet = new DBObjectSet(
DBObjectSearch::FromOQL($sTriggersQuery),
[],
['parent_classes' => $aParentClasses]
);
/** @var \Trigger $oTrigger */
while ($oTrigger = $oTriggerSet->Fetch())
{
try
{
while ($oTrigger = $oTriggerSet->Fetch()) {
try {
$oTrigger->DoActivate($this->oObject->ToArgs('this'));
}
catch(Exception $e)
{
} catch (Exception $e) {
utils::EnrichRaisedException($oTrigger, $e);
}
}
@@ -966,30 +922,24 @@ class ObjectFormManager extends FormManager
// Resetting caselog fields value, otherwise the value will stay in it after submit.
$this->oForm->ResetCaseLogFields();
if ($bWasModified)
{
if ($bWasModified) {
//=if (isNew) because $bActivateTriggers = (!$this->oObject->IsNew() && $this->oObject->IsModified())
if(!$bActivateTriggers)
{
$aData['messages']['success'] += array( '_main' => array(Dict::Format('UI:Title:Object_Of_Class_Created', $this->oObject->GetName(),MetaModel::GetName(get_class($this->oObject)))));
}
else
{
$aData['messages']['success'] += array('_main' => array(Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($this->oObject)), $this->oObject->GetName())));
if (!$bActivateTriggers) {
$aData['messages']['success'] += [ '_main' => [Dict::Format('UI:Title:Object_Of_Class_Created', $this->oObject->GetName(), MetaModel::GetName(get_class($this->oObject)))]];
} else {
$aData['messages']['success'] += ['_main' => [Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($this->oObject)), $this->oObject->GetName())]];
}
}
}
catch (CoreCannotSaveObjectException $e) {
} catch (CoreCannotSaveObjectException $e) {
$aData['valid'] = false;
$aData['messages']['error'] += array('_main' => array($e->getTextMessage()));
$aData['messages']['error'] += ['_main' => [$e->getTextMessage()]];
if (false === $bExceptionLogged) {
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : '.$e->getMessage());
}
}
catch (Exception $e) {
} catch (Exception $e) {
$aData['valid'] = false;
$aData['messages']['error'] += [
'_main' => [ ($e instanceof CoreCannotSaveObjectException) ? $e->getTextMessage() : $e->getMessage()]
'_main' => [ ($e instanceof CoreCannotSaveObjectException) ? $e->getTextMessage() : $e->getMessage()],
];
if (false === $bExceptionLogged) {
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : '.$e->getMessage());
@@ -1016,11 +966,9 @@ class ObjectFormManager extends FormManager
{
$aFormProperties = [];
if (is_array($aArgs))
{
if (is_array($aArgs)) {
// Then we retrieve properties of the form to build
if (isset($aArgs['formProperties']))
{
if (isset($aArgs['formProperties'])) {
$aFormProperties = $aArgs['formProperties'];
}
}
@@ -1054,20 +1002,17 @@ class ObjectFormManager extends FormManager
*/
protected function FinalizeAttachments($aAttachmentIds)
{
$aRemovedAttachmentsIds = (isset($aAttachmentIds['removed_attachments_ids'])) ? $aAttachmentIds['removed_attachments_ids'] : array();
$aRemovedAttachmentsIds = (isset($aAttachmentIds['removed_attachments_ids'])) ? $aAttachmentIds['removed_attachments_ids'] : [];
// Not used for now. //$aActualAttachmentsIds = (isset($aAttachmentIds['actual_attachments_ids'])) ? $aAttachmentIds['actual_attachments_ids'] : array();
$aActions = array();
$aActions = [];
// Removing attachments from currents
if (!empty($aRemovedAttachmentsIds))
{
if (!empty($aRemovedAttachmentsIds)) {
$oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id");
$oSet = new DBObjectSet($oSearch, array(), array('class' => get_class($this->oObject), 'item_id' => $this->oObject->GetKey()));
while ($oAttachment = $oSet->Fetch())
{
$oSet = new DBObjectSet($oSearch, [], ['class' => get_class($this->oObject), 'item_id' => $this->oObject->GetKey()]);
while ($oAttachment = $oSet->Fetch()) {
// Remove attachments that are no longer attached to the current object
if (in_array($oAttachment->GetKey(), $aRemovedAttachmentsIds))
{
if (in_array($oAttachment->GetKey(), $aRemovedAttachmentsIds)) {
$aData = ['attachment' => $oAttachment];
$this->oObject->FireEvent(EVENT_REMOVE_ATTACHMENT_FROM_OBJECT, $aData);
$oAttachment->DBDelete();
@@ -1080,16 +1025,12 @@ class ObjectFormManager extends FormManager
$sTempId = utils::GetUploadTempId($this->oForm->GetTransactionId());
$sOQL = 'SELECT Attachment WHERE temp_id = :temp_id';
$oSearch = DBObjectSearch::FromOQL($sOQL);
$oSet = new DBObjectSet($oSearch, array(), array('temp_id' => $sTempId));
while ($oAttachment = $oSet->Fetch())
{
$oSet = new DBObjectSet($oSearch, [], ['temp_id' => $sTempId]);
while ($oAttachment = $oSet->Fetch()) {
// Temp attachment removed
if (in_array($oAttachment->GetKey(), $aRemovedAttachmentsIds))
{
if (in_array($oAttachment->GetKey(), $aRemovedAttachmentsIds)) {
$oAttachment->DBDelete();
}
else
{
} else {
$oAttachment->SetItem($this->oObject);
$oAttachment->Set('temp_id', '');
$oAttachment->DBUpdate();
@@ -1101,8 +1042,7 @@ class ObjectFormManager extends FormManager
// Save changes to current object history
// inspired from itop-attachments/main.attachments.php / RecordHistory
foreach ($aActions as $oChangeOp)
{
foreach ($aActions as $oChangeOp) {
$oChangeOp->Set("objclass", get_class($this->oObject));
$oChangeOp->Set("objkey", $this->oObject->GetKey());
$oChangeOp->DBInsertNoReload();
@@ -1125,9 +1065,8 @@ class ObjectFormManager extends FormManager
$sTempId = utils::GetUploadTempId($this->oForm->GetTransactionId());
$sOQL = 'SELECT Attachment WHERE temp_id = :temp_id';
$oSearch = DBObjectSearch::FromOQL($sOQL);
$oSet = new DBObjectSet($oSearch, array(), array('temp_id' => $sTempId));
while ($oAttachment = $oSet->Fetch())
{
$oSet = new DBObjectSet($oSearch, [], ['temp_id' => $sTempId]);
while ($oAttachment = $oSet->Fetch()) {
$oAttachment->DBDelete();
}
}
@@ -1147,14 +1086,11 @@ class ObjectFormManager extends FormManager
{
$oBlob = $oAttachment->Get('contents');
$sFileName = $oBlob->GetFileName();
if ($bCreate)
{
if ($bCreate) {
$oChangeOp = new CMDBChangeOpAttachmentAdded();
$oChangeOp->Set('attachment_id', $oAttachment->GetKey());
$oChangeOp->Set('filename', $sFileName);
}
else
{
} else {
$oChangeOp = new CMDBChangeOpAttachmentRemoved();
$oChangeOp->Set('filename', $sFileName);
}
@@ -1238,8 +1174,7 @@ class ObjectFormManager extends FormManager
{
$sObjectClass = get_class($this->oObject);
foreach ($aCurrentValues as $sAttCode => $value)
{
foreach ($aCurrentValues as $sAttCode => $value) {
if (count($this->aFieldsAtts) !== 0) {
if (!array_key_exists($sAttCode, $this->aFieldsAtts)) {
continue;
@@ -1342,8 +1277,7 @@ class ObjectFormManager extends FormManager
}
$oOrmSet->ApplyDelta(json_decode($value, true));
$this->oObject->Set($sAttCode, $oOrmSet);
} elseif ($oAttDef instanceof AttributeDateTime) // AttributeDate is derived from AttributeDateTime
{
} elseif ($oAttDef instanceof AttributeDateTime) { // AttributeDate is derived from AttributeDateTime
if ($value != null) {
$value = $oAttDef->GetFormat()->Parse($value);
if (is_object($value)) {
@@ -1351,11 +1285,9 @@ class ObjectFormManager extends FormManager
}
}
$this->oObject->Set($sAttCode, $value);
}
elseif ($oAttDef->IsScalar() && is_array($value)) {
} elseif ($oAttDef->IsScalar() && is_array($value)) {
$this->oObject->Set($sAttCode, current($value));
}
elseif ($oAttDef->GetEditClass() === 'CustomFields') {
} elseif ($oAttDef->GetEditClass() === 'CustomFields') {
// We don't update attribute as ormCustomField comparaison is not working as excepted.
// When several templates available, "template_id" is not sent by the portal has it is a read-only select input
// therefore, the TemplateFieldsHandler::CompareValues() doesn't work.
@@ -1377,8 +1309,7 @@ class ObjectFormManager extends FormManager
$this->oObject->Set($sAttCode, $value);
}
// Else don't update! Otherwise we might loose current value
}
else {
} else {
$this->oObject->Set($sAttCode, $value);
}
}
@@ -1400,9 +1331,9 @@ class ObjectFormManager extends FormManager
public function PrepareFields(): void
{
$sObjectClass = get_class($this->oObject);
$this->aFieldsAtts = array();
$this->aExtraData = array();
$aFieldsDMOnlyAttCodes = array();
$this->aFieldsAtts = [];
$this->aExtraData = [];
$aFieldsDMOnlyAttCodes = [];
if (array_key_exists('type', $this->aFormProperties)) {
switch ($this->aFormProperties['type']) {
case 'custom_list':
@@ -1518,8 +1449,7 @@ class ObjectFormManager extends FormManager
if (array_key_exists('type', $this->aFormProperties) && $this->aFormProperties['type'] !== 'static') {
if ($this->IsTransitionForm()) {
$aDatamodelAttCodes = $this->oObject->GetTransitionAttributes($this->aFormProperties['stimulus_code']);
}
else {
} else {
$aDatamodelAttCodes = MetaModel::ListAttributeDefs($sObjectClass);
}
@@ -1536,12 +1466,10 @@ class ObjectFormManager extends FormManager
// Retrieving only mandatory flag from DM when on a transition
$iFieldFlags = $value & OPT_ATT_MANDATORY;
$oAttDef = MetaModel::GetAttributeDef(get_class($this->oObject), $sAttCode);
}
elseif ($this->oObject->IsNew()) {
} elseif ($this->oObject->IsNew()) {
$iFieldFlags = $this->oObject->GetInitialStateAttributeFlags($sAttCode);
$oAttDef = $value;
}
else {
} else {
$iFieldFlags = $this->oObject->GetAttributeFlags($sAttCode);
$oAttDef = $value;
}
@@ -1581,11 +1509,9 @@ class ObjectFormManager extends FormManager
if ($this->IsTransitionForm()) {
$aTransitionAtts = $this->oObject->GetTransitionAttributes($this->aFormProperties['stimulus_code']);
$iFieldFlags = $aTransitionAtts[$sAttCode];
}
elseif ($this->oObject->IsNew()) {
} elseif ($this->oObject->IsNew()) {
$iFieldFlags = $this->oObject->GetInitialStateAttributeFlags($sAttCode);
}
else {
} else {
$iFieldFlags = $this->oObject->GetAttributeFlags($sAttCode);
}
@@ -1629,7 +1555,7 @@ class ObjectFormManager extends FormManager
$sRendered = $this->oFormHandlerHelper->RenderFormFromTwig(
999, // doesn't matter here
$this->aFormProperties['layout']['content'],
array('oRenderer' => $this->oRenderer, 'oObject' => $this->oObject)
['oRenderer' => $this->oRenderer, 'oObject' => $this->oObject]
);
} else {
$sRendered = 'Form not rendered because of missing container';

View File

@@ -39,7 +39,7 @@ use UserRights;
class PasswordFormManager extends FormManager
{
/** @var string FORM_TYPE */
const FORM_TYPE = 'change_password';
public const FORM_TYPE = 'change_password';
/**
* @throws \Exception
@@ -106,87 +106,66 @@ class PasswordFormManager extends FormManager
$this->OnUpdate($aArgs);
// Check if form valid
if ($this->oForm->Validate())
{
if ($this->oForm->Validate()) {
// The try catch is essentially to start a MySQL transaction
try
{
try {
// Updating password
$sAuthUser = Session::Get('auth_user');
$sOldPassword = $this->oForm->GetField('old_password')->GetCurrentValue();
$sNewPassword = $this->oForm->GetField('new_password')->GetCurrentValue();
$sConfirmPassword = $this->oForm->GetField('confirm_password')->GetCurrentValue();
if ($sOldPassword !== '' && $sNewPassword !== '' && $sConfirmPassword !== '')
{
if (!UserRights::CanChangePassword())
{
if ($sOldPassword !== '' && $sNewPassword !== '' && $sConfirmPassword !== '') {
if (!UserRights::CanChangePassword()) {
$aData['valid'] = false;
$aData['messages']['error'] += array(
'_main' => array(
$aData['messages']['error'] += [
'_main' => [
Dict::Format('Brick:Portal:UserProfile:Password:CantChangeContactAdministrator', ITOP_APPLICATION_SHORT),
),
);
}
else
{
if (!UserRights::CheckCredentials($sAuthUser, $sOldPassword))
{
],
];
} else {
if (!UserRights::CheckCredentials($sAuthUser, $sOldPassword)) {
$aData['valid'] = false;
$aData['messages']['error'] += array('old_password' => array(Dict::S('UI:Login:IncorrectOldPassword')));
}
else
{
if ($sNewPassword !== $sConfirmPassword)
{
$aData['messages']['error'] += ['old_password' => [Dict::S('UI:Login:IncorrectOldPassword')]];
} else {
if ($sNewPassword !== $sConfirmPassword) {
$aData['valid'] = false;
$aData['messages']['error'] += array('confirm_password' => array(Dict::S('UI:Login:RetypePwdDoesNotMatch')));
}
elseif ($sNewPassword === $sOldPassword)
{
$aData['messages']['error'] += ['confirm_password' => [Dict::S('UI:Login:RetypePwdDoesNotMatch')]];
} elseif ($sNewPassword === $sOldPassword) {
$aData['valid'] = false;
$aData['messages']['error'] += array('new_password' => array(Dict::S('UI:Login:PasswordNotChanged')));
}
else
{
$aData['messages']['error'] += ['new_password' => [Dict::S('UI:Login:PasswordNotChanged')]];
} else {
try {
if (!UserRights::ChangePassword($sOldPassword, $sNewPassword))
{
if (!UserRights::ChangePassword($sOldPassword, $sNewPassword)) {
$aData['valid'] = false;
$aData['messages']['error'] += array(
'confirm_password' => array(
Dict::Format('Brick:Portal:UserProfile:Password:CantChangeForUnknownReason',
ITOP_APPLICATION_SHORT),
),
);
$aData['messages']['error'] += [
'confirm_password' => [
Dict::Format(
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason',
ITOP_APPLICATION_SHORT
),
],
];
} else {
$aData['messages']['success'] += ['_main' => [Dict::S('Brick:Portal:Object:Form:Message:Saved')]];
}
else
{
$aData['messages']['success'] += array('_main' => array(Dict::S('Brick:Portal:Object:Form:Message:Saved')));
}
}
catch (\CoreCannotSaveObjectException $e)
{
} catch (\CoreCannotSaveObjectException $e) {
$aData['valid'] = false;
$aData['messages']['error'] += array(
$aData['messages']['error'] += [
'new_password' => $e->getIssues(),
'confirm_password' => array(),
);
'confirm_password' => [],
];
}
}
}
}
}
}
catch (Exception $e)
{
} catch (Exception $e) {
$aData['valid'] = false;
$aData['messages']['error'] += array('_main' => array($e->getMessage()));
$aData['messages']['error'] += ['_main' => [$e->getMessage()]];
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Exception during submit ('.$e->getMessage().')');
}
}
else
{
} else {
// Handle errors
$aData['valid'] = false;
$aData['messages']['error'] += $this->oForm->GetErrorMessages();
@@ -207,12 +186,9 @@ class PasswordFormManager extends FormManager
$this->Build();
// Then we update it with new values
if (is_array($aArgs))
{
if (isset($aArgs['currentValues']))
{
foreach ($aArgs['currentValues'] as $sPreferenceName => $value)
{
if (is_array($aArgs)) {
if (isset($aArgs['currentValues'])) {
foreach ($aArgs['currentValues'] as $sPreferenceName => $value) {
$this->oForm->GetField($sPreferenceName)->SetCurrentValue($value);
}
}

View File

@@ -39,7 +39,7 @@ use UserRights;
class PreferencesFormManager extends FormManager
{
/** @var string FORM_TYPE */
const FORM_TYPE = 'preferences';
public const FORM_TYPE = 'preferences';
/**
* @throws \Exception
@@ -63,9 +63,8 @@ class PreferencesFormManager extends FormManager
->SetCurrentValue(Dict::GetUserLanguage())
->SetStartsWithNullChoice(false);
// - Preparing choices
$aChoices = array();
foreach (Dict::GetLanguages() as $sCode => $aLanguage)
{
$aChoices = [];
foreach (Dict::GetLanguages() as $sCode => $aLanguage) {
$aChoices[$sCode] = $aLanguage['description'].' ('.$aLanguage['localized_description'].')';
}
asort($aChoices);
@@ -109,11 +108,9 @@ class PreferencesFormManager extends FormManager
$this->OnUpdate($aArgs);
// Check if form valid
if ($this->oForm->Validate())
{
if ($this->oForm->Validate()) {
// The try catch is essentially to start a MySQL transaction
try
{
try {
// Starting transaction
CMDBSource::Query('START TRANSACTION');
$iFieldChanged = 0;
@@ -123,34 +120,28 @@ class PreferencesFormManager extends FormManager
$oCurUser = UserRights::GetUserObject();
// - Language
$sLanguage = $this->oForm->GetField('language')->GetCurrentValue();
if (($sLanguage !== null) && ($oCurUser->Get('language') !== $sLanguage))
{
if (($sLanguage !== null) && ($oCurUser->Get('language') !== $sLanguage)) {
$oCurUser->Set('language', $sLanguage);
$iFieldChanged++;
}
// Updating only if preferences changed
if ($iFieldChanged > 0)
{
if ($iFieldChanged > 0) {
$oCurUser->AllowWrite(true);
$oCurUser->DBUpdate();
$aData['messages']['success'] += array('_main' => array(Dict::S('Brick:Portal:Object:Form:Message:Saved')));
$aData['messages']['success'] += ['_main' => [Dict::S('Brick:Portal:Object:Form:Message:Saved')]];
}
// Ending transaction with a commit as everything was fine
CMDBSource::Query('COMMIT');
}
catch (Exception $e)
{
} catch (Exception $e) {
// End transaction with a rollback as something failed
CMDBSource::Query('ROLLBACK');
$aData['valid'] = false;
$aData['messages']['error'] += array('_main' => array($e->getMessage()));
$aData['messages']['error'] += ['_main' => [$e->getMessage()]];
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Rollback during submit ('.$e->getMessage().')');
}
}
else
{
} else {
// Handle errors
$aData['valid'] = false;
$aData['messages']['error'] += $this->oForm->GetErrorMessages();
@@ -171,12 +162,9 @@ class PreferencesFormManager extends FormManager
$this->Build();
// Then we update it with new values
if (is_array($aArgs))
{
if (isset($aArgs['currentValues']))
{
foreach ($aArgs['currentValues'] as $sPreferenceName => $value)
{
if (is_array($aArgs)) {
if (isset($aArgs['currentValues'])) {
foreach ($aArgs['currentValues'] as $sPreferenceName => $value) {
$this->oForm->GetField($sPreferenceName)->SetCurrentValue($value);
}
}

View File

@@ -41,13 +41,13 @@ use utils;
class ApplicationHelper
{
/** @var string FORM_ENUM_DISPLAY_MODE_COSY */
const FORM_ENUM_DISPLAY_MODE_COSY = 'cosy';
public const FORM_ENUM_DISPLAY_MODE_COSY = 'cosy';
/** @var string FORM_ENUM_DISPLAY_MODE_COMPACT */
const FORM_ENUM_DISPLAY_MODE_COMPACT = 'compact';
public const FORM_ENUM_DISPLAY_MODE_COMPACT = 'compact';
/** @var string FORM_DEFAULT_DISPLAY_MODE */
const FORM_DEFAULT_DISPLAY_MODE = self::FORM_ENUM_DISPLAY_MODE_COSY;
public const FORM_DEFAULT_DISPLAY_MODE = self::FORM_ENUM_DISPLAY_MODE_COSY;
/** @var bool FORM_DEFAULT_ALWAYS_SHOW_SUBMIT */
const FORM_DEFAULT_ALWAYS_SHOW_SUBMIT = false;
public const FORM_DEFAULT_ALWAYS_SHOW_SUBMIT = false;
/**
* Loads classes from the base portal
@@ -72,16 +72,11 @@ class ApplicationHelper
);
// Loading classes from base portal
foreach (scandir($sScannedDir) as $sFile)
{
if (strpos($sFile, $sFilePattern) !== false && file_exists($sFilepath = $sScannedDir.'/'.$sFile))
{
try
{
foreach (scandir($sScannedDir) as $sFile) {
if (strpos($sFile, $sFilePattern) !== false && file_exists($sFilepath = $sScannedDir.'/'.$sFile)) {
try {
require_once $sFilepath;
}
catch (Exception $e)
{
} catch (Exception $e) {
throw new Exception('Error while trying to load '.$sType.' '.$sFile);
}
}
@@ -97,32 +92,25 @@ class ApplicationHelper
*/
public static function LoadBrickSecurity(AbstractBrick $oBrick)
{
try
{
try {
// Allowed profiles
if (utils::IsNotNullOrEmptyString($oBrick->GetAllowedProfilesOql()))
{
if (utils::IsNotNullOrEmptyString($oBrick->GetAllowedProfilesOql())) {
$oSearch = DBObjectSearch::FromOQL_AllData($oBrick->GetAllowedProfilesOql());
$oSet = new DBObjectSet($oSearch);
while ($oProfile = $oSet->Fetch())
{
while ($oProfile = $oSet->Fetch()) {
$oBrick->AddAllowedProfile($oProfile->Get('name'));
}
}
// Denied profiles
if (utils::IsNotNullOrEmptyString($oBrick->GetDeniedProfilesOql()))
{
if (utils::IsNotNullOrEmptyString($oBrick->GetDeniedProfilesOql())) {
$oSearch = DBObjectSearch::FromOQL_AllData($oBrick->GetDeniedProfilesOql());
$oSet = new DBObjectSet($oSearch);
while ($oProfile = $oSet->Fetch())
{
while ($oProfile = $oSet->Fetch()) {
$oBrick->AddDeniedProfile($oProfile->Get('name'));
}
}
}
catch (Exception $e)
{
} catch (Exception $e) {
throw new Exception('Error while loading security from '.$oBrick->GetId().' brick');
}
}
@@ -147,18 +135,14 @@ class ApplicationHelper
$aForm = null;
// We try to find the form for that class
if (isset($aForms[$sClass]) && isset($aForms[$sClass][$sMode]))
{
if (isset($aForms[$sClass]) && isset($aForms[$sClass][$sMode])) {
$aForm = $aForms[$sClass][$sMode];
}
// If not found, we try find one from the closest parent class
else
{
else {
$bFound = false;
foreach (MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_EXCLUDELEAF, false) as $sParentClass)
{
if (isset($aForms[$sParentClass]) && isset($aForms[$sParentClass][$sMode]))
{
foreach (MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_EXCLUDELEAF, false) as $sParentClass) {
if (isset($aForms[$sParentClass]) && isset($aForms[$sParentClass][$sMode])) {
$aForm = $aForms[$sParentClass][$sMode];
$bFound = true;
break;
@@ -166,8 +150,7 @@ class ApplicationHelper
}
// If we have still not found one, we return a default form
if (!$bFound)
{
if (!$bFound) {
$aForm = static::GenerateDefaultFormForClass($sClass);
}
}
@@ -192,32 +175,26 @@ class ApplicationHelper
public static function GetLoadedListFromClass($aLists, $sClass, $sList = 'default')
{
$aFoundList = null;
$aAttCodes = array();
$aAttCodes = [];
// We try to find the list for that class
if (isset($aLists[$sClass]) && isset($aLists[$sClass][$sList]))
{
if (isset($aLists[$sClass]) && isset($aLists[$sClass][$sList])) {
$aFoundList = $aLists[$sClass][$sList];
}
// Else we try to found the default list for that class
elseif (isset($aLists[$sClass]) && isset($aLists[$sClass]['default']))
{
elseif (isset($aLists[$sClass]) && isset($aLists[$sClass]['default'])) {
$aFoundList = $aLists[$sClass]['default'];
}
// If not found, we try find one from the closest parent class
else
{
foreach (MetaModel::EnumParentClasses($sClass) as $sParentClass)
{
else {
foreach (MetaModel::EnumParentClasses($sClass) as $sParentClass) {
// Trying to find the right list
if (isset($aLists[$sParentClass]) && isset($aLists[$sParentClass][$sList]))
{
if (isset($aLists[$sParentClass]) && isset($aLists[$sParentClass][$sList])) {
$aFoundList = $aLists[$sParentClass][$sList];
break;
}
// Or the default list
elseif (isset($aLists[$sParentClass]) && isset($aLists[$sParentClass]['default']))
{
elseif (isset($aLists[$sParentClass]) && isset($aLists[$sParentClass]['default'])) {
$aFoundList = $aLists[$sParentClass]['default'];
break;
}
@@ -225,15 +202,11 @@ class ApplicationHelper
}
// If found, we flatten the list to keep only the attribute codes (not the rank)
if ($aFoundList !== null)
{
foreach ($aFoundList as $aItem)
{
if ($aFoundList !== null) {
foreach ($aFoundList as $aItem) {
$aAttCodes[] = $aItem['att_code'];
}
}
else
{
} else {
$aAttCodes = MetaModel::FlattenZList(MetaModel::GetZListItems($sClass, 'list'));
}
@@ -252,32 +225,31 @@ class ApplicationHelper
*/
protected static function GenerateDefaultFormForClass($sClass, $bAddLinksets = false)
{
$aForm = array(
$aForm = [
'id' => strtolower($sClass)."-default-".uniqid(),
'type' => 'custom_list',
'properties' => array(
'properties' => [
'display_mode' => static::FORM_DEFAULT_DISPLAY_MODE,
'always_show_submit' => static::FORM_DEFAULT_ALWAYS_SHOW_SUBMIT,
'navigation_rules' => array(
'navigation_rules' => [
'submit' => null,
'cancel' => null,
),
),
'fields' => array(),
'layout' => array(
],
],
'fields' => [],
'layout' => [
'type' => 'xhtml',
'content' => '',
),
);
],
];
// Generate layout
$sContent = "";
// - Retrieve zlist details
$aDetailsList = MetaModel::GetZListItems($sClass, 'details');
$aDetailsStruct = cmdbAbstractObject::ProcessZlist($aDetailsList, array(), 'UI:PropertiesTab', 'col1', '');
if(!isset($aDetailsStruct['UI:PropertiesTab']))
{
$aDetailsStruct = cmdbAbstractObject::ProcessZlist($aDetailsList, [], 'UI:PropertiesTab', 'col1', '');
if (!isset($aDetailsStruct['UI:PropertiesTab'])) {
// For the iTop administrator
IssueLog::Error('Could not generate default form for "'.$sClass.'" class. Is the "details" zlist empty?');
// For the end-user
@@ -287,14 +259,10 @@ class ApplicationHelper
// Count cols (not linksets)
$iColCount = 0;
foreach ($aPropertiesStruct as $sColId => $aColFieldsets)
{
if (substr($sColId, 0, 1) !== '_')
{
foreach ($aColFieldsets as $sFieldsetName => $aAttCodes)
{
if (substr($sFieldsetName, 0, 1) !== '_')
{
foreach ($aPropertiesStruct as $sColId => $aColFieldsets) {
if (substr($sColId, 0, 1) !== '_') {
foreach ($aColFieldsets as $sFieldsetName => $aAttCodes) {
if (substr($sFieldsetName, 0, 1) !== '_') {
$iColCount++;
break;
}
@@ -302,28 +270,24 @@ class ApplicationHelper
}
}
// If no cols, return a default form with all fields one after another
if ($iColCount === 0)
{
return array(
if ($iColCount === 0) {
return [
'id' => 'default',
'type' => 'zlist',
'fields' => 'details',
'layout' => null,
);
];
}
// Warning, this might not be great when 12 modulo $iColCount is greater than 0.
$sColCSSClass = 'col-sm-'.floor(12 / $iColCount);
$sLinksetsHTML = "";
$sRowHTML = "<div class=\"row\">\n";
foreach ($aPropertiesStruct as $sColId => $aColFieldsets)
{
foreach ($aPropertiesStruct as $sColId => $aColFieldsets) {
$sColsHTML = "\t<div class=\"".$sColCSSClass."\">\n";
foreach ($aColFieldsets as $sFieldsetName => $aAttCodes)
{
foreach ($aColFieldsets as $sFieldsetName => $aAttCodes) {
// Add fieldset, not linkset
if (substr($sFieldsetName, 0, 1) !== '_')
{
if (substr($sFieldsetName, 0, 1) !== '_') {
$sFieldsetHTML = "\t\t<fieldset>\n";
$sFieldsetHTML .= "\t\t\t<legend>".utils::EscapeHtml(Dict::S($sFieldsetName))."</legend>\n";
@@ -335,11 +299,8 @@ class ApplicationHelper
// Add to col
$sColsHTML .= $sFieldsetHTML;
}
elseif ($bAddLinksets)
{
foreach ($aAttCodes as $sAttCode)
{
} elseif ($bAddLinksets) {
foreach ($aAttCodes as $sAttCode) {
$sLinksetsHTML .= "<div class=\"form_field\" data-field-id=\"".$sAttCode."\"></div>\n";
}
}
@@ -368,8 +329,9 @@ class ApplicationHelper
* @return array
* @since 2.7.0
*/
public static function GetAttDefClassesToExcludeFromMarkupMetadataRawValue(){
return array(
public static function GetAttDefClassesToExcludeFromMarkupMetadataRawValue()
{
return [
'AttributeBlob',
'AttributeCustomFields',
'AttributeDashboard',
@@ -377,7 +339,7 @@ class ApplicationHelper
'AttributeStopWatch',
'AttributeSubItem',
'AttributeTable',
'AttributeText'
);
'AttributeText',
];
}
}

View File

@@ -18,7 +18,6 @@
* You should have received a copy of the GNU Affero General Public License
*/
namespace Combodo\iTop\Portal\Helper;
/**
@@ -53,14 +52,13 @@ class BrickControllerHelper
public function ExtractSortParams()
{
// Getting sort params
$aSortParams = $this->oRequestManipulator->ReadParam('aSortParams', array(), FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY);
$aSortParams = $this->oRequestManipulator->ReadParam('aSortParams', [], FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY);
// Converting sort direction to proper format for DBObjectSet as it only accept real booleans
foreach ($aSortParams as $sAttributeAlias => $sDirection)
{
foreach ($aSortParams as $sAttributeAlias => $sDirection) {
$aSortParams[$sAttributeAlias] = ($sDirection === 'true');
}
return $aSortParams;
}
}
}

View File

@@ -18,10 +18,8 @@
* You should have received a copy of the GNU Affero General Public License
*/
namespace Combodo\iTop\Portal\Helper;
use AttributeImage;
use AttributeSet;
use AttributeTagSet;
@@ -44,9 +42,9 @@ use utils;
class BrowseBrickHelper
{
/** @var string LEVEL_SEPARATOR */
const LEVEL_SEPARATOR = '-';
public const LEVEL_SEPARATOR = '-';
/** @var array OPTIONAL_ATTRIBUTES */
const OPTIONAL_ATTRIBUTES = array('tooltip_att', 'description_att', 'image_att');
public const OPTIONAL_ATTRIBUTES = ['tooltip_att', 'description_att', 'image_att'];
/** @var \Combodo\iTop\Portal\Helper\SecurityHelper */
private $oSecurityHelper;
@@ -62,7 +60,10 @@ class BrowseBrickHelper
* @param \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator
* @param \Symfony\Component\Routing\Generator\UrlGeneratorInterface $oUrlGenerator
*/
public function __construct(SecurityHelper $oSecurityHelper, ScopeValidatorHelper $oScopeValidator, UrlGeneratorInterface $oUrlGenerator
public function __construct(
SecurityHelper $oSecurityHelper,
ScopeValidatorHelper $oScopeValidator,
UrlGeneratorInterface $oUrlGenerator
) {
$this->oSecurityHelper = $oSecurityHelper;
$this->oScopeValidator = $oScopeValidator;
@@ -89,24 +90,24 @@ class BrowseBrickHelper
*/
public function TreeToFlatLevelsProperties(array $aLevels, array &$aLevelsProperties, $sLevelAliasPrefix = 'L')
{
foreach ($aLevels as $aLevel)
{
foreach ($aLevels as $aLevel) {
$sCurrentLevelAlias = $sLevelAliasPrefix.static::LEVEL_SEPARATOR.$aLevel['id'];
$oSearch = DBSearch::CloneWithAlias(DBSearch::FromOQL($aLevel['oql']), $sCurrentLevelAlias);
// Restricting to the allowed scope
$oScopeSearch = $this->oScopeValidator->GetScopeFilterForProfiles(UserRights::ListProfiles(), $oSearch->GetClass(),
UR_ACTION_READ);
$oScopeSearch = $this->oScopeValidator->GetScopeFilterForProfiles(
UserRights::ListProfiles(),
$oSearch->GetClass(),
UR_ACTION_READ
);
$oSearch = ($oScopeSearch !== null) ? $oSearch->Intersect($oScopeSearch) : null;
// - Allowing all data if necessary
if ($oScopeSearch !== null && $oScopeSearch->IsAllDataAllowed())
{
if ($oScopeSearch !== null && $oScopeSearch->IsAllDataAllowed()) {
$oSearch->AllowAllData();
}
if ($oSearch !== null)
{
$aLevelsProperties[$sCurrentLevelAlias] = array(
if ($oSearch !== null) {
$aLevelsProperties[$sCurrentLevelAlias] = [
'alias' => $sCurrentLevelAlias,
'title' => ($aLevel['title'] !== null) ? Dict::S($aLevel['title']) : MetaModel::GetName($oSearch->GetClass()),
'parent_att' => $aLevel['parent_att'],
@@ -115,42 +116,35 @@ class BrowseBrickHelper
'description_att' => $aLevel['description_att'],
'image_att' => $aLevel['image_att'],
'search' => $oSearch,
'fields' => array(),
'actions' => array(),
);
'fields' => [],
'actions' => [],
];
// Adding current level's fields
if (isset($aLevel['fields']))
{
$aLevelsProperties[$sCurrentLevelAlias]['fields'] = array();
if (isset($aLevel['fields'])) {
$aLevelsProperties[$sCurrentLevelAlias]['fields'] = [];
foreach ($aLevel['fields'] as $sFieldAttCode => $aFieldProperties)
{
$aLevelsProperties[$sCurrentLevelAlias]['fields'][] = array(
foreach ($aLevel['fields'] as $sFieldAttCode => $aFieldProperties) {
$aLevelsProperties[$sCurrentLevelAlias]['fields'][] = [
'code' => $sFieldAttCode,
'label' => MetaModel::GetAttributeDef($oSearch->GetClass(), $sFieldAttCode)->GetLabel(),
'hidden' => $aFieldProperties['hidden'],
);
];
}
}
// Flattening and adding sub levels
if (isset($aLevel['levels']))
{
foreach ($aLevel['levels'] as $aChildLevel)
{
if (isset($aLevel['levels'])) {
foreach ($aLevel['levels'] as $aChildLevel) {
// Checking if the sub level if allowed
$oChildSearch = DBSearch::FromOQL($aChildLevel['oql']);
if ($this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $oChildSearch->GetClass()))
{
if ($this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $oChildSearch->GetClass())) {
// Adding the sub level to this one
$aLevelsProperties[$sCurrentLevelAlias]['levels'][] = $sCurrentLevelAlias.static::LEVEL_SEPARATOR.$aChildLevel['id'];
// Adding drill down action if necessary
foreach ($aLevel['actions'] as $sId => $aAction)
{
if ($aAction['type'] === BrowseBrick::ENUM_ACTION_DRILLDOWN)
{
foreach ($aLevel['actions'] as $sId => $aAction) {
if ($aAction['type'] === BrowseBrick::ENUM_ACTION_DRILLDOWN) {
$aLevelsProperties[$sCurrentLevelAlias]['actions'][$sId] = $aAction;
break;
}
@@ -162,49 +156,43 @@ class BrowseBrickHelper
}
// Adding actions to the level
foreach ($aLevel['actions'] as $sId => $aAction)
{
foreach ($aLevel['actions'] as $sId => $aAction) {
// ... Only if it's not already there (eg. the drilldown added with the sublevels)
if (!array_key_exists($sId, $aLevelsProperties[$sCurrentLevelAlias]['actions']))
{
if (!array_key_exists($sId, $aLevelsProperties[$sCurrentLevelAlias]['actions'])) {
// Adding action only if allowed
if (($aAction['type'] === BrowseBrick::ENUM_ACTION_VIEW) && !$this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ,
$oSearch->GetClass()))
{
if (($aAction['type'] === BrowseBrick::ENUM_ACTION_VIEW) && !$this->oSecurityHelper->IsActionAllowed(
UR_ACTION_READ,
$oSearch->GetClass()
)) {
continue;
}
elseif (($aAction['type'] === BrowseBrick::ENUM_ACTION_EDIT) && !$this->oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY,
$oSearch->GetClass()))
{
} elseif (($aAction['type'] === BrowseBrick::ENUM_ACTION_EDIT) && !$this->oSecurityHelper->IsActionAllowed(
UR_ACTION_MODIFY,
$oSearch->GetClass()
)) {
continue;
}
elseif ($aAction['type'] === BrowseBrick::ENUM_ACTION_DRILLDOWN)
{
} elseif ($aAction['type'] === BrowseBrick::ENUM_ACTION_DRILLDOWN) {
continue;
}
// Setting action title
if (isset($aAction['title']))
{
if (isset($aAction['title'])) {
// Note : There could be an enhancement here, by checking if the string code has the '%1' needle and use Dict::S or Dict::Format accordingly.
// But it would require to benchmark a potential performance drop as it will be done for all items
$aAction['title'] = Dict::S($aAction['title']);
}
else
{
switch ($aAction['type'])
{
} else {
switch ($aAction['type']) {
case BrowseBrick::ENUM_ACTION_CREATE_FROM_THIS:
// We can only make translate a dictionary entry with a class placeholder when the action has a class tag. if it has a factory method, we don't know yet what class is going to be created
if ($aAction['factory']['type'] === BrowseBrick::ENUM_FACTORY_TYPE_CLASS)
{
$aAction['title'] = Dict::Format('Brick:Portal:Browse:Action:CreateObjectFromThis',
MetaModel::GetName($aAction['factory']['value']));
$aAction['url'] = $this->oUrlGenerator->generate('p_object_create',
array('sObjectClass' => $aAction['factory']['value']));
}
else
{
if ($aAction['factory']['type'] === BrowseBrick::ENUM_FACTORY_TYPE_CLASS) {
$aAction['title'] = Dict::Format(
'Brick:Portal:Browse:Action:CreateObjectFromThis',
MetaModel::GetName($aAction['factory']['value'])
);
$aAction['url'] = $this->oUrlGenerator->generate(
'p_object_create',
['sObjectClass' => $aAction['factory']['value']]
);
} else {
$aAction['title'] = Dict::S('Brick:Portal:Browse:Action:Create');
}
break;
@@ -221,10 +209,8 @@ class BrowseBrickHelper
}
// Setting action icon class
if (!isset($aAction['icon_class']))
{
switch ($aAction['type'])
{
if (!isset($aAction['icon_class'])) {
switch ($aAction['type']) {
case BrowseBrick::ENUM_ACTION_CREATE_FROM_THIS:
$aAction['icon_class'] = BrowseBrick::ENUM_ACTION_ICON_CLASS_CREATE_FROM_THIS;
break;
@@ -241,21 +227,19 @@ class BrowseBrickHelper
}
// Setting action url
switch ($aAction['type'])
{
switch ($aAction['type']) {
case BrowseBrick::ENUM_ACTION_CREATE_FROM_THIS:
if ($aAction['factory']['type'] === BrowseBrick::ENUM_FACTORY_TYPE_CLASS)
{
$aAction['url'] = $this->oUrlGenerator->generate('p_object_create',
array('sObjectClass' => $aAction['factory']['value']));
}
else
{
$aAction['url'] = $this->oUrlGenerator->generate('p_object_create_from_factory', array(
if ($aAction['factory']['type'] === BrowseBrick::ENUM_FACTORY_TYPE_CLASS) {
$aAction['url'] = $this->oUrlGenerator->generate(
'p_object_create',
['sObjectClass' => $aAction['factory']['value']]
);
} else {
$aAction['url'] = $this->oUrlGenerator->generate('p_object_create_from_factory', [
'sEncodedMethodName' => base64_encode($aAction['factory']['value']),
'sObjectClass' => '-objectClass-',
'sObjectId' => '-objectId-',
));
]);
}
break;
}
@@ -278,10 +262,9 @@ class BrowseBrickHelper
*/
public function PrepareActionRulesForItems(array $aItems, $sLevelsAlias, array &$aLevelsProperties)
{
$aActionRules = array();
$aActionRules = [];
foreach ($aLevelsProperties[$sLevelsAlias]['actions'] as $sId => $aAction)
{
foreach ($aLevelsProperties[$sLevelsAlias]['actions'] as $sId => $aAction) {
$aActionRules[$sId] = ContextManipulatorHelper::PrepareAndEncodeRulesToken($aAction['rules'], $aItems);
}
@@ -317,11 +300,10 @@ class BrowseBrickHelper
*/
public function AddToFlatItems(array $aCurrentRow, array &$aLevelsProperties)
{
$aRow = array();
$aRow = [];
/** @var \DBObject $value */
foreach ($aCurrentRow as $key => $value)
{
foreach ($aCurrentRow as $key => $value) {
// Retrieving objects from all levels
$aItems = array_values($aCurrentRow);
@@ -332,36 +314,31 @@ class BrowseBrickHelper
$sNameAttDef = MetaModel::GetAttributeDef($sCurrentObjectClass, $sNameAttCode);
$sNameAttDefClass = get_class($sNameAttDef);
$aRow[$key] = array(
$aRow[$key] = [
'level_alias' => $key,
'id' => $sCurrentObjectId,
'name' => utils::EscapeHtml($value->Get($sNameAttCode)),
'class' => $sCurrentObjectClass,
'action_rules_token' => $this->PrepareActionRulesForItems($aItems, $key, $aLevelsProperties),
'metadata' => array(
'metadata' => [
'object_class' => $sCurrentObjectClass,
'object_id' => $sCurrentObjectId,
'attribute_code' => $sNameAttCode,
'attribute_type' => $sNameAttDefClass,
'value_raw' => $value->Get($sNameAttCode),
),
);
],
];
// Adding optional attributes if necessary
foreach (static::OPTIONAL_ATTRIBUTES as $sOptionalAttribute)
{
if ($aLevelsProperties[$key][$sOptionalAttribute] !== null)
{
foreach (static::OPTIONAL_ATTRIBUTES as $sOptionalAttribute) {
if ($aLevelsProperties[$key][$sOptionalAttribute] !== null) {
$sPropertyName = substr($sOptionalAttribute, 0, -4);
$oAttDef = MetaModel::GetAttributeDef($sCurrentObjectClass, $aLevelsProperties[$key][$sOptionalAttribute]);
if ($oAttDef instanceof AttributeImage)
{
if ($oAttDef instanceof AttributeImage) {
$tmpAttValue = $value->Get($aLevelsProperties[$key][$sOptionalAttribute]);
if ($sOptionalAttribute === 'image_att')
{
if (is_object($tmpAttValue) && !$tmpAttValue->IsEmpty())
{
if ($sOptionalAttribute === 'image_att') {
if (is_object($tmpAttValue) && !$tmpAttValue->IsEmpty()) {
$oOrmDoc = $tmpAttValue;
$tmpAttValue = $this->oUrlGenerator->generate('p_object_document_display', [
'sObjectClass' => $sCurrentObjectClass,
@@ -370,15 +347,11 @@ class BrowseBrickHelper
'cache' => 86400,
's' => $oOrmDoc->GetSignature(),
]);
}
else
{
} else {
$tmpAttValue = $oAttDef->Get('default_image');
}
}
}
else
{
} else {
$tmpAttValue = $value->GetAsHTML($aLevelsProperties[$key][$sOptionalAttribute]);
}
@@ -386,16 +359,13 @@ class BrowseBrickHelper
}
}
// Adding fields attributes if necessary
if (!empty($aLevelsProperties[$key]['fields']))
{
$aRow[$key]['fields'] = array();
foreach ($aLevelsProperties[$key]['fields'] as $aField)
{
if (!empty($aLevelsProperties[$key]['fields'])) {
$aRow[$key]['fields'] = [];
foreach ($aLevelsProperties[$key]['fields'] as $aField) {
$oAttDef = MetaModel::GetAttributeDef($sCurrentObjectClass, $aField['code']);
$sAttDefClass = get_class($oAttDef);
switch (true)
{
switch (true) {
case $oAttDef instanceof AttributeTagSet:
/** @var \ormTagSet $oSetValues */
$oSetValues = $value->Get($aField['code']);
@@ -412,8 +382,7 @@ class BrowseBrickHelper
case $oAttDef instanceof AttributeImage:
// Todo: This should be refactored, it has been seen multiple times in the portal
$oOrmDoc = $value->Get($aField['code']);
if (is_object($oOrmDoc) && !$oOrmDoc->IsEmpty())
{
if (is_object($oOrmDoc) && !$oOrmDoc->IsEmpty()) {
$sUrl = $this->oUrlGenerator->generate('p_object_document_display', [
'sObjectClass' => $sCurrentObjectClass,
'sObjectId' => $sCurrentObjectId,
@@ -421,9 +390,7 @@ class BrowseBrickHelper
'cache' => 86400,
's' => $oOrmDoc->GetSignature(),
]);
}
else
{
} else {
$sUrl = $oAttDef->Get('default_image');
}
$sHtmlForFieldValue = '<img src="'.$sUrl.'" />';
@@ -436,24 +403,22 @@ class BrowseBrickHelper
// For simple fields, we get the raw (stored) value as well
$bExcludeRawValue = false;
foreach (ApplicationHelper::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude)
{
if (is_a($sAttDefClass, $sAttDefClassToExclude, true))
{
foreach (ApplicationHelper::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude) {
if (is_a($sAttDefClass, $sAttDefClassToExclude, true)) {
$bExcludeRawValue = true;
break;
}
}
$attValueRaw = ($bExcludeRawValue === false) ? $value->Get($aField['code']) : null;
$aRow[$key]['fields'][$aField['code']] = array(
$aRow[$key]['fields'][$aField['code']] = [
'object_class' => $sCurrentObjectClass,
'object_id' => $sCurrentObjectId,
'attribute_code' => $aField['code'],
'attribute_type' => $sAttDefClass,
'value_raw' => $attValueRaw,
'value_html' => $sHtmlForFieldValue,
);
];
}
}
}
@@ -503,39 +468,34 @@ class BrowseBrickHelper
// We make sure to keep all row objects through levels by copying them when processing the first level.
// Otherwise they will be sliced through levels, one by one.
if ($aCurrentRowObjects === null)
{
if ($aCurrentRowObjects === null) {
$aCurrentRowObjects = $aCurrentRowValues;
}
if (!isset($aItems[$sCurrentIndex]))
{
$aItems[$sCurrentIndex] = array(
if (!isset($aItems[$sCurrentIndex])) {
$aItems[$sCurrentIndex] = [
'level_alias' => $aCurrentRowKeys[0],
'id' => $aCurrentRowValues[0]->GetKey(),
'name' => utils::EscapeHtml($aCurrentRowValues[0]->Get($aLevelsProperties[$aCurrentRowKeys[0]]['name_att'])),
'class' => get_class($aCurrentRowValues[0]),
'subitems' => array(),
'subitems' => [],
'filter_data' => $this->GetFilterData($aLevelsProperties[$aCurrentRowKeys[0]], $aCurrentRowKeys[0], $aCurrentRowValues[0]),
'action_rules_token' => $this->PrepareActionRulesForItems($aCurrentRowObjects, $aCurrentRowKeys[0], $aLevelsProperties),
);
];
// Adding optional attributes if necessary
foreach (static::OPTIONAL_ATTRIBUTES as $sOptionalAttribute)
{
if ($aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute] !== null)
{
foreach (static::OPTIONAL_ATTRIBUTES as $sOptionalAttribute) {
if ($aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute] !== null) {
$sPropertyName = substr($sOptionalAttribute, 0, -4);
$oAttDef = MetaModel::GetAttributeDef(get_class($aCurrentRowValues[0]),
$aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute]);
$oAttDef = MetaModel::GetAttributeDef(
get_class($aCurrentRowValues[0]),
$aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute]
);
if ($oAttDef instanceof AttributeImage)
{
if ($oAttDef instanceof AttributeImage) {
$tmpAttValue = $aCurrentRowValues[0]->Get($aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute]);
if ($sOptionalAttribute === 'image_att')
{
if (is_object($tmpAttValue) && !$tmpAttValue->IsEmpty())
{
if ($sOptionalAttribute === 'image_att') {
if (is_object($tmpAttValue) && !$tmpAttValue->IsEmpty()) {
$oOrmDoc = $tmpAttValue;
$tmpAttValue = $this->oUrlGenerator->generate('p_object_document_display', [
'sObjectClass' => get_class($aCurrentRowValues[0]),
@@ -544,15 +504,11 @@ class BrowseBrickHelper
'cache' => 86400,
's' => $oOrmDoc->GetSignature(),
]);
}
else
{
} else {
$tmpAttValue = $oAttDef->Get('default_image');
}
}
}
else
{
} else {
$tmpAttValue = $aCurrentRowValues[0]->GetAsHTML($aLevelsProperties[$aCurrentRowKeys[0]][$sOptionalAttribute]);
}
@@ -562,8 +518,7 @@ class BrowseBrickHelper
}
$aCurrentRowSliced = array_slice($aCurrentRow, 1);
if (!empty($aCurrentRowSliced))
{
if (!empty($aCurrentRowSliced)) {
$this->AddToTreeItems($aItems[$sCurrentIndex]['subitems'], $aCurrentRowSliced, $aLevelsProperties, $aCurrentRowObjects);
}
}
@@ -580,7 +535,7 @@ class BrowseBrickHelper
* @throws \CoreException
* @throws \Exception
*/
private function GetFilterData(array $aLevelProperties, string $sRowKey, DBObject $oRowValue) : array
private function GetFilterData(array $aLevelProperties, string $sRowKey, DBObject $oRowValue): array
{
// result
$sValues = "";
@@ -599,17 +554,17 @@ class BrowseBrickHelper
$sValue = $oAttDef->GetAsHTML($oRowValue->Get($aField['code']));
// do not print empty fields
if(!utils::IsNullOrEmptyString($sValue)){
if (!utils::IsNullOrEmptyString($sValue)) {
// append to result
$sValues .= $sValue;
$sValuesAndCodes .= '<span><span class="tree-item-filter-data-label">' . $aField['label'] . ':</span> ' . $sValue . '</span>';
$sValuesAndCodes .= '<span><span class="tree-item-filter-data-label">'.$aField['label'].':</span> '.$sValue.'</span>';
}
}
return [
'values' => $sValues,
'values_and_codes' => $sValuesAndCodes
'values_and_codes' => $sValuesAndCodes,
];
}
}

View File

@@ -28,6 +28,7 @@ use SimpleCrypt;
use Symfony\Component\Routing\RouterInterface;
use TrueExpression;
use UserRights;
use const UR_ACTION_READ;
/**
@@ -40,19 +41,19 @@ use const UR_ACTION_READ;
class ContextManipulatorHelper
{
/** @var string ENUM_RULE_CALLBACK_BACK */
const ENUM_RULE_CALLBACK_BACK = 'back';
public const ENUM_RULE_CALLBACK_BACK = 'back';
/** @var string ENUM_RULE_CALLBACK_GOTO */
const ENUM_RULE_CALLBACK_GOTO = 'goto';
public const ENUM_RULE_CALLBACK_GOTO = 'goto';
/** @var string ENUM_RULE_CALLBACK_OPEN */
const ENUM_RULE_CALLBACK_OPEN = 'open';
public const ENUM_RULE_CALLBACK_OPEN = 'open';
/** @var string ENUM_RULE_CALLBACK_OPEN_VIEW */
const ENUM_RULE_CALLBACK_OPEN_VIEW = 'view';
public const ENUM_RULE_CALLBACK_OPEN_VIEW = 'view';
/** @var string ENUM_RULE_CALLBACK_OPEN_EDIT */
const ENUM_RULE_CALLBACK_OPEN_EDIT = 'edit';
public const ENUM_RULE_CALLBACK_OPEN_EDIT = 'edit';
/** @var string DEFAULT_RULE_CALLBACK_OPEN */
const DEFAULT_RULE_CALLBACK_OPEN = self::ENUM_RULE_CALLBACK_OPEN_VIEW;
public const DEFAULT_RULE_CALLBACK_OPEN = self::ENUM_RULE_CALLBACK_OPEN_VIEW;
const PRIVATE_KEY = 'portal-priv-key';
public const PRIVATE_KEY = 'portal-priv-key';
/** @var array $aRules */
protected $aRules;
@@ -76,8 +77,9 @@ class ContextManipulatorHelper
*
* @throws \DOMFormatException
*/
public function __construct(ModuleDesign $oModuleDesign, RouterInterface $oRouter, BrickCollection $oBrickCollection, ScopeValidatorHelper $oScopeValidator) {
$this->aRules = array();
public function __construct(ModuleDesign $oModuleDesign, RouterInterface $oRouter, BrickCollection $oBrickCollection, ScopeValidatorHelper $oScopeValidator)
{
$this->aRules = [];
$this->oRouter = $oRouter;
$this->oBrickCollection = $oBrickCollection;
@@ -95,38 +97,34 @@ class ContextManipulatorHelper
*/
public function Init(DOMNodeList $oNodes)
{
$this->aRules = array();
$this->aRules = [];
// Iterating over the scope nodes
/** @var \Combodo\iTop\DesignElement $oRuleNode */
foreach ($oNodes as $oRuleNode)
{
foreach ($oNodes as $oRuleNode) {
// Retrieving mandatory id attribute
$sRuleId = $oRuleNode->getAttribute('id');
if ($sRuleId === '')
{
if ($sRuleId === '') {
throw new DOMFormatException('Rule tag must have an id attribute.', null, null, $oRuleNode);
}
// Setting if the rule needs a source object
$bNeedsSource = false;
// Note : preset and retrofit are no longer plurals as it should match as much as possible iTopObjectCopier specs. We use plurals only in the xml for the collection tags
$aRule = array(
$aRule = [
'source_oql' => null,
'dest_class' => null,
'preset' => array(),
'retrofit' => array(),
'preset' => [],
'retrofit' => [],
'submit' => null,
'cancel' => null,
);
];
// Iterating over the rule's nodes
/** @var \Combodo\iTop\DesignElement $oSubNode */
foreach ($oRuleNode->GetNodes('*') as $oSubNode)
{
foreach ($oRuleNode->GetNodes('*') as $oSubNode) {
$sSubNodeName = $oSubNode->nodeName;
switch ($sSubNodeName)
{
switch ($sSubNodeName) {
case 'source_class':
$aRule['source_oql'] = 'SELECT '.$oSubNode->GetText();
break;
@@ -139,17 +137,14 @@ class ContextManipulatorHelper
case 'presets':
case 'retrofits':
/** @var \Combodo\iTop\DesignElement $oActionNode */
foreach ($oSubNode->GetNodes('*') as $oActionNode)
{
foreach ($oSubNode->GetNodes('*') as $oActionNode) {
// Note : Caution, the index of $aRule is now $oActionNode->nodeName instead of $sSubNodeName, as we want to match iTopObjectCopier specs like told previously
if (in_array($oActionNode->nodeName, array('preset', 'retrofit')))
{
if (in_array($oActionNode->nodeName, ['preset', 'retrofit'])) {
$sActionText = $oActionNode->GetText();
$aRule[$oActionNode->nodeName][] = $sActionText;
// Checking if the rule needs a source object
if (substr($sActionText, 0, 4) === 'copy')
{
if (substr($sActionText, 0, 4) === 'copy') {
$bNeedsSource = true;
}
}
@@ -160,25 +155,21 @@ class ContextManipulatorHelper
case 'cancel':
// Retrieving callback type and checking that it is allowed
$sType = $oSubNode->getAttribute('xsi:type');
if ($sType === '')
{
if ($sType === '') {
throw new DOMFormatException($sSubNodeName.' must have an xsi:type attribute.', null, null, $oSubNode);
}
if (($sType === static::ENUM_RULE_CALLBACK_OPEN) && ($sSubNodeName === 'cancel'))
{
if (($sType === static::ENUM_RULE_CALLBACK_OPEN) && ($sSubNodeName === 'cancel')) {
throw new DOMFormatException('Cancel tag cannot be of type '.$sType.'.', null, null, $oSubNode);
}
$aRule[$sSubNodeName] = array('type' => $sType);
switch ($sType)
{
$aRule[$sSubNodeName] = ['type' => $sType];
switch ($sType) {
case static::ENUM_RULE_CALLBACK_BACK:
// Default value
$sRefresh = false;
// Retrieving value
$oRefreshNode = $oSubNode->GetOptionalElement('refresh');
if (($oRefreshNode !== null) && ($oRefreshNode->GetText() !== null))
{
if (($oRefreshNode !== null) && ($oRefreshNode->GetText() !== null)) {
$sRefresh = $oRefreshNode->GetText();
}
@@ -187,8 +178,7 @@ class ContextManipulatorHelper
case static::ENUM_RULE_CALLBACK_GOTO:
// Retrieving value
$sBrickId = $oSubNode->GetUniqueElement('brick')->GetText();
if ($sBrickId === null)
{
if ($sBrickId === null) {
throw new DOMFormatException('Brick tag value must not be empty.', null, null, $oSubNode);
}
@@ -199,8 +189,7 @@ class ContextManipulatorHelper
$sMode = static::ENUM_RULE_CALLBACK_OPEN_VIEW;
// Retrieving value
$oModeNode = $oSubNode->GetOptionalElement('mode');
if (($oModeNode !== null) && ($oModeNode->GetText() !== null))
{
if (($oModeNode !== null) && ($oModeNode->GetText() !== null)) {
$sMode = $oModeNode->GetText();
}
@@ -212,8 +201,7 @@ class ContextManipulatorHelper
}
// If there is no source information we check if there is a preset that requires a copy in order to throw an exception
if (($aRule['source_oql'] === null) && ($bNeedsSource === true))
{
if (($aRule['source_oql'] === null) && ($bNeedsSource === true)) {
throw new DOMFormatException('Rule tag must have either a "source_oql" or a "source_class" child node.', null, null, $oRuleNode);
}
@@ -221,7 +209,6 @@ class ContextManipulatorHelper
}
}
/**
* Returns a hash array of rules
*
@@ -242,8 +229,7 @@ class ContextManipulatorHelper
*/
public function GetRule($sId)
{
if (!array_key_exists($sId, $this->aRules))
{
if (!array_key_exists($sId, $this->aRules)) {
throw new Exception('Context creator : Could not find "'.$sId.'" in the rules list');
}
@@ -276,30 +262,26 @@ class ContextManipulatorHelper
*/
public function PrepareObject(array $aData, DBObject $oObject)
{
if (isset($aData['rules']) && isset($aData['sources']))
{
if (isset($aData['rules']) && isset($aData['sources'])) {
$aRules = $aData['rules'];
$aSources = $aData['sources'];
$aActionRulesErrors = array();
foreach ($aRules as $sRuleId)
{
try
{
$aActionRulesErrors = [];
foreach ($aRules as $sRuleId) {
try {
$this->PrepareAndExecActionRule($sRuleId, $aSources, $oObject);
}
catch (CorePortalInvalidActionRuleException $e)
{
} catch (CorePortalInvalidActionRuleException $e) {
$aActionRulesErrors[$sRuleId] = $e->getMessage();
}
}
if (!empty($aActionRulesErrors))
{
if (!empty($aActionRulesErrors)) {
$sDestinationObjectDesc = '';
$sDestinationObjectDesc .= get_class($oObject);
$sDestinationObjectDesc .= '['.$oObject->GetKey().']';
throw new CorePortalInvalidActionRuleException('Some action rules were not executed',
throw new CorePortalInvalidActionRuleException(
'Some action rules were not executed',
$aActionRulesErrors,
'destination object: '.$sDestinationObjectDesc);
'destination object: '.$sDestinationObjectDesc
);
}
}
}
@@ -323,8 +305,7 @@ class ContextManipulatorHelper
$aRule = $this->GetRule($sRuleId);
// Retrieving source object if needed
if ($aRule['source_oql'] !== null)
{
if ($aRule['source_oql'] !== null) {
// Preparing query to retrieve source object(s)
/** @var \DBObjectSearch $oSearch */
$oSearch = DBSearch::FromOQL($aRule['source_oql']);
@@ -336,45 +317,37 @@ class ContextManipulatorHelper
$sSearchClass = $oSearch->GetClass();
$aSearchParams = $oSearch->GetInternalParams();
if (array_key_exists($sSearchClass, $aSources))
{
if (array_key_exists($sSearchClass, $aSources)) {
$sourceId = $aSources[$sSearchClass];
if (array_key_exists('id', $oSearch->GetQueryParams()))
{
if (is_array($sourceId))
{
if (array_key_exists('id', $oSearch->GetQueryParams())) {
if (is_array($sourceId)) {
throw new Exception('Context creator : ":id" parameter in rule "'.$sRuleId.'" cannot be an array (This is a limitation of DBSearch)');
}
$aSearchParams['id'] = $sourceId;
}
else
{
if (!is_array($sourceId))
{
$sourceId = array($sourceId);
} else {
if (!is_array($sourceId)) {
$sourceId = [$sourceId];
}
$iLoopMax = count($sourceId);
$oFullBinExpr = null;
for ($i = 0; $i < $iLoopMax; $i++)
{
for ($i = 0; $i < $iLoopMax; $i++) {
// - Building full search expression
$oBinExpr = new BinaryExpression(new FieldExpression('id', $oSearch->GetClassAlias()), '=',
new ScalarExpression($sourceId[$i]));
if ($i === 0)
{
$oBinExpr = new BinaryExpression(
new FieldExpression('id', $oSearch->GetClassAlias()),
'=',
new ScalarExpression($sourceId[$i])
);
if ($i === 0) {
$oFullBinExpr = $oBinExpr;
}
else
{
} else {
$oFullBinExpr = new BinaryExpression($oFullBinExpr, 'OR', $oBinExpr);
}
// - Adding it to the query when complete
if ($i === ($iLoopMax - 1))
{
if ($i === ($iLoopMax - 1)) {
$oSearch->AddConditionExpression($oFullBinExpr);
}
}
@@ -382,8 +355,7 @@ class ContextManipulatorHelper
}
$oSearchRootCondition = $oSearch->GetCriteria();
if (($oSearchRootCondition === null) || ($oSearchRootCondition instanceof TrueExpression))
{
if (($oSearchRootCondition === null) || ($oSearchRootCondition instanceof TrueExpression)) {
// N°2555 : disallow searches without any condition
$sErrMsg = "Portal query was stopped: action_rule '$sRuleId' searches for '$sSearchClass' without any condition is forbidden";
IssueLog::Error($sErrMsg);
@@ -391,35 +363,31 @@ class ContextManipulatorHelper
}
// Checking for silos
$oScopeSearch = $this->oScopeValidator->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sSearchClass,
UR_ACTION_READ);
if ($oScopeSearch->IsAllDataAllowed())
{
$oScopeSearch = $this->oScopeValidator->GetScopeFilterForProfiles(
UserRights::ListProfiles(),
$sSearchClass,
UR_ACTION_READ
);
if ($oScopeSearch->IsAllDataAllowed()) {
$oSearch->AllowAllData();
}
// Retrieving source object(s) and applying rules
$oSet = new DBObjectSet($oSearch, array(), $aSearchParams);
while ($oSourceObject = $oSet->Fetch()) // we need a loop for certain preset verbs like add_to_list, see N°2555
{
$oSet = new DBObjectSet($oSearch, [], $aSearchParams);
while ($oSourceObject = $oSet->Fetch()) { // we need a loop for certain preset verbs like add_to_list, see N°2555
// Presets
if (isset($aRule['preset']) && !empty($aRule['preset']))
{
$oDestinationObject->ExecActions($aRule['preset'], array('source' => $oSourceObject));
if (isset($aRule['preset']) && !empty($aRule['preset'])) {
$oDestinationObject->ExecActions($aRule['preset'], ['source' => $oSourceObject]);
}
// Retrofits
if (isset($aRule['retrofit']) && !empty($aRule['retrofit']))
{
$oSourceObject->ExecActions($aRule['retrofit'], array('source' => $oDestinationObject));
if (isset($aRule['retrofit']) && !empty($aRule['retrofit'])) {
$oSourceObject->ExecActions($aRule['retrofit'], ['source' => $oDestinationObject]);
}
}
}
else
{
} else {
// Presets
if (isset($aRule['preset']) && !empty($aRule['preset']))
{
$oDestinationObject->ExecActions($aRule['preset'], array('source' => $oDestinationObject));
if (isset($aRule['preset']) && !empty($aRule['preset'])) {
$oDestinationObject->ExecActions($aRule['preset'], ['source' => $oDestinationObject]);
}
}
}
@@ -447,10 +415,10 @@ class ContextManipulatorHelper
public function GetCallbackUrls(array $aData, DBObject $oObject, $bModal = false)
{
DeprecatedCallsLog::NotifyDeprecatedPhpMethod('Use navigation rules for form callbacks');
$aResults = array(
$aResults = [
'submit' => null,
'cancel' => null,
);
];
if (isset($aData['rules'])) {
foreach ($aData['rules'] as $sId) {
@@ -458,29 +426,27 @@ class ContextManipulatorHelper
$aRule = $this->GetRule($sId);
// For each type of callbacks, we check if there is a rule to apply
foreach (array('submit', 'cancel') as $sCallbackName)
{
if (is_array($aRule[$sCallbackName]))
{
foreach (['submit', 'cancel'] as $sCallbackName) {
if (is_array($aRule[$sCallbackName])) {
// Previously declared rule on a callback is overwritten by the last
$sCallbackUrl = null;
switch ($aRule[$sCallbackName]['type'])
{
switch ($aRule[$sCallbackName]['type']) {
case static::ENUM_RULE_CALLBACK_BACK:
if (!$bModal)
{
if (!$bModal) {
$sCallbackUrl = ($_SERVER['HTTP_REFERER'] !== '') ? $_SERVER['HTTP_REFERER'] : null;
}
break;
case static::ENUM_RULE_CALLBACK_GOTO:
$oBrick = $this->oBrickCollection->GetBrickById($aRule[$sCallbackName]['brick_id']);
$sCallbackUrl = $this->oRouter->generate($oBrick->GetRouteName(), array('sBrickId' => $oBrick->GetId()));
$sCallbackUrl = $this->oRouter->generate($oBrick->GetRouteName(), ['sBrickId' => $oBrick->GetId()]);
break;
case static::ENUM_RULE_CALLBACK_OPEN:
$sCallbackUrl = ($oObject->IsNew()) ? null : $this->oRouter->generate('p_object_'.$aRule[$sCallbackName]['mode'],
array('sObjectClass' => get_class($oObject), 'sObjectId' => $oObject->GetKey()));
$sCallbackUrl = ($oObject->IsNew()) ? null : $this->oRouter->generate(
'p_object_'.$aRule[$sCallbackName]['mode'],
['sObjectClass' => get_class($oObject), 'sObjectId' => $oObject->GetKey()]
);
break;
}
@@ -501,20 +467,19 @@ class ContextManipulatorHelper
*
* @return array
*/
public static function PrepareRulesForToken($aRules, $aObjects = array())
public static function PrepareRulesForToken($aRules, $aObjects = [])
{
// Getting necessary information from objects
$aSources = array();
foreach ($aObjects as $oObject)
{
$aSources = [];
foreach ($aObjects as $oObject) {
$aSources[get_class($oObject)] = $oObject->GetKey();
}
// Preparing data
$aTokenRules = array(
$aTokenRules = [
'rules' => $aRules,
'sources' => $aSources,
);
];
return $aTokenRules;
}
@@ -545,7 +510,7 @@ class ContextManipulatorHelper
*
* @return string
*/
public static function PrepareAndEncodeRulesToken($aRules, $aObjects = array())
public static function PrepareAndEncodeRulesToken($aRules, $aObjects = [])
{
// Preparing rules before making a token
$aTokenRules = static::PrepareRulesForToken($aRules, $aObjects);
@@ -572,19 +537,20 @@ class ContextManipulatorHelper
$sDecryptedToken = $oCrypt->Decrypt($sPrivateKey, self::base64url_decode($sToken));
$aTokenRules = json_decode($sDecryptedToken, true);
if (!is_array($aTokenRules))
{
if (!is_array($aTokenRules)) {
throw new Exception('DecodeRulesToken not a proper json structure.');
}
return $aTokenRules;
}
private static function base64url_encode($sData) {
private static function base64url_encode($sData)
{
return rtrim(strtr(base64_encode($sData), '+/', '-_'), '=');
}
private static function base64url_decode($sData) {
private static function base64url_decode($sData)
{
return base64_decode(str_pad(strtr($sData, '-_', '+/'), strlen($sData) % 4, '=', STR_PAD_RIGHT));
}
@@ -596,7 +562,7 @@ class ContextManipulatorHelper
*/
private static function GetPrivateKey()
{
if(self::$sPrivateKey === null) {
if (self::$sPrivateKey === null) {
self::$sPrivateKey = DBProperty::GetProperty(self::PRIVATE_KEY);
if (is_null(self::$sPrivateKey)) {
self::$sPrivateKey = bin2hex(random_bytes(32));

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -93,4 +94,4 @@ class ExtensibilityHelper
return $aTabSectionExtensions;
}
}
}

View File

@@ -38,7 +38,7 @@ use MetaModel;
class LifecycleValidatorHelper
{
/** @var string DEFAULT_GENERATED_CLASS */
const DEFAULT_GENERATED_CLASS = 'PortalLifecycleValues';
public const DEFAULT_GENERATED_CLASS = 'PortalLifecycleValues';
/** @var string|null $sCachePath */
protected $sCachePath;
@@ -64,9 +64,10 @@ class LifecycleValidatorHelper
{
$this->sFilename = "{$sPortalId}.lifecycle.php";
$this->sCachePath = $sPortalCachePath;
$this->sInstancePrefix = "{$sPortalId}-";;
$this->sInstancePrefix = "{$sPortalId}-";
;
$this->sGeneratedClass = static::DEFAULT_GENERATED_CLASS;
$this->aProfilesMatrix = array();
$this->aProfilesMatrix = [];
$this->Init($moduleDesign->GetNodes('/module_design/classes/class'));
}
@@ -143,8 +144,7 @@ class LifecycleValidatorHelper
public function Init(DOMNodeList $oNodes)
{
// Checking cache path
if ($this->sCachePath === null)
{
if ($this->sCachePath === null) {
$this->sCachePath = utils::GetCachePath();
}
// Building full pathname for file
@@ -152,61 +152,48 @@ class LifecycleValidatorHelper
// Creating file if not existing
// Note: This is a temporary cache system, it should soon evolve to a cache provider (fs, apc, memcache, ...)
if (!file_exists($sFilePath))
{
if (!file_exists($sFilePath)) {
// - Build php array from xml
$aProfiles = array();
$aProfiles = [];
// This will be used to know which classes have been set, so we can set the missing ones.
$aProfileClasses = array();
$aProfileClasses = [];
// Iterating over the class nodes
/** @var \Combodo\iTop\DesignElement $oClassNode */
foreach ($oNodes as $oClassNode)
{
foreach ($oNodes as $oClassNode) {
// Retrieving mandatory class id attribute
$sClass = $oClassNode->getAttribute('id');
if ($sClass === '')
{
if ($sClass === '') {
throw new DOMFormatException('Class tag must have an id attribute.', null, null, $oClassNode);
}
// Retrieving lifecycle node of the class
$oLifecycleNode = $oClassNode->GetOptionalElement('lifecycle');
if ($oLifecycleNode !== null)
{
if ($oLifecycleNode !== null) {
// Iterating over scope nodes of the class
$oStimuliNode = $oLifecycleNode->GetOptionalElement('stimuli');
if ($oStimuliNode !== null)
{
if ($oStimuliNode !== null) {
/** @var \Combodo\iTop\DesignElement $oStimulusNode */
foreach ($oStimuliNode->GetNodes('./stimulus') as $oStimulusNode)
{
foreach ($oStimuliNode->GetNodes('./stimulus') as $oStimulusNode) {
// Retrieving mandatory scope id attribute
$sStimulusId = $oStimulusNode->getAttribute('id');
if ($sStimulusId === '')
{
if ($sStimulusId === '') {
throw new DOMFormatException('Stimulus tag must have an id attribute.', null, null, $oStimulusNode);
}
// Retrieving profiles for the stimulus
$oProfilesNode = $oStimulusNode->GetOptionalElement('denied_profiles');
$aProfilesNames = array();
$aProfilesNames = [];
// If no profile is specified, we consider that it's for ALL the profiles
if (($oProfilesNode === null) || ($oProfilesNode->GetNodes('./denied_profile')->length === 0))
{
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
{
if (($oProfilesNode === null) || ($oProfilesNode->GetNodes('./denied_profile')->length === 0)) {
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue) {
$aProfilesNames[] = $aValue['name'];
}
}
else
{
} else {
/** @var \Combodo\iTop\DesignElement $oProfileNode */
foreach ($oProfilesNode->GetNodes('./denied_profile') as $oProfileNode)
{
foreach ($oProfilesNode->GetNodes('./denied_profile') as $oProfileNode) {
// Retrieving mandatory profile id attribute
$sProfileId = $oProfileNode->getAttribute('id');
if ($sProfileId === '')
{
if ($sProfileId === '') {
throw new DOMFormatException('Profile tag must have an id attribute.', null, null, $oProfileNode);
}
$aProfilesNames[] = $sProfileId;
@@ -214,21 +201,18 @@ class LifecycleValidatorHelper
}
//
foreach ($aProfilesNames as $sProfileName)
{
foreach ($aProfilesNames as $sProfileName) {
// Stimulus profile id
$iProfileId = $this->GetProfileIdFromProfileName($sProfileName);
// Now that we have the queries infos, we are going to build the queries for that profile / class
$sMatrixPrefix = $iProfileId.'_'.$sClass;
// - Creating profile / class entry if not already present
if (!array_key_exists($sMatrixPrefix, $aProfiles))
{
$aProfiles[$sMatrixPrefix] = array();
if (!array_key_exists($sMatrixPrefix, $aProfiles)) {
$aProfiles[$sMatrixPrefix] = [];
}
// - Adding stimulus if not already present
if (!in_array($sStimulusId, $aProfiles[$sMatrixPrefix]))
{
if (!in_array($sStimulusId, $aProfiles[$sMatrixPrefix])) {
$aProfiles[$sMatrixPrefix][] = $sStimulusId;
}
}
@@ -244,20 +228,15 @@ class LifecycleValidatorHelper
// If not, we add them
//
// Note: Classes / Stimuli not in the matrix are implicitly ALLOWED. That can happen by omitting the <lifecycle> in a <class>
foreach ($aProfileClasses as $sProfileClass)
{
foreach (MetaModel::EnumChildClasses($sProfileClass) as $sChildClass)
{
foreach ($aProfileClasses as $sProfileClass) {
foreach (MetaModel::EnumChildClasses($sProfileClass) as $sChildClass) {
// If the child class is not in the scope, we are going to try to add it
if (!in_array($sChildClass, $aProfileClasses))
{
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
{
if (!in_array($sChildClass, $aProfileClasses)) {
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue) {
$iProfileId = $iKey;
// If the current profile has scope for that class in that mode, we duplicate it
if (isset($aProfiles[$iProfileId.'_'.$sProfileClass]))
{
if (isset($aProfiles[$iProfileId.'_'.$sProfileClass])) {
$aProfiles[$iProfileId.'_'.$sChildClass] = $aProfiles[$iProfileId.'_'.$sProfileClass];
}
}
@@ -270,14 +249,12 @@ class LifecycleValidatorHelper
// - Write file on disk
// - Creating dir if necessary
if (!is_dir($this->sCachePath))
{
if (!is_dir($this->sCachePath)) {
mkdir($this->sCachePath, 0777, true);
}
// -- Then creating the file
$ret = file_put_contents($sFilePath, $sPHP);
if ($ret === false)
{
if ($ret === false) {
$iLen = strlen($sPHP);
$fFree = @disk_free_space(dirname($sFilePath));
$aErr = error_get_last();
@@ -285,8 +262,7 @@ class LifecycleValidatorHelper
}
}
if (!class_exists($this->sGeneratedClass))
{
if (!class_exists($this->sGeneratedClass)) {
require_once $this->sCachePath.$this->sFilename;
}
}
@@ -303,7 +279,7 @@ class LifecycleValidatorHelper
*/
public function GetStimuliForProfile($sProfile, $sClass)
{
return $this->GetStimuliForProfiles(array($sProfile), $sClass);
return $this->GetStimuliForProfiles([$sProfile], $sClass);
}
/**
@@ -319,17 +295,15 @@ class LifecycleValidatorHelper
*/
public function GetStimuliForProfiles($aProfiles, $sClass)
{
$aStimuli = array();
$aStimuli = [];
// Preparing available stimuli
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $aData)
{
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $aData) {
$aStimuli[$sStimulusCode] = true;
}
// Iterating on profiles to retrieving the different OQLs parts
foreach ($aProfiles as $sProfile)
{
foreach ($aProfiles as $sProfile) {
// Retrieving matrix information
$iProfileId = $this->GetProfileIdFromProfileName($sProfile);
@@ -337,10 +311,8 @@ class LifecycleValidatorHelper
$sLifecycleValuesClass = $this->sGeneratedClass;
$aProfileMatrix = $sLifecycleValuesClass::GetProfileStimuli($iProfileId, $sClass);
foreach ($aProfileMatrix as $sStimulusCode)
{
if (array_key_exists($sStimulusCode, $aStimuli))
{
foreach ($aProfileMatrix as $sStimulusCode) {
if (array_key_exists($sStimulusCode, $aStimuli)) {
unset($aStimuli[$sStimulusCode]);
}
}
@@ -364,18 +336,12 @@ class LifecycleValidatorHelper
// We try to find the profile from its name in order to retrieve it's id
// - If the regular UserRights add-on is installed we check the profiles array
if (class_exists('ProfilesConfig'))
{
if (defined($sProfile) && in_array($sProfile, ProfilesConfig::GetProfilesValues()))
{
if (class_exists('ProfilesConfig')) {
if (defined($sProfile) && in_array($sProfile, ProfilesConfig::GetProfilesValues())) {
$iProfileId = constant($sProfile);
}
else
{
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
{
if ($aValue['name'] === $sProfile)
{
} else {
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue) {
if ($aValue['name'] === $sProfile) {
$iProfileId = $iKey;
break;
}
@@ -383,14 +349,12 @@ class LifecycleValidatorHelper
}
}
// - Else, we can't find the id from the name as we don't know the used UserRights add-on. It has to be a constant
else
{
else {
throw new Exception('Lifecycle validator : Unknown UserRights addon, lifecycle\'s profile must be a constant');
}
// If profile was not found from its name or from a constant, we throw an exception
if ($iProfileId === null)
{
if ($iProfileId === null) {
throw new Exception('Lifecycle validator : Could not find "'.$sProfile.'" in the profiles list');
}
@@ -404,7 +368,7 @@ class LifecycleValidatorHelper
*
* @return string
*/
protected function BuildPHPClass($aProfiles = array())
protected function BuildPHPClass($aProfiles = [])
{
$sProfiles = var_export($aProfiles, true);
$sClassName = $this->sGeneratedClass;
@@ -447,4 +411,3 @@ EOF;
}
}

View File

@@ -44,50 +44,50 @@ use utils;
class NavigationRuleHelper
{
// Available point of origin for the navigation
const ENUM_ORIGIN_PAGE = 'default';
const ENUM_ORIGIN_MODAL = 'modal';
public const ENUM_ORIGIN_PAGE = 'default';
public const ENUM_ORIGIN_MODAL = 'modal';
// Available rule categories (of rule types)
/** @var string ENUM_RULE_CAT_CLOSE (eg. close modal/window) */
const ENUM_RULE_CAT_CLOSE = 'close';
public const ENUM_RULE_CAT_CLOSE = 'close';
/** @var string ENUM_RULE_CAT_REDIRECT (eg. go-to-homepage, go-to-object, go-to-brick, ...) */
const ENUM_RULE_CAT_REDIRECT = 'redirect';
public const ENUM_RULE_CAT_REDIRECT = 'redirect';
// Available rule types
/** @var string ENUM_RULE_CLOSE */
const ENUM_RULE_CLOSE = 'close';
public const ENUM_RULE_CLOSE = 'close';
/** @var string ENUM_RULE_GO_TO_HOMEPAGE */
const ENUM_RULE_GO_TO_HOMEPAGE = 'go-to-homepage';
public const ENUM_RULE_GO_TO_HOMEPAGE = 'go-to-homepage';
/** @var string ENUM_RULE_GO_TO_OBJECT */
const ENUM_RULE_GO_TO_OBJECT = 'go-to-object';
public const ENUM_RULE_GO_TO_OBJECT = 'go-to-object';
/** @var string ENUM_RULE_GO_TO_BRICK */
const ENUM_RULE_GO_TO_BRICK = 'go-to-brick';
public const ENUM_RULE_GO_TO_BRICK = 'go-to-brick';
/** @var string ENUM_RULE_GO_TO_MANAGE_BRICK */
const ENUM_RULE_GO_TO_MANAGE_BRICK = 'go-to-manage-brick';
public const ENUM_RULE_GO_TO_MANAGE_BRICK = 'go-to-manage-brick';
/** @var string ENUM_RULE_GO_TO_BROWSE_BRICK */
const ENUM_RULE_GO_TO_BROWSE_BRICK = 'go-to-browse-brick';
public const ENUM_RULE_GO_TO_BROWSE_BRICK = 'go-to-browse-brick';
// - Defaults
/** @var string DEFAULT_RULE_SUBMIT_PAGE */
const DEFAULT_RULE_SUBMIT_PAGE = self::ENUM_RULE_GO_TO_OBJECT;
public const DEFAULT_RULE_SUBMIT_PAGE = self::ENUM_RULE_GO_TO_OBJECT;
/** @var string DEFAULT_RULE_SUBMIT_MODAL */
const DEFAULT_RULE_SUBMIT_MODAL = self::ENUM_RULE_CLOSE;
public const DEFAULT_RULE_SUBMIT_MODAL = self::ENUM_RULE_CLOSE;
/** @var string DEFAULT_RULE_CANCEL_PAGE */
const DEFAULT_RULE_CANCEL_PAGE = self::ENUM_RULE_CLOSE;
public const DEFAULT_RULE_CANCEL_PAGE = self::ENUM_RULE_CLOSE;
/** @var string DEFAULT_RULE_CANCEL_MODAL */
const DEFAULT_RULE_CANCEL_MODAL = self::ENUM_RULE_CLOSE;
public const DEFAULT_RULE_CANCEL_MODAL = self::ENUM_RULE_CLOSE;
// Rule go-to-object properties
/** @var string DEFAULT_RULE_GO_TO_OBJECT_PROP_MODE */
const DEFAULT_RULE_GO_TO_OBJECT_PROP_MODE = ObjectFormHandlerHelper::ENUM_MODE_VIEW;
public const DEFAULT_RULE_GO_TO_OBJECT_PROP_MODE = ObjectFormHandlerHelper::ENUM_MODE_VIEW;
/** @var string ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL */
const ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL = 'modal';
public const ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL = 'modal';
/** @var string ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_PAGE */
const ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_PAGE = 'page';
public const ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_PAGE = 'page';
/** @var string ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_CURRENT */
const ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_CURRENT = 'current';
public const ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_CURRENT = 'current';
/** @var string DEFAULT_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET */
const DEFAULT_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET = self::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL;
public const DEFAULT_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET = self::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL;
// Rule go-to-brick properties
// TODO
@@ -112,9 +112,12 @@ class NavigationRuleHelper
* @throws \DOMFormatException
*/
public function __construct(
ModuleDesign $oModuleDesign, RouterInterface $oRouter, BrickCollection $oBrickCollection, ScopeValidatorHelper $oScopeValidator
ModuleDesign $oModuleDesign,
RouterInterface $oRouter,
BrickCollection $oBrickCollection,
ScopeValidatorHelper $oScopeValidator
) {
$this->aRules = array();
$this->aRules = [];
$this->oRouter = $oRouter;
$this->oBrickCollection = $oBrickCollection;
@@ -132,31 +135,29 @@ class NavigationRuleHelper
*/
public function Init(DOMNodeList $oNodes)
{
$this->aRules = array();
$this->aRules = [];
// Iterating over the navigation_rule nodes
/** @var \Combodo\iTop\DesignElement $oRuleNode */
foreach ($oNodes as $oRuleNode)
{
foreach ($oNodes as $oRuleNode) {
// Checking node name
if ($oRuleNode->nodeName !== 'navigation_rule')
{
if ($oRuleNode->nodeName !== 'navigation_rule') {
continue;
}
// Retrieving mandatory attributes
// - ID
$sRuleId = $oRuleNode->getAttribute('id');
if ($sRuleId === '')
{
if ($sRuleId === '') {
throw new DOMFormatException('Rule tag must have an id attribute.', null, null, $oRuleNode);
}
// - Type
$sRuleType = $oRuleNode->getAttribute('xsi:type');
if (($sRuleType === '') || !in_array($sRuleType, static::GetAllowedTypes()))
{
throw new DOMFormatException('Navigation rule tag must have a valid xsi:type, "'.$sRuleType.'" given, expected '.implode('|',
static::GetAllowedTypes()), null, null, $oRuleNode);
if (($sRuleType === '') || !in_array($sRuleType, static::GetAllowedTypes())) {
throw new DOMFormatException('Navigation rule tag must have a valid xsi:type, "'.$sRuleType.'" given, expected '.implode(
'|',
static::GetAllowedTypes()
), null, null, $oRuleNode);
}
// Load rule from XML
@@ -176,10 +177,10 @@ class NavigationRuleHelper
*/
public static function GetAllowedOrigins()
{
return array(
return [
static::ENUM_ORIGIN_PAGE,
static::ENUM_ORIGIN_MODAL,
);
];
}
/**
@@ -189,14 +190,14 @@ class NavigationRuleHelper
*/
public static function GetAllowedTypes()
{
return array(
return [
static::ENUM_RULE_CLOSE,
static::ENUM_RULE_GO_TO_HOMEPAGE,
static::ENUM_RULE_GO_TO_OBJECT,
static::ENUM_RULE_GO_TO_BRICK,
static::ENUM_RULE_GO_TO_BROWSE_BRICK,
static::ENUM_RULE_GO_TO_MANAGE_BRICK,
);
];
}
/**
@@ -209,8 +210,7 @@ class NavigationRuleHelper
*/
public function GetRuleDefinition($sId)
{
if (!array_key_exists($sId, $this->aRules))
{
if (!array_key_exists($sId, $this->aRules)) {
throw new Exception('NavigationRuleHelper: Could not find "'.$sId.'" in the rules list');
}
@@ -251,10 +251,10 @@ class NavigationRuleHelper
*/
public function GetDefaultCloseRuleDefinition()
{
return array(
return [
'category' => static::ENUM_RULE_CAT_CLOSE,
'type' => static::ENUM_RULE_CLOSE,
);
];
}
/**
@@ -264,10 +264,10 @@ class NavigationRuleHelper
*/
public function GetDefaultGoToHomepageRuleDefinition()
{
return array(
return [
'category' => static::ENUM_RULE_CAT_REDIRECT,
'type' => static::ENUM_RULE_GO_TO_HOMEPAGE,
);
];
}
/**
@@ -277,15 +277,15 @@ class NavigationRuleHelper
*/
public function GetDefaultGoToObjectRuleDefinition()
{
return array(
return [
'category' => static::ENUM_RULE_CAT_REDIRECT,
'type' => static::ENUM_RULE_GO_TO_OBJECT,
'properties' => array(
'properties' => [
'mode' => static::DEFAULT_RULE_GO_TO_OBJECT_PROP_MODE,
'opening_target' => static::DEFAULT_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET,
'oql' => null,
),
);
],
];
}
/**
@@ -295,16 +295,16 @@ class NavigationRuleHelper
*/
public function GetDefaultGoToBrickRuleDefinition()
{
return array(
return [
'category' => static::ENUM_RULE_CAT_REDIRECT,
'type' => static::ENUM_RULE_GO_TO_BRICK,
'properties' => array(
'route' => array(
'properties' => [
'route' => [
'id' => null,
'params' => array(),
),
),
);
'params' => [],
],
],
];
}
//----------------------------
@@ -351,21 +351,18 @@ class NavigationRuleHelper
// Default values
$aRule = $this->GetDefaultGoToObjectRuleDefinition();
$aAllowedOpeningTarget = array(
$aAllowedOpeningTarget = [
static::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_CURRENT,
static::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL,
static::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_PAGE,
);
];
/** @var \Combodo\iTop\DesignElement $oPropNode */
foreach($oRuleNode->GetNodes('*') as $oPropNode)
{
switch($oPropNode->nodeName)
{
foreach ($oRuleNode->GetNodes('*') as $oPropNode) {
switch ($oPropNode->nodeName) {
case 'mode':
$sMode = $oPropNode->GetText();
if(!in_array($sMode, ObjectFormHandlerHelper::GetAllowedModes()))
{
if (!in_array($sMode, ObjectFormHandlerHelper::GetAllowedModes())) {
throw new DOMFormatException('mode tag of navigation_rule "'.$sRuleId.'" must be valid. Expected '.implode('|', ObjectFormHandlerHelper::GetAllowedModes()).', "'.$sMode.'" given.', null, null, $oRuleNode);
}
$aRule['properties']['mode'] = $sMode;
@@ -373,8 +370,7 @@ class NavigationRuleHelper
case 'opening_target':
$sOpeningTarget = $oPropNode->GetText();
if(!in_array($sOpeningTarget, $aAllowedOpeningTarget))
{
if (!in_array($sOpeningTarget, $aAllowedOpeningTarget)) {
throw new DOMFormatException('opening_target tag of navigation_rule "'.$sRuleId.'" must be valid. Expected '.implode('|', $aAllowedOpeningTarget).', "'.$sOpeningTarget.'" given.', null, null, $oRuleNode);
}
$aRule['properties']['opening_target'] = $sOpeningTarget;
@@ -382,8 +378,7 @@ class NavigationRuleHelper
case 'oql':
$sOQL = $oPropNode->GetText();
if(empty($sOQL))
{
if (empty($sOQL)) {
throw new DOMFormatException('oql tag of navigation_rule "'.$sRuleId.'" can not be empty.');
}
$aRule['properties']['oql'] = $sOQL;
@@ -409,30 +404,24 @@ class NavigationRuleHelper
$aRule = $this->GetDefaultGoToBrickRuleDefinition();
/** @var \Combodo\iTop\DesignElement $oPropNode */
foreach($oRuleNode->GetNodes('*') as $oPropNode)
{
switch($oPropNode->nodeName)
{
foreach ($oRuleNode->GetNodes('*') as $oPropNode) {
switch ($oPropNode->nodeName) {
case 'route':
/** @var array $aRouteProperties Route ID and parameters */
$aRouteProperties = array();
$aRouteProperties = [];
/** @var DesignElement $oRoutePropNode */
foreach($oPropNode->GetNodes('*') as $oRoutePropNode)
{
switch($oRoutePropNode->nodeName)
{
foreach ($oPropNode->GetNodes('*') as $oRoutePropNode) {
switch ($oRoutePropNode->nodeName) {
case 'id':
$aRouteProperties['id'] = $oRoutePropNode->GetText();
break;
case 'params':
/** @var DesignElement $oRouteParamNode */
foreach($oRoutePropNode->GetNodes('*') as $oRouteParamNode)
{
foreach ($oRoutePropNode->GetNodes('*') as $oRouteParamNode) {
$sRouteParamId = $oRouteParamNode->getAttribute('id');
$sRouteParamValue = $oRouteParamNode->GetText();
if(empty($sRouteParamId) || empty($sRouteParamValue))
{
if (empty($sRouteParamId) || empty($sRouteParamValue)) {
throw new DOMFormatException('param tag of navigation_rule "'.$sRuleId.'" must have a valid ID and value.', null, null, $oRuleNode);
}
@@ -443,8 +432,7 @@ class NavigationRuleHelper
}
// Consistency check
if(empty($aRouteProperties['id']))
{
if (empty($aRouteProperties['id'])) {
throw new DOMFormatException('navigation_rule "'.$sRuleId.'" must have a valid ID', null, null, $oRuleNode);
}
@@ -474,16 +462,15 @@ class NavigationRuleHelper
$aRule['properties']['route']['params']['sDisplayMode'] = ManageBrick::DEFAULT_DISPLAY_MODE;
// Rule parameters to automatically map to the route parameters
$aParamsMapping = array(
$aParamsMapping = [
'id' => 'sBrickId',
'display_mode' => 'sDisplayMode',
'grouping_tab' => 'sGroupingTab',
'filter' => 'sSearchValue',
);
];
/** @var \Combodo\iTop\DesignElement $oPropNode */
foreach($oRuleNode->GetNodes('*') as $oPropNode)
{
foreach ($oRuleNode->GetNodes('*') as $oPropNode) {
$sRouteParamId = (array_key_exists($oPropNode->nodeName, $aParamsMapping)) ? $aParamsMapping[$oPropNode->nodeName] : $oPropNode->nodeName;
$aRule['properties']['route']['params'][$sRouteParamId] = $oPropNode->GetText();
}
@@ -509,15 +496,14 @@ class NavigationRuleHelper
$aRule['properties']['route']['params']['sBrowseMode'] = BrowseBrick::DEFAULT_BROWSE_MODE;
// Rule parameters to automatically map to the route parameters
$aParamsMapping = array(
$aParamsMapping = [
'id' => 'sBrickId',
'browse_mode' => 'sBrowseMode',
'filter' => 'sSearchValue',
);
];
/** @var \Combodo\iTop\DesignElement $oPropNode */
foreach($oRuleNode->GetNodes('*') as $oPropNode)
{
foreach ($oRuleNode->GetNodes('*') as $oPropNode) {
$sRouteParamId = (array_key_exists($oPropNode->nodeName, $aParamsMapping)) ? $aParamsMapping[$oPropNode->nodeName] : $oPropNode->nodeName;
$aRule['properties']['route']['params'][$sRouteParamId] = $oPropNode->GetText();
}
@@ -555,33 +541,30 @@ class NavigationRuleHelper
public function PrepareRulesForForm(array $aFormProperties, DBObject $oCurrentObject, $bIsCurrentFormInModal = false)
{
// Default values
$aResults = array(
'submit' => array(
$aResults = [
'submit' => [
'category' => static::ENUM_RULE_CAT_REDIRECT,
'url' => null,
'modal' => false,
),
'cancel' => array(
],
'cancel' => [
'category' => static::ENUM_RULE_CAT_CLOSE,
'url' => null,
'modal' => false,
),
);
],
];
// Get form's navigation rules
$aFormNavRules = (isset($aFormProperties['properties']['navigation_rules'])) ? $aFormProperties['properties']['navigation_rules'] : array('submit' => null, 'cancel' => null);
$aFormNavRules = (isset($aFormProperties['properties']['navigation_rules'])) ? $aFormProperties['properties']['navigation_rules'] : ['submit' => null, 'cancel' => null];
// Check from which origin the rule will be called
$sRuleCallOrigin = ($bIsCurrentFormInModal) ? 'modal' : 'default';
foreach(array_keys($aResults) as $sButtonCode)
{
foreach (array_keys($aResults) as $sButtonCode) {
// Retrieve rule definition
// - Default behavior when no rule specified
if(empty($aFormNavRules[$sButtonCode][$sRuleCallOrigin]))
{
switch($sButtonCode)
{
if (empty($aFormNavRules[$sButtonCode][$sRuleCallOrigin])) {
switch ($sButtonCode) {
case 'submit':
$sDefaultRuleType = ($bIsCurrentFormInModal) ? static::DEFAULT_RULE_SUBMIT_MODAL : static::DEFAULT_RULE_SUBMIT_PAGE;
break;
@@ -593,8 +576,7 @@ class NavigationRuleHelper
$aRuleDef = $this->GetDefaultRuleDefinitionFromType($sDefaultRuleType);
}
// - Specified rule
else
{
else {
$sRuleId = $aFormNavRules[$sButtonCode][$sRuleCallOrigin];
$aRuleDef = $this->GetRuleDefinition($sRuleId);
}
@@ -603,36 +585,31 @@ class NavigationRuleHelper
$aResults[$sButtonCode]['category'] = $aRuleDef['category'];
// Set properties regarding the type
switch($aRuleDef['type'])
{
switch ($aRuleDef['type']) {
case static::ENUM_RULE_GO_TO_HOMEPAGE:
$aResults[$sButtonCode]['url'] = $this->oRouter->generate('p_home');
break;
case static::ENUM_RULE_GO_TO_OBJECT:
// Target opening mode to modal if specified or should be as current form
if( ($aRuleDef['properties']['opening_target'] === static::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL)
if (($aRuleDef['properties']['opening_target'] === static::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_MODAL)
|| (($aRuleDef['properties']['opening_target'] === static::ENUM_RULE_GO_TO_OBJECT_PROP_OPENING_TARGET_CURRENT) && ($bIsCurrentFormInModal === true))
)
{
) {
$aResults[$sButtonCode]['modal'] = true;
}
// Target URL
// - Find object
if(empty($aRuleDef['properties']['oql']))
{
if (empty($aRuleDef['properties']['oql'])) {
$oTargetObject = $oCurrentObject;
}
else
{
} else {
$oSearch = DBSearch::FromOQL($aRuleDef['properties']['oql']);
$oSet = new DBObjectSet($oSearch, array(), array('this' => $oCurrentObject));
$oSet->OptimizeColumnLoad(array($oSearch->GetClassAlias() => array()));
$oSet = new DBObjectSet($oSearch, [], ['this' => $oCurrentObject]);
$oSet->OptimizeColumnLoad([$oSearch->GetClassAlias() => []]);
$oTargetObject = $oSet->Fetch();
}
// - Build URL
$aResults[$sButtonCode]['url'] = $this->oRouter->generate('p_object_'.$aRuleDef['properties']['mode'], array('sObjectClass' => get_class($oTargetObject), 'sObjectId' => $oTargetObject->GetKey()));
$aResults[$sButtonCode]['url'] = $this->oRouter->generate('p_object_'.$aRuleDef['properties']['mode'], ['sObjectClass' => get_class($oTargetObject), 'sObjectId' => $oTargetObject->GetKey()]);
break;
case static::ENUM_RULE_GO_TO_BRICK:

View File

@@ -18,7 +18,6 @@
* You should have received a copy of the GNU Affero General Public License
*/
namespace Combodo\iTop\Portal\Helper;
use ApplicationContext;
@@ -51,16 +50,16 @@ use UserRights;
class ObjectFormHandlerHelper
{
/** @var string */
const ENUM_MODE_VIEW = 'view';
public const ENUM_MODE_VIEW = 'view';
/** @var string */
const ENUM_MODE_EDIT = 'edit';
public const ENUM_MODE_EDIT = 'edit';
/** @var string */
const ENUM_MODE_CREATE = 'create';
public const ENUM_MODE_CREATE = 'create';
/**
* @var string
* @since 2.7.7 3.0.1 3.1.0
*/
const ENUM_MODE_APPLY_STIMULUS = 'apply_stimulus';
public const ENUM_MODE_APPLY_STIMULUS = 'apply_stimulus';
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
private $oRequestManipulator;
@@ -95,10 +94,16 @@ class ObjectFormHandlerHelper
* @param \Combodo\iTop\Portal\Twig\AppExtension $oAppExtension
*/
public function __construct(
RequestManipulatorHelper $oRequestManipulator, ContextManipulatorHelper $oContextManipulator, NavigationRuleHelper $oNavigationRuleHelper, ScopeValidatorHelper $oScopeValidator, SecurityHelper $oSecurityHelper, UrlGeneratorInterface $oUrlGenerator, $aCombodoPortalInstanceConf, $sPortalId,
RequestManipulatorHelper $oRequestManipulator,
ContextManipulatorHelper $oContextManipulator,
NavigationRuleHelper $oNavigationRuleHelper,
ScopeValidatorHelper $oScopeValidator,
SecurityHelper $oSecurityHelper,
UrlGeneratorInterface $oUrlGenerator,
$aCombodoPortalInstanceConf,
$sPortalId,
AppExtension $oAppExtension
)
{
) {
$this->oRequestManipulator = $oRequestManipulator;
$this->oContextManipulator = $oContextManipulator;
$this->oNavigationRuleHelper = $oNavigationRuleHelper;
@@ -126,7 +131,7 @@ class ObjectFormHandlerHelper
*/
public function HandleForm(Request $oRequest, $sMode, $sObjectClass, $sObjectId = null, array $aFormProperties = null)
{
$aFormData = array();
$aFormData = [];
$sOperation = $this->oRequestManipulator->ReadParam('operation', '');
$bModal = ($oRequest->isXmlHttpRequest() && empty($sOperation));
@@ -134,71 +139,58 @@ class ObjectFormHandlerHelper
$aFormProperties = $aFormProperties ?? ApplicationHelper::GetLoadedFormFromClass($this->aCombodoPortalInstanceConf['forms'], $sObjectClass, $sMode);
// - Create and
if (empty($sOperation))
{
if (empty($sOperation)) {
// Retrieving action rules
//
// Note : The action rules must be a base64-encoded JSON object, this is just so users are tempted to changes values.
// But it would not be a security issue as it only presets values in the form.
$sActionRulesToken = $this->oRequestManipulator->ReadParam('ar_token', '');
$aActionRules = (!empty($sActionRulesToken)) ? ContextManipulatorHelper::DecodeRulesToken($sActionRulesToken) : array();
$aActionRules = (!empty($sActionRulesToken)) ? ContextManipulatorHelper::DecodeRulesToken($sActionRulesToken) : [];
// Preparing object
if ($sObjectId === null)
{
if ($sObjectId === null) {
// Create new UserRequest
$oObject = MetaModel::NewObject($sObjectClass);
// Retrieve action rules information to auto-fill the form if available
// Preparing object
$this->oContextManipulator->PrepareObject($aActionRules, $oObject);
$aPrefillFormParam = array(
$aPrefillFormParam = [
'user' => UserRights::GetUser(),
'origin' => 'portal',
);
];
$oObject->PrefillForm('creation_from_0', $aPrefillFormParam);
}
else
{
} else {
$oObject = MetaModel::GetObject($sObjectClass, $sObjectId, true, $this->oScopeValidator->IsAllDataAllowedForScope(UserRights::ListProfiles(), $sObjectClass));
}
// Preparing buttons
$aFormData['buttons'] = array(
'transitions' => array(),
'actions' => array(),
'links' => array(),
'submit' => array(
$aFormData['buttons'] = [
'transitions' => [],
'actions' => [],
'links' => [],
'submit' => [
'label' => Dict::S('Portal:Button:Submit'),
),
);
if ($sMode !== static::ENUM_MODE_APPLY_STIMULUS)
{
],
];
if ($sMode !== static::ENUM_MODE_APPLY_STIMULUS) {
// Add transition buttons
$oSetToCheckRights = DBObjectSet::FromObject($oObject);
$aStimuli = Metamodel::EnumStimuli($sObjectClass);
foreach ($oObject->EnumTransitions() as $sStimulusCode => $aTransitionDef)
{
if ($this->oSecurityHelper->IsStimulusAllowed($sStimulusCode, $sObjectClass, $oSetToCheckRights))
{
foreach ($oObject->EnumTransitions() as $sStimulusCode => $aTransitionDef) {
if ($this->oSecurityHelper->IsStimulusAllowed($sStimulusCode, $sObjectClass, $oSetToCheckRights)) {
$aFormData['buttons']['transitions'][$sStimulusCode] = $aStimuli[$sStimulusCode]->GetLabel();
}
}
// Add plugin buttons
/** @var \iPopupMenuExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance)
{
foreach ($oExtensionInstance->EnumItems(iPopupMenuExtension::PORTAL_OBJDETAILS_ACTIONS, array('portal_id' => $this->sPortalId, 'object' => $oObject, 'mode' => $sMode)) as $oMenuItem)
{
if (is_object($oMenuItem))
{
if ($oMenuItem instanceof JSButtonItem)
{
$aFormData['buttons']['actions'][] = $oMenuItem->GetMenuItem() + array('js_files' => $oMenuItem->GetLinkedScripts());
}
elseif ($oMenuItem instanceof URLButtonItem)
{
foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance) {
foreach ($oExtensionInstance->EnumItems(iPopupMenuExtension::PORTAL_OBJDETAILS_ACTIONS, ['portal_id' => $this->sPortalId, 'object' => $oObject, 'mode' => $sMode]) as $oMenuItem) {
if (is_object($oMenuItem)) {
if ($oMenuItem instanceof JSButtonItem) {
$aFormData['buttons']['actions'][] = $oMenuItem->GetMenuItem() + ['js_files' => $oMenuItem->GetLinkedScripts()];
} elseif ($oMenuItem instanceof URLButtonItem) {
$aFormData['buttons']['links'][] = $oMenuItem->GetMenuItem();
}
}
@@ -206,22 +198,17 @@ class ObjectFormHandlerHelper
}
// Hiding submit button or changing its label if necessary
if (!empty($aFormData['buttons']['transitions']) && isset($aFormProperties['properties']) && $aFormProperties['properties']['always_show_submit'] === false)
{
if (!empty($aFormData['buttons']['transitions']) && isset($aFormProperties['properties']) && $aFormProperties['properties']['always_show_submit'] === false) {
unset($aFormData['buttons']['submit']);
}
elseif ($sMode === static::ENUM_MODE_EDIT)
{
} elseif ($sMode === static::ENUM_MODE_EDIT) {
$aFormData['buttons']['submit']['label'] = Dict::S('Portal:Button:Apply');
}
}
else
{
$aPrefillFormParam = array(
} else {
$aPrefillFormParam = [
'user' => UserRights::GetUser(),
'origin' => 'portal',
'stimulus' => $this->oRequestManipulator->ReadParam('apply_stimulus', null, FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY)['code'],
);
];
$oObject->PrefillForm('state_change', $aPrefillFormParam);
}
@@ -235,32 +222,31 @@ class ObjectFormHandlerHelper
// Preparing renderer
// Note : We might need to distinguish form & renderer endpoints
switch($sMode)
{
switch ($sMode) {
case static::ENUM_MODE_CREATE:
case static::ENUM_MODE_EDIT:
case static::ENUM_MODE_VIEW:
if(array_key_exists('submit_endpoint', $aFormProperties)) {
$sFormEndpoint = $aFormProperties['submit_endpoint'];
} else {
$sFormEndpoint = $this->oUrlGenerator->generate(
'p_object_' . $sMode,
array(
'sObjectClass' => $sObjectClass,
'sObjectId' => $sObjectId,
)
);
}
if (array_key_exists('submit_endpoint', $aFormProperties)) {
$sFormEndpoint = $aFormProperties['submit_endpoint'];
} else {
$sFormEndpoint = $this->oUrlGenerator->generate(
'p_object_'.$sMode,
[
'sObjectClass' => $sObjectClass,
'sObjectId' => $sObjectId,
]
);
}
break;
case static::ENUM_MODE_APPLY_STIMULUS:
$sFormEndpoint = $this->oUrlGenerator->generate(
'p_object_apply_stimulus',
array(
[
'sObjectClass' => $sObjectClass,
'sObjectId' => $sObjectId,
'sStimulusCode' => $this->oRequestManipulator->ReadParam('sStimulusCode'),
)
]
);
break;
@@ -294,8 +280,7 @@ class ObjectFormHandlerHelper
/** @var \Combodo\iTop\Portal\Form\ObjectFormManager $sFormManagerClass */
$sFormManagerClass = $this->oRequestManipulator->ReadParam('formmanager_class', '', FILTER_UNSAFE_RAW);
$sFormManagerData = $this->oRequestManipulator->ReadParam('formmanager_data', '', FILTER_UNSAFE_RAW);
if (empty($sFormManagerClass) || empty($sFormManagerData))
{
if (empty($sFormManagerClass) || empty($sFormManagerData)) {
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Parameters formmanager_class and formmanager_data must be defined.');
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Parameters formmanager_class and formmanager_data must be defined.');
}
@@ -312,48 +297,45 @@ class ObjectFormHandlerHelper
$oFormManager->SetObject($oObj);
}
switch ($sOperation)
{
switch ($sOperation) {
case 'submit':
// Applying modification to object
$aFormData['validation'] = $oFormManager->OnSubmit(
array(
'currentValues' => $this->oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
'attachmentIds' => $this->oRequestManipulator->ReadParam('attachment_ids', array(), FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
[
'currentValues' => $this->oRequestManipulator->ReadParam('current_values', [], FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
'attachmentIds' => $this->oRequestManipulator->ReadParam('attachment_ids', [], FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
'formProperties' => $aFormProperties,
'applyStimulus' => $this->oRequestManipulator->ReadParam('apply_stimulus', null, FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY),
)
]
);
if ($aFormData['validation']['valid'] === true)
{
if ($aFormData['validation']['valid'] === true) {
// Note : We don't use $sObjectId there as it can be null if we are creating a new one. Instead we use the id from the created object once it has been serialized
// Check if stimulus has to be applied
$sStimulusCode = $this->oRequestManipulator->ReadParam('stimulus_code', '');
if (!empty($sStimulusCode))
{
$aFormData['validation']['redirection'] = array(
'url' => $this->oUrlGenerator->generate('p_object_apply_stimulus', array('sObjectClass' => $sObjectClass, 'sObjectId' => $oFormManager->GetObject()->GetKey(), 'sStimulusCode' => $sStimulusCode)),
if (!empty($sStimulusCode)) {
$aFormData['validation']['redirection'] = [
'url' => $this->oUrlGenerator->generate('p_object_apply_stimulus', ['sObjectClass' => $sObjectClass, 'sObjectId' => $oFormManager->GetObject()->GetKey(), 'sStimulusCode' => $sStimulusCode]),
'modal' => true,
);
];
}
} else {
$sErrorMessages = '';
foreach ($aFormData['validation']['messages']['error'] as $sFieldId => $aMessages) {
if ($sFieldId == '_main') {
$sErrorMessages .= implode(' - ', $aFormData['validation']['messages']['error']['_main']);
} else {
$oObj = $oFormManager->GetObject();
$sLabel = $oObj->GetLabel($sFieldId);
$sErrorMessages .= Dict::Format('Portal:Error:CheckToWriteFailed', $sLabel, (is_array($aMessages) ? implode(' - ', $aMessages) : $aMessages));
}
}
$sErrorMessages = '';
foreach ($aFormData['validation']['messages']['error'] as $sFieldId => $aMessages) {
if ($sFieldId == '_main') {
$sErrorMessages .= implode(' - ', $aFormData['validation']['messages']['error']['_main']);
} else {
$oObj = $oFormManager->GetObject();
$sLabel = $oObj->GetLabel($sFieldId);
$sErrorMessages .= Dict::Format('Portal:Error:CheckToWriteFailed', $sLabel, (is_array($aMessages) ? implode(' - ', $aMessages) : $aMessages));
}
}
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, $sErrorMessages);
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, $sErrorMessages);
}
break;
case 'update':
$oFormManager->OnUpdate(array('currentValues' => $this->oRequestManipulator->ReadParam('current_values', array(), FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY), 'formProperties' => $aFormProperties));
$oFormManager->OnUpdate(['currentValues' => $this->oRequestManipulator->ReadParam('current_values', [], FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY), 'formProperties' => $aFormProperties]);
break;
case 'cancel':
@@ -363,33 +345,27 @@ class ObjectFormHandlerHelper
}
// Preparing field_set data
$aFieldSetData = array(
$aFieldSetData = [
//'fields_list' => $oFormManager->GetRenderer()->Render(), // GLA : This should be done just after in the if statement.
'fields_impacts' => $oFormManager->GetForm()->GetFieldsImpacts(),
'form_path' => $oFormManager->GetForm()->GetId(),
);
];
// Preparing fields list regarding the operation
if ($sOperation === 'update')
{
$aRequestedFields = $this->oRequestManipulator->ReadParam('requested_fields', array(), FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY);
if ($sOperation === 'update') {
$aRequestedFields = $this->oRequestManipulator->ReadParam('requested_fields', [], FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY);
$sFormPath = $this->oRequestManipulator->ReadParam('form_path', '');
// Checking if the update was on a subform, if so we need to make the rendering for that part only
if (!empty($sFormPath) && $sFormPath !== $oFormManager->GetForm()->GetId())
{
if (!empty($sFormPath) && $sFormPath !== $oFormManager->GetForm()->GetId()) {
$oSubForm = $oFormManager->GetForm()->FindSubForm($sFormPath);
$oSubFormRenderer = new BsFormRenderer($oSubForm);
$oSubFormRenderer->SetEndpoint($oFormManager->GetRenderer()->GetEndpoint());
$aFormData['updated_fields'] = $oSubFormRenderer->Render($aRequestedFields);
}
else
{
} else {
$aFormData['updated_fields'] = $oFormManager->GetRenderer()->Render($aRequestedFields);
}
}
else
{
} else {
$aFieldSetData['fields_list'] = $oFormManager->GetRenderer()->Render();
}
@@ -407,8 +383,7 @@ class ObjectFormHandlerHelper
$aFormData['display_mode'] = (isset($aFormProperties['properties'])) ? $aFormProperties['properties']['display_mode'] : ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE;
$aFormData['hidden_fields'] = $oFormManager->GetHiddenFieldsId();
// - Set a text to be copied on title if the object is not in creation
if($sMode !== static::ENUM_MODE_CREATE && !empty($sObjectId))
{
if ($sMode !== static::ENUM_MODE_CREATE && !empty($sObjectId)) {
$aFormData['title_clipboard_text'] = Dict::Format(
'Brick:Portal:Object:Copy:TextToCopy',
$aFormData['object_name'],
@@ -435,17 +410,15 @@ class ObjectFormHandlerHelper
public function RenderFormFromTwig($sId, $sTwigString, $aData)
{
// Creating sandbox twig env. to load and test the custom form template
$oTwig = new Environment(new ArrayLoader(array($sId => $sTwigString)));
$oTwig = new Environment(new ArrayLoader([$sId => $sTwigString]));
// Manually registering filters and functions as we didn't find how to do it automatically
$aFilters = $this->oAppExtension->getFilters();
foreach ($aFilters as $oFilter)
{
foreach ($aFilters as $oFilter) {
$oTwig->addFilter($oFilter);
}
$aFunctions = $this->oAppExtension->getFunctions();
foreach ($aFunctions as $oFunction)
{
foreach ($aFunctions as $oFunction) {
$oTwig->addFunction($oFunction);
}
@@ -469,9 +442,9 @@ class ObjectFormHandlerHelper
public function CheckReadFormDataAllowed($sFormManagerData)
{
$aJsonFromData = ObjectFormManager::DecodeFormManagerData($sFormManagerData);
if(isset($aJsonFromData['formobject_class'])
if (isset($aJsonFromData['formobject_class'])
&& isset($aJsonFromData['formobject_id'])
&& !$this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $aJsonFromData['formobject_class'], $aJsonFromData['formobject_id'])){
&& !$this->oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $aJsonFromData['formobject_class'], $aJsonFromData['formobject_id'])) {
throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Form data access denied.');
}
}
@@ -484,11 +457,11 @@ class ObjectFormHandlerHelper
*/
public static function GetAllowedModes()
{
return array(
return [
static::ENUM_MODE_VIEW,
static::ENUM_MODE_EDIT,
static::ENUM_MODE_CREATE,
);
];
}
/**
@@ -530,4 +503,4 @@ class ObjectFormHandlerHelper
{
return $this->aCombodoPortalInstanceConf;
}
}
}

View File

@@ -63,18 +63,15 @@ class RequestManipulatorHelper
*/
public function HasParam($sKey)
{
if ($this->GetCurrentRequest()->query->has($sKey))
{
if ($this->GetCurrentRequest()->query->has($sKey)) {
return true;
}
if ($this->GetCurrentRequest()->attributes->has($sKey))
{
if ($this->GetCurrentRequest()->attributes->has($sKey)) {
return true;
}
if ($this->GetCurrentRequest()->request->has($sKey))
{
if ($this->GetCurrentRequest()->request->has($sKey)) {
return true;
}
@@ -90,7 +87,7 @@ class RequestManipulatorHelper
* @param string $sKey
* @param mixed $default
* @param int $iFilter Default is FILTER_SANITIZE_SPECIAL_CHARS
* @param int $aFilterOptions @since 3.2.0 - N°6934 - Symfony 6.4 - upgrade Symfony bundles to 6.4
* @param int $aFilterOptions @since 3.2.0 - N°6934 - Symfony 6.4 - upgrade Symfony bundles to 6.4
*
* @return mixed|null
*
@@ -98,18 +95,15 @@ class RequestManipulatorHelper
*/
public function ReadParam($sKey, $default = null, $iFilter = FILTER_SANITIZE_SPECIAL_CHARS, $aFilterOptions = [])
{
if ($this->GetCurrentRequest()->query->has($sKey))
{
if ($this->GetCurrentRequest()->query->has($sKey)) {
return $this->GetCurrentRequest()->query->filter($sKey, $default, $iFilter, $aFilterOptions);
}
if ($this->GetCurrentRequest()->attributes->has($sKey))
{
if ($this->GetCurrentRequest()->attributes->has($sKey)) {
return $this->GetCurrentRequest()->attributes->filter($sKey, $default, $iFilter, $aFilterOptions);
}
if ($this->GetCurrentRequest()->request->has($sKey))
{
if ($this->GetCurrentRequest()->request->has($sKey)) {
return $this->GetCurrentRequest()->request->filter($sKey, $default, $iFilter, $aFilterOptions);
}

View File

@@ -41,18 +41,18 @@ use utils;
class ScopeValidatorHelper
{
/** @var string ENUM_MODE_READ */
const ENUM_MODE_READ = 'r';
public const ENUM_MODE_READ = 'r';
/** @var string ENUM_MODE_WRITE */
const ENUM_MODE_WRITE = 'w';
public const ENUM_MODE_WRITE = 'w';
/** @var string ENUM_TYPE_ALLOW */
const ENUM_TYPE_ALLOW = 'allow';
public const ENUM_TYPE_ALLOW = 'allow';
/** @var string ENUM_TYPE_RESTRICT */
const ENUM_TYPE_RESTRICT = 'restrict';
public const ENUM_TYPE_RESTRICT = 'restrict';
/** @var string DEFAULT_GENERATED_CLASS */
const DEFAULT_GENERATED_CLASS = '\\PortalScopesValues';
public const DEFAULT_GENERATED_CLASS = '\\PortalScopesValues';
/** @var bool DEFAULT_IGNORE_SILOS */
const DEFAULT_IGNORE_SILOS = false;
public const DEFAULT_IGNORE_SILOS = false;
/** @var string|null $sCachePath */
protected $sCachePath;
@@ -80,7 +80,7 @@ class ScopeValidatorHelper
$this->sCachePath = $sPortalCachePath;
$this->sInstancePrefix = "{$sPortalId}-";
$this->sGeneratedClass = static::DEFAULT_GENERATED_CLASS;
$this->aProfilesMatrix = array();
$this->aProfilesMatrix = [];
$this->Init($moduleDesign->GetNodes('/module_design/classes/class'));
}
@@ -96,8 +96,7 @@ class ScopeValidatorHelper
public function Init(DOMNodeList $oNodes)
{
// Checking cache path
if ($this->sCachePath === null)
{
if ($this->sCachePath === null) {
$this->sCachePath = utils::GetCachePath();
}
// Building full pathname for file
@@ -105,20 +104,18 @@ class ScopeValidatorHelper
// Creating file if not existing
// Note : This is a temporary cache system, it should soon evolve to a cache provider (fs, apc, memcache, ...)
if (!file_exists($sFilePath))
{
if (!file_exists($sFilePath)) {
$this->InitGenerateAndWriteCache($oNodes, $sFilePath);
}
if (!class_exists($this->sGeneratedClass))
{
if (!class_exists($this->sGeneratedClass)) {
require_once $this->sCachePath.$this->sFilename;
}
}
public static function EnumTypeValues()
{
return array(static::ENUM_TYPE_ALLOW, static::ENUM_TYPE_RESTRICT);
return [static::ENUM_TYPE_ALLOW, static::ENUM_TYPE_RESTRICT];
}
/**
@@ -197,7 +194,7 @@ class ScopeValidatorHelper
*/
public function GetScopeFilterForProfile($sProfile, $sClass, $iAction = null)
{
return $this->GetScopeFilterForProfiles(array($sProfile), $sClass, $iAction);
return $this->GetScopeFilterForProfiles([$sProfile], $sClass, $iAction);
}
/**
@@ -217,19 +214,17 @@ class ScopeValidatorHelper
public function GetScopeFilterForProfiles($aProfiles, $sClass, $iAction = null)
{
$oSearch = null;
$aAllowSearches = array();
$aRestrictSearches = array();
$aAllowSearches = [];
$aRestrictSearches = [];
$bIgnoreSilos = static::DEFAULT_IGNORE_SILOS;
// Checking the default mode
if ($iAction === null)
{
if ($iAction === null) {
$iAction = UR_ACTION_READ;
}
// Iterating on profiles to retrieving the different OQLs parts
foreach ($aProfiles as $sProfile)
{
foreach ($aProfiles as $sProfile) {
// Retrieving matrix information
$iProfileId = $this->GetProfileIdFromProfileName($sProfile);
$sMode = ($iAction === UR_ACTION_READ) ? static::ENUM_MODE_READ : static::ENUM_MODE_WRITE;
@@ -237,39 +232,31 @@ class ScopeValidatorHelper
// Retrieving profile OQLs
$sScopeValuesClass = $this->sGeneratedClass;
$aProfileMatrix = $sScopeValuesClass::GetProfileScope($iProfileId, $sClass, $sMode);
if ($aProfileMatrix !== null)
{
if (isset($aProfileMatrix['allow']) && $aProfileMatrix['allow'] !== null)
{
if ($aProfileMatrix !== null) {
if (isset($aProfileMatrix['allow']) && $aProfileMatrix['allow'] !== null) {
$aAllowSearches[] = DBSearch::FromOQL($aProfileMatrix['allow']);
}
if (isset($aProfileMatrix['restrict']) && $aProfileMatrix['restrict'] !== null)
{
if (isset($aProfileMatrix['restrict']) && $aProfileMatrix['restrict'] !== null) {
$aRestrictSearches[] = DBSearch::FromOQL($aProfileMatrix['restrict']);
}
// If a profile should ignore allowed org, we set it for all its queries no matter the profile
if (isset($aProfileMatrix['ignore_silos']) && $aProfileMatrix['ignore_silos'] === true)
{
if (isset($aProfileMatrix['ignore_silos']) && $aProfileMatrix['ignore_silos'] === true) {
$bIgnoreSilos = true;
}
}
}
// Building the real OQL from all the parts from the different profiles
for ($i = 0; $i < count($aAllowSearches); $i++)
{
foreach ($aRestrictSearches as $oRestrictSearch)
{
for ($i = 0; $i < count($aAllowSearches); $i++) {
foreach ($aRestrictSearches as $oRestrictSearch) {
$aAllowSearches[$i] = $aAllowSearches[$i]->Intersect($oRestrictSearch);
}
}
if (count($aAllowSearches) > 0)
{
if (count($aAllowSearches) > 0) {
$oSearch = new DBUnionSearch($aAllowSearches);
$oSearch = $oSearch->RemoveDuplicateQueries();
}
if ($bIgnoreSilos === true)
{
if ($bIgnoreSilos === true) {
$oSearch->AllowAllData();
}
@@ -291,12 +278,10 @@ class ScopeValidatorHelper
public function AddScopeToQuery(DBSearch &$oQuery, $sClass, $sAction = UR_ACTION_READ)
{
$oScopeQuery = $this->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sClass, $sAction);
if ($oScopeQuery !== null)
{
if ($oScopeQuery !== null) {
$oQuery = $oQuery->Intersect($oScopeQuery);
// - Allowing all data if necessary
if ($oScopeQuery->IsAllDataAllowed())
{
if ($oScopeQuery->IsAllDataAllowed()) {
$oQuery->AllowAllData();
}
@@ -321,19 +306,16 @@ class ScopeValidatorHelper
$bIgnoreSilos = false;
// Iterating on profiles to retrieving the different OQLs parts
foreach ($aProfiles as $sProfile)
{
foreach ($aProfiles as $sProfile) {
// Retrieving matrix information
$iProfileId = $this->GetProfileIdFromProfileName($sProfile);
// Retrieving profile OQLs
$sScopeValuesClass = $this->sGeneratedClass;
$aProfileMatrix = $sScopeValuesClass::GetProfileScope($iProfileId, $sClass, static::ENUM_MODE_READ);
if ($aProfileMatrix !== null)
{
if ($aProfileMatrix !== null) {
// If a profile should ignore allowed org, we set it for all its queries no matter the profile
if (isset($aProfileMatrix['ignore_silos']) && $aProfileMatrix['ignore_silos'] === true)
{
if (isset($aProfileMatrix['ignore_silos']) && $aProfileMatrix['ignore_silos'] === true) {
$bIgnoreSilos = true;
}
}
@@ -357,18 +339,12 @@ class ScopeValidatorHelper
// We try to find the profile from its name in order to retrieve it's id
// - If the regular UserRights add-on is installed we check the profiles array
if (class_exists('ProfilesConfig'))
{
if (defined($sProfile) && in_array($sProfile, ProfilesConfig::GetProfilesValues()))
{
if (class_exists('ProfilesConfig')) {
if (defined($sProfile) && in_array($sProfile, ProfilesConfig::GetProfilesValues())) {
$iProfileId = constant($sProfile);
}
else
{
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
{
if ($aValue['name'] === $sProfile)
{
} else {
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue) {
if ($aValue['name'] === $sProfile) {
$iProfileId = $iKey;
break;
}
@@ -376,14 +352,12 @@ class ScopeValidatorHelper
}
}
// - Else, we can't find the id from the name as we don't know the used UserRights add-on. It has to be a constant
else
{
else {
throw new Exception('Scope validator : Unknown UserRights addon, scope\'s profile must be a constant');
}
// If profile was not found from its name or from a constant, we throw an exception
if ($iProfileId === null)
{
if ($iProfileId === null) {
throw new Exception('Scope validator : Could not find "'.$sProfile.'" in the profiles list');
}
@@ -397,7 +371,7 @@ class ScopeValidatorHelper
*
* @return string
*/
protected function BuildPHPClass($aProfiles = array())
protected function BuildPHPClass($aProfiles = [])
{
$sProfiles = var_export($aProfiles, true);
$sClassName = ltrim($this->sGeneratedClass, '\\');
@@ -450,31 +424,26 @@ EOF;
protected function InitGenerateAndWriteCache(DOMNodeList $oNodes, $sFilePath)
{
// - Build php array from xml
$aProfiles = array();
$aProfiles = [];
// This will be used to know which classes have been set, so we can set the missing ones.
$aProfileClasses = array();
$aProfileClasses = [];
// Iterating over the class nodes
/** @var \Combodo\iTop\DesignElement $oClassNode */
foreach ($oNodes as $oClassNode)
{
foreach ($oNodes as $oClassNode) {
// retrieving mandatory class id attribute
$sClass = $oClassNode->getAttribute('id');
if ($sClass === '')
{
if ($sClass === '') {
throw new DOMFormatException('Class tag must have an id attribute.', null, null, $oClassNode);
}
// Iterating over scope nodes of the class
$oScopesNode = $oClassNode->GetOptionalElement('scopes');
if ($oScopesNode !== null)
{
if ($oScopesNode !== null) {
/** @var \Combodo\iTop\DesignElement $oScopeNode */
foreach ($oScopesNode->GetNodes('./scope') as $oScopeNode)
{
foreach ($oScopesNode->GetNodes('./scope') as $oScopeNode) {
// Retrieving mandatory scope id attribute
$sScopeId = $oScopeNode->getAttribute('id');
if ($sScopeId === '')
{
if ($sScopeId === '') {
throw new DOMFormatException('Scope tag must have an id attribute.', null, null, $oScopeNode);
}
@@ -486,8 +455,7 @@ EOF;
// Retrieving the view query
$oOqlViewNode = $oScopeNode->GetUniqueElement('oql_view');
$sOqlView = $oOqlViewNode->GetText();
if ($sOqlView === null)
{
if ($sOqlView === null) {
throw new DOMFormatException(
'Scope tag in class must have a not empty oql_view tag',
0,
@@ -504,24 +472,18 @@ EOF;
// Retrieving profiles for the scope
$oProfilesNode = $oScopeNode->GetOptionalElement('allowed_profiles');
$aProfilesNames = array();
$aProfilesNames = [];
// If no profile is specified, we consider that it's for ALL the profiles
if (($oProfilesNode === null) || ($oProfilesNode->GetNodes('./allowed_profile')->length === 0))
{
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
{
if (($oProfilesNode === null) || ($oProfilesNode->GetNodes('./allowed_profile')->length === 0)) {
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue) {
$aProfilesNames[] = $aValue['name'];
}
}
else
{
} else {
/** @var \Combodo\iTop\DesignElement $oProfileNode */
foreach ($oProfilesNode->GetNodes('./allowed_profile') as $oProfileNode)
{
foreach ($oProfilesNode->GetNodes('./allowed_profile') as $oProfileNode) {
// Retrieving mandatory profile id attribute
$sProfileId = $oProfileNode->getAttribute('id');
if ($sProfileId === '')
{
if ($sProfileId === '') {
throw new DOMFormatException(
'Scope tag must have an id attribute.',
null,
@@ -534,8 +496,7 @@ EOF;
}
//
foreach ($aProfilesNames as $sProfileName)
{
foreach ($aProfilesNames as $sProfileName) {
// Scope profile id
$iProfileId = $this->GetProfileIdFromProfileName($sProfileName);
@@ -545,48 +506,37 @@ EOF;
$oViewFilter = DBSearch::FromOQL($sOqlView);
// ... We have to union the query if this profile has another scope for that class
if (array_key_exists($sMatrixPrefix.static::ENUM_MODE_READ, $aProfiles) && array_key_exists(
$sOqlViewType,
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ]
))
{
$sOqlViewType,
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ]
)) {
$oExistingFilter = DBSearch::FromOQL(
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ][$sOqlViewType]
);
$aFilters = array($oExistingFilter, $oViewFilter);
$aFilters = [$oExistingFilter, $oViewFilter];
$oResFilter = new DBUnionSearch($aFilters);
// Applying ignore_silos flag on result filter if necessary (As the union will remove it if it is not on all sub-queries)
if ($aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ]['ignore_silos'] === true)
{
if ($aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ]['ignore_silos'] === true) {
$bIgnoreSilos = true;
}
}
else
{
} else {
$oResFilter = $oViewFilter;
}
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ] = array(
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_READ] = [
$sOqlViewType => $oResFilter->ToOQL(),
'ignore_silos' => $bIgnoreSilos,
);
];
// - Edit query
if ($sOqlEdit !== null)
{
if ($sOqlEdit !== null) {
$oEditFilter = DBSearch::FromOQL($sOqlEdit);
// - If the queries are the same, we don't make an intersect, we just reuse the view query
if ($sOqlEdit === $sOqlView)
{
if ($sOqlEdit === $sOqlView) {
// Do not intersect, edit query is identical to view query
}
else
{
if (($oEditFilter->GetClass() === $oViewFilter->GetClass()) && $oEditFilter->IsAny())
{
} else {
if (($oEditFilter->GetClass() === $oViewFilter->GetClass()) && $oEditFilter->IsAny()) {
$oEditFilter = $oViewFilter;
// Do not intersect, edit query is identical to view query
}
else
{
} else {
// Intersect
$oEditFilter = $oViewFilter->Intersect($oEditFilter);
}
@@ -594,27 +544,24 @@ EOF;
// ... We have to union the query if this profile has another scope for that class
if (array_key_exists(
$sMatrixPrefix.static::ENUM_MODE_WRITE,
$aProfiles
) && array_key_exists(
$sOqlViewType,
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE]
))
{
$sMatrixPrefix.static::ENUM_MODE_WRITE,
$aProfiles
) && array_key_exists(
$sOqlViewType,
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE]
)) {
$oExistingFilter = DBSearch::FromOQL(
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE][$sOqlViewType]
);
$aFilters = array($oExistingFilter, $oEditFilter);
$aFilters = [$oExistingFilter, $oEditFilter];
$oResFilter = new DBUnionSearch($aFilters);
}
else
{
} else {
$oResFilter = $oEditFilter;
}
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE] = array(
$aProfiles[$sMatrixPrefix.static::ENUM_MODE_WRITE] = [
$sOqlViewType => $oResFilter->ToOQL(),
'ignore_silos' => $bIgnoreSilos,
);
];
}
}
}
@@ -626,27 +573,19 @@ EOF;
// Filling the array with missing classes from MetaModel, so we can have an inheritance principle on the scope
// For each class explicitly given in the scopes, we check if its child classes were also in the scope :
// If not, we add them with the same OQL
foreach ($aProfileClasses as $sProfileClass)
{
foreach (MetaModel::EnumChildClasses($sProfileClass) as $sChildClass)
{
foreach ($aProfileClasses as $sProfileClass) {
foreach (MetaModel::EnumChildClasses($sProfileClass) as $sChildClass) {
// If the child class is not in the scope, we are going to try to add it
if (!in_array($sChildClass, $aProfileClasses))
{
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
{
if (!in_array($sChildClass, $aProfileClasses)) {
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue) {
$iProfileId = $iKey;
foreach (array(static::ENUM_MODE_READ, static::ENUM_MODE_WRITE) as $sAction)
{
foreach ([static::ENUM_MODE_READ, static::ENUM_MODE_WRITE] as $sAction) {
// If the current profile has scope for that class in that mode, we duplicate it
if (isset($aProfiles[$iProfileId.'_'.$sProfileClass.'_'.$sAction]))
{
if (isset($aProfiles[$iProfileId.'_'.$sProfileClass.'_'.$sAction])) {
$aTmpProfile = $aProfiles[$iProfileId.'_'.$sProfileClass.'_'.$sAction];
foreach ($aTmpProfile as $sType => $sOql)
{
foreach ($aTmpProfile as $sType => $sOql) {
// IF condition is just to skip the 'ignore_silos' flag
if (in_array($sType, array(static::ENUM_TYPE_ALLOW, static::ENUM_TYPE_RESTRICT)))
{
if (in_array($sType, [static::ENUM_TYPE_ALLOW, static::ENUM_TYPE_RESTRICT])) {
$oTmpFilter = DBSearch::FromOQL($sOql);
$oTmpFilter->ChangeClass($sChildClass);
@@ -667,14 +606,12 @@ EOF;
// - Write file on disk
// - Creating dir if necessary
if (!is_dir($this->sCachePath))
{
if (!is_dir($this->sCachePath)) {
mkdir($this->sCachePath, 0777, true);
}
// -- Then creating the file
$ret = file_put_contents($sFilePath, $sPHP);
if ($ret === false)
{
if ($ret === false) {
$iLen = strlen($sPHP);
$fFree = @disk_free_space(dirname($sFilePath));
$aErr = error_get_last();
@@ -685,4 +622,3 @@ EOF;
}
}

View File

@@ -43,10 +43,10 @@ use BinaryExpression;
class SecurityHelper
{
/** @var array $aAllowedScopeObjectsCache */
public static $aAllowedScopeObjectsCache = array(
UR_ACTION_READ => array(),
UR_ACTION_MODIFY => array(),
);
public static $aAllowedScopeObjectsCache = [
UR_ACTION_READ => [],
UR_ACTION_MODIFY => [],
];
/** @var \Combodo\iTop\Portal\Helper\ScopeValidatorHelper $oScopeValidator */
private $oScopeValidator;
@@ -69,7 +69,6 @@ class SecurityHelper
$this->bDebug = $bDebug;
}
/**
* Returns true if the current user is allowed to do the $sAction on an $sObjectClass object (with optional $sObjectId id)
* Checks are:
@@ -94,45 +93,37 @@ class SecurityHelper
$sDebugTracePrefix = __CLASS__.' / '.__METHOD__.' : Returned false for action '.$sAction.' on '.$sObjectClass.'::'.$sObjectId;
// Checking action type
if (!in_array($sAction, array(UR_ACTION_READ, UR_ACTION_MODIFY, UR_ACTION_CREATE)))
{
if (!in_array($sAction, [UR_ACTION_READ, UR_ACTION_MODIFY, UR_ACTION_CREATE])) {
IssueLog::Debug($sDebugTracePrefix.' as the action value could not be understood ('.UR_ACTION_READ.'/'.UR_ACTION_MODIFY.'/'.UR_ACTION_CREATE.' expected', LogChannels::PORTAL);
return false;
}
// Forcing allowed writing on the object if necessary. This is used in some particular cases.
$bObjectIsCurrentUser = ($sObjectClass === 'Person' && $sObjectId == UserRights::GetContactId());
if(in_array($sAction , array(UR_ACTION_MODIFY, UR_ACTION_READ)) && $bObjectIsCurrentUser){
if (in_array($sAction, [UR_ACTION_MODIFY, UR_ACTION_READ]) && $bObjectIsCurrentUser) {
return true;
}
}
// Checking the scopes layer
// - Transforming scope action as there is only 2 values
$sScopeAction = ($sAction === UR_ACTION_READ) ? UR_ACTION_READ : UR_ACTION_MODIFY;
// - Retrieving the query. If user has no scope, it can't access that kind of objects
$oScopeQuery = $this->oScopeValidator->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sObjectClass, $sScopeAction);
if ($oScopeQuery === null)
{
if ($oScopeQuery === null) {
IssueLog::Debug($sDebugTracePrefix.' as there was no scope defined for action '.$sScopeAction.' and profiles '.implode('/', UserRights::ListProfiles()), LogChannels::PORTAL);
return false;
}
// - If action != create we do some additionnal checks
if ($sAction !== UR_ACTION_CREATE)
{
if ($sAction !== UR_ACTION_CREATE) {
// - Checking specific object if id is specified
if ($sObjectId !== null)
{
if ($sObjectId !== null) {
// Checking if object status is in cache (to avoid unnecessary query)
if (isset(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId]))
{
if (static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId] === false)
{
if (isset(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId])) {
if (static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId] === false) {
IssueLog::Debug($sDebugTracePrefix.' as it was denied in the scope objects cache', LogChannels::PORTAL);
return false;
}
}
else
{
} else {
// Modifying query to filter on the ID
// - Adding expression
$sObjectKeyAtt = MetaModel::DBGetKey($sObjectClass);
@@ -147,8 +138,7 @@ class SecurityHelper
// - Checking if query result is null (which means that the user has no right to view this specific object)
$oSet = new DBObjectSet($oScopeQuery);
if ($oSet->Count() === 0)
{
if ($oSet->Count() === 0) {
// Updating cache
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass][$sObjectId] = false;
@@ -163,8 +153,7 @@ class SecurityHelper
}
// Checking reading security layer. The object could be listed, check if it is actually allowed to view it
if (UserRights::IsActionAllowed($sObjectClass, $sAction) == UR_ALLOWED_NO)
{
if (UserRights::IsActionAllowed($sObjectClass, $sAction) == UR_ALLOWED_NO) {
// For security reasons, we don't want to give the user too many information on why he cannot access the object.
//throw new SecurityException('User not allowed to view this object', array('class' => $sObjectClass, 'id' => $sObjectId));
IssueLog::Debug($sDebugTracePrefix.' as the user is not allowed to access this object according to the datamodel security (cf. Console settings)', LogChannels::PORTAL);
@@ -187,15 +176,13 @@ class SecurityHelper
// Checking DataModel layer
$aStimuliFromDatamodel = Metamodel::EnumStimuli($sObjectClass);
$iActionAllowed = (get_class($aStimuliFromDatamodel[$sStimulusCode]) == 'StimulusUserAction') ? UserRights::IsStimulusAllowed($sObjectClass, $sStimulusCode, $oInstanceSet) : UR_ALLOWED_NO;
if (($iActionAllowed === false) || ($iActionAllowed === UR_ALLOWED_NO))
{
if (($iActionAllowed === false) || ($iActionAllowed === UR_ALLOWED_NO)) {
return false;
}
// Checking portal security layer
$aStimuliFromPortal = $this->oLifecycleValidator->GetStimuliForProfiles(UserRights::ListProfiles(), $sObjectClass);
if (!in_array($sStimulusCode, $aStimuliFromPortal))
{
if (!in_array($sStimulusCode, $aStimuliFromPortal)) {
return false;
}
@@ -217,20 +204,17 @@ class SecurityHelper
public function PreloadForCache(DBSearch $oSearch, $aExtKeysToPreload = null)
{
$sObjectClass = $oSearch->GetClass();
$aObjectIds = array();
$aExtKeysIds = array();
$aColumnsToLoad = array();
$aObjectIds = [];
$aExtKeysIds = [];
$aColumnsToLoad = [];
if ($aExtKeysToPreload !== null)
{
foreach ($aExtKeysToPreload as $sAttCode)
{
if ($aExtKeysToPreload !== null) {
foreach ($aExtKeysToPreload as $sAttCode) {
/** @var \AttributeDefinition $oAttDef */
$oAttDef = MetaModel::GetAttributeDef($sObjectClass, $sAttCode);
if ($oAttDef->IsExternalKey())
{
if ($oAttDef->IsExternalKey()) {
/** @var \AttributeExternalKey $oAttDef */
$aExtKeysIds[$oAttDef->GetTargetClass()] = array();
$aExtKeysIds[$oAttDef->GetTargetClass()] = [];
$aColumnsToLoad[] = $sAttCode;
}
}
@@ -239,69 +223,56 @@ class SecurityHelper
// Retrieving IDs of all objects
// Note: We have to clone $oSet otherwise the source object will be modified
$oSet = new DBObjectSet($oSearch);
$oSet->OptimizeColumnLoad(array($oSearch->GetClassAlias() => $aColumnsToLoad));
while ($oCurrentRow = $oSet->Fetch())
{
$oSet->OptimizeColumnLoad([$oSearch->GetClassAlias() => $aColumnsToLoad]);
while ($oCurrentRow = $oSet->Fetch()) {
// Note: By presetting value to false, it is quicker to find which objects where not returned by the scope query later
$aObjectIds[$oCurrentRow->GetKey()] = false;
// Preparing ExtKeys to preload
foreach ($aColumnsToLoad as $sAttCode)
{
foreach ($aColumnsToLoad as $sAttCode) {
$iExtKey = $oCurrentRow->Get($sAttCode);
if ($iExtKey > 0)
{
if ($iExtKey > 0) {
/** @var \AttributeExternalKey $oAttDef */
$oAttDef = MetaModel::GetAttributeDef($sObjectClass, $sAttCode);
if (!in_array($iExtKey, $aExtKeysIds[$oAttDef->GetTargetClass()]))
{
if (!in_array($iExtKey, $aExtKeysIds[$oAttDef->GetTargetClass()])) {
$aExtKeysIds[$oAttDef->GetTargetClass()][] = $iExtKey;
}
}
}
}
foreach (array(UR_ACTION_READ, UR_ACTION_MODIFY) as $sScopeAction)
{
foreach ([UR_ACTION_READ, UR_ACTION_MODIFY] as $sScopeAction) {
// Retrieving scope query
/** @var DBSearch $oScopeQuery */
$oScopeQuery = $this->oScopeValidator->GetScopeFilterForProfiles(UserRights::ListProfiles(), $sObjectClass, $sScopeAction);
if ($oScopeQuery !== null)
{
if ($oScopeQuery !== null) {
// Restricting scope if specified
if (!empty($aObjectIds))
{
if (!empty($aObjectIds)) {
$oScopeQuery->AddCondition('id', array_keys($aObjectIds), 'IN');
}
// Preparing object set
$oScopeSet = new DBObjectSet($oScopeQuery);
$oScopeSet->OptimizeColumnLoad(array($oScopeQuery->GetClassAlias() => array()));
$oScopeSet->OptimizeColumnLoad([$oScopeQuery->GetClassAlias() => []]);
// Checking objects status
$aScopeObjectIds = $aObjectIds;
while ($oCurrentRow = $oScopeSet->Fetch())
{
while ($oCurrentRow = $oScopeSet->Fetch()) {
$aScopeObjectIds[$oCurrentRow->GetKey()] = true;
}
// Updating cache
if (!isset(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass]))
{
if (!isset(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass])) {
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass] = $aScopeObjectIds;
}
else
{
} else {
static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass] = array_merge_recursive(static::$aAllowedScopeObjectsCache[$sScopeAction][$sObjectClass], $aScopeObjectIds);
}
}
}
// Preloading ExtKeys
foreach ($aExtKeysIds as $sTargetClass => $aTargetIds)
{
if (!empty($aTargetIds))
{
foreach ($aExtKeysIds as $sTargetClass => $aTargetIds) {
if (!empty($aTargetIds)) {
$oTargetSearch = new DBObjectSearch($sTargetClass);
$oTargetSearch->AddCondition('id', $aTargetIds, 'IN');

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -35,21 +36,21 @@ use utils;
class SessionMessageHelper implements IteratorAggregate
{
/** @var string ENUM_SEVERITY_INFO */
const ENUM_SEVERITY_INFO = 'info';
public const ENUM_SEVERITY_INFO = 'info';
/** @var string ENUM_SEVERITY_OK */
const ENUM_SEVERITY_OK = 'ok';
public const ENUM_SEVERITY_OK = 'ok';
/** @var string ENUM_SEVERITY_WARNING */
const ENUM_SEVERITY_WARNING = 'warning';
public const ENUM_SEVERITY_WARNING = 'warning';
/** @var string ENUM_SEVERITY_ERROR */
const ENUM_SEVERITY_ERROR = 'error';
public const ENUM_SEVERITY_ERROR = 'error';
/** @var string DEFAULT_SEVERITY */
const DEFAULT_SEVERITY = self::ENUM_SEVERITY_INFO;
public const DEFAULT_SEVERITY = self::ENUM_SEVERITY_INFO;
/** @var \Symfony\Component\DependencyInjection\ContainerInterface $oContainer */
private $oContainer;
/** @var array $aAllMessages */
private $aAllMessages = array();
private $aAllMessages = [];
/**
* SessionMessageHelper constructor.
@@ -71,11 +72,10 @@ class SessionMessageHelper implements IteratorAggregate
* @param array $aMetadata An array of key => scalar value
* @param int $iRank
*/
public function AddMessage($sId, $sContent, $sSeverity = self::DEFAULT_SEVERITY, $aMetadata = array(), $iRank = 1)
public function AddMessage($sId, $sContent, $sSeverity = self::DEFAULT_SEVERITY, $aMetadata = [], $iRank = 1)
{
$sKey = $this->GetMessagesKey();
if(!Session::IsSet(['obj_messages', $sKey]))
{
if (!Session::IsSet(['obj_messages', $sKey])) {
Session::Set(['obj_messages', $sKey], []);
}
@@ -115,7 +115,7 @@ class SessionMessageHelper implements IteratorAggregate
*/
private function GetMessagesKey()
{
return 'GUI:' . $this->oContainer->getParameter('combodo.portal.instance.id');
return 'GUI:'.$this->oContainer->getParameter('combodo.portal.instance.id');
}
/**
@@ -126,23 +126,18 @@ class SessionMessageHelper implements IteratorAggregate
*/
private function FetchMessages()
{
if (!empty($this->aAllMessages))
{
if (!empty($this->aAllMessages)) {
return;
}
$this->aAllMessages = array();
if (is_array(Session::Get('obj_messages')))
{
foreach (Session::Get('obj_messages') as $sMessageKey => $aMessageObjectData)
{
$aObjectMessages = array();
$aRanks = array();
foreach ($aMessageObjectData as $sMessageId => $aMessageData)
{
$this->aAllMessages = [];
if (is_array(Session::Get('obj_messages'))) {
foreach (Session::Get('obj_messages') as $sMessageKey => $aMessageObjectData) {
$aObjectMessages = [];
$aRanks = [];
foreach ($aMessageObjectData as $sMessageId => $aMessageData) {
$sMsgClass = 'alert alert-dismissible alert-';
switch ($aMessageData['severity'])
{
switch ($aMessageData['severity']) {
case static::ENUM_SEVERITY_INFO:
$sMsgClass .= 'info';
break;
@@ -168,17 +163,16 @@ class SessionMessageHelper implements IteratorAggregate
$sMsgMetadata .= 'data-'.str_replace('_', '-', $sMetadatumName).'="'.utils::HtmlEntities($sMetadatumValue).'" ';
}
}
$aObjectMessages[] = array('css_classes' => $sMsgClass, 'message' => $aMessageData['message'], 'metadata' => $sMsgMetadata);
$aObjectMessages[] = ['css_classes' => $sMsgClass, 'message' => $aMessageData['message'], 'metadata' => $sMsgMetadata];
$aRanks[] = $aMessageData['rank'];
}
Session::Unset(['obj_messages', $sMessageKey]);
array_multisort($aRanks, $aObjectMessages);
foreach ($aObjectMessages as $aObjectMessage)
{
foreach ($aObjectMessages as $aObjectMessage) {
$this->aAllMessages[] = $aObjectMessage;
}
}
}
}
}
}

View File

@@ -18,10 +18,8 @@
* You should have received a copy of the GNU Affero General Public License
*/
namespace Combodo\iTop\Portal\Helper;
use InvalidParameterException;
use iPortalUIExtension;
use MetaModel;
@@ -66,13 +64,11 @@ class UIExtensionsHelper
*/
public function __get($sPropName)
{
if ($this->aUIExtensions === null)
{
if ($this->aUIExtensions === null) {
$this->InitUIExtensions();
}
if (array_key_exists($sPropName, $this->aUIExtensions))
{
if (array_key_exists($sPropName, $this->aUIExtensions)) {
return $this->aUIExtensions[$sPropName];
}
@@ -87,8 +83,7 @@ class UIExtensionsHelper
*/
public function __isset($sPropName)
{
if ($this->aUIExtensions === null)
{
if ($this->aUIExtensions === null) {
$this->InitUIExtensions();
}
@@ -110,67 +105,63 @@ class UIExtensionsHelper
*/
protected function InitUIExtensions()
{
$aUIExtensions = array(
'css_files' => array(),
$aUIExtensions = [
'css_files' => [],
'css_inline' => null,
'js_files' => array(),
'js_files' => [],
'js_inline' => null,
'html' => array(),
);
'html' => [],
];
$aUIExtensionHooks = array(
$aUIExtensionHooks = [
iPortalUIExtension::ENUM_PORTAL_EXT_UI_BODY,
iPortalUIExtension::ENUM_PORTAL_EXT_UI_NAVIGATION_MENU,
iPortalUIExtension::ENUM_PORTAL_EXT_UI_MAIN_CONTENT,
);
];
/** @var iPortalUIExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iPortalUIExtension') as $oExtensionInstance)
{
foreach (MetaModel::EnumPlugins('iPortalUIExtension') as $oExtensionInstance) {
// Adding CSS files
$aImportPaths = array($_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'].'css/');
foreach ($oExtensionInstance->GetCSSFiles($this->oContainer) as $sCSSFile)
{
$aImportPaths = [$_ENV['COMBODO_PORTAL_BASE_ABSOLUTE_PATH'].'css/'];
foreach ($oExtensionInstance->GetCSSFiles($this->oContainer) as $sCSSFile) {
// Removing app root url as we need to pass a path on the file system (relative to app root)
$sCSSFilePath = str_replace(utils::GetAbsoluteUrlAppRoot(), '', $sCSSFile);
// Compiling SCSS file
$sCSSFileCompiled = utils::GetAbsoluteUrlAppRoot().utils::GetCSSFromSASS($sCSSFilePath,
$aImportPaths);
$sCSSFileCompiled = utils::GetAbsoluteUrlAppRoot().utils::GetCSSFromSASS(
$sCSSFilePath,
$aImportPaths
);
if (!in_array($sCSSFileCompiled, $aUIExtensions['css_files']))
{
if (!in_array($sCSSFileCompiled, $aUIExtensions['css_files'])) {
$aUIExtensions['css_files'][] = $sCSSFileCompiled;
}
}
// Adding CSS inline
$sCSSInline = $oExtensionInstance->GetCSSInline($this->oContainer);
if ($sCSSInline !== null)
{
if ($sCSSInline !== null) {
$aUIExtensions['css_inline'] .= "\n\n".$sCSSInline;
}
// Adding JS files
$aUIExtensions['js_files'] = array_merge($aUIExtensions['js_files'],
$oExtensionInstance->GetJSFiles($this->oContainer));
$aUIExtensions['js_files'] = array_merge(
$aUIExtensions['js_files'],
$oExtensionInstance->GetJSFiles($this->oContainer)
);
// Adding JS inline
$sJSInline = $oExtensionInstance->GetJSInline($this->oContainer);
if ($sJSInline !== null)
{
if ($sJSInline !== null) {
// Note: Semi-colon is to prevent previous script that would have omitted it.
$aUIExtensions['js_inline'] .= "\n\n;\n".$sJSInline;
}
// Adding HTML for each hook
foreach ($aUIExtensionHooks as $sUIExtensionHook)
{
foreach ($aUIExtensionHooks as $sUIExtensionHook) {
$sFunctionName = 'Get'.$sUIExtensionHook.'HTML';
$sHTML = $oExtensionInstance->$sFunctionName($this->oContainer);
if ($sHTML !== null)
{
if (!array_key_exists($sUIExtensionHook, $aUIExtensions['html']))
{
if ($sHTML !== null) {
if (!array_key_exists($sUIExtensionHook, $aUIExtensions['html'])) {
$aUIExtensions['html'][$sUIExtensionHook] = '';
}
$aUIExtensions['html'][$sUIExtensionHook] .= "\n\n".$sHTML;
@@ -180,4 +171,4 @@ class UIExtensionsHelper
$this->aUIExtensions = $aUIExtensions;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -70,4 +71,4 @@ interface iAbstractPortalTabContentExtension
* @since iTop 3.2.1
*/
public function GetSectionRank(): float;
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -59,4 +60,4 @@ interface iAbstractPortalTabExtension
* @since iTop 3.2.1
*/
public function GetTabLabel(): string;
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -14,5 +15,4 @@ namespace Combodo\iTop\Portal\Hook;
*/
interface iUserProfileTabContentExtension extends iAbstractPortalTabContentExtension
{
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -14,5 +15,4 @@ namespace Combodo\iTop\Portal\Hook;
*/
interface iUserProfileTabExtension extends iAbstractPortalTabExtension
{
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -37,8 +38,8 @@ class Kernel extends BaseKernel
{
use MicroKernelTrait;
/** @var string CONFIG_EXTS */
const CONFIG_EXTS = '.{php,xml,yaml,yml}';
/** @var string CONFIG_EXTS */
public const CONFIG_EXTS = '.{php,xml,yaml,yml}';
/**
* @return string
@@ -55,23 +56,23 @@ class Kernel extends BaseKernel
*/
public function getLogDir(): string
{
$logDir = $_ENV['PORTAL_ID'] . '-' . $this->environment;
$logDir = $_ENV['PORTAL_ID'].'-'.$this->environment;
return utils::GetLogPath() . "/portals/$logDir";
}
return utils::GetLogPath()."/portals/$logDir";
}
/**
* @return \Generator|iterable|\Symfony\Component\HttpKernel\Bundle\BundleInterface[]
*/
public function registerBundles(): iterable
{
$contents = require $this->getProjectDir().'/config/bundles.php';
foreach ($contents as $class => $envs) {
if (isset($envs[$this->environment]) || isset($envs['all'])) {
yield new $class();
}
}
}
$contents = require $this->getProjectDir().'/config/bundles.php';
foreach ($contents as $class => $envs) {
if (isset($envs[$this->environment]) || isset($envs['all'])) {
yield new $class();
}
}
}
/**
* @param \Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator $container
@@ -106,7 +107,6 @@ class Kernel extends BaseKernel
$routes->import($confDir.'/{routes}'.self::CONFIG_EXTS);
}
/**
* Checks if a given class name belongs to an active bundle.
*

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -19,7 +20,6 @@
namespace Combodo\iTop\Portal\Routing;
use Exception;
/**
@@ -32,13 +32,13 @@ use Exception;
class ItopExtensionsExtraRoutes
{
/** @var array $aRoutes */
static private $aRoutes = array();
private static $aRoutes = [];
/**
* @var array $aControllersClasses
* @since 3.1.0
*/
static private $aControllersClasses = array();
private static $aControllersClasses = [];
/**
* @param array $extraRoutes
@@ -85,4 +85,4 @@ class ItopExtensionsExtraRoutes
{
return self::$aControllersClasses;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -117,4 +118,4 @@ class UrlGenerator implements RouterInterface
return $aParameters;
}
}
}

View File

@@ -64,8 +64,7 @@ class TemplateDefinitionDto
private ?string $sPath = null,
private readonly ?bool $bIsOverridable = false,
private readonly ?string $sAlias = null,
)
{
) {
// save overridable values
$this->sInitialValue = $sPath;
}
@@ -89,7 +88,7 @@ class TemplateDefinitionDto
*/
public function GetPath(bool $bInitialValue = false): string
{
if($bInitialValue){
if ($bInitialValue) {
return $this->sInitialValue !== null ? $this->sInitialValue : '';
}
@@ -142,4 +141,4 @@ class TemplateDefinitionDto
return $this->bIsOverridden;
}
}
}

View File

@@ -36,4 +36,4 @@ interface TemplatesProviderInterface
* @return void
*/
public static function RegisterTemplates(TemplatesRegister $oTemplatesRegister): void;
}
}

View File

@@ -275,8 +275,7 @@ class TemplatesProviderService
if ($oParent) {
$sCurrentClass = $oReflexion->getParentClass()->getName();
}
}
catch (Exception) {
} catch (Exception) {
}
} while ($oParent); // continue while parent class exists
@@ -321,4 +320,4 @@ class TemplatesProviderService
&& array_key_exists($sTemplateId, $this->aInstancesOverriddenTemplatesPaths[$sObjectId]['templates']));
}
}
}

View File

@@ -29,11 +29,9 @@ namespace Combodo\iTop\Portal\Service\TemplatesProvider;
*/
class TemplatesRegister
{
/** @var array Templates definitions (possibly altered by portal configuration) */
private array $aTemplatesDefinitions = [];
public function __construct(private string $sTemplateUIVersion = 'unset')
{
@@ -118,7 +116,7 @@ class TemplatesRegister
*/
public function GetProviderTemplatesIds(string $sProviderId): array
{
return array_map(fn($oTemplateDefinition) => $oTemplateDefinition->GetId(), $this->aTemplatesDefinitions[$sProviderId] ?? ['tile', 'page']);
return array_map(fn ($oTemplateDefinition) => $oTemplateDefinition->GetId(), $this->aTemplatesDefinitions[$sProviderId] ?? ['tile', 'page']);
}
/**
@@ -130,4 +128,4 @@ class TemplatesRegister
{
return $this->aTemplatesDefinitions;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -22,7 +23,6 @@ namespace Combodo\iTop\Portal\Twig;
use Combodo\iTop\Application\TwigBase\Twig\Extension;
use Twig\Extension\AbstractExtension;
/**
* Class AppExtension
*
@@ -50,4 +50,4 @@ class AppExtension extends AbstractExtension
{
return Extension::GetFunctions();
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -54,10 +55,10 @@ class AppGlobal extends AbstractExtension implements GlobalsInterface
*/
public function getGlobals(): array
{
$data = array();
$data = [];
$data['allowed_portals'] = $this->userProvider->getAllowedPortals();
return $data;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -33,93 +34,92 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*/
class AppVariable implements ArrayAccess
{
/** @var ContainerInterface */
private $container;
/** @var ContainerInterface */
private $container;
/** @var DecoratedAppVariable */
private $decorated;
/** @var DecoratedAppVariable */
private $decorated;
public function __construct(DecoratedAppVariable $decorated, ContainerInterface $container = null)
{
$this->decorated = $decorated;
$this->container = $container;
}
public function __construct(DecoratedAppVariable $decorated, ContainerInterface $container = null)
{
$this->decorated = $decorated;
$this->container = $container;
}
public function __call($name, $arguments)
{
if ($this->silexApplicationEmulation->offsetExists($name)) {
return $this->silexApplicationEmulation->offsetGet($name);
}
public function __call($name, $arguments)
{
if ($this->silexApplicationEmulation->offsetExists($name)) {
return $this->silexApplicationEmulation->offsetGet($name);
}
return $this->decorated->$name(...$arguments); //WARNING: use of http://php.net/manual/fr/functions.arguments.php#functions.variable-arg-list
}
return $this->decorated->$name(...$arguments); //WARNING: use of http://php.net/manual/fr/functions.arguments.php#functions.variable-arg-list
}
/**
* @inheritDoc
*/
public function offsetExists($offset): bool
{
if ($this->container->hasParameter($offset)) {
return true;
}
if ($this->container->has($offset)) {
return true;
}
/**
* @inheritDoc
*/
public function offsetExists($offset): bool
{
if ($this->container->hasParameter($offset)) {
return true;
}
if ($this->container->has($offset)) {
return true;
}
return false;
}
return false;
}
/**
* @inheritDoc
*/
/**
* @inheritDoc
*/
#[\ReturnTypeWillChange]
public function offsetGet($offset)
{
if ($this->container->hasParameter($offset)) {
return $this->container->getParameter($offset);
}
if ($this->container->has($offset)) {
return $this->container->get($offset);
}
public function offsetGet($offset)
{
if ($this->container->hasParameter($offset)) {
return $this->container->getParameter($offset);
}
if ($this->container->has($offset)) {
return $this->container->get($offset);
}
return null;
}
return null;
}
/**
* @inheritDoc
*/
public function offsetSet($offset, $value): void
{
/**
* @inheritDoc
*/
public function offsetSet($offset, $value): void
{
if ($this->container->hasParameter($offset)) {
$this->container->setParameter($offset, $value);
return;
}
if ($this->container->hasParameter($offset)) {
$this->container->setParameter($offset, $value);
return;
}
if ($this->container->has($offset)) {
$this->container->set($offset, $value);
return;
}
if ($this->container->has($offset)) {
$this->container->set($offset, $value);
return;
}
if (is_object($value)) {
$this->container->set($offset, $value);
return;
}
if (is_object($value)) {
$this->container->set($offset, $value);
return;
}
$this->container->setParameter($offset, $value);
}
$this->container->setParameter($offset, $value);
}
/**
* @inheritDoc
*/
public function offsetUnset($offset): void
{
if ($this->container->hasParameter($offset)) {
$this->container->setParameter($offset, null);
} else if ($this->container->has($offset)) {
$this->container->set($offset, null);
}
}
/**
* @inheritDoc
*/
public function offsetUnset($offset): void
{
if ($this->container->hasParameter($offset)) {
$this->container->setParameter($offset, null);
} elseif ($this->container->has($offset)) {
$this->container->set($offset, null);
}
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2023 Combodo SARL
*
@@ -35,7 +36,7 @@ use Twig\TwigFunction;
class CKEditorExtension extends AbstractExtension
{
/** @inheritdoc */
public function getFunctions() : array
public function getFunctions(): array
{
return [
new TwigFunction('inject_ckeditor_resources', [$this, 'injectCKEditorResources']),
@@ -48,17 +49,17 @@ class CKEditorExtension extends AbstractExtension
* @return string
* @throws \Exception
*/
public function injectCKEditorResources() : string
public function injectCKEditorResources(): string
{
$sScriptTemplate = '';
$aJSFilesRelPaths = CKEditorHelper::GetJSFilesRelPathsForCKEditor();
foreach ($aJSFilesRelPaths as $sJSFileRelPath){
$sUrl = \utils::GetAbsoluteUrlAppRoot() . $sJSFileRelPath;
foreach ($aJSFilesRelPaths as $sJSFileRelPath) {
$sUrl = \utils::GetAbsoluteUrlAppRoot().$sJSFileRelPath;
$sUrl = \utils::AddParameterToUrl($sUrl, 't', \utils::GetCacheBusterTimestamp());
$sScriptTemplate .= '<script type="text/javascript" src="' . $sUrl . '"></script>';
$sScriptTemplate .= '<script type="text/javascript" src="'.$sUrl.'"></script>';
}
return $sScriptTemplate;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -70,4 +71,4 @@ class CurrentUserAccessor
{
return $this->userProvider->getCurrentUserCanLogOff();
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -34,7 +35,7 @@ class PortalBlockExtension
*
* @since iTop 3.2.1
*/
function __construct(string $sTwig, array $aData = [])
public function __construct(string $sTwig, array $aData = [])
{
$this->sTwig = $sTwig;
$this->aData = $aData;

View File

@@ -1,4 +1,5 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -16,7 +17,6 @@ namespace Combodo\iTop\Portal\Twig;
*/
class PortalTwigContext
{
private array $aBlockExtension;
public function __construct()
@@ -35,7 +35,7 @@ class PortalTwigContext
*
* @since iTop 3.2.1
*/
function AddBlockExtension(string $sBlockName, PortalBlockExtension $oBlockExtension): void
public function AddBlockExtension(string $sBlockName, PortalBlockExtension $oBlockExtension): void
{
$this->aBlockExtension[$sBlockName] = $oBlockExtension;
}
@@ -58,4 +58,4 @@ class PortalTwigContext
$oBlockExtension = $this->aBlockExtension[$sBlockName] ?? null;
return $oBlockExtension;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2023 Combodo SARL
*
@@ -31,7 +32,7 @@ use Twig\TwigFunction;
*/
class TemplatesTwigExtension extends AbstractExtension
{
const DEFAULT_PROVIDER_CLASS = 'Combodo\\iTop\\Portal\\Controller\\AbstractController';
public const DEFAULT_PROVIDER_CLASS = 'Combodo\\iTop\\Portal\\Controller\\AbstractController';
public function __construct(private readonly TemplatesProviderService $oTemplatesService)
{
@@ -78,4 +79,4 @@ class TemplatesTwigExtension extends AbstractExtension
{
return $this->oTemplatesService->GetTemplatePath($sProviderClass, $sId, true);
}
}
}

View File

@@ -37,10 +37,10 @@ use utils;
abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
{
/** @var string PORTAL_ID */
const PORTAL_ID = '';
public const PORTAL_ID = '';
/** @var \Combodo\iTop\Portal\Kernel[] $aKernels */
private static $aKernels = array();
private static $aKernels = [];
/**
* Generate an (absolute) URL to an object, either in view or edit mode.
@@ -64,8 +64,7 @@ abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
$sUrl = self::DoPrepareObjectURL($sClass, $iId, $sMode);
if (!empty($sPreviousPortalId))
{
if (!empty($sPreviousPortalId)) {
$_ENV['PORTAL_ID'] = $sPreviousPortalId;
}
@@ -97,48 +96,39 @@ abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
//
// Note: Scopes only apply when URL check is triggered from the portal GUI.
$sObjectQueryString = null;
switch ($sMode)
{
switch ($sMode) {
case 'view':
if (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $iId))
{
$sObjectQueryString = $oUrlGenerator->generate('p_object_view', array('sObjectClass' => $sClass, 'sObjectId' => $iId));
if (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $iId)) {
$sObjectQueryString = $oUrlGenerator->generate('p_object_view', ['sObjectClass' => $sClass, 'sObjectId' => $iId]);
}
break;
case 'edit':
default:
// Checking if user is allowed to edit object, if not we check if it can at least view it.
if (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY, $sClass, $iId))
{
$sObjectQueryString = $oUrlGenerator->generate('p_object_edit', array('sObjectClass' => $sClass, 'sObjectId' => $iId));
}
elseif (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $iId))
{
$sObjectQueryString = $oUrlGenerator->generate('p_object_view', array('sObjectClass' => $sClass, 'sObjectId' => $iId));
if (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY, $sClass, $iId)) {
$sObjectQueryString = $oUrlGenerator->generate('p_object_edit', ['sObjectClass' => $sClass, 'sObjectId' => $iId]);
} elseif (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $iId)) {
$sObjectQueryString = $oUrlGenerator->generate('p_object_view', ['sObjectClass' => $sClass, 'sObjectId' => $iId]);
}
break;
}
$sPortalAbsoluteUrl = utils::GetAbsoluteUrlModulePage('itop-portal-base', 'index.php', array('portal_id' => $sPortalId));
if ($sObjectQueryString === null)
{
$sPortalAbsoluteUrl = utils::GetAbsoluteUrlModulePage('itop-portal-base', 'index.php', ['portal_id' => $sPortalId]);
if ($sObjectQueryString === null) {
$sUrl = null;
}
elseif (strpos($sPortalAbsoluteUrl, '?') !== false)
{
} elseif (strpos($sPortalAbsoluteUrl, '?') !== false) {
// Removing generated url query parameters so it can be replaced with those from the absolute url
// Mostly necessary when iTop instance has multiple portals
if (strpos($sObjectQueryString, '?') !== false)
{
if (strpos($sObjectQueryString, '?') !== false) {
$sObjectQueryString = substr($sObjectQueryString, 0, strpos($sObjectQueryString, '?'));
}
$sUrl = substr($sPortalAbsoluteUrl, 0, strpos($sPortalAbsoluteUrl, '?')).$sObjectQueryString.substr($sPortalAbsoluteUrl,
strpos($sPortalAbsoluteUrl, '?'));
}
else
{
$sUrl = substr($sPortalAbsoluteUrl, 0, strpos($sPortalAbsoluteUrl, '?')).$sObjectQueryString.substr(
$sPortalAbsoluteUrl,
strpos($sPortalAbsoluteUrl, '?')
);
} else {
$sUrl = $sPortalAbsoluteUrl.$sObjectQueryString;
}
@@ -153,8 +143,7 @@ abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
*/
private static function GetKernelInstance()
{
if (!array_key_exists(static::PORTAL_ID, self::$aKernels))
{
if (!array_key_exists(static::PORTAL_ID, self::$aKernels)) {
self::$aKernels[static::PORTAL_ID] = new Kernel($_SERVER['APP_ENV'], (bool)$_SERVER['APP_DEBUG']);
self::$aKernels[static::PORTAL_ID]->boot();
}
@@ -175,4 +164,3 @@ abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
return static::PrepareObjectURL($sClass, $iId, 'edit');
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -34,4 +35,4 @@ abstract class AbstractStringVariableAccessor extends AbstractVariableAccessor
{
return $this->getVariable();
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -27,22 +28,22 @@ namespace Combodo\iTop\Portal\VariableAccessor;
*/
abstract class AbstractVariableAccessor
{
/** @var string $storedVariable */
private $storedVariable;
/** @var string $storedVariable */
private $storedVariable;
/**
* @param string $variableToStore
*/
public function __construct($variableToStore)
{
$this->storedVariable = $variableToStore;
}
/**
* @param string $variableToStore
*/
public function __construct($variableToStore)
{
$this->storedVariable = $variableToStore;
}
/**
* @return string
*/
public function getVariable()
{
return $this->storedVariable;
}
}
public function getVariable()
{
return $this->storedVariable;
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -19,7 +20,6 @@
namespace Combodo\iTop\Portal\VariableAccessor;
use Combodo\iTop\Portal\EventListener\UserProvider;
use Exception;
use MetaModel;
@@ -85,8 +85,7 @@ class CombodoCurrentContactPhotoUrl
try {
/** @var \cmdbAbstractObject $oContact */
$oContact = UserRights::GetContactObject();
}
catch (Exception $e) {
} catch (Exception $e) {
$oUser = $this->oUserProvider->getCurrentUser();
$oAllowedOrgSet = $oUser->Get('allowed_org_list');
if ($oAllowedOrgSet->Count() > 0) {
@@ -118,4 +117,4 @@ class CombodoCurrentContactPhotoUrl
return $sContactPhotoUrl;
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* Copyright (C) 2013-2024 Combodo SAS
*
@@ -28,5 +29,4 @@ namespace Combodo\iTop\Portal\VariableAccessor;
*/
class CombodoPortalInstanceConf extends AbstractVariableAccessor
{
}
}