Compare commits

...

84 Commits

Author SHA1 Message Date
Guillaume Lajarige
5b9bca0922 Creating (omitted) SVN tag for iTop 2.4.0
SVN:2.4.0[5354]
2018-02-21 16:40:14 +00:00
Denis Flaven
21d44c664f (Regression - retrofit from trunk) Fix display trouble for auto_reload menus. This was caused by a collision of HTML/DOM ids where the menu item of the left (accordion) menu had the same id as the div displaying the actual content in the right pane. This caused (when the id was a valid one !) the refresh of the content (list of objects) to occur INSIDE the accordion menu !
SVN:2.4[5122]
2017-10-31 10:46:09 +00:00
Guillaume Lajarige
b318cbe211 (Retrofit from trunk) N°634.3 Portal: Argh!! Secondary actions menu in BrowseBrick was broken due to previous CSS "fixes"...
SVN:2.4[5120]
2017-10-30 16:05:26 +00:00
Romain Quetiez
7106501812 (Retrofit from trunk) Ready for releasing...
SVN:2.4[5118]
2017-10-30 14:27:56 +00:00
Eric Espié
567dd39270 Retrofit from trunk
2.4.0 - New readme format. [from revision 5115]

SVN:2.4[5116]
2017-10-30 14:16:11 +00:00
Eric Espié
b292621f82 Retrofit from trunk
Core russian translation kindly provided by Vladimir Kunin. [from revision 5113]

SVN:2.4[5114]
2017-10-30 11:38:21 +00:00
Guillaume Lajarige
46f0b48add (Retrofit from trunk on behalf of sabello) added german translation for obsolescence. Thanks to ITOMIG.
SVN:2.4[5110]
2017-10-27 14:34:04 +00:00
Denis Flaven
9a5f16bd3e (retrofit from trunk) Simplification of the obsolescence condition (N°890) to avoid reaching the limit of 61 tables (N°1049)
SVN:2.4[5108]
2017-10-27 13:11:55 +00:00
Guillaume Lajarige
6224ec7a37 (Retrofit from trunk) Internal: Updated modules version to 2.4.0 (as well as some copyright dates)
SVN:2.4[5106]
2017-10-27 08:58:20 +00:00
Pierre Goiffon
c460edcd5e (Retrofit from trunk) r5093 Change version number for static resources calls
SVN:2.4[5101]
2017-10-27 07:55:07 +00:00
Pierre Goiffon
b839b42cd4 (Retrofit from trunk) r5091 Change modules XML version to the latest (1.4)
SVN:2.4[5100]
2017-10-27 07:54:58 +00:00
Pierre Goiffon
fabc8b91d7 (Retrofit from trunk) r5090 Change version number in CSS url() calls
SVN:2.4[5099]
2017-10-27 07:54:37 +00:00
Guillaume Lajarige
4c38cd570c (Retrofit from trunk) N°1138 Portal: Scrollbar appeared sometimes in navigation menu when on the last brick.
SVN:2.4[5098]
2017-10-26 17:41:28 +00:00
Guillaume Lajarige
c4fd15ae90 (Retrofit from trunk) N°930.2 Console UI: Better object details layout step 2.
SVN:2.4[5096]
2017-10-26 17:07:44 +00:00
Eric Espié
bbca491118 Retrofit from trunk
Fix utils::GetCurrentModuleUrl() bug introduced in revision 4920 [from revision 5085]

SVN:2.4[5086]
2017-10-25 16:01:16 +00:00
Guillaume Lajarige
0d04bd8b0e (Retrofit from trunk) Translations: Added icon attribute for ServiceFamily and Service classes. English and French done, feel free to contribute for others ! :)
SVN:2.4[5084]
2017-10-24 15:23:02 +00:00
Guillaume Lajarige
3bcb3a2154 (Retrofit from trunk) Internal: Updated sample data for Person, ServiceFamily and Service (use of AttributeImage)
SVN:2.4[5083]
2017-10-24 15:21:49 +00:00
Guillaume Lajarige
aa863c40d3 (Retrofit from trunk) N°634.2 Portal: CSS fixes on mosaic mode of BrowseBrick
SVN:2.4[5082]
2017-10-24 15:19:39 +00:00
Guillaume Lajarige
5d7ad9f6dd (Retrofit from trunk) Internal: Updated module version (itop-portal, itop-portal-base)
SVN:2.4[5081]
2017-10-24 15:18:05 +00:00
Eric Espié
72cb41dd7e Retrofit from trunk
N°1134 - Bad version number when MTP
* The order of the installed versions is changed when doing MTP. [from revision 5073]

SVN:2.4[5075]
2017-10-24 08:20:36 +00:00
Eric Espié
6ef39c9f5b Retrofit from trunk
N°1131 - Setup: Can't add options to ITIL Ticketing in update mode
* Fix the alternative selection when updating the setup
* Uncheck options when the alternatives are deselected [from revision 5067]

SVN:2.4[5068]
2017-10-23 11:40:46 +00:00
Eric Espié
614b948c82 Retrofit from trunk
N°1109 - itop-object-copier Create ticket from CI was not adding the CI in the CI list of the newly created ticket.
* Fix 'add_to_list' command.
* Fix Adding a n-n link at the creation time.

SVN:2.4[5064]
2017-10-20 14:16:54 +00:00
Eric Espié
7c0715ad59 Retrofit from trunk
N°1109 - itop-object-copier Create ticket from CI was not adding the CI in the CI list of the newly created ticket.
* Fix 'add_to_list' command.
* Fix Adding a n-n link at the creation time.

SVN:2.4[5063]
2017-10-20 14:13:12 +00:00
Guillaume Lajarige
31819497ae (Retrofit from trunk) N°1123.4 AttributeImage: Better UI when editing in console. Also, export was showing url for empty value.
SVN:2.4[5062]
2017-10-20 13:28:02 +00:00
Guillaume Lajarige
c86e2c6c79 (Retrofit from trunk) N°642.3 Portal: Lifecycle: Exception on UserRequest opening due to a bad variable initialization.
SVN:2.4[5059]
2017-10-20 12:43:21 +00:00
Eric Espié
1d54b66de9 Retrofit from trunk
N°1131 - Setup: Can't add options to ITIL Ticketing in update mode
* Fix the disable attribute of the options [from revision 5057]

SVN:2.4[5058]
2017-10-20 12:08:00 +00:00
Romain Quetiez
f932765e19 (Retrofit from trunk) N.1100 Regression introduced in [r4943], aka 2.4 RC3, and causing error during MTP (accessing the wrong expression cache)
SVN:2.4[5055]
2017-10-19 19:10:25 +00:00
Pierre Goiffon
11b4085566 (Retrofit from trunk) r5051 N.689 workaround on MySQL number of joins limit (61)
* change MySQLException to store initial exception code
* added a try/catch to launch query with full lazy load (no attr => only id)
* load finalClass field if needed (class is nor standalone nor a final leaf)

SVN:2.4[5052]
2017-10-19 13:58:39 +00:00
Guillaume Lajarige
12afcd7cce (Retrofit from trunk) N°1094 & N°1107 Portal: Mosaic mode in BrowseBrick displays icon nicely in IE9. Also, "name" on tiles doesn't break layout anymore when too long.
SVN:2.4[5049]
2017-10-19 13:02:24 +00:00
Guillaume Lajarige
666c95a656 (Retrofit from trunk) N°1071 UI: Better rendering for external keys in linkedset (no more wrapping)
SVN:2.4[5048]
2017-10-19 13:01:28 +00:00
Guillaume Lajarige
fde9c28263 (Retrofit from trunk) N°1129.1 Support of $this->hyperlink(itop-portal)$ in notifications (only "portal" was implemented for the default portal).
SVN:2.4[5047]
2017-10-19 13:00:36 +00:00
Guillaume Lajarige
52c3ff0406 (Retrofit from trunk) N°1094
- Adding "icon" attribute to ServiceFamily and Service classes
- Show icon on ServiceFamily and Service levels in BrowseBrick


SVN:2.4[5043]
2017-10-18 15:00:50 +00:00
Guillaume Lajarige
9f4d07aaa5 (Retrofit from trunk) N°1123.2 AttributeImage: default_image is no longer mandatory.
SVN:2.4[5041]
2017-10-18 14:53:36 +00:00
Guillaume Lajarige
70561d6331 (Retrofit from trunk) N°1123 AttributeImage: PHP notice when displaying an object without default_image on a AttributeImage attribute.
SVN:2.4[5039]
2017-10-18 14:44:19 +00:00
Eric Espié
ae8311e224 Retrofit from trunk
N.1065 Fix performance issues.
* Added the bGetCount flag into the cache to differentiate the cache entries for COUNT only. [from revision 5034]

SVN:2.4[5035]
2017-10-18 12:58:32 +00:00
Guillaume Lajarige
e09fa0ffc1 (Retrofit from trunk) N°911.2 Portal: Updated typeahead repository url in files headers.
SVN:2.4[5033]
2017-10-18 12:26:29 +00:00
Guillaume Lajarige
5b6a20048f (Retrofit from trunk) N°1122 Portal: Clean-up of 2 redundants JS files regarding the autocomplete inputs in forms.
SVN:2.4[5032]
2017-10-18 12:25:00 +00:00
Romain Quetiez
d86c211b73 (Retrofit from trunk) N.1108 return exception if $bMustBeFound and result is archived
SVN:2.4[5027]
2017-10-17 09:04:26 +00:00
Romain Quetiez
8499babcb3 (Retrofit from trunk) N°1092.1 Setup / MTP improvements regarding the environments folders:
- /env-production-build rights check before running setup
- /env-xxx-build is no longer deleted after MTT / MTP from the ITSM Designer. This prevents permissions issue when webserver user doesn't have suffisant rights on the root folder.


SVN:2.4[5026]
2017-10-17 08:02:30 +00:00
Romain Quetiez
2d44cbbb60 (Retrofit from trunk) Fixed dictionary typos (Chemin d'installation, En attente d'approbation)
SVN:2.4[5024]
2017-10-16 07:42:28 +00:00
Eric Espié
3d89ef9076 Merged from trunk
N.1065 Fix performance issues.
* Does not cache requests containing "id IN ..." and "id NOT IN ..." (too specific) [from revisions 5012, 5019]

SVN:2.4[5020]
2017-10-12 15:33:23 +00:00
Eric Espié
e896f8af3d (Retrofit from trunk)
N°1110 - DataSynchro: PHP Notice Undefined Index
* Fix access to REQUEST_URI when called by script [from revisions 5007, 5017]

SVN:2.4[5018]
2017-10-12 13:57:31 +00:00
Eric Espié
23268e8969 (Retrofit from trunk) Message when no data are available [from revision 5011]
SVN:2.4[5016]
2017-10-12 13:49:06 +00:00
Eric Espié
421e12debd (Retrofit from trunk)
N°870: Bulk operation and obsolescence flag
* Avoid the hidden selection (and update) of obsolete data when the user does not want to see the obsolete data. [from revision 4997]

SVN:2.4[5014]
2017-10-12 13:13:22 +00:00
Eric Espié
389848cef4 (Retrofit from trunk)
N.1065 Fix performance issues.
Cache display CSV format fix. [from revision 4996]

SVN:2.4[5013]
2017-10-12 13:10:50 +00:00
Guillaume Lajarige
7da4423346 (Retrofit from trunk) N°642.2 Portal: Lifecycle transitions security is now a blacklist instead of a white list. Making migration transparent and portal configuration easier.
SVN:2.4[5010]
2017-10-12 08:55:01 +00:00
Guillaume Lajarige
2a770b9dc4 (Retrofit from trunk) N°1107.1 Portal: Fixed image display in mosaic mode of BrowseBrick for Chrome and Firefox. IE still pending !
SVN:2.4[5009]
2017-10-12 08:54:10 +00:00
Pierre Goiffon
8df12e64f2 (Retrofit from trunk) r4492 N.1065 Fix performance issues.
Add statistics on query table join optimization.

SVN:2.4[4995]
2017-10-06 14:25:49 +00:00
Romain Quetiez
341261c14e (Retrofit from trunk) Fixed integration issue (possibly a regression): if an extension implements iApplicationExtension::OnDBInsert, and it calls DBWrite, then a fatal error occurs (call a member function on a null value). The error occurs for several types of attributes such as ormCustomField, ormCaseLog, ormLinkSet. The fix consists in aligning the internal values of a DBObject as soon as it has been written into the Database.
SVN:2.4[4994]
2017-10-06 14:07:33 +00:00
Guillaume Lajarige
bfc7c73e18 (Retrofit from trunk) Standard DataModel: Add org_id and location_id to 'Rack' reconciliation keys. Mandatory for CSV import of CI on a Rack, when Rack name is not a unique identifier.
SVN:2.4[4990]
2017-10-06 08:09:31 +00:00
Guillaume Lajarige
9a6c4ba7bb (Retrofit from trunk on behalf of cisou) FR dictionnary typo for obsolescence
SVN:2.4[4989]
2017-10-06 08:06:23 +00:00
Pierre Goiffon
dc47c34981 (Retrofit from trunk) r4983 N.1065 When joining, reverse leaf-root order : now it's root first !
* decrease the amount of joins on obsolescence use cases
* should also improve other uses cases as most of the time we believe the attribute linked is in the root class !
* the root table join is done using expressions instead of OQL for perf reasons
* a where clause on finalclass is also added to avoid problems if the leaf table join is not used (would be removed during query optimization phase)

SVN:2.4[4988]
2017-10-05 16:03:08 +00:00
Eric Espié
3ac5131a19 (Retrofit from trunk) r4969
N°1098 Fix CSV import by id. Fix a regression introduced in rev 4885.
---------------------
r4968
N°1100 - External field pointing to a magic attribute * A specific pass has been added in MetaModel::InitClasses() to generate the magic attributes before the external fields.
---------------------

SVN:2.4[4987]
2017-10-05 16:00:49 +00:00
Eric Espié
134a9aa684 (Retrofir from trunk) N.1065 Fix performance issues (unexpected objects reload).
* Fix regression in 2.4 into attribute optimization (archive_flag, obsolescence_flag).
* Fix attribute optimization (friendlyname for ExternalField pointing to ExternalKey)

SVN:2.4[4986]
2017-10-05 15:59:21 +00:00
Eric Espié
a98c0d32ae (Retrofit from trunk)
r4961
N°1065 Fixed a regression introduced in r4965.


SVN:2.4[4985]
2017-10-05 15:57:16 +00:00
Eric Espié
38af2b85c4 (Retrofit from trunk)
r4961
N°1065 Fixed a regression introduced in r4965.
---------------------
r4960
N.1065 Fix performance issues. Limit APC emulation cache entries to avoid disk saturation. New configuration entry added: 'apc_cache_emulation.max_entries'.
---------------------
r4956
N.1065 Fix performance issues. ormLinkSet creates the objects on demand.
---------------------
r4954
APC emulation using files when APC or APCu is not installed.

SVN:2.4[4984]
2017-10-05 15:55:15 +00:00
Guillaume Lajarige
c9c84735c4 (Retrofit from trunk) N°1025 Portal: Fixed regression introduced in r4863.
SVN:2.4[4982]
2017-10-05 15:52:12 +00:00
Guillaume Lajarige
646972838a (retrofit from trunk) N°1034 New EventOnObject class to store explaination on object's updates
SVN:2.4[4981]
2017-10-05 15:50:34 +00:00
Guillaume Lajarige
ce92241593 (Retrofit from trunk) N°653.2 Lifecycle: Fixed a regression introduced on r4767, transition buttons not working properly when editing an object.
SVN:2.4[4980]
2017-10-05 15:49:36 +00:00
Guillaume Lajarige
715eeff627 (Retrofit from trunk) N°1082 Fixed a regression introduced with ormLinkSet rework: Modified links not updated.
SVN:2.4[4979]
2017-10-05 15:48:13 +00:00
Romain Quetiez
651de821df (Retrofit from trunk) N.1065 and #372 Query build cache not efficient with global search (each search generates about 80 new entries in the APCu cache)
SVN:2.4[4978]
2017-10-05 15:46:53 +00:00
Guillaume Lajarige
2233ea5f54 (Retrofit from trunk) N°1067 Rework on ormLinkSet BC with DBObjectSet.
- PHP notice are not thrown anymore, see PHPDoc instead.
- GetColumnAsArray() introduced.

SVN:2.4[4977]
2017-10-05 15:46:21 +00:00
Eric Espié
39e6915e05 r4945
(Retrofit from trunk) Fix regression introduced in trunk[4943]
---------------------
r4944
Code cleanup.
---------------------
r4943
N.1065 Fix performance issues (caches added on query build)

SVN:2.4[4976]
2017-10-05 15:45:35 +00:00
Guillaume Lajarige
6279f4ac70 (Retrofit from trunk) Internal: Typo in PHPDoc
SVN:2.4[4975]
2017-10-05 15:45:01 +00:00
Guillaume Lajarige
badf10e74e (Retrofit from trunk) N°1073 Reentrance issue on cmdbAbstractObject when coming from an extension implementing iApplicationObjectExtension.
SVN:2.4[4974]
2017-10-05 15:43:50 +00:00
Guillaume Lajarige
2e9cd6a342 (Retrofit from trunk) Internal: Changed way AttributeLinkedSet check if two ormLinkSet are equal.
SVN:2.4[4973]
2017-10-05 15:42:51 +00:00
Guillaume Lajarige
cef70ee9a2 (Retrofit from trunk) Internal: Typo in itop-tickets XML comments
SVN:2.4[4972]
2017-10-05 15:41:52 +00:00
Eric Espié
37e15706b2 (Retrofit from trunk) Fix utils::GetCurrentModuleUrl() introduced in revision 4844
SVN:2.4[4970]
2017-10-05 15:34:09 +00:00
Denis Flaven
4b210273d2 (retrofit from trunk) N°1806, N°1069: CSV and Excel export and import of documents (files) and images as URLs.
SVN:2.4[4953]
2017-09-30 09:24:29 +00:00
Romain Quetiez
951e8e03b0 (Retrofit from trunk] N.1072 Localization for magic attributes archive_date (completed the existing implementation) and obsolescence_date (full implementation)
SVN:2.4[4947]
2017-09-27 12:38:01 +00:00
Denis Flaven
c016ca364d Internal: Make sure that UI dialogs are never bigger than the browser's window (not used in iTop though).
SVN:2.4[4941]
2017-09-26 10:00:24 +00:00
Romain Quetiez
4611442665 (Retrofit from trunk) N.707 Export of custom fields: improved the xlsx format and implemented the spreadsheet format (both are aligned)
SVN:2.4[4936]
2017-09-22 13:52:25 +00:00
Denis Flaven
c7e7976607 Added the open source logo as a character (uppercase letter O) to the font.
Increased the version number in the CSS to prevent caching/refresh issues.

SVN:2.4[4931]
2017-09-21 14:29:25 +00:00
Romain Quetiez
0ca9fac04b (Retrofit from trunk) N°813 Enable bulk deletion of Data Synchro Replica
SVN:2.4[4928]
2017-09-21 10:13:02 +00:00
Romain Quetiez
7edc79f398 (Retrofit from trunk) Code robustness: Though the commit [4922] solves the issue N.1052, it is safer to reset the cache as part of the "Commit" performed during the installation process.
SVN:2.4[4925]
2017-09-20 14:53:41 +00:00
Romain Quetiez
c110206264 (Retrofit from trunk) N.1052 After a setup or MTP, the datamodel is not taken into account... until the web server gets restarted or the APC cache (user data) gets reset.
SVN:2.4[4924]
2017-09-20 14:48:07 +00:00
Guillaume Lajarige
b3ad2030cb (Retrofit from trunk) N°1006.2 Templates: $this->raw(attcode)$ can be used to display an date(time) attribute in the SQL format like before.
SVN:2.4[4919]
2017-09-18 15:56:08 +00:00
Guillaume Lajarige
0938ba939c (Retrofit from trunk) N°1006 Templates: Date & time format is now applied when using a date(time) attribute in a placeholder (eg. Notifications)
SVN:2.4[4918]
2017-09-18 15:55:02 +00:00
Guillaume Lajarige
bca393def3 (Retrofit from trunk) N°1019 Portal: OpenSans font embedded in iTop instead of fetching from google servers.
SVN:2.4[4917]
2017-09-18 15:53:31 +00:00
Guillaume Lajarige
796ac55ff4 (Retrofit from trunk) N°762 Portal: Pre-filtering a browse brick in tree mode was making tree collapsing instead of showing results.
SVN:2.4[4916]
2017-09-18 15:43:19 +00:00
Guillaume Lajarige
66ae89e91d (Retrofit from trunk) N°1038 Fatal error on transition with AttributeBlob or AttributeCaseLog
SVN:2.4[4908]
2017-09-13 16:09:02 +00:00
Denis Flaven
361cca465a (retrofit from trunk) Added E and F glyphs.
SVN:2.4[4906]
2017-09-13 08:55:24 +00:00
Denis Flaven
7462d66643 Combodo font enhancements.
SVN:2.4[4904]
2017-09-12 14:49:46 +00:00
Guillaume Lajarige
a177b9b1d4 iTop 2.4: Code freeze
SVN:2.4[4902]
2017-09-08 14:25:46 +00:00
183 changed files with 5413 additions and 3672 deletions

View File

@@ -409,26 +409,8 @@ EOF
$sLinkedClass = $oAttDef->GetLinkedClass();
// Filter out links pointing to obsolete objects (if relevant)
$oLinkSearch = $this->Get($sAttCode)->GetFilter();
if ($oAttDef->IsIndirect())
{
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
$oLinkingAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sExtKeyToRemote);
$sTargetClass = $oLinkingAttDef->GetTargetClass();
if (!utils::ShowObsoleteData() && MetaModel::IsObsoletable($sTargetClass))
{
$oNotObsolete = new BinaryExpression(
new FieldExpression('obsolescence_flag', $sTargetClass),
'=',
new ScalarExpression(0)
);
$oNotObsoleteRemote = new DBObjectSearch($sTargetClass);
$oNotObsoleteRemote->AddConditionExpression($oNotObsolete);
$oLinkSearch->AddCondition_PointingTo($oNotObsoleteRemote, $sExtKeyToRemote);
}
}
$oLinkSet = new DBObjectSet($oLinkSearch);
$oLinkSet->SetShowObsoleteData(utils::ShowObsoleteData());
$oOrmLinkSet = $this->Get($sAttCode);
$oLinkSet = $oOrmLinkSet->ToDBObjectSet(utils::ShowObsoleteData());
$iCount = $oLinkSet->Count();
$sCount = '';
@@ -643,17 +625,22 @@ EOF
{
$aDetails[$sTab] = array();
$aTableStyles[] = 'vertical-align:top';
$aTableClasses = array();
ksort($aCols);
$iColCount = count($aCols);
if($iColCount > 1)
{
$aTableStyles[] = 'width: 100%';
$aTableClasses[] = 'n-cols-details';
$aTableClasses[] = $iColCount.'-cols-details';
}
else
{
$aTableClasses[] = 'one-col-details';
}
// Else, will size regarding the largest field of the column
$oPage->SetCurrentTab(Dict::S($sTab));
$oPage->add('<table style="'.implode('; ', $aTableStyles).'" data-mode="'.$sEditMode.'"><tr>');
$oPage->add('<table style="'.implode('; ', $aTableStyles).'" class="'.implode(' ', $aTableClasses).'" data-mode="'.$sEditMode.'"><tr>');
foreach($aCols as $sColIndex => $aFieldsets)
{
$oPage->add('<td style="vertical-align:top">');
@@ -2346,7 +2333,7 @@ EOF
{
$sSelected = ' selected';
}
$sStatesSelection .= '<option value="'.$sStateCode.'"'.$sSelected.'>'.MetaModel::GetStateLabel($sClass, $sStateCode).'</option>';
$sStatesSelection .= '<option value="'.$sStateCode.'" '.$sSelected.'>'.MetaModel::GetStateLabel($sClass, $sStateCode).'</option>';
}
$sStatesSelection .= '</select>';
$oPage->add_ready_script("$('.state_select_{$this->m_iFormId}').change( function() { oWizardHelper$sPrefix.ReloadObjectCreationForm('form_{$this->m_iFormId}', $(this).val()); } );");
@@ -3536,14 +3523,34 @@ EOF
public function DBUpdate()
{
$res = parent::DBUpdate();
$res = parent::DBUpdate();
// Invoke extensions after the update (could be before)
foreach (MetaModel::EnumPlugins('iApplicationObjectExtension') as $oExtensionInstance)
{
$oExtensionInstance->OnDBUpdate($this, self::GetCurrentChange());
}
return $res;
// Protection against reentrance (e.g. cascading the update of ticket logs)
// Note: This is based on the fix made on r 3190 in DBObject::DBUpdate()
static $aUpdateReentrance = array();
$sKey = get_class($this).'::'.$this->GetKey();
if(array_key_exists($sKey, $aUpdateReentrance))
{
return $res;
}
$aUpdateReentrance[$sKey] = true;
try
{
// Invoke extensions after the update (could be before)
foreach (MetaModel::EnumPlugins('iApplicationObjectExtension') as $oExtensionInstance)
{
$oExtensionInstance->OnDBUpdate($this, self::GetCurrentChange());
}
}
catch(Exception $e)
{
unset($aUpdateReentrance[$sKey]);
throw $e;
}
unset($aUpdateReentrance[$sKey]);
return $res;
}
protected static function BulkUpdateTracked_Internal(DBSearch $oFilter, array $aValues)
@@ -3744,7 +3751,15 @@ EOF
$oPage->add('</fieldset>');
}
}
/**
* @param $sCurrentState
* @param $sStimulus
* @param $bOnlyNewOnes
* @return array
* @throws ApplicationException
* @deprecated Since iTop 2.4, use DBObject::GetTransitionAttributes() instead.
*/
public function GetExpectedAttributes($sCurrentState, $sStimulus, $bOnlyNewOnes)
{
$aTransitions = $this->EnumTransitions();

View File

@@ -360,6 +360,7 @@ EOF
<<<EOF
$('#$sDialogId').dialog({
height: 'auto',
maxHeight: $(window).height() - 8,
width: $iDialogWidth,
modal: true,
autoOpen: $sAutoOpen,

View File

@@ -331,31 +331,6 @@ EOF
// This selector will be reused when selecting actual tab widget A elements.
var tab_a_selector = 'ul.ui-tabs-nav a';
// This helper will be used to resize tab width
var resizeTab = function(oElem){
var iTableWidth = (oElem.children('table:first').length > 0) ? oElem.children('table:first').outerWidth() : 0;
var oLayoutContentElem = oElem.closest('.ui-layout-content');
var bEditMode = (oLayoutContentElem.find('.wizContainer').length > 0);
var oContainerElem = (bEditMode) ? oLayoutContentElem.find('.wizContainer:first') : oLayoutContentElem.find('.ui-tabs:first');
// Resizing wizard container
oContainerElem.css('min-width',
parseInt(iTableWidth) +
parseInt(oElem.css('margin-left'))*2 +
parseInt(oElem.css('padding-left'))*2 +
parseInt(tabs.css('margin-left'))*2 +
parseInt(tabs.css('padding-left'))*2
)
// Resizing header according to content container
var iLayoutContentWidth = parseInt(oContainerElem.width());
if(bEditMode)
{
iLayoutContentWidth += parseInt(oContainerElem.css('margin-left'))*2 + parseInt(oContainerElem.css('padding-left'))*2
}
oLayoutContentElem.find('.page_header').css('min-width', iLayoutContentWidth);
};
// Ugly patch for a change in the behavior of jQuery UI:
// Before jQuery UI 1.9, tabs were always considered as "local" (opposed to Ajax)
// when their href was beginning by #. Starting with 1.9, a <base> tag in the page
@@ -379,9 +354,6 @@ EOF
event: 'change', 'show': function(event, ui) {
$('.resizable', ui.panel).resizable(); // Make resizable everything that claims to be resizable !
},
create: function( event, ui ) {
resizeTab(ui.panel);
},
beforeLoad: function( event, ui ) {
if ( ui.tab.data('loaded') && (ui.tab.attr('data-cache') == 'true')) {
event.preventDefault();
@@ -391,9 +363,6 @@ EOF
ui.jqXHR.success(function() {
ui.tab.data( "loaded", true );
});
},
activate: function( event, ui ) {
resizeTab(ui.newPanel);
}
});

View File

@@ -174,7 +174,7 @@ class ApplicationMenu
{
$oMenuNode = self::GetMenuNode($aMenu['index']);
if (!$oMenuNode->IsEnabled()) continue; // Don't display a non-enabled menu
$oPage->AddToMenu('<h3 id="Menu_'.$oMenuNode->GetMenuID().'">'.$oMenuNode->GetTitle().'</h3>');
$oPage->AddToMenu('<h3 id="'.utils::GetSafeId('AccordionMenu_'.$oMenuNode->GetMenuID()).'">'.$oMenuNode->GetTitle().'</h3>');
$oPage->AddToMenu('<div>');
$aChildren = self::GetChildren($aMenu['index']);
if (count($aChildren) > 0)
@@ -217,11 +217,11 @@ EOF
$sHyperlink = $oMenu->GetHyperlink($aExtraParams);
if ($sHyperlink != '')
{
$oPage->AddToMenu('<li id="Menu_'.$oMenu->GetMenuID().'"'.$sCSSClass.'><a href="'.$oMenu->GetHyperlink($aExtraParams).'">'.$oMenu->GetTitle().'</a></li>');
$oPage->AddToMenu('<li id="'.utils::GetSafeId('AccordionMenu_'.$oMenu->GetMenuID()).'"'.$sCSSClass.'><a href="'.$oMenu->GetHyperlink($aExtraParams).'">'.$oMenu->GetTitle().'</a></li>');
}
else
{
$oPage->AddToMenu('<li id="Menu_'.$oMenu->GetMenuID().'"'.$sCSSClass.'>'.$oMenu->GetTitle().'</li>');
$oPage->AddToMenu('<li id="'.utils::GetSafeId('AccordionMenu_'.$oMenu->GetMenuID()).'"'.$sCSSClass.'>'.$oMenu->GetTitle().'</li>');
}
$aCurrentMenu = self::$aMenusIndex[$index];
if ($iActiveMenu == $index)

View File

@@ -138,7 +138,9 @@ class UILinksWidget
$sValue = $linkObjOrId->Get($sFieldCode);
$sDisplayValue = $linkObjOrId->GetEditValue($sFieldCode);
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
$aRow[$sFieldCode] = cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId, $sNameSuffix, 0, $aArgs);
$aRow[$sFieldCode] = '<div class="field_container" style="border:none;"><div class="field_data"><div class="field_value">'.
cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId, $sNameSuffix, 0, $aArgs).
'</div></div></div>';
$aFieldsMap[$sFieldCode] = $sSafeId;
}
}
@@ -166,7 +168,7 @@ class UILinksWidget
$sPrefix .= "[-$iUniqueId][";
$sNameSuffix = "]"; // To make a tabular form
$aArgs['prefix'] = $sPrefix;
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}_".$iUniqueId;
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}_".($iUniqueId < 0 ? -$iUniqueId : $iUniqueId);
$aArgs['this'] = $oNewLinkObj;
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"-$iUniqueId\">";
foreach($this->m_aEditableFields as $sFieldCode)
@@ -176,17 +178,24 @@ class UILinksWidget
$sValue = $oNewLinkObj->Get($sFieldCode);
$sDisplayValue = $oNewLinkObj->GetEditValue($sFieldCode);
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
$aRow[$sFieldCode] = cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId /* id */, $sNameSuffix, 0, $aArgs);
$aRow[$sFieldCode] = '<div class="field_container" style="border:none;"><div class="field_data"><div class="field_value">'.
cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId /* id */, $sNameSuffix, 0, $aArgs).
'</div></div></div>';
$aFieldsMap[$sFieldCode] = $sSafeId;
}
$sState = '';
$oP->add_script(
<<<EOF
// Rows created with ajax call need OnLinkAdded call.
// Rows added before loading the form cannot call OnLinkAdded.
if ($iUniqueId > 0)
{
$oP->add_script(
<<<EOF
PrepareWidgets();
oWidget{$this->m_iInputId}.OnLinkAdded($iUniqueId, $iRemoteObjKey);
EOF
);
);
}
}
if(!$bReadOnly)

View File

@@ -141,6 +141,9 @@ class utils
}
protected static $bPageMode = null;
/**
* @var boolean[]
*/
protected static $aModes = array();
public static function InitArchiveMode()
@@ -164,6 +167,10 @@ class utils
self::$bPageMode = ($iCurrent == 1);
}
/**
* @param boolean $bMode if true then activate archive mode (archived objects are visible), otherwise archived objects are
* hidden (archive = "soft deletion")
*/
public static function PushArchiveMode($bMode)
{
array_push(self::$aModes, $bMode);
@@ -174,6 +181,9 @@ class utils
array_pop(self::$aModes);
}
/**
* @return boolean true if archive mode is enabled
*/
public static function IsArchiveMode()
{
if (count(self::$aModes) > 0)
@@ -917,7 +927,7 @@ class utils
*/
public static function GetCachePath()
{
return APPROOT.'data/cache-'.self::GetCurrentEnvironment().'/';
return APPROOT.'data/cache-'.MetaModel::GetEnvironment().'/';
}
/**
* Merge standard menu items with plugin provided menus items
@@ -1590,4 +1600,207 @@ class utils
}
return null;
}
/**
* Check if the given path/url is an http(s) URL
* @param string $sPath
* @return boolean
*/
public static function IsURL($sPath)
{
$bRet = false;
if ((substr($sPath, 0, 7) == 'http://') || (substr($sPath, 0, 8) == 'https://') || (substr($sPath, 0, 8) == 'ftp://'))
{
$bRet = true;
}
return $bRet;
}
/**
* Check if the given URL is a link to download a document/image on the CURRENT iTop
* In such a case we can read the content of the file directly in the database (if the users rights allow) and return the ormDocument
* @param string $sPath
* @return false|ormDocument
* @throws Exception
*/
public static function IsSelfURL($sPath)
{
$result = false;
$sPageUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.document.php';
if (substr($sPath, 0, strlen($sPageUrl)) == $sPageUrl)
{
// If the URL is an URL pointing to this instance of iTop, then
// extract the "query" part of the URL and analyze it
$sQuery = parse_url($sPath, PHP_URL_QUERY);
if ($sQuery !== null)
{
$aParams = array();
foreach(explode('&', $sQuery) as $sChunk)
{
$aParts = explode('=', $sChunk);
if (count($aParts) != 2) continue;
$aParams[$aParts[0]] = urldecode($aParts[1]);
}
$result = array_key_exists('operation', $aParams) && array_key_exists('class', $aParams) && array_key_exists('id', $aParams) && array_key_exists('field', $aParams) && ($aParams['operation'] == 'download_document');
if ($result)
{
// This is a 'download_document' operation, let's retrieve the document directly from the database
$sClass = $aParams['class'];
$iKey = $aParams['id'];
$sAttCode = $aParams['field'];
$oObj = MetaModel::GetObject($sClass, $iKey, false /* must exist */); // Users rights apply here !!
if ($oObj)
{
/**
* @var ormDocument $result
*/
$result = clone $oObj->Get($sAttCode);
return $result;
}
}
}
throw new Exception('Invalid URL. This iTop URL is not pointing to a valid Document/Image.');
}
return $result;
}
/**
* Read the content of a file (and retrieve its MIME type) from either:
* - an URL pointing to a blob (image/document) on the current iTop server
* - an http(s) URL
* - the local file system (but only if you are an administrator)
* @param string $sPath
* @return ormDocument|null
* @throws Exception
*/
public static function FileGetContentsAndMIMEType($sPath)
{
$oUploadedDoc = null;
$aKnownExtensions = array(
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'gif' => 'image/gif',
'png' => 'image/png',
'pdf' => 'application/pdf',
'doc' => 'application/msword',
'dot' => 'application/msword',
'xls' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'vsd' => 'application/x-visio',
'vdx' => 'application/visio.drawing',
'odt' => 'application/vnd.oasis.opendocument.text',
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
'odp' => 'application/vnd.oasis.opendocument.presentation',
'zip' => 'application/zip',
'txt' => 'text/plain',
'htm' => 'text/html',
'html' => 'text/html',
'exe' => 'application/octet-stream'
);
$sData = null;
$sMimeType = 'text/plain'; // Default MIME Type: treat the file as a bunch a characters...
$sFileName = 'uploaded-file'; // Default name for downloaded-files
$sExtension = '.txt'; // Default file extension in case we don't know the MIME Type
if(empty($sPath))
{
// Empty path (NULL or '') means that there is no input, making an empty document.
$oUploadedDoc = new ormDocument('', '', '');
}
elseif (static::IsURL($sPath))
{
if ($oUploadedDoc = static::IsSelfURL($sPath))
{
// Nothing more to do, we've got it !!
}
else
{
// Remote file, let's use the HTTP headers to find the MIME Type
$sData = @file_get_contents($sPath);
if ($sData === false)
{
throw new Exception("Failed to load the file from the URL '$sPath'.");
}
else
{
if (isset($http_response_header))
{
$aHeaders = static::ParseHeaders($http_response_header);
$sMimeType = array_key_exists('Content-Type', $aHeaders) ? strtolower($aHeaders['Content-Type']) : 'application/x-octet-stream';
// Compute the file extension from the MIME Type
foreach($aKnownExtensions as $sExtValue => $sMime)
{
if ($sMime === $sMimeType)
{
$sExtension = '.'.$sExtValue;
break;
}
}
}
$sFileName .= $sExtension;
}
$oUploadedDoc = new ormDocument($sData, $sMimeType, $sFileName);
}
}
else if (UserRights::IsAdministrator())
{
// Only administrators are allowed to read local files
$sData = @file_get_contents($sPath);
if ($sData === false)
{
throw new Exception("Failed to load the file '$sPath'. The file does not exist or the current process is not allowed to access it.");
}
$sExtension = strtolower(pathinfo($sPath, PATHINFO_EXTENSION));
$sFileName = basename($sPath);
if (array_key_exists($sExtension, $aKnownExtensions))
{
$sMimeType = $aKnownExtensions[$sExtension];
}
else if (extension_loaded('fileinfo'))
{
$finfo = new finfo(FILEINFO_MIME);
$sMimeType = $finfo->file($sPath);
}
$oUploadedDoc = new ormDocument($sData, $sMimeType, $sFileName);
}
return $oUploadedDoc;
}
protected static function ParseHeaders($aHeaders)
{
$aCleanHeaders = array();
foreach( $aHeaders as $sKey => $sValue )
{
$aTokens = explode(':', $sValue, 2);
if(isset($aTokens[1]))
{
$aCleanHeaders[trim($aTokens[0])] = trim($aTokens[1]);
}
else
{
// The header is not in the form Header-Code: Value
$aCleanHeaders[] = $sValue; // Store the value as-is
$aMatches = array();
// Check if it's not the HTTP response code
if( preg_match("|HTTP/[0-9\.]+\s+([0-9]+)|", $sValue, $aMatches) )
{
$aCleanHeaders['reponse_code'] = intval($aMatches[1]);
}
}
}
return $aCleanHeaders;
}
}

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2016 Combodo SARL
// Copyright (C) 2016-2017 Combodo SARL
//
// This file is part of iTop.
//
@@ -67,3 +67,32 @@ if (!function_exists('apc_store') && function_exists('apcu_store'))
return apcu_store($key, $var, $ttl);
}
}
/**
* Returns user cache info... beware of the format of the returned structure that may vary (See usages)
* @return array
*/
function apc_cache_info_compat()
{
if (!function_exists('apc_cache_info')) return array();
$oFunction = new ReflectionFunction('apc_cache_info');
if ($oFunction->getNumberOfParameters() != 2)
{
// Beware: APCu behaves slightly differently from APC !!
// Worse: the compatibility layer integrated into APC differs from apcu-bc (testing the number of parameters is a must)
// In CLI mode (PHP > 7) apc_cache_info returns null and outputs an error message.
$aCacheUserData = @apc_cache_info();
}
else
{
$aCacheUserData = @apc_cache_info('user');
}
return $aCacheUserData;
}
// Cache emulation
if (!function_exists('apc_store'))
{
require_once(APPROOT.'core/apc-emulation.php');
}

301
core/apc-emulation.php Normal file
View File

@@ -0,0 +1,301 @@
<?php
// Copyright (c) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
//
/**
* Date: 27/09/2017
*/
/**
* @param string $cache_type
* @param bool $limited
* @return array|bool
*/
function apc_cache_info($cache_type = '', $limited = false)
{
$aInfo = array();
$sRootCacheDir = apc_emul_get_cache_filename('');
$aInfo['cache_list'] = apc_emul_get_cache_entries($sRootCacheDir);
return $aInfo;
}
function apc_emul_get_cache_entries($sEntry)
{
$aResult = array();
if (is_dir($sEntry))
{
$aFiles = array_diff(scandir($sEntry), array('.', '..'));
foreach($aFiles as $sFile)
{
$sSubFile = $sEntry.'/'.$sFile;
$aResult = array_merge($aResult, apc_emul_get_cache_entries($sSubFile));
}
}
else
{
$sKey = basename($sEntry);
if (strpos($sKey, '-') === 0)
{
$sKey = substr($sKey, 1);
}
$aResult[] = array('info' => $sKey);
}
return $aResult;
}
/**
* @param array|string $key
* @param $var
* @param int $ttl
* @return array|bool
*/
function apc_store($key, $var = NULL, $ttl = 0)
{
if (is_array($key))
{
$aResult = array();
foreach($key as $sKey => $value)
{
$aResult[] = apc_emul_store_unit($sKey, $value, $ttl);
}
return $aResult;
}
return apc_emul_store_unit($key, $var, $ttl);
}
/**
* @param string $sKey
* @param $value
* @param int $iTTL time to live
* @return bool
*/
function apc_emul_store_unit($sKey, $value, $iTTL)
{
if ($iTTL > 0)
{
// hint for ttl management
$sKey = '-'.$sKey;
}
$sFilename = apc_emul_get_cache_filename($sKey);
// try to create the folder
$sDirname = dirname($sFilename);
if (!file_exists($sDirname))
{
if (!@mkdir($sDirname, 0755, true))
{
return false;
}
}
$bRes = !(@file_put_contents($sFilename, serialize($value), LOCK_EX) === false);
apc_emul_manage_new_entry($sFilename);
return $bRes;
}
/**
* @param $key string|array
* @return mixed
*/
function apc_fetch($key)
{
if (is_array($key))
{
$aResult = array();
foreach($key as $sKey)
{
$aResult[$sKey] = apc_emul_fetch_unit($sKey);
}
return $aResult;
}
return apc_emul_fetch_unit($key);
}
/**
* @param $sKey
* @return bool|mixed
*/
function apc_emul_fetch_unit($sKey)
{
// Try the 'TTLed' version
$sValue = apc_emul_readcache_locked(apc_emul_get_cache_filename('-'.$sKey));
if ($sValue === false)
{
$sValue = apc_emul_readcache_locked(apc_emul_get_cache_filename($sKey));
if ($sValue === false)
{
return false;
}
}
$oRes = @unserialize($sValue);
return $oRes;
}
function apc_emul_readcache_locked($sFilename)
{
$file = @fopen($sFilename, 'r');
if ($file === false)
{
return false;
}
flock($file, LOCK_SH);
$sContent = @fread($file, @filesize($sFilename));
flock($file, LOCK_UN);
fclose($file);
return $sContent;
}
/**
* @param string $cache_type
* @return bool
*/
function apc_clear_cache($cache_type = '')
{
$sRootCacheDir = apc_emul_get_cache_filename('');
apc_emul_delete_entry($sRootCacheDir);
return true;
}
function apc_emul_delete_entry($sCache)
{
if (is_dir($sCache))
{
$aFiles = array_diff(scandir($sCache), array('.', '..'));
foreach($aFiles as $sFile)
{
$sSubFile = $sCache.'/'.$sFile;
if (!apc_emul_delete_entry($sSubFile))
{
return false;
}
}
if (!@rmdir($sCache))
{
return false;
}
}
else
{
if (!@unlink($sCache))
{
return false;
}
}
return true;
}
/**
* @param $key
* @return bool|string[]
*/
function apc_delete($key)
{
return apc_emul_delete_entry(apc_emul_get_cache_filename($key));
}
function apc_emul_get_cache_filename($sKey)
{
$sPath = str_replace(array(' ', '/', '\\', '.'), '-', $sKey);
return utils::GetCachePath().'apc-emul/'.$sPath;
}
/** Manage the cache files when a new cache entry is added
* @param string $sNewFilename new cache file added
*/
function apc_emul_manage_new_entry($sNewFilename)
{
// Check only once per request
static $aFilesByTime = null;
static $iFileCount = 0;
$iMaxFiles = MetaModel::GetConfig()->Get('apc_cache_emulation.max_entries');
if ($iMaxFiles == 0)
{
return;
}
if (!$aFilesByTime)
{
$sRootCacheDir = apc_emul_get_cache_filename('');
$aFilesByTime = apc_emul_list_files_time($sRootCacheDir);
$iFileCount = count($aFilesByTime);
if ($iMaxFiles !== 0)
{
asort($aFilesByTime);
}
}
else
{
$aFilesByTime[$sNewFilename] = time();
$iFileCount++;
}
if ($iFileCount > $iMaxFiles)
{
$iFileNbToRemove = $iFileCount - $iMaxFiles;
foreach($aFilesByTime as $sFileToRemove => $iTime)
{
@unlink($sFileToRemove);
if ($iFileNbToRemove-- === 0)
{
break;
}
}
$aFilesByTime = array_slice($aFilesByTime, $iFileCount - $iMaxFiles, null, true);
$iFileCount = $iMaxFiles;
}
}
/** Get the list of files with their associated access time
* @param string $sCheck Directory to scan
* @param array $aFilesByTime used by recursion
* @return array
*/
function apc_emul_list_files_time($sCheck, &$aFilesByTime = array())
{
// Garbage collection
$aFiles = array_diff(@scandir($sCheck), array('.', '..'));
foreach($aFiles as $sFile)
{
$sSubFile = $sCheck.'/'.$sFile;
if (is_dir($sSubFile))
{
apc_emul_list_files_time($sSubFile, $aFilesByTime);
}
else
{
$iTime = apc_emul_get_file_time($sSubFile);
if ($iTime !== false)
{
$aFilesByTime[$sSubFile] = $iTime;
}
}
}
return $aFilesByTime;
}
/** Get the file access time if TTL is managed
* @param string $sFilename
* @return bool|int returns the file atime or false if not relevant
*/
function apc_emul_get_file_time($sFilename)
{
if (strpos(basename($sFilename), '-') === 0)
{
return @fileatime($sFilename);
}
return false;
}

View File

@@ -702,7 +702,7 @@ abstract class AttributeDefinition
break;
default:
throw new Exception("Unknown verb '$sVerb' for attribute ".$this->GetCode().' in class '.get_class($oHostObj));
throw new Exception("Unknown verb '$sVerb' for attribute ".$this->GetCode().' in class '.get_class($oHostObject));
}
}
return null;
@@ -1355,7 +1355,7 @@ class AttributeLinkedSet extends AttributeDefinition
}
else
{
$bAreEquivalent = $val1->Equals($val2);
$bAreEquivalent = ($val2->HasDelta() === false);
}
return $bAreEquivalent;
}
@@ -3963,6 +3963,42 @@ class AttributeDateTime extends AttributeDBField
return $oFormField;
}
/**
* @inheritdoc
*/
public function EnumTemplateVerbs()
{
return array(
'' => 'Formatted representation',
'raw' => 'Not formatted representation',
);
}
/**
* @inheritdoc
*/
public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true)
{
switch ($sVerb)
{
case '':
case 'text':
return static::GetFormat()->format($value);
break;
case 'html':
// Note: Not passing formatted value as the method will format it.
return $this->GetAsHTML($value);
break;
case 'raw':
return $value;
break;
default:
return parent::GetForTemplate($value, $sVerb, $oHostObject, $bLocalize);
break;
}
return null;
}
static public function ListExpectedParams()
{
return parent::ListExpectedParams();
@@ -5207,75 +5243,34 @@ class AttributeBlob extends AttributeDefinition
{
return '';
}
// Facilitate things: allow administrators to upload a document
// from a CSV by specifying its path/URL
/**
* Users can provide the document from an URL (including an URL on iTop itself)
* for CSV import. Administrators can even provide the path to a local file
* {@inheritDoc}
* @see AttributeDefinition::MakeRealValue()
*/
public function MakeRealValue($proposedValue, $oHostObj)
{
if ($proposedValue === null) return null;
if (is_object($proposedValue))
{
$proposedValue = clone $proposedValue;
}
else
{
if (file_exists($proposedValue) && UserRights::IsAdministrator())
try
{
$sContent = file_get_contents($proposedValue);
$sExtension = strtolower(pathinfo($proposedValue, PATHINFO_EXTENSION));
$sMimeType = "application/x-octet-stream";
$aKnownExtensions = array(
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12.xlsx',
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'gif' => 'image/gif',
'png' => 'image/png',
'pdf' => 'application/pdf',
'doc' => 'application/msword',
'dot' => 'application/msword',
'xls' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'vsd' => 'application/x-visio',
'vdx' => 'application/visio.drawing',
'odt' => 'application/vnd.oasis.opendocument.text',
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
'odp' => 'application/vnd.oasis.opendocument.presentation',
'zip' => 'application/zip',
'txt' => 'text/plain',
'htm' => 'text/html',
'html' => 'text/html',
'exe' => 'application/octet-stream'
);
if (!array_key_exists($sExtension, $aKnownExtensions) && extension_loaded('fileinfo'))
{
$finfo = new finfo(FILEINFO_MIME);
$sMimeType = $finfo->file($proposedValue);
}
return new ormDocument($sContent, $sMimeType);
// Read the file from iTop, an URL (or the local file system - for admins only)
$proposedValue = Utils::FileGetContentsAndMIMEType($proposedValue);
}
else
catch(Exception $e)
{
return new ormDocument($proposedValue, 'text/plain');
}
IssueLog::Warning(get_class($this)."::MakeRealValue - ".$e->getMessage());
// Not a real document !! store is as text !!! (This was the default behavior before)
$proposedValue = new ormDocument($e->getMessage()." \n".$proposedValue, 'text/plain');
}
}
return $proposedValue;
}
@@ -5390,6 +5385,11 @@ class AttributeBlob extends AttributeDefinition
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, $bConvertToPlainText = false)
{
$sAttCode = $this->GetCode();
if ($sValue instanceof ormDocument && !$sValue->IsEmpty())
{
return $sValue->GetDownloadURL(get_class($oHostObject), $oHostObject->GetKey(), $sAttCode);
}
return ''; // Not exportable in CSV !
}
@@ -5493,48 +5493,49 @@ class AttributeImage extends AttributeBlob
{
public function GetEditClass() {return "Image";}
// Facilitate things: allow administrators to upload a document
// from a CSV by specifying its path/URL
/**
* {@inheritDoc}
* @see AttributeBlob::MakeRealValue()
*/
public function MakeRealValue($proposedValue, $oHostObj)
{
if (is_object($proposedValue))
{
$proposedValue = clone $proposedValue;
}
else
{
if (file_exists($proposedValue) && UserRights::IsAdministrator())
{
$sContent = file_get_contents($proposedValue);
$sExtension = strtolower(pathinfo($proposedValue, PATHINFO_EXTENSION));
$sMimeType = "application/x-octet-stream";
$aKnownExtensions = array(
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'gif' => 'image/gif',
'png' => 'image/png'
);
if (!array_key_exists($sExtension, $aKnownExtensions) && extension_loaded('fileinfo'))
{
$finfo = new finfo(FILEINFO_MIME);
$sMimeType = $finfo->file($proposedValue);
}
return new ormDocument($sContent, $sMimeType);
}
}
return $proposedValue;
$oDoc = parent::MakeRealValue($proposedValue, $oHostObj);
// The validation of the MIME Type is done by CheckFormat below
return $oDoc;
}
/**
* Check that the supplied ormDocument actually contains an image
* {@inheritDoc}
* @see AttributeDefinition::CheckFormat()
*/
public function CheckFormat($value)
{
if ($value instanceof ormDocument && !$value->IsEmpty())
{
return ($value->GetMainMimeType() == 'image');
}
return true;
}
public function GetAsHTML($value, $oHostObject = null, $bLocalize = true)
{
$iMaxWidthPx = $this->Get('display_max_width');
$iMaxHeightPx = $this->Get('display_max_height');
$sUrl = $this->Get('default_image');
$sRet = '<img src="'.$sUrl.'" style="max-width: '.$iMaxWidthPx.'px; max-height: '.$iMaxHeightPx.'px">';
$sRet = ($sUrl !== null) ? '<img src="'.$sUrl.'" style="max-width: '.$iMaxWidthPx.'px; max-height: '.$iMaxHeightPx.'px">' : '';
if (is_object($value) && !$value->IsEmpty())
{
$sUrl = $value->GetDownloadURL(get_class($oHostObject), $oHostObject->GetKey(), $this->GetCode());
if ($oHostObject->IsNew() || ($oHostObject->IsModified() && (array_key_exists($this->GetCode(), $oHostObject->ListChanges()))))
{
// If the object is modified (or not yet stored in the database) we must serve the content of the image directly inline
// otherwise (if we just give an URL) the browser will be given the wrong content... and may cache it
$sUrl = 'data:'.$value->GetMimeType().';base64,'.base64_encode($value->GetData());
}
else
{
$sUrl = $value->GetDownloadURL(get_class($oHostObject), $oHostObject->GetKey(), $this->GetCode());
}
$sRet = '<img src="'.$sUrl.'" style="max-width: '.$iMaxWidthPx.'px; max-height: '.$iMaxHeightPx.'px">';
}
return '<div class="view-image" style="width: '.$iMaxWidthPx.'px; height: '.$iMaxHeightPx.'px;"><span class="helper-middle"></span>'.$sRet.'</div>';
@@ -7370,7 +7371,7 @@ class AttributeCustomFields extends AttributeDefinition
public function GetEditValue($sValue, $oHostObj = null)
{
return 'GetEditValueNotImplemented for '.get_class($this);
return $this->GetForTemplate($sValue, '', $oHostObj, true);
}
/**
@@ -7773,3 +7774,16 @@ class AttributeObsolescenceFlag extends AttributeBoolean
}
}
class AttributeObsolescenceDate extends AttributeDate
{
public function GetLabel($sDefault = null)
{
$sDefault = Dict::S('Core:AttributeObsolescenceDate/Label', $sDefault);
return parent::GetLabel($sDefault);
}
public function GetDescription($sDefault = null)
{
$sDefault = Dict::S('Core:AttributeObsolescenceDate/Label+', $sDefault);
return parent::GetDescription($sDefault);
}
}

View File

@@ -468,10 +468,11 @@ class BulkChange
//
foreach ($this->m_aAttList as $sAttCode => $iCol)
{
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
// skip the private key, if any
if ($sAttCode == 'id') continue;
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
// skip reconciliation keys
if (!$oAttDef->IsWritable() && in_array($sAttCode, $this->m_aReconcilKeys)){ continue; }

View File

@@ -33,13 +33,15 @@ class MySQLException extends CoreException
{
if ($oException != null)
{
$aContext['mysql_error'] = $oException->getCode();
$aContext['mysql_errno'] = $oException->getMessage();
$aContext['mysql_errno'] = $oException->getCode();
$this->code = $oException->getCode();
$aContext['mysql_error'] = $oException->getMessage();
}
else
{
$aContext['mysql_error'] = CMDBSource::GetError();
$aContext['mysql_errno'] = CMDBSource::GetErrNo();
$this->code = CMDBSource::GetErrNo();
$aContext['mysql_error'] = CMDBSource::GetError();
}
parent::__construct($sIssue, $aContext);
}

View File

@@ -18,7 +18,8 @@
define('ITOP_APPLICATION', 'iTop');
define('ITOP_VERSION', '2.4.x');
define('ITOP_APPLICATION_SHORT', 'iTop');
define('ITOP_VERSION', '2.4.0');
define('ITOP_REVISION', 'svn');
define('ITOP_BUILD_DATE', '$WCNOW$');
@@ -435,6 +436,14 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'apc_cache_emulation.max_entries' => array(
'type' => 'integer',
'description' => 'Maximum number of cache entries (0 means no limit)',
'default' => 1000,
'value' => 1000,
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'timezone' => array(
'type' => 'string',
'description' => 'Timezone (reference: http://php.net/manual/en/timezones.php). If empty, it will be left unchanged and MUST be explicitely configured in PHP',

View File

@@ -112,4 +112,13 @@ class SecurityException extends CoreException
{
}
/**
* Throwned when querying on an object that exists in the database but is archived
*
* @see N.1108
*/
class ArchivedObjectException extends CoreException
{
}
?>

View File

@@ -1731,6 +1731,14 @@ abstract class DBObject implements iDisplay
$this->m_bIsInDB = true;
$this->m_bDirty = false;
foreach ($this->m_aCurrValues as $sAttCode => $value)
{
if (is_object($value))
{
$value = clone $value;
}
$this->m_aOrigValues[$sAttCode] = $value;
}
$this->AfterInsert();

View File

@@ -1,9 +1,9 @@
<?php
// Copyright (C) 2010-2017 Combodo SARL
// Copyright (c) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -15,14 +15,7 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Define filters for a given class of objects (formerly named "filter")
*
* @copyright Copyright (C) 2010-2017 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
//
// Dev hack for disabling the some query build optimizations (Folding/Merging)
define('ENABLE_OPT', true);
@@ -33,7 +26,6 @@ class DBObjectSearch extends DBSearch
private $m_aSelectedClasses; // selected for the output (alias => class name)
private $m_oSearchCondition;
private $m_aParams;
private $m_aFullText;
private $m_aPointingTo;
private $m_aReferencedBy;
@@ -54,7 +46,6 @@ class DBObjectSearch extends DBSearch
$this->m_aClasses = array($sClassAlias => $sClass);
$this->m_oSearchCondition = new TrueExpression;
$this->m_aParams = array();
$this->m_aFullText = array();
$this->m_aPointingTo = array();
$this->m_aReferencedBy = array();
}
@@ -285,7 +276,6 @@ class DBObjectSearch extends DBSearch
public function IsAny()
{
if (!$this->m_oSearchCondition->IsTrue()) return false;
if (count($this->m_aFullText) > 0) return false;
if (count($this->m_aPointingTo) > 0) return false;
if (count($this->m_aReferencedBy) > 0) return false;
return true;
@@ -390,7 +380,7 @@ class DBObjectSearch extends DBSearch
// Parse search strings if needed and if the filter code corresponds to a valid attcode
if($bParseSeachString && MetaModel::IsValidAttCode($this->GetClass(), $sFilterCode))
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sFilterCode);
$oAttDef = MetaModel::GetAttributeDef($this->GetClass(), $sFilterCode);
$value = $oAttDef->ParseSearchString($value);
}
@@ -549,9 +539,24 @@ class DBObjectSearch extends DBSearch
}
}
public function AddCondition_FullText($sFullText)
public function AddCondition_FullText($sNeedle)
{
$this->m_aFullText[] = $sFullText;
// Transform the full text condition into additional condition expression
$aFullTextFields = array();
foreach (MetaModel::ListAttributeDefs($this->GetClass()) as $sAttCode => $oAttDef)
{
if (!$oAttDef->IsScalar()) continue;
if ($oAttDef->IsExternalKey()) continue;
$aFullTextFields[] = new FieldExpression($sAttCode, $this->GetClassAlias());
}
$oTextFields = new CharConcatWSExpression(' ', $aFullTextFields);
$sQueryParam = 'needle';
$oFlexNeedle = new CharConcatExpression(array(new ScalarExpression('%'), new VariableExpression($sQueryParam), new ScalarExpression('%')));
$oNewCond = new BinaryExpression($oTextFields, 'LIKE', $oFlexNeedle);
$this->AddConditionExpression($oNewCond);
$this->m_aParams[$sQueryParam] = $sNeedle;
}
protected function AddToNameSpace(&$aClassAliases, &$aAliasTranslation, $bTranslateMainAlias = true)
@@ -973,8 +978,6 @@ class DBObjectSearch extends DBSearch
// Translate search condition into our aliasing scheme
$aAliasTranslation[$oFilter->GetClassAlias()]['*'] = $this->GetClassAlias();
$this->m_aFullText = array_merge($this->m_aFullText, $oFilter->m_aFullText);
foreach($oFilter->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo)
{
foreach($aPointingTo as $iOperatorCode => $aFilter)
@@ -1001,7 +1004,7 @@ class DBObjectSearch extends DBSearch
}
public function GetCriteria() {return $this->m_oSearchCondition;}
public function GetCriteria_FullText() {return $this->m_aFullText;}
public function GetCriteria_FullText() {throw new Exception("Removed GetCriteria_FullText");}
protected function GetCriteria_PointingTo($sKeyAttCode = "")
{
if (empty($sKeyAttCode))
@@ -1119,11 +1122,6 @@ class DBObjectSearch extends DBSearch
$sRes .= $this->ToOQL_Joins();
$sRes .= " WHERE ".$this->m_oSearchCondition->Render($aParams, $bRetrofitParams);
// Temporary: add more info about other conditions, necessary to avoid strange behaviors with the cache
foreach($this->m_aFullText as $sFullText)
{
$sRes .= " AND MATCHES '$sFullText'";
}
if ($bWithAllowAllFlag && $this->m_bAllowAllData)
{
$sRes .= " ALLOW ALL DATA";
@@ -1468,10 +1466,32 @@ class DBObjectSearch extends DBSearch
// Create a unique cache id
//
$aContextData = array();
$bCanCache = true;
if (self::$m_bQueryCacheEnabled || self::$m_bTraceQueries)
{
if (isset($_SERVER['REQUEST_URI']))
{
$aContextData['sRequestUri'] = $_SERVER['REQUEST_URI'];
}
else if (isset($_SERVER['SCRIPT_NAME']))
{
$aContextData['sRequestUri'] = $_SERVER['SCRIPT_NAME'];
}
else
{
$aContextData['sRequestUri'] = '';
}
// Need to identify the query
$sOqlQuery = $oSearch->ToOql(false, null, true);
if ((strpos($sOqlQuery, '`id` IN (') !== false) || (strpos($sOqlQuery, '`id` NOT IN (') !== false))
{
// Requests containing "id IN" are not worth caching
$bCanCache = false;
}
$aContextData['sOqlQuery'] = $sOqlQuery;
if (count($aModifierProperties))
{
@@ -1482,12 +1502,14 @@ class DBObjectSearch extends DBSearch
{
$sModifierProperties = '';
}
$aContextData['sModifierProperties'] = $sModifierProperties;
$sRawId = $sOqlQuery.$sModifierProperties;
if (!is_null($aAttToLoad))
{
$sRawId .= json_encode($aAttToLoad);
}
$aContextData['aAttToLoad'] = $aAttToLoad;
if (!is_null($aGroupByExpr))
{
foreach($aGroupByExpr as $sAlias => $oExpr)
@@ -1495,13 +1517,20 @@ class DBObjectSearch extends DBSearch
$sRawId .= 'g:'.$sAlias.'!'.$oExpr->Render();
}
}
$aContextData['aGroupByExpr'] = $aGroupByExpr;
$sRawId .= $bGetCount;
$aContextData['bGetCount'] = $bGetCount;
if (is_array($aSelectedClasses))
{
$sRawId .= implode(',', $aSelectedClasses); // Unions may alter the list of selected columns
}
$sRawId .= $oSearch->GetArchiveMode() ? '--arch' : '';
$sRawId .= $oSearch->GetShowObsoleteData() ? '--obso' : '';
$aContextData['aSelectedClasses'] = $aSelectedClasses;
$bIsArchiveMode = $oSearch->GetArchiveMode();
$sRawId .= $bIsArchiveMode ? '--arch' : '';
$bShowObsoleteData = $oSearch->GetShowObsoleteData();
$sRawId .= $bShowObsoleteData ? '--obso' : '';
$aContextData['bIsArchiveMode'] = $bIsArchiveMode;
$aContextData['bShowObsoleteData'] = $bShowObsoleteData;
$sOqlId = md5($sRawId);
}
else
@@ -1557,8 +1586,9 @@ class DBObjectSearch extends DBSearch
if (self::$m_bQueryCacheEnabled)
{
if (self::$m_bUseAPCCache)
if ($bCanCache && self::$m_bUseAPCCache)
{
$oSQLQuery->m_aContextData = $aContextData;
$oKPI = new ExecutionKPI();
apc_store($sOqlAPCCacheId, $oSQLQuery, self::$m_iQueryCacheTTL);
$oKPI->ComputeStats('Query APC (store)', $sOqlQuery);
@@ -1570,6 +1600,14 @@ class DBObjectSearch extends DBSearch
return $oSQLQuery;
}
/**
* @param $aAttToLoad
* @param $bGetCount
* @param $aModifierProperties
* @param null $aGroupByExpr
* @param null $aSelectedClasses
* @return null|SQLObjectQuery
*/
protected function BuildSQLQueryStruct($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr = null, $aSelectedClasses = null)
{
$oBuild = new QueryBuilderContext($this, $aModifierProperties, $aGroupByExpr, $aSelectedClasses);
@@ -1614,6 +1652,12 @@ class DBObjectSearch extends DBSearch
}
/**
* @param $oBuild
* @param null $aAttToLoad
* @param array $aValues
* @return null|SQLObjectQuery
*/
protected function MakeSQLObjectQuery(&$oBuild, $aAttToLoad = null, $aValues = array())
{
// Note: query class might be different than the class of the filter
@@ -1623,9 +1667,9 @@ class DBObjectSearch extends DBSearch
$bIsOnQueriedClass = array_key_exists($sClassAlias, $oBuild->GetRootFilter()->GetSelectedClasses());
self::DbgTrace("Entering: ".$this->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY"));
//self::DbgTrace("Entering: ".$this->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY"));
$sRootClass = MetaModel::GetRootClass($sClass);
//$sRootClass = MetaModel::GetRootClass($sClass);
$sKeyField = MetaModel::DBGetKey($sClass);
if ($bIsOnQueriedClass)
@@ -1658,30 +1702,10 @@ class DBObjectSearch extends DBSearch
}
}
}
// Transform the full text condition into additional condition expression
$aFullText = $this->GetCriteria_FullText();
if (count($aFullText) > 0)
{
$aFullTextFields = array();
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
if (!$oAttDef->IsScalar()) continue;
if ($oAttDef->IsExternalKey()) continue;
$aFullTextFields[] = new FieldExpression($sAttCode, $sClassAlias);
}
$oTextFields = new CharConcatWSExpression(' ', $aFullTextFields);
foreach($aFullText as $sFTNeedle)
{
$oNewCond = new BinaryExpression($oTextFields, 'LIKE', new ScalarExpression("%$sFTNeedle%"));
$oBuild->m_oQBExpressions->AddCondition($oNewCond);
}
}
}
//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oBuild->m_oQBExpressions, true)."</pre></p>\n";
//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oBuild->m_oQBExpressions, true)."</pre></p>\n";
$aExpectedAtts = array(); // array of (attcode => fieldexpression)
//echo "<p>".__LINE__.": GetUnresolvedFields($sClassAlias, ...)</p>\n";
//echo "<p>".__LINE__.": GetUnresolvedFields($sClassAlias, ...)</p>\n";
$oBuild->m_oQBExpressions->GetUnresolvedFields($sClassAlias, $aExpectedAtts);
// Compute a clear view of required joins (from the current class)
@@ -1798,37 +1822,46 @@ class DBObjectSearch extends DBSearch
}
}
// First query built upon on the leaf (ie current) class
// First query built from the root, adding all tables including the leaf
// Before N.1065 we were joining from the leaf first, but this wasn't a good choice :
// most of the time (obsolescence, friendlyname, ...) we want to get a root attribute !
//
self::DbgTrace("Main (=leaf) class, call MakeSQLObjectQuerySingleTable()");
if (MetaModel::HasTable($sClass))
$oSelectBase = null;
$aClassHierarchy = MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL, true);
$bIsClassStandaloneClass = (count($aClassHierarchy) == 1);
foreach($aClassHierarchy as $sSomeClass)
{
$oSelectBase = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sClass, $aExtKeys, $aValues);
}
else
{
$oSelectBase = null;
if (!MetaModel::HasTable($sSomeClass))
{
continue;
}
// As the join will not filter on the expected classes, we have to specify it explicitely
$sExpectedClasses = implode("', '", MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL));
$oFinalClassRestriction = Expression::FromOQL("`$sClassAlias`.finalclass IN ('$sExpectedClasses')");
$oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction);
}
// Then we join the queries of the eventual parent classes (compound model)
foreach(MetaModel::EnumParentClasses($sClass) as $sParentClass)
{
if (!MetaModel::HasTable($sParentClass)) continue;
self::DbgTrace("Parent class: $sParentClass... let's call MakeSQLObjectQuerySingleTable()");
$oSelectParentTable = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sParentClass, $aExtKeys, $aValues);
self::DbgTrace("Adding join from root to leaf: $sSomeClass... let's call MakeSQLObjectQuerySingleTable()");
$oSelectParentTable = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sSomeClass, $aExtKeys, $aValues);
if (is_null($oSelectBase))
{
$oSelectBase = $oSelectParentTable;
if (!$bIsClassStandaloneClass && (MetaModel::IsRootClass($sSomeClass)))
{
// As we're linking to root class first, we're adding a where clause on the finalClass attribute :
// COALESCE($sRootClassFinalClass IN ('$sExpectedClasses'), 1)
// If we don't, the child classes can be removed in the query optimisation phase, including the leaf that was queried
// So we still need to filter records to only those corresponding to the child classes !
// The coalesce is mandatory if we have a polymorphic query (left join)
$oClassListExpr = ListExpression::FromScalars(MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL));
$sFinalClassSqlColumnName = MetaModel::DBGetClassField($sSomeClass);
$oClassExpr = new FieldExpression($sFinalClassSqlColumnName, $oSelectBase->GetTableAlias());
$oInExpression = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr);
$oTrueExpression = new TrueExpression();
$aCoalesceAttr = array($oInExpression, $oTrueExpression);
$oFinalClassRestriction = new FunctionExpression("COALESCE", $aCoalesceAttr);
$oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction);
}
}
else
{
$oSelectBase->AddInnerJoin($oSelectParentTable, $sKeyField, MetaModel::DBGetKey($sParentClass));
$oSelectBase->AddInnerJoin($oSelectParentTable, $sKeyField, MetaModel::DBGetKey($sSomeClass));
}
}
@@ -2159,8 +2192,14 @@ class DBObjectSearch extends DBSearch
* Get the expression for the class and its subclasses (if finalclass = 'subclass' ...)
* Simplifies the final expression by grouping classes having the same expression
*/
static protected function GetPolymorphicExpression($sClass, $sAttCode)
static public function GetPolymorphicExpression($sClass, $sAttCode)
{
$oExpression = ExpressionCache::GetCachedExpression($sClass, $sAttCode);
if (!empty($oExpression))
{
return $oExpression;
}
// 1st step - get all of the required expressions (instantiable classes)
// and group them using their OQL representation
//

View File

@@ -69,7 +69,7 @@ class DBObjectSet implements iDBObjectSetIterator
* @var int
*/
protected $m_iCurrRow;
/*
/**
* @var DBSearch
*/
protected $m_oFilter;
@@ -195,11 +195,25 @@ class DBObjectSet implements iDBObjectSetIterator
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttToLoad);
$aAttToLoadWithAttDef[$sClassAlias][$sAttToLoad] = $oAttDef;
if ($oAttDef->IsExternalKey())
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
{
// Add the external key friendly name anytime
$oFriendlyNameAttDef = MetaModel::GetAttributeDef($sClass, $sAttToLoad.'_friendlyname');
$aAttToLoadWithAttDef[$sClassAlias][$sAttToLoad.'_friendlyname'] = $oFriendlyNameAttDef;
if (MetaModel::IsArchivable($oAttDef->GetTargetClass(EXTKEY_ABSOLUTE)))
{
// Add the archive flag if necessary
$oArchiveFlagAttDef = MetaModel::GetAttributeDef($sClass, $sAttToLoad.'_archive_flag');
$aAttToLoadWithAttDef[$sClassAlias][$sAttToLoad.'_archive_flag'] = $oArchiveFlagAttDef;
}
if (MetaModel::IsObsoletable($oAttDef->GetTargetClass(EXTKEY_ABSOLUTE)))
{
// Add the obsolescence flag if necessary
$oObsoleteFlagAttDef = MetaModel::GetAttributeDef($sClass, $sAttToLoad.'_obsolescence_flag');
$aAttToLoadWithAttDef[$sClassAlias][$sAttToLoad.'_obsolescence_flag'] = $oObsoleteFlagAttDef;
}
}
}
}
@@ -207,6 +221,20 @@ class DBObjectSet implements iDBObjectSetIterator
$oFriendlyNameAttDef = MetaModel::GetAttributeDef($sClass, 'friendlyname');
$aAttToLoadWithAttDef[$sClassAlias]['friendlyname'] = $oFriendlyNameAttDef;
if (MetaModel::IsArchivable($sClass))
{
// Add the archive flag if necessary
$oArchiveFlagAttDef = MetaModel::GetAttributeDef($sClass, 'archive_flag');
$aAttToLoadWithAttDef[$sClassAlias]['archive_flag'] = $oArchiveFlagAttDef;
}
if (MetaModel::IsObsoletable($sClass))
{
// Add the obsolescence flag if necessary
$oObsoleteFlagAttDef = MetaModel::GetAttributeDef($sClass, 'obsolescence_flag');
$aAttToLoadWithAttDef[$sClassAlias]['obsolescence_flag'] = $oObsoleteFlagAttDef;
}
// Make sure that the final class is requested anytime, whatever the specification (needed for object construction!)
if (!MetaModel::IsStandaloneClass($sClass) && !array_key_exists('finalclass', $aAttToLoadWithAttDef[$sClassAlias]))
{
@@ -312,7 +340,7 @@ class DBObjectSet implements iDBObjectSetIterator
}
/**
* Note: After calling this method, the set cursor will be at the end of the set. You might to rewind it.
* Note: After calling this method, the set cursor will be at the end of the set. You might want to rewind it.
*
* @param bool $bWithId
* @return array
@@ -386,7 +414,7 @@ class DBObjectSet implements iDBObjectSetIterator
}
/**
* Note: After calling this method, the set cursor will be at the end of the set. You might to rewind it.
* Note: After calling this method, the set cursor will be at the end of the set. You might want to rewind it.
*
* @param string $sAttCode
* @param bool $bWithId
@@ -598,14 +626,7 @@ class DBObjectSet implements iDBObjectSetIterator
// Note: it is mandatory to set this value now, to protect against reentrance
$this->m_bLoaded = true;
if ($this->m_iLimitCount > 0)
{
$sSQL = $this->m_oFilter->MakeSelectQuery($this->GetRealSortOrder(), $this->m_aArgs, $this->m_aAttToLoad, $this->m_aExtendedDataSpec, $this->m_iLimitCount, $this->m_iLimitStart);
}
else
{
$sSQL = $this->m_oFilter->MakeSelectQuery($this->GetRealSortOrder(), $this->m_aArgs, $this->m_aAttToLoad, $this->m_aExtendedDataSpec);
}
$sSQL = $this->_makeSelectQuery($this->m_aAttToLoad);
if (is_object($this->m_oSQLResult))
{
@@ -614,8 +635,36 @@ class DBObjectSet implements iDBObjectSetIterator
$this->m_oSQLResult = null;
}
$this->m_iNumTotalDBRows = null;
$this->m_oSQLResult = CMDBSource::Query($sSQL);
try
{
$this->m_oSQLResult = CMDBSource::Query($sSQL);
} catch (MySQLException $e)
{
// 1116 = ER_TOO_MANY_TABLES
// https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html#error_er_too_many_tables
if ($e->getCode() != 1116)
{
throw $e;
}
// N.689 Workaround for the 61 max joins in MySQL : full lazy load !
$aAttToLoad = array();
foreach($this->m_oFilter->GetSelectedClasses() as $sClassAlias => $sClass)
{
$aAttToLoad[$sClassAlias] = array();
$bIsAbstractClass = MetaModel::IsAbstract($sClass);
$bIsClassWithChildren = MetaModel::HasChildrenClasses($sClass);
if ($bIsAbstractClass || $bIsClassWithChildren)
{
// we need finalClass field at least to be able to instantiate the real corresponding object !
$aAttToLoad[$sClassAlias]['finalclass'] = MetaModel::GetAttributeDef($sClass, 'finalclass');
}
}
$sSQL = $this->_makeSelectQuery($aAttToLoad);
$this->m_oSQLResult = CMDBSource::Query($sSQL); // may fail again
}
if ($this->m_oSQLResult === false) return;
if (($this->m_iLimitCount == 0) && ($this->m_iLimitStart == 0))
@@ -626,10 +675,33 @@ class DBObjectSet implements iDBObjectSetIterator
}
/**
* The total number of rows in this set. Independently of the SetLimit used for loading the set and taking into account the rows added in-memory.
*
* May actually perform the SQL query SELECT COUNT... if the set was not previously loaded, or loaded with a SetLimit
*
* @param string[] $aAttToLoad
*
* @return string SQL query
*/
private function _makeSelectQuery($aAttToLoad)
{
if ($this->m_iLimitCount > 0)
{
$sSQL = $this->m_oFilter->MakeSelectQuery($this->GetRealSortOrder(), $this->m_aArgs, $aAttToLoad,
$this->m_aExtendedDataSpec, $this->m_iLimitCount, $this->m_iLimitStart);
}
else
{
$sSQL = $this->m_oFilter->MakeSelectQuery($this->GetRealSortOrder(), $this->m_aArgs, $aAttToLoad,
$this->m_aExtendedDataSpec);
}
return $sSQL;
}
/**
* The total number of rows in this set. Independently of the SetLimit used for loading the set and taking into
* account the rows added in-memory.
*
* May actually perform the SQL query SELECT COUNT... if the set was not previously loaded, or loaded with a
* SetLimit
*
* @return int The total number of rows for this set.
*/
public function Count()
@@ -639,11 +711,12 @@ class DBObjectSet implements iDBObjectSetIterator
$sSQL = $this->m_oFilter->MakeSelectQuery(array(), $this->m_aArgs, null, null, 0, 0, true);
$resQuery = CMDBSource::Query($sSQL);
if (!$resQuery) return 0;
$aRow = CMDBSource::FetchArray($resQuery);
CMDBSource::FreeResult($resQuery);
$this->m_iNumTotalDBRows = $aRow['COUNT'];
}
return $this->m_iNumTotalDBRows + count($this->m_aAddedObjects); // Does it fix Trac #887 ??
}

View File

@@ -835,4 +835,9 @@ abstract class DBSearch
CMDBSource::Query($sUpdateQuery);
}
}
public function UpdateContextFromUser()
{
$this->SetShowObsoleteData(utils::ShowObsoleteData());
}
}

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2013 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
@@ -408,4 +408,30 @@ class EventLoginUsage extends Event
}
}
?>
class EventOnObject extends Event
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_event_onobject",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
"order_by_default" => array('date' => false)
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("obj_class", array("allowed_values"=>null, "sql"=>"obj_class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("obj_key", array("allowed_values"=>null, "sql"=>"obj_key", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'obj_class', 'obj_key', 'message')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'obj_class', 'obj_key', 'message')); // Attributes to be displayed for a list
}
}

View File

@@ -188,10 +188,10 @@ EOF
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
}
else if ($value instanceOf ormCustomFieldsValue)
else if ($value instanceOf ormDocument)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, "\n", '', $oObj);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
}
else
{

View File

@@ -0,0 +1,110 @@
<?php
// Copyright (c) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
//
class ExpressionCache
{
static private $aCache = array();
static public function GetCachedExpression($sClass, $sAttCode)
{
// read current cache
@include_once (static::GetCacheFileName());
$oExpr = null;
$sKey = static::GetKey($sClass, $sAttCode);
if (array_key_exists($sKey, static::$aCache))
{
$oExpr = static::$aCache[$sKey];
}
else
{
if (class_exists('ExpressionCacheData'))
{
if (array_key_exists($sKey, ExpressionCacheData::$aCache))
{
$sVal = ExpressionCacheData::$aCache[$sKey];
$oExpr = unserialize($sVal);
static::$aCache[$sKey] = $oExpr;
}
}
}
return $oExpr;
}
static public function Warmup()
{
$sFilePath = static::GetCacheFileName();
if (!is_file($sFilePath))
{
$content = <<<EOF
<?php
// Copyright (c) 2010-2017 Combodo SARL
// Generated Expression Cache file
class ExpressionCacheData
{
static \$aCache = array(
EOF;
foreach(MetaModel::GetClasses() as $sClass)
{
$content .= static::GetSerializedExpression($sClass, 'friendlyname');
if (MetaModel::IsObsoletable($sClass))
{
$content .= static::GetSerializedExpression($sClass, 'obsolescence_flag');
}
}
$content .= <<<EOF
);
}
EOF;
file_put_contents($sFilePath, $content);
}
}
static private function GetSerializedExpression($sClass, $sAttCode)
{
$sKey = static::GetKey($sClass, $sAttCode);
$oExpr = DBObjectSearch::GetPolymorphicExpression($sClass, $sAttCode);
return "'".$sKey."' => '".serialize($oExpr)."',\n";
}
/**
* @param $sClass
* @param $sAttCode
* @return string
*/
static private function GetKey($sClass, $sAttCode)
{
return $sClass.'::'.$sAttCode;
}
public static function GetCacheFileName()
{
return utils::GetCachePath().'expressioncache.php';
}
}

View File

@@ -1,9 +1,9 @@
<?php
// Copyright (C) 2010-2017 Combodo SARL
// Copyright (c) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -15,6 +15,7 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
//
require_once(APPROOT.'core/modulehandler.class.inc.php');
require_once(APPROOT.'core/querybuildercontext.class.inc.php');
@@ -23,6 +24,7 @@ require_once(APPROOT.'core/metamodelmodifier.inc.php');
require_once(APPROOT.'core/computing.inc.php');
require_once(APPROOT.'core/relationgraph.class.inc.php');
require_once(APPROOT.'core/apc-compat.php');
require_once(APPROOT.'core/expressioncache.class.inc.php');
/**
* Metamodel
@@ -331,9 +333,16 @@ abstract class MetaModel
}
final static public function GetObsolescenceExpression($sClass)
{
self::_check_subclass($sClass);
$sOql = self::$m_aClassParams[$sClass]['obsolescence_expression'];
$oRet = Expression::FromOQL("COALESCE($sOql, 0)");
if (self::IsObsoletable($sClass))
{
self::_check_subclass($sClass);
$sOql = self::$m_aClassParams[$sClass]['obsolescence_expression'];
$oRet = Expression::FromOQL("COALESCE($sOql, 0)");
}
else
{
$oRet = Expression::FromOQL("0");
}
return $oRet;
}
final static public function GetNameSpec($sClass)
@@ -1857,15 +1866,13 @@ abstract class MetaModel
}
}
// Prepare external fields and filters
// Add final class to external keys
//
// Add magic attributes to the classes
foreach (self::GetClasses() as $sClass)
{
$sRootClass = self::$m_aRootClasses[$sClass];
// Create the friendly name attribute
$sFriendlyNameAttCode = 'friendlyname';
$sFriendlyNameAttCode = 'friendlyname';
$oFriendlyName = new AttributeFriendlyName($sFriendlyNameAttCode);
self::AddMagicAttribute($oFriendlyName, $sClass);
@@ -1875,7 +1882,7 @@ abstract class MetaModel
$oArchiveFlag = new AttributeArchiveFlag('archive_flag');
self::AddMagicAttribute($oArchiveFlag, $sClass);
$oArchiveDate = new AttributeDate('archive_date', array('magic' => true, "allowed_values"=>null, "sql"=>'archive_date', "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array()));
$oArchiveDate = new AttributeArchiveDate('archive_date', array('magic' => true, "allowed_values" => null, "sql" => 'archive_date', "default_value" => '', "is_null_allowed" => true, "depends_on" => array()));
self::AddMagicAttribute($oArchiveDate, $sClass);
}
elseif (self::$m_aClassParams[$sClass]["archive"])
@@ -1898,7 +1905,7 @@ abstract class MetaModel
if (self::$m_aRootClasses[$sClass] == $sClass)
{
$oObsolescenceDate = new AttributeDate('obsolescence_date', array('magic' => true, "allowed_values" => null, "sql" => 'obsolescence_date', "default_value" => '', "is_null_allowed" => true, "depends_on" => array()));
$oObsolescenceDate = new AttributeObsolescenceDate('obsolescence_date', array('magic' => true, "allowed_values" => null, "sql" => 'obsolescence_date', "default_value" => '', "is_null_allowed" => true, "depends_on" => array()));
self::AddMagicAttribute($oObsolescenceDate, $sClass);
}
else
@@ -1909,6 +1916,13 @@ abstract class MetaModel
self::$m_aAttribOrigins[$sClass]['obsolescence_date'] = $sRootClass;
}
}
}
// Prepare external fields and filters
// Add final class to external keys
// Add magic attributes to external keys (finalclass, friendlyname, archive_flag, obsolescence_flag)
foreach (self::GetClasses() as $sClass)
{
foreach (self::$m_aAttribDefs[$sClass] as $sAttCode => $oAttDef)
{
// Compute the filter codes
@@ -4394,6 +4408,8 @@ abstract class MetaModel
echo "Debug<br/>\n";
self::static_var_dump();
}
ExpressionCache::Warmup();
}
public static function LoadConfig($oConfiguration, $bAllowCache = false)
@@ -4590,6 +4606,14 @@ abstract class MetaModel
return self::$m_oConfig;
}
/**
* @return string The environment in which the model has been loaded (e.g. 'production')
*/
public static function GetEnvironment()
{
return self::$m_sEnvironment;
}
public static function GetEnvironmentId()
{
return md5(APPROOT).'-'.self::$m_sEnvironment;
@@ -4675,6 +4699,18 @@ abstract class MetaModel
return $iTotalHits.' ('.implode(', ', $aRes).')';
}
/**
* @param string $sClass
* @param int $iKey
* @param bool $bMustBeFound
* @param bool $bAllowAllData if true then no rights filtering
* @param array $aModifierProperties
*
* @return string[] column name / value array
* @throws CoreException if no result found and $bMustBeFound=true
*
* @see utils::PushArchiveMode() to enable search on archived objects
*/
public static function MakeSingleRow($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
{
// Build the query cache signature
@@ -4731,13 +4767,27 @@ abstract class MetaModel
$aRow = CMDBSource::FetchArray($res);
CMDBSource::FreeResult($res);
if ($bMustBeFound && empty($aRow))
{
throw new CoreException("No result for the single row query: '$sSQL'");
}
return $aRow;
}
/**
* Converts a column name / value array to a {@link DBObject}
*
* @param string $sClass
* @param string[] $aRow column name / value array
* @param string $sClassAlias
* @param string[] $aAttToLoad
* @param array $aExtendedDataSpec
*
* @return DBObject
* @throws CoreException if finalClass cannot be found
*/
public static function GetObjectByRow($sClass, $aRow, $sClassAlias = '', $aAttToLoad = null, $aExtendedDataSpec = null)
{
self::_check_subclass($sClass);
@@ -4771,30 +4821,75 @@ abstract class MetaModel
}
/**
* @param $sClass
* Search for the specified class and id.
*
* @param string $sClass
* @param $iKey
* @param bool $bMustBeFound
* @param bool $bAllowAllData
* @param null $aModifierProperties
* @return DBObject|null
* @return DBObject|null null if : (the object is not found) or (archive mode disabled and object is archived and $bMustBeFound=false)
* @throws CoreException if no result found and $bMustBeFound=true
* @throws ArchivedObjectException if archive mode disabled and result is archived and $bMustBeFound=true
*
* @see MetaModel::GetObjectWithArchive to get object even if it's archived
* @see utils::PushArchiveMode() to enable search on archived objects
*/
public static function GetObject($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
{
self::_check_subclass($sClass);
$oObject = self::GetObjectWithArchive($sClass, $iKey, $bMustBeFound, $bAllowAllData, $aModifierProperties);
if (empty($oObject))
{
return null;
}
if (!utils::IsArchiveMode() && $oObject->IsArchived())
{
if ($bMustBeFound)
{
throw new ArchivedObjectException("The object $sClass::$iKey is archived");
}
else
{
return null;
}
}
return $oObject;
}
/**
* Search for the specified class and id. If the object is archived it will be returned anyway (this is for pre-2.4
* module compatibility, see N.1108)
*
* @param string $sClass
* @param int $iKey
* @param bool $bMustBeFound
* @param bool $bAllowAllData
* @param array $aModifierProperties
*
* @return DBObject|null
* @throws CoreException if no result found and $bMustBeFound=true
*
* @since 2.4 introduction of the archive functionalities
*
* @see MetaModel::GetObject() same but returns null or ArchivedObjectFoundException if object exists but is archived
*/
public static function GetObjectWithArchive($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
{
self::_check_subclass($sClass);
utils::PushArchiveMode(true);
$aRow = self::MakeSingleRow($sClass, $iKey, $bMustBeFound, $bAllowAllData, $aModifierProperties);
utils::PopArchiveMode();
if (empty($aRow))
{
return null;
}
return self::GetObjectByRow($sClass, $aRow);
}
public static function GetObjectWithArchive($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
{
utils::PushArchiveMode(true);
$oObject = static::GetObject($sClass, $iKey, $bMustBeFound, $bAllowAllData, $aModifierProperties);
utils::PopArchiveMode();
return $oObject;
return self::GetObjectByRow($sClass, $aRow); // null should not be returned, this is handled in the callee
}
public static function GetObjectByName($sClass, $sName, $bMustBeFound = true)
@@ -5226,21 +5321,12 @@ abstract class MetaModel
public static function GetCacheEntries($sEnvironment = null)
{
if (!function_exists('apc_cache_info')) return array();
if (is_null($sEnvironment))
{
$sEnvironment = MetaModel::GetEnvironmentId();
}
$aEntries = array();
if (extension_loaded('apcu'))
{
// Beware: APCu behaves slightly differently from APC !!
$aCacheUserData = @apc_cache_info();
}
else
{
$aCacheUserData = @apc_cache_info('user');
}
$aCacheUserData = apc_cache_info_compat();
if (is_array($aCacheUserData) && isset($aCacheUserData['cache_list']))
{
$sPrefix = 'itop-'.$sEnvironment.'-';

View File

@@ -1,9 +1,9 @@
<?php
// Copyright (C) 2010-2017 Combodo SARL
// Copyright (c) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
@@ -15,14 +15,7 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* General definition of an expression tree (could be OQL, SQL or whatever)
*
* @copyright Copyright (C) 2010-2017 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
//
class MissingQueryArgument extends CoreException
{
@@ -89,9 +82,15 @@ abstract class Expression
*/
static public function FromOQL($sConditionExpr)
{
static $aCache = array();
if (array_key_exists($sConditionExpr, $aCache))
{
return $aCache[$sConditionExpr];
}
$oOql = new OqlInterpreter($sConditionExpr);
$oExpression = $oOql->ParseExpression();
$aCache[$sConditionExpr] = $oExpression;
return $oExpression;
}

View File

@@ -191,8 +191,15 @@ class ormCaseLog {
public function __toString()
{
return $this->m_sLog;
if($this->IsEmpty()) return '';
return $this->m_sLog;
}
public function IsEmpty()
{
return ($this->m_sLog === null);
}
public function ClearModifiedFlag()
{

View File

@@ -51,6 +51,8 @@ class ormDocument
public function __toString()
{
if($this->IsEmpty()) return '';
return MyHelpers::beautifulstr($this->m_data, 100, true);
}

View File

@@ -52,7 +52,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
* Object from the original set, minus the removed objects
* @var DBObject[] array of iObjectId => DBObject
*/
protected $aPreserved;
protected $aPreserved = array();
/**
* @var DBObject[] New items
@@ -130,12 +130,10 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
/**
* @param DBObject $oObject
* @param string $sClassAlias
* @deprecated
* @deprecated Since iTop 2.4, use ormLinkset->AddItem() instead.
*/
public function AddObject(DBObject $oObject, $sClassAlias = '')
{
trigger_error('iTop: ormLinkSet::AddObject() is deprecated use ormLinkSet::AddItem() instead.', E_USER_DEPRECATED);
$this->AddItem($oObject);
}
@@ -158,9 +156,14 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
public function ModifyItem(DBObject $oLink)
{
assert($oLink instanceof $this->sClass);
$iObjectId = $oLink->GetKey();
$this->aModified[$iObjectId] = $oLink;
$this->bHasDelta = true;
if (array_key_exists($iObjectId, $this->aPreserved))
{
unset($this->aPreserved[$iObjectId]);
$this->aModified[$iObjectId] = $oLink;
$this->bHasDelta = true;
}
}
protected function LoadOriginalIds()
@@ -169,15 +172,22 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
{
if ($this->oOriginalSet)
{
$this->aOriginalObjects = $this->oOriginalSet->ToArray();
$this->aOriginalObjects = $this->GetArrayOfIndex();
$this->aPreserved = $this->aOriginalObjects; // Copy (not effective until aPreserved gets modified)
foreach ($this->aRemoved as $iObjectId)
{
if (array_key_exists($iObjectId, $this->aPreserved))
{
unset($this->aPreserved[$iObjectId]);
}
}
foreach ($this->aRemoved as $iObjectId)
{
if (array_key_exists($iObjectId, $this->aPreserved))
{
unset($this->aPreserved[$iObjectId]);
}
}
foreach ($this->aModified as $iObjectId => $oLink)
{
if (array_key_exists($iObjectId, $this->aPreserved))
{
unset($this->aPreserved[$iObjectId]);
}
}
}
else
{
@@ -189,17 +199,29 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
}
}
/**
* Note: After calling this method, the set cursor will be at the end of the set. You might want to rewind it.
* @return array
*/
protected function GetArrayOfIndex()
{
$aRet = array();
$this->oOriginalSet->Rewind();
$iRow = 0;
while ($oObject = $this->oOriginalSet->Fetch())
{
$aRet[$oObject->GetKey()] = $iRow++;
}
return $aRet;
}
/**
* Note: After calling this method, the set cursor will be at the end of the set. You might to rewind it.
*
* @param bool $bWithId
* @return array
* @deprecated
* @deprecated Since iTop 2.4, use foreach($this as $oItem){} instead
*/
public function ToArray($bWithId = true)
{
trigger_error('iTop: ormLinkSet::ToArray() is deprecated use foreach instead.', E_USER_DEPRECATED);
$aRet = array();
foreach($this as $oItem)
{
@@ -215,6 +237,28 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
return $aRet;
}
/**
* @param string $sAttCode
* @param bool $bWithId
* @return array
*/
public function GetColumnAsArray($sAttCode, $bWithId = true)
{
$aRet = array();
foreach($this as $oItem)
{
if ($bWithId)
{
$aRet[$oItem->GetKey()] = $oItem->Get($sAttCode);
}
else
{
$aRet[] = $oItem->Get($sAttCode);
}
}
return $aRet;
}
/**
* The class of the objects of the collection (at least a common ancestor)
*
@@ -233,7 +277,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
public function Count()
{
$this->LoadOriginalIds();
$iRet = count($this->aPreserved) + count($this->aAdded);
$iRet = count($this->aPreserved) + count($this->aAdded) + count($this->aModified);
return $iRet;
}
@@ -290,11 +334,21 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$iPreservedCount = count($this->aPreserved);
if ($this->iCursor < $iPreservedCount)
{
$oRet = current($this->aPreserved);
$iRet = current($this->aPreserved);
$this->oOriginalSet->Seek($iRet);
$oRet = $this->oOriginalSet->Fetch();
}
else
{
$oRet = current($this->aAdded);
$iModifiedCount = count($this->aModified);
if($this->iCursor < $iPreservedCount + $iModifiedCount)
{
$oRet = current($this->aModified);
}
else
{
$oRet = current($this->aAdded);
}
}
return $oRet;
}
@@ -315,9 +369,17 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
}
else
{
next($this->aAdded);
$iModifiedCount = count($this->aModified);
if($this->iCursor < $iPreservedCount + $iModifiedCount)
{
next($this->aModified);
}
else
{
next($this->aAdded);
}
}
// Increment AFTER moving the internal cursors because when starting aAdded, we must leave it intact
// Increment AFTER moving the internal cursors because when starting aModified / aAdded, we must leave it intact
$this->iCursor++;
}
@@ -353,11 +415,12 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
*/
public function rewind()
{
$this->LoadOriginalIds();
$this->LoadOriginalIds();
$this->iCursor = 0;
$this->iCursor = 0;
reset($this->aPreserved);
reset($this->aAdded);
reset($this->aAdded);
reset($this->aModified);
}
public function HasDelta()
@@ -429,7 +492,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$this->aAdded = array();
$this->aRemoved = array();
$this->aModified = array();
$this->aPreserved = $this->aOriginalObjects;
$this->aPreserved = ($this->aOriginalObjects === null) ? array() : $this->aOriginalObjects;
$this->bHasDelta = false;
/** @var AttributeLinkedSet $oAttDef */
@@ -504,12 +567,15 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
// Check for the existing links
//
/** @var DBObject[] $aExistingLinks */
$aExistingLinks = array();
/** @var Int[] $aExistingRemote */
$aExistingRemote = array();
if (count($aCheckLinks) > 0)
{
$oSearch = new DBObjectSearch($this->sClass);
$oSearch->AddCondition('id', $aCheckLinks, 'IN');
$oSet = new DBObjectSet($oSearch);
/** @var DBObject[] $aExistingLinks */
$aExistingLinks = $oSet->ToArray();
}
@@ -521,7 +587,6 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$oSearch->AddCondition($sExtKeyToMe, $oHostObject->GetKey(), '=');
$oSearch->AddCondition($sExtKeyToRemote, $aCheckRemote, 'IN');
$oSet = new DBObjectSet($oSearch);
/** @var Int[] $aExistingRemote */
$aExistingRemote = $oSet->GetColumnAsArray($sExtKeyToRemote);
}
@@ -598,4 +663,34 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
//
$oMtx->Unlock();
}
public function ToDBObjectSet($bShowObsolete = true)
{
$oAttDef = MetaModel::GetAttributeDef($this->sHostClass, $this->sAttCode);
$oLinkSearch = $this->GetFilter();
if ($oAttDef->IsIndirect())
{
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
$oLinkingAttDef = MetaModel::GetAttributeDef($this->sClass, $sExtKeyToRemote);
$sTargetClass = $oLinkingAttDef->GetTargetClass();
if (!$bShowObsolete && MetaModel::IsObsoletable($sTargetClass))
{
$oNotObsolete = new BinaryExpression(
new FieldExpression('obsolescence_flag', $sTargetClass),
'=',
new ScalarExpression(0)
);
$oNotObsoleteRemote = new DBObjectSearch($sTargetClass);
$oNotObsoleteRemote->AddConditionExpression($oNotObsolete);
$oLinkSearch->AddCondition_PointingTo($oNotObsoleteRemote, $sExtKeyToRemote);
}
}
$oLinkSet = new DBObjectSet($oLinkSearch);
$oLinkSet->SetShowObsoleteData($bShowObsolete);
if ($this->HasDelta())
{
$oLinkSet->AddObjectArray($this->aAdded);
}
return $oLinkSet;
}
}

View File

@@ -226,9 +226,9 @@ EOF
$iNewWidth = $iWidth * $fScale;
$iNewHeight = $iHeight * $fScale;
$sUrl = 'data:' . $value->GetMimeType() . ';base64,' . base64_encode($value->GetData());
$sUrl = 'data:'.$value->GetMimeType().';base64,'.base64_encode($value->GetData());
}
$sRet = '<img src="' . $sUrl . '" style="width: ' . $iNewWidth . 'px; height: ' . $iNewHeight . 'px">';
$sRet = ($sUrl !== null) ? '<img src="'.$sUrl.'" style="width: '.$iNewWidth.'px; height: '.$iNewHeight.'px">' : '';
$sRet = '<div class="view-image">'.$sRet.'</div>';
}
else

View File

@@ -175,7 +175,8 @@ EOF
}
elseif ($oAttDef instanceof AttributeCustomFields)
{
$sRet = $oObj->GetAsHTML($sAttCode);
// Stick to the weird implementation made in GetNextChunk
$sRet = utils::TextToHtml($oObj->GetEditValue($sAttCode));
}
else
{
@@ -326,6 +327,12 @@ EOF
}
$sData .= "<td x:str>$sField</td>";
}
elseif ($oAttDef instanceof AttributeCustomFields)
{
// GetAsHTML returns a table that would not fit
$sField = utils::TextToHtml($oObj->GetEditValue($sAttCode));
$sData .= "<td x:str>$sField</td>";
}
else if($oAttDef instanceof AttributeString)
{
$sField = $oObj->GetAsHTML($sAttCode, $this->bLocalizeOutput);

View File

@@ -36,7 +36,8 @@
class SQLObjectQuery extends SQLQuery
{
private $m_SourceOQL = '';
public $m_aContextData = null;
public $m_iOriginalTableCount = 0;
private $m_sTable = '';
private $m_sTableAlias = '';
private $m_aFields = array();
@@ -510,6 +511,7 @@ class SQLObjectQuery extends SQLQuery
public function OptimizeJoins($aUsedTables, $bTopCall = true)
{
$this->m_iOriginalTableCount = $this->CountTables();
if ($bTopCall)
{
// Top call: complete the list of tables absolutely required to perform the right query
@@ -612,4 +614,5 @@ class SQLObjectQuery extends SQLQuery
// None of the tables is in the list of required tables
return $bResult;
}
}

View File

@@ -5,4 +5,4 @@ $complement-light: #d6e8ef;
$frame-background-color: #F1F1F1;
$text-color: #000;
// Beware the version number MUST be enclosed with quotes otherwise v2.3.0 becomes v2 0.3 .0
$version: "v2.4.0-beta";
$version: "v2.4.0";

Binary file not shown.

View File

@@ -21,7 +21,7 @@ OS2Version: 0
OS2_WeightWidthSlopeOnly: 0
OS2_UseTypoMetrics: 1
CreationTime: 1463745065
ModificationTime: 1464178421
ModificationTime: 1506001058
OS2TypoAscent: 0
OS2TypoAOffset: 1
OS2TypoDescent: 0
@@ -35,7 +35,6 @@ HheadAscent: 0
HheadAOffset: 1
HheadDescent: 0
HheadDOffset: 1
OS2Vendor: 'PfEd'
MarkAttachClasses: 1
DEI: 91125
Encoding: ISO8859-1
@@ -47,7 +46,7 @@ FitToEm: 0
WinInfo: 0 31 10
BeginPrivate: 0
EndPrivate
BeginChars: 256 8
BeginChars: 256 11
StartChar: zero
Encoding: 48 48 0
@@ -210,7 +209,7 @@ StartChar: three
Encoding: 51 51 3
Width: 1022
VWidth: 0
Flags: MO
Flags: M
LayerCount: 3
Fore
SplineSet
@@ -261,11 +260,13 @@ StartChar: C
Encoding: 67 67 4
Width: 1080
VWidth: 0
Flags: HW
Flags: W
HStem: -112 36<398.67 444.211> 97 36<463.993 575.071> 116 37<411.524 459.906> 250 37<334.123 402.464> 335 37<749.246 821.773> 387 37<836.543 929.295> 396 37<873.093 933.545> 442 37<475 482 739.647 795.664> 621 37<286.042 389.13> 650 37<510.192 579.789>
VStem: 53 37<216.048 298> 218 37<457.867 579.651> 272 36<60.6299 128.446> 439 37<479.452 577.67> 451 37<-73.2171 5.85426> 472 37<568.829 649.107> 553 37<359.872 417.574> 651 38<-34.3438 62.6665> 718 38<8.82031 164.606> 934 38<341.569 396>
LayerCount: 3
Fore
SplineSet
641 -116 m 4x9b20
641 -116 m 4x9b39f0
637 -116 633 -115 630 -113 c 4
624 -110 616 -102 616 -88 c 4
616 -84 617 -80 618 -75 c 4
@@ -275,14 +276,14 @@ SplineSet
651 31 641 52 624 75 c 4
609 94 595 108 586 115 c 5
562 107 523 97 500 97 c 6
499 97 l 6xdb20
499 97 l 6xdb39f0
479 97 468 105 460 111 c 4
457 114 455 115 453 116 c 4
450 116 438 112 423 104 c 4
412 98 405 94 401 90 c 5
411 80 436 61 448 52 c 4
460 43 468 37 473 32 c 4
485 20 488 -4 488 -20 c 4
485 20 488 -4 488 -20 c 4xb93af0
488 -27 487 -33 487 -36 c 4
485 -55 477 -90 452 -105 c 4
444 -110 435 -112 426 -112 c 4
@@ -321,10 +322,10 @@ SplineSet
219 484 218 493 218 504 c 4
218 526 222 550 231 575 c 4
237 593 255 636 284 651 c 4
293 656 305 658 320 658 c 4xb9a0
293 656 305 658 320 658 c 4
342 658 367 653 389 644 c 4
416 633 437 617 452 597 c 4
472 571 476 537 476 508 c 4
472 571 476 537 476 508 c 4xb9bcf0
476 497 476 487 475 479 c 5
482 479 l 5
505 499 l 5
@@ -352,7 +353,7 @@ SplineSet
766 473 767 473 768 473 c 4
787 473 808 460 831 446 c 4
845 437 865 424 873 424 c 4
874 424 l 6x9d60
874 424 l 6x9d79f0
875 424 880 425 884 426 c 4
897 429 915 433 930 433 c 4
956 433 965 421 969 412 c 4
@@ -362,7 +363,7 @@ SplineSet
916 289 911 288 905 288 c 4
888 288 863 299 835 311 c 4
810 322 780 335 766 335 c 4
765 335 764 335 764 335 c 4
764 335 l 4
763 335 757 331 748 315 c 4
741 301 734 283 727 264 c 4
721 248 715 231 708 216 c 5
@@ -370,7 +371,7 @@ SplineSet
756 69 755 58 753 47 c 4
748 19 727 -22 708 -51 c 4
697 -68 687 -82 677 -93 c 4
663 -109 652 -116 641 -116 c 4x9b20
663 -109 652 -116 641 -116 c 4x9b39f0
308 85 m 5
308 83 312 72 340 46 c 4
357 30 374 18 374 18 c 6
@@ -387,14 +388,14 @@ SplineSet
383 55 362 72 362 90 c 4
362 92 362 93 362 95 c 4
363 100 366 113 402 134 c 4
410 138 435 153 453 153 c 4xb9a0
410 138 435 153 453 153 c 4xb9baf0
455 153 458 152 460 152 c 4
470 150 476 145 482 141 c 4
488 136 491 133 499 133 c 6
500 133 l 6xd920
500 133 l 6xd93af0
521 133 562 145 581 153 c 6
589 156 l 5
596 153 l 6xb920
596 153 l 6xb93af0
612 146 637 119 654 97 c 4
670 75 689 44 689 16 c 4
689 13 689 10 688 7 c 4
@@ -413,7 +414,7 @@ SplineSet
868 337 893 326 903 325 c 5
907 329 916 340 924 359 c 4
932 377 934 390 934 396 c 4
933 396 932 396 930 396 c 4xdb20
933 396 932 396 930 396 c 4xdb3af0
919 396 902 392 892 390 c 4
886 389 881 388 878 388 c 4
876 388 875 387 873 387 c 4
@@ -433,9 +434,9 @@ SplineSet
629 559 619 566 619 566 c 6
615 569 l 5
580 633 l 5
566 639 539 650 520 650 c 4x9d60
566 639 539 650 520 650 c 4
514 650 512 650 511 649 c 4
510 648 509 644 509 637 c 4
510 648 509 644 509 637 c 4x9d79f0
509 629 510 618 514 602 c 4
517 589 520 577 523 569 c 5
562 561 l 5
@@ -446,7 +447,7 @@ SplineSet
435 465 l 6
437 474 439 491 439 510 c 4
439 533 436 558 423 575 c 4
400 605 354 621 320 621 c 4x99a0
400 605 354 621 320 621 c 4x99bcf0
310 621 304 619 301 618 c 4
281 608 255 548 255 504 c 4
255 497 255 490 257 484 c 4
@@ -475,22 +476,25 @@ SplineSet
424 204 390 196 377 186 c 4
330 149 310 105 308 85 c 5
EndSplineSet
Validated: 1
EndChar
StartChar: I
Encoding: 73 73 5
Width: 1024
VWidth: 0
Flags: HW
Flags: W
HStem: -154 166<226 365 659 798> 126 26<498.267 525.733> 151 131<288 343 681 735> 313 132<288 343 681 735> 330 32<424.389 599.754> 443 26<498.267 525.733> 584 184<226 365 659 798>
VStem: 51 175<12 151 445 584> 365 132<74 126 469 521> 366 31<282 313> 527 132<74 126 469 521> 627 31<282 313> 798 175<12 151 445 584>
LayerCount: 3
Fore
SplineSet
51 -154 m 1
51 -154 m 1x8308
51 768 l 1
973 768 l 1
973 -154 l 1
51 -154 l 1
497 469 m 2
51 -154 l 1x8308
497 469 m 1x87a8
502 469 507 470 512 470 c 0
517 470 522 469 527 469 c 1
527 521 l 1
@@ -498,35 +502,34 @@ SplineSet
512 702 l 1
414 604 l 1
497 521 l 1
497 469 l 1
497 469 l 2
497 469 l 1x87a8
653 417 m 1
681 445 l 1
798 445 l 1
798 445 l 1x9328
798 584 l 1
659 584 l 1
659 467 l 1
633 440 l 1
643 433 649 425 653 417 c 1
366 282 m 1
366 282 m 1xb348
366 313 l 1
288 313 l 1
206 396 l 1
108 298 l 1
206 200 l 1
288 282 l 1
366 282 l 1
366 282 l 1xb348
343 445 m 1
371 417 l 1
375 425 381 433 391 440 c 1
365 467 l 1
365 584 l 1
365 584 l 1x9388
226 584 l 1
226 445 l 1
343 445 l 1
371 178 m 1
343 151 l 1
226 151 l 1
226 151 l 1xa388
226 12 l 1
365 12 l 1
365 129 l 1
@@ -535,7 +538,7 @@ SplineSet
818 396 m 1
735 313 l 1
658 313 l 1
658 282 l 1
658 282 l 1xb318
735 282 l 1
818 200 l 1
916 298 l 1
@@ -543,12 +546,12 @@ SplineSet
653 178 m 1
649 170 643 162 633 155 c 1
659 129 l 1
659 12 l 1
659 12 l 1xa328
798 12 l 1
798 151 l 1
681 151 l 1
653 178 l 1
527 126 m 1
527 126 m 1xc3a8
522 126 517 126 512 126 c 0
507 126 502 126 497 126 c 1
497 74 l 1
@@ -556,8 +559,7 @@ SplineSet
512 -106 l 1
610 -8 l 1
527 74 l 1
527 126 l 1
527 126 l 1
527 126 l 1xc3a8
610 348 m 0
584 337 549 330 512 330 c 0
475 330 441 337 414 348 c 0
@@ -567,9 +569,9 @@ SplineSet
449 157 479 152 512 152 c 0
545 152 575 157 598 167 c 0
616 174 627 184 627 192 c 2
627 356 l 1
627 356 l 1xcb58
622 353 616 351 610 348 c 0
512 443 m 1
512 443 m 1x8f58
479 443 449 438 426 428 c 0
408 421 397 410 397 402 c 0
397 394 408 384 426 377 c 0
@@ -577,8 +579,7 @@ SplineSet
545 362 575 367 598 377 c 0
616 384 627 394 627 402 c 0
627 410 616 421 598 428 c 0
575 438 545 443 512 443 c 1
512 443 l 1
575 438 545 443 512 443 c 1x8f58
EndSplineSet
Validated: 5
EndChar
@@ -587,7 +588,8 @@ StartChar: four
Encoding: 52 52 6
Width: 1024
VWidth: 0
Flags: H
HStem: -2 41<389.544 635.489> 292 109<316 441 550 675> 639 41<389.544 636.396>
VStem: 117 41<241.556 436.857> 441 109<167 292 401 525> 868 41<249.643 435.223>
LayerCount: 3
Fore
SplineSet
@@ -607,7 +609,6 @@ SplineSet
909 288 892 238 861 189 c 0
835 149 801 111 757 77 c 1
801 -67 l 1
801 -67 l 1
649 63 m 1
733 17 l 1
710 93 l 1
@@ -618,7 +619,6 @@ SplineSet
158 174 317 39 513 39 c 0
552 39 592 49 634 59 c 2
649 63 l 1
649 63 l 1
675 306 m 1
675 298 667 292 657 292 c 2
550 292 l 1
@@ -640,7 +640,6 @@ SplineSet
657 401 l 2
667 401 675 394 675 386 c 2
675 306 l 1
675 306 l 1
EndSplineSet
Validated: 5
EndChar
@@ -649,15 +648,17 @@ StartChar: D
Encoding: 68 68 7
Width: 1080
VWidth: 0
Flags: HW
Flags: W
HStem: 198 131<79.9424 131.341> 306 98<835.102 921.871> 353 100<731.982 810.871>
VStem: 238 219<460.138 583.719> 292 88<67.6511 114.863> 369 100<-72.2559 6.9753> 667 66<3.74069 76.8123>
LayerCount: 3
Fore
SplineSet
469 -14 m 4
469 -14 m 4x26
469 -45 459 -89 425 -89 c 4
397 -89 372 -53 369 -41 c 4
397 -89 372 -53 369 -41 c 4x26
365 -27 363 7 363 7 c 5
363 7 292 63 292 88 c 4
363 7 292 63 292 88 c 4x2a
292 113 317 164 366 202 c 4
388 219 439 225 439 225 c 5
439 225 414 269 373 269 c 4
@@ -669,7 +670,7 @@ SplineSet
119 206 108 198 97 198 c 4
78 198 76 234 76 261 c 4
76 268 76 274 76 279 c 4
76 288 76 295 76 295 c 6
76 295 l 6
76 295 82 320 96 328 c 4
97 328 98 329 99 329 c 4
121 329 217 268 217 268 c 6
@@ -696,12 +697,12 @@ SplineSet
570 401 569 394 569 388 c 4
569 355 614 330 614 330 c 5
614 330 646 364 662 384 c 4
678 404 734 453 763 453 c 4
678 404 734 453 763 453 c 4xb2
790 453 841 404 867 404 c 4
878 404 902 413 924 413 c 4
938 413 945 409 945 396 c 4
945 371 922 318 905 307 c 4
903 306 902 306 899 306 c 4
903 306 902 306 899 306 c 4x52
872 306 795 353 761 353 c 4
758 353 756 353 754 352 c 4
723 342 708 263 682 213 c 5
@@ -714,11 +715,232 @@ SplineSet
667 64 605 129 586 138 c 5
565 130 522 118 499 118 c 4
475 118 470 137 453 137 c 4
437 137 380 108 380 93 c 4
437 137 380 108 380 93 c 4x2a
380 77 446 36 460 23 c 4
465 18 469 3 469 -14 c 4
465 18 469 3 469 -14 c 4x26
EndSplineSet
Validated: 1
EndChar
StartChar: E
Encoding: 69 69 8
Width: 1024
VWidth: 0
HStem: -65 248<767.992 903.557> 62.9598 56.9516<226.56 349.224 705.189 710> 143 26.9554<256.859 324.845> 192.776 27.2245<289.957 314.952> 295.071 27.9295<269.575 354.789> 344 66<376.038 439.962> 433 25<407.015 431.988> 469 248<767.951 904.873>
VStem: 66.5097 115.469<193.203 298.14> 204 32.9583<187.285 267.499> 257.966 57.0345<194.835 224.243> 335.831 30.8205<177.895 239.59> 388.713 44.4108<157.773 270.37> 407 25<433.012 457.985> 442 55.4336<365.791 447.874> 711 249<-8.06335 62 583 662.557>
LayerCount: 3
Fore
SplineSet
279 573 m 0x7ffb
292 573 313 570 343 563 c 0
462 535 489 420 496 389 c 0
496.963 384.737 497.434 380.795 497.434 377.167 c 0
497.434 354.414 478.912 344 447 344 c 0
422.333 344 394.111 344.889 359.074 344.889 c 0
341.556 344.889 322.333 344.667 301 344 c 0
237 342 192 300 183 241 c 0
182.31 236.477 181.979 231.948 181.979 227.44 c 0
181.979 173.142 230.063 121.847 279 120 c 0
280.57 119.941 282.134 119.911 283.69 119.911 c 0
334.636 119.911 377.296 151.452 387 199 c 0
388.159 204.678 388.713 210.303 388.713 215.813 c 0
388.713 257.852 356.437 293.232 314 295 c 0
312.865 295.047 311.742 295.071 310.63 295.071 c 0
264.267 295.071 236.958 255.02 236.958 229.128 c 0
236.958 206.914 253.918 170.972 286 170 c 0
287.107 169.97 288.186 169.955 289.238 169.955 c 0
323.358 169.955 329.15 185.419 334 199 c 0
335.206 202.378 335.831 206.221 335.831 210.207 c 0
335.831 222.743 329.657 236.689 316 242 c 0
298 249 291 238 290 234 c 0
289 228 294 220 299 220 c 0
306 220 316 220 315 206 c 0
314.143 195.714 302.265 192.776 292.592 192.776 c 0
290.98 192.776 289.429 192.857 288 193 c 0
278.231 193.977 257.966 202.588 257.966 228.155 c 0
257.966 248.46 275.443 271.256 306.289 271.256 c 0
308.143 271.256 310.047 271.172 312 271 c 0
351.28 267.429 366.651 246.325 366.651 219.783 c 0
366.651 216.594 366.429 213.326 366 210 c 0
362 179 343 143 284 143 c 0
225 143 204 192 204 229 c 0
204 266 232 322 318 323 c 0
318.502 323.006 319.002 323.009 319.501 323.009 c 0
394.354 323.009 433.124 257.543 433.124 205.254 c 0
433.124 198.198 432.418 191.383 431 185 c 0
420.148 134.686 398.59 62.9598 273.187 62.9598 c 0
271.478 62.9598 269.749 62.9731 268 63 c 0
134.539 65.8599 66.5097 196.855 66.5097 295.718 c 0
66.5097 300.562 66.673 305.329 67 310 c 0
74 410 112 447 146 480 c 0
204.987 537.114 264.85 531.109 264.85 543.245 c 0
264.85 544.071 264.573 544.981 264 546 c 0
260.913 551.732 257.827 557.659 257.827 562.495 c 0
257.827 568.625 262.788 573 279 573 c 0x7ffb
408 478 m 0
389 478 374 463 374 444 c 0
374 425 389 410 408 410 c 0
427 410 442 425 442 444 c 0
442 463 427 478 408 478 c 0
835 717 m 0
904 717 960 662 960 593 c 0
960 524 904 469 835 469 c 0
798 469 751 495 731 526 c 1
515 456 l 1
503 483 491 498 481 511 c 1
712 583 l 2
712 586 711 590 711 593 c 0
711 662 766 717 835 717 c 0
462 207 m 1
727 121 l 1
747 155 795 183 834 183 c 0
903 183 958 128 958 59 c 0
958 -10 903 -65 834 -65 c 0x9ff3
765 -65 710 -10 710 59 c 0
710 60 710 61 710 62 c 2
456 143 l 1
458.679 159.077 462.157 171.165 462.157 197.076 c 0
462.157 200.176 462.107 203.474 462 207 c 1
407 445 m 0x1ff7
407 453 412 458 420 458 c 0
428 458 432 453 432 445 c 0
432 437 428 433 420 433 c 0
412 433 407 437 407 445 c 0x1ff7
EndSplineSet
Validated: 1
EndChar
StartChar: F
Encoding: 70 70 9
Width: 1024
VWidth: 0
HStem: -36 87<438.038 591.036> 87 39<470.027 570.5> 163 41<517.914 555.989> 241 41<519.089 577.135> 317 43<482.813 612.995> 394 100<654.807 741.193> 528 39<697.004 734.996>
VStem: 177 177<195.689 296.938> 387 50<156.758 272.234> 469 87<171.273 203.985> 588 47<139.283 231.811> 669 67<122.953 266.087> 697 38<528.004 566.995> 750 85<426.5 559.5>
LayerCount: 3
Fore
SplineSet
502 742 m 0xfff4
522 742 553 738 599 727 c 0
780 684 822 509 833 462 c 0
835 456 835 450 835 444 c 0
835 409 806 392 758 392 c 0
721 392 678 394 624 394 c 0
597 394 568 393 535 392 c 0
437 388 368 325 355 235 c 0
354 228 354 222 354 215 c 0
354 132 426 55 501 51 c 0
504 51 507 51 510 51 c 0
587 51 652 99 666 171 c 0
668 180 669 188 669 196 c 0
669 260 620 313 555 317 c 0
553 317 550 317 548 317 c 0
478 317 437 256 437 218 c 0
437 184 463 127 512 126 c 0
514 126 516 126 518 126 c 0
569 126 578 150 586 171 c 0
588 176 588 181 588 187 c 0
588 207 579 228 557 237 c 0
550 240 545 241 540 241 c 0
525 241 520 230 518 225 c 0
516 216 524 204 532 204 c 0
543 204 556 202 556 183 c 0
556 166 541 163 525 163 c 0
522 163 518 163 515 163 c 0
499 164 469 177 469 217 c 0
469 247 497 282 543 282 c 0
546 282 549 282 552 282 c 0
611 277 635 243 635 202 c 0
635 197 635 193 634 188 c 0
628 141 598 87 508 87 c 0
418 87 387 162 387 218 c 0
387 274 430 358 561 360 c 0
562 360 563 360 564 360 c 0
677 360 736 262 736 182 c 0
736 171 735 160 733 150 c 0
716 74 683 -36 494 -36 c 0
491 -36 487 -36 484 -36 c 0
280 -32 177 170 177 321 c 0
177 328 178 335 178 342 c 0
188 495 246 549 298 600 c 0
388 687 479 677 479 696 c 0
479 697 479 698 478 700 c 0
473 709 469 718 469 725 c 0
469 735 477 742 502 742 c 0xfff4
698 597 m 0
669 597 646 574 646 545 c 0
646 516 669 494 698 494 c 0
727 494 750 516 750 545 c 0
750 574 727 597 698 597 c 0
697 547 m 0xffec
697 560 703 567 716 567 c 0
729 567 735 560 735 547 c 0
735 534 729 528 716 528 c 0
703 528 697 534 697 547 c 0xffec
EndSplineSet
Validated: 1
EndChar
StartChar: O
Encoding: 79 79 10
Width: 1024
VWidth: 0
HStem: 1.59961 8<801.97 829.007> 20 35.2002<801.975 810.774 823.574 824.837> 33.5996 5.60059<810.774 817.806> 48.7998 6.40039<810.774 818.736> 61.5996 8.7998<801.043 829.91> 434.399 245.601<441.712 567.228>
VStem: 780.375 8.7998<21.8033 49.6942> 801.975 8.7998<20 33.5996 39.2002 48.7998> 819.574 8.80078<40.0451 47.9513> 841.175 8.7998<21.5374 50.3356>
LayerCount: 3
Fore
SplineSet
504.375 680 m 0x8fc0
672.375 680 816.375 560 846.774 395.2 c 0
877.175 230.399 785.975 67.2002 629.175 7.2002 c 0
621.975 4.7998 613.975 8 611.574 15.2002 c 2
533.175 218.399 l 2
530.774 225.6 533.975 234.399 541.175 236.8 c 0
587.574 254.399 613.975 301.6 605.175 350.399 c 0
596.375 399.2 553.975 434.399 504.375 434.399 c 0
454.774 434.399 413.175 399.2 404.375 350.399 c 0
395.574 301.6 421.175 254.399 467.574 236.8 c 0
474.774 234.399 477.975 225.6 475.574 218.399 c 2
397.975 15.2002 l 2
395.574 8 386.774 4.7998 379.574 7.2002 c 0
222.774 67.2002 131.574 230.399 161.975 395.2 c 0
192.375 560 336.375 680 504.375 680 c 0x8fc0
815.574 70.3994 m 0
834.774 70.3994 849.975 55.2002 849.975 36 c 0
849.975 16.7998 834.774 1.59961 815.574 1.59961 c 0
796.375 1.59961 780.375 16.7998 780.375 36 c 0
780.375 55.2002 796.375 70.3994 815.574 70.3994 c 0
815.574 61.5996 m 0
801.175 61.5996 789.175 50.3994 789.175 36 c 0
789.175 21.5996 801.175 9.59961 815.574 9.59961 c 0
829.975 9.59961 841.175 21.5996 841.175 36 c 0
841.175 50.3994 829.975 61.5996 815.574 61.5996 c 0
814.774 39.2002 m 2xbfc0
816.375 39.2002 817.975 40 818.774 40.7998 c 0
819.574 41.5996 819.574 42.3994 819.574 44 c 0
819.574 45.5996 819.574 46.3994 818.774 47.2002 c 0
817.975 48 816.375 48.7998 814.774 48.7998 c 2
810.774 48.7998 l 1
810.774 39.2002 l 1
814.774 39.2002 l 2xbfc0
810.774 33.5996 m 1
810.774 20 l 1
801.975 20 l 1
801.975 55.2002 l 1xcfc0
815.574 55.2002 l 2x9fc0
820.375 55.2002 822.774 54.3994 825.175 52.7998 c 0
827.574 51.2002 828.375 48.7998 828.375 45.5996 c 0
828.375 43.2002 827.574 41.5996 826.774 40 c 0
825.975 38.3994 824.375 36.7998 821.975 36 c 1
823.574 36 824.375 35.2002 825.175 34.3994 c 0
825.975 33.5996 827.574 32 828.375 29.5996 c 2
833.175 20 l 1
823.574 20 l 1xcfc0
819.574 28.7998 l 2
818.774 30.3994 817.175 31.2002 816.375 32 c 0
815.574 32.7998 814.774 33.5996 813.175 33.5996 c 2
810.774 33.5996 l 1
EndSplineSet
Validated: 524321
EndChar
EndChars
EndSplineFont

Binary file not shown.

View File

@@ -1,8 +1,8 @@
@font-face {
font-family: 'CombodoRegular';
src: url('combodo-webfont.woff2?v=1.0') format('woff2'),
url('combodo-webfont.woff?v=1.0') format('woff'),
url('combodo-webfont.ttf?v=1.0') format('truetype');
src: url('combodo-webfont.woff2?v=2.0') format('woff2'),
url('combodo-webfont.woff?v=2.0') format('woff'),
url('combodo-webfont.ttf?v=2.0') format('truetype');
font-weight: normal;
font-style: normal;
@@ -193,7 +193,16 @@
.fc-combodo-icon:before {
content: "D";
}
.fc-itophub-icon:before {
content: "E";
}
.fc-chameleon-icon:before {
content: "F";
}
.fc-itop-icon:before {
content: "I";
}
.fc-opensource-icon:before {
content: "O";
}

50
css/font-combodo/glyphs/E.svg Executable file
View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="1000"
height="1000"
viewBox="0 0 264.58333 264.58334"
version="1.1"
id="svg909">
<defs
id="defs903" />
<metadata
id="metadata906">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
style="fill:#000000;fill-opacity:1"
transform="matrix(2.6189878,0,0,2.6189878,-138.11438,-66.566639)"
id="layer1">
<path
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 77.776825,48.628779 c -3.105953,0.0165 -2.465143,1.56905 -1.672249,3.00189 0.969595,1.75214 -6.046384,0.53457 -12.856064,7.17372 -3.69523,3.60269 -7.8302,7.46233 -8.56485,18.39112 -0.73465,10.9288 6.57401,26.601051 21.834325,26.890351 14.098468,0.26727 16.523001,-7.762201 17.760671,-13.268961 1.323287,-5.88768 -2.939907,-15.10068 -12.294338,-14.96704 -9.354428,0.13364 -12.428178,6.14692 -12.428178,10.15597 0,4.00904 2.27182,9.35447 8.686288,9.35447 6.414468,0 8.552552,-3.87524 8.953457,-7.2161 0.400905,-3.34087 -1.12866,-6.23284 -5.863206,-6.68176 -3.664545,-0.34747 -5.823431,2.30622 -5.896281,4.44314 -0.100228,2.93996 2.194808,3.98392 3.307291,4.04264 1.112483,0.0587 2.766575,-0.003 2.856155,-1.33635 0.10023,-1.49182 -0.935023,-1.63676 -1.686717,-1.62005 -0.534409,0.0119 -1.147985,-0.88438 -0.985986,-1.50379 0.121989,-0.46643 0.78549,-1.62036 2.790009,-0.81855 2.004523,0.8018 2.544982,3.13823 2.021065,4.67723 -0.534538,1.57021 -1.18617,3.2909 -5.228621,3.17397 -3.536694,-0.1023 -5.411874,-4.25964 -5.328354,-6.68177 0.0939,-2.724 3.190312,-7.1826 8.402068,-6.91534 5.211754,0.26728 8.953352,5.07775 7.884274,10.42314 -1.069079,5.34539 -6.013196,8.82024 -11.759488,8.55297 -5.746294,-0.26727 -11.359094,-6.68189 -10.423654,-13.09636 0.93544,-6.41447 5.87967,-10.95789 12.828675,-11.22516 6.949005,-0.26727 11.885592,0.016 15.894636,0.016 4.009047,0 6.155487,-1.61955 5.353677,-4.96042 -0.8018,-3.34086 -3.786135,-15.85543 -16.689419,-18.91977 -3.29736,-0.78307 -5.483391,-1.09268 -6.895186,-1.0852 z m 13.978992,10.35854 a 3.685268,3.685268 0 0 1 3.685563,3.68505 3.685268,3.685268 0 0 1 -3.685563,3.68556 3.685268,3.685268 0 0 1 -3.685048,-3.68556 3.685268,3.685268 0 0 1 3.685048,-3.68505 z"
id="path882" />
<path
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 138.24445,32.953249 a 13.49711,13.49711 0 0 0 -13.49685,13.49685 13.49711,13.49711 0 0 0 0.0465,1.06195 l -25.043431,7.84087 c 1.104251,1.4075 2.257151,3.10658 3.611151,6.01255 l 23.55566,-7.5799 a 13.49711,13.49711 0 0 0 11.32696,6.1619 13.49711,13.49711 0 0 0 13.49737,-13.49737 13.49711,13.49711 0 0 0 -13.49737,-13.49685 z"
id="rect827" />
<path
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 97.624193,88.491979 c 0.07421,3.57897 -0.303877,5.04652 -0.587044,6.95772 l 27.570411,8.739001 a 13.49711,13.49711 0 0 0 -0.0134,0.37258 13.49711,13.49711 0 0 0 13.49737,13.49737 13.49711,13.49711 0 0 0 13.49685,-13.49737 13.49711,13.49711 0 0 0 -13.49685,-13.496851 13.49711,13.49711 0 0 0 -11.65201,6.71794 z"
id="rect827-1" />
<circle
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.40000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path888"
cx="93.031555"
cy="62.530666"
r="1.3701637" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

41
css/font-combodo/glyphs/F.svg Executable file
View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="1000"
height="1000"
viewBox="0 0 264.58333 264.58334"
version="1.1"
id="svg909">
<defs
id="defs903" />
<metadata
id="metadata906">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-32.41665)"
id="layer1">
<path
style="fill:#1b1b1b;fill-opacity:1;stroke:#000000;stroke-width:1.71210456;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 128.74663,48.188011 c -13.29429,0.07062 -10.55146,6.715944 -7.15766,12.848874 4.15012,7.499617 -25.880108,2.288099 -55.027316,30.705397 -15.81655,15.420458 -33.515303,31.940728 -36.659797,78.718798 -3.144494,46.77813 28.138482,113.85946 93.456613,115.09774 60.34513,1.14398 70.72277,-33.22425 76.02032,-56.79463 5.66401,-25.20081 -12.58357,-64.63485 -52.62298,-64.06284 -40.0394,0.57201 -53.195848,26.31042 -53.195848,43.47021 0,17.15974 9.723978,40.03957 37.179578,40.03957 27.4556,0 36.60716,-16.58704 38.32314,-30.88679 1.71598,-14.2998 -4.83096,-26.67818 -25.09606,-28.59968 -15.68521,-1.48726 -24.9258,9.87122 -25.23762,19.0178 -0.429,12.5838 9.39435,17.05222 14.15607,17.30356 4.76172,0.25125 11.84166,-0.0128 12.22509,-5.71993 0.42901,-6.38538 -4.00214,-7.00576 -7.21959,-6.93424 -2.28741,0.0509 -4.91368,-3.78538 -4.22028,-6.43661 0.52215,-1.99644 3.3621,-6.93557 11.94197,-3.50361 8.57988,3.43191 10.89319,13.43244 8.65069,20.01977 -2.28797,6.72091 -5.07712,14.08591 -22.37987,13.58542 -15.13797,-0.43787 -23.16423,-18.23237 -22.80675,-28.59972 0.40192,-11.65944 13.65537,-30.74341 35.96305,-29.59947 22.30767,1.14403 38.32269,21.7341 33.74675,44.61377 -4.57593,22.87966 -25.73805,37.75293 -50.33368,36.60894 -24.59564,-1.14398 -48.619888,-28.60023 -44.615958,-56.05584 4.00393,-27.45561 25.166518,-46.90263 54.910078,-48.04662 29.74356,-1.14398 50.87344,0.0685 68.0332,0.0685 17.15977,0 26.34709,-6.93209 22.91514,-21.23189 -3.43192,-14.29975 -16.20565,-67.865386 -71.43508,-80.981563 -14.11356,-3.351744 -23.47035,-4.676956 -29.5132,-4.644939 z m 59.83374,44.337259 a 15.77391,15.77391 0 0 1 15.77517,15.77298 15.77391,15.77391 0 0 1 -15.77517,15.77516 15.77391,15.77391 0 0 1 -15.77297,-15.77516 15.77391,15.77391 0 0 1 15.77297,-15.77298 z"
id="path882" />
<circle
style="opacity:1;fill:#101010;fill-opacity:1;stroke:#000000;stroke-width:1.71210456;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path888"
cx="194.04086"
cy="107.69173"
r="5.8646588" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

87
css/font-combodo/glyphs/O.svg Executable file
View File

@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1000"
height="1000"
viewBox="0 0 264.58333 264.58334"
version="1.1"
id="svg876"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="O.svg">
<defs
id="defs870" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="-272.85714"
inkscape:cy="560"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1005"
inkscape:window-x="1911"
inkscape:window-y="-9"
inkscape:window-maximized="1" />
<metadata
id="metadata873">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-32.41664)">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:middle;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:8.99672318;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 131.53572,50.179132 c -54.174274,0 -100.702568,38.6765 -110.575582,91.938598 -9.873159,53.26282 19.698102,106.06258 70.277674,125.4761 2.319548,0.89024 4.921621,-0.26836 5.811987,-2.58786 L 122.30183,199.2106 c 0.89023,-2.31957 -0.26838,-4.92164 -2.58789,-5.812 -14.87072,-5.70891 -23.515673,-21.14784 -20.612431,-36.80689 2.903191,-15.6588 16.504681,-26.96534 32.434211,-26.96534 15.92952,0 29.53338,11.30654 32.43657,26.96534 2.90326,15.65905 -5.74171,31.09798 -20.61242,36.80689 -2.31951,0.89036 -3.47812,3.49245 -2.58788,5.812 l 25.25202,65.79537 c 0.89038,2.31821 3.49074,3.47652 5.8096,2.58786 50.57958,-19.41352 80.15083,-72.21328 70.27768,-125.4761 -9.87301,-53.262098 -56.4013,-91.938598 -110.57557,-91.938598 z"
id="path3773"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ssccscsssccccss" />
<g
style="display:inline"
id="g3797"
transform="matrix(1.2200654,0,0,1.2200654,455.86197,1099.5367)"
inkscape:export-filename="/home/rafael/workspace/logo-osi/3/png/logo396x412.png"
inkscape:export-xdpi="48.18"
inkscape:export-ydpi="48.18">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.25831962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m -183.5617,-698.57555 c -5.02556,0 -9.12392,4.09113 -9.12392,9.10782 0,5.01668 4.09836,9.10781 9.12392,9.10781 5.02556,0 9.12392,-4.09113 9.12392,-9.10781 0,-5.01669 -4.09836,-9.10782 -9.12392,-9.10782 z m 0,2.25596 c 3.80399,0 6.8633,3.05458 6.8633,6.85186 0,3.79727 -3.05931,6.85119 -6.8633,6.85119 -3.80399,0 -6.86397,-3.05392 -6.86397,-6.85119 0,-3.79728 3.05998,-6.85186 6.86397,-6.85186 z"
id="path3015"
inkscape:connector-curvature="0" />
<g
aria-label="R"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:0%;font-family:OpenSymbol;-inkscape-font-specification:'OpenSymbol Bold';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
id="text3793">
<path
inkscape:connector-curvature="0"
d="m -183.7552,-690.46513 q 0.74769,0 1.06902,-0.27807 0.3275,-0.27807 0.3275,-0.91454 0,-0.63028 -0.3275,-0.90217 -0.32133,-0.27189 -1.06902,-0.27189 h -1.00105 v 2.36667 z m -1.00105,1.64369 v 3.4913 h -2.37902 v -9.22569 h 3.63342 q 1.82289,0 2.66946,0.61175 0.85274,0.61175 0.85274,1.93412 0,0.91454 -0.44491,1.50157 -0.43873,0.58703 -1.32855,0.8651 0.48817,0.11123 0.87128,0.50671 0.3893,0.38929 0.78477,1.18642 l 1.29147,2.62002 h -2.53351 l -1.12463,-2.29252 q -0.33986,-0.69208 -0.69208,-0.94543 -0.34604,-0.25335 -0.92689,-0.25335 z"
style="font-size:12.65519524px;line-height:1.25"
id="path863" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -18,6 +18,9 @@ aIcons = {
'combodo-icon': 'Combodo icon',
'combodo-icon-o': 'Combodo icon (outline)',
'itop-icon': 'iTop icon',
'itophub-icon': 'iTop Hub icon',
'chameleon-icon': 'Hub\'s Chameleon icon',
'opensource-icon': 'Open Source Logo',
}
function GenerateTable() {

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,112 @@
/* cyrillic-ext */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-cyrillic-ext.woff2') format('woff2');
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
}
/* cyrillic */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-cyrillic.woff2') format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-greek-ext.woff2') format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-greek.woff2') format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-vietnamese.woff2') format('woff2');
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-latin-ext.woff2') format('woff2');
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'), url('./OpenSans-Regular-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
/* cyrillic-ext */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-cyrillic-ext.woff2') format('woff2');
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
}
/* cyrillic */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-cyrillic.woff2') format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-greek-ext.woff2') format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-greek.woff2') format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-vietnamese.woff2') format('woff2');
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-latin-ext.woff2') format('woff2');
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
src: local('Open Sans Bold'), local('OpenSans-Bold'), url('./OpenSans-Bold-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}

File diff suppressed because it is too large Load Diff

View File

@@ -35,6 +35,14 @@ body.printable-version {
.ui-layout-content {
padding-left: 10px;
}
.ui-layout-content .ui-tabs-nav li {
/* Overriding jQuery UI theme to see active tab better */
margin-bottom: 2px;
&.ui-tabs-active{
padding-bottom: 3px;
}
}
.raw_output {
font-family: Courier-New, Courier, Arial, Helvetica;
@@ -107,6 +115,12 @@ table.listResults td .view-image {
.view-image {
display: inline-block;
img[src=""],
img[src="null"] {
// Hiding "broken" image when src is not set
visibility: hidden;
}
&.dirty {
// The image will be modified when saving the changes
@@ -835,7 +849,7 @@ table.listResults tr.even td.truncated, .wizContainer table.listResults tr.even
}
/* Beware: IE6 does not support multiple selector with multiple classes, only the last class is used */
table.listResults tr.even td.hover.truncated, , .wizContainer table.listResults tr.even td.hover.truncated {
table.listResults tr.even td.hover.truncated, .wizContainer table.listResults tr.even td.hover.truncated {
background: #fdf5d0 url(../images/truncated.png?v=#{$version}) bottom repeat-x;
}
@@ -1245,6 +1259,18 @@ span.form_validation {
margin-bottom: 0.25em;
}
/* Helper classes for object details display. */
.one-col-details {
min-width: 300px;
max-width: 600px;
}
.n-cols-details {
width: 100%;
> tbody > tr > td {
min-width: 240px;
}
}
.details {
border-collapse: collapse;
noborder-bottom: 2px #fff solid;
@@ -1269,18 +1295,24 @@ fieldset .details>.field_container {
margin-bottom: 0px;
}
&.field_large{
&.field_large {
display: inherit;
/* .field_label, .field_data */
> div {
display: inherit;
&.field_label{
&.field_label {
width: inherit;
margin-bottom: 5px;
}
&.field_data {
margin-top: 8px;
margin-bottom: 10px;
word-break: break-all;
}
/* .field_value, .field_comments, .field_infos */
> div {
}
@@ -1496,6 +1528,12 @@ fieldset .details>.field_container {
}
}
}
.one-col-details .details .field_container.field_small {
div.field_label {
/* On a single column, field labels can take more width but they are limited so it doesn't feel weird when all labels are short */
width: 145px;
}
}
/* This is extracted from the ".details > .field_container ..." because of the fullscreen option (element is moved at the end of the body */
.field_input_text{
border: none;

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2012 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
@@ -21,13 +21,13 @@
* Authent External
* Module definition file for the "External Authentication" module
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @copyright Copyright (C) 2010-2017 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-external/2.2.0',
'authent-external/2.4.0',
array(
// Identification
//
@@ -63,4 +63,3 @@ SetupWebPage::AddModule(
'settings' => array(),
)
);
?>

View File

@@ -9,7 +9,7 @@ if (function_exists('ldap_connect'))
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-ldap/2.2.0',
'authent-ldap/2.4.0',
array(
// Identification
//
@@ -63,5 +63,3 @@ SetupWebPage::AddModule(
);
} // if (function_exists('ldap_connect'))
?>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-local/2.2.0',
'authent-local/2.4.0',
array(
// Identification
//
@@ -40,5 +40,3 @@ SetupWebPage::AddModule(
),
)
);
?>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.4">
<classes>
<class id="Attachment" _delta="define">
<parent>DBObject</parent>

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2014 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
@@ -39,4 +39,3 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Attachments:NoAttachment' => 'Kein Attachment. ',
'Attachments:PreviewNotAvailable' => 'Vorschau für diesen Attachment-Typ nicht verfügbar.',
));
?>

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2016 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2012 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
@@ -19,7 +19,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-attachments/2.3.0',
'itop-attachments/2.4.0',
array(
// Identification
//
@@ -145,5 +145,3 @@ if (!class_exists('AttachmentInstaller'))
}
}
}
?>

View File

@@ -24,4 +24,4 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Attachment:Max_Ko' => '(Максимальный размер файла: %1$s кБ)',
'Attachments:NoAttachment' => 'Нет вложений.',
'Attachments:PreviewNotAvailable' => 'Предварительный просмотр не доступен для этого типа вложений.',
));
));

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2014 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//

View File

@@ -291,4 +291,3 @@ class ItopBackup extends ModuleHandlerAPI
}
}
}

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-backup/2.2.0',
'itop-backup/2.4.0',
array(
// Identification
//
@@ -56,5 +56,3 @@ SetupWebPage::AddModule(
),
)
);
?>

View File

@@ -47,4 +47,3 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'bkp-wait-restore' => 'Пожалуйста, дождитесь завершения восстановления...',
'bkp-success-restore' => 'Восстановление успешно завершено.',
));
?>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.4">
<classes>
<class id="lnkVirtualDeviceToVolume" _delta="define">
<parent>cmdbAbstractObject</parent>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-bridge-virtualization-storage/2.3.0',
'itop-bridge-virtualization-storage/2.4.0',
array(
// Identification
//
@@ -43,6 +43,3 @@ SetupWebPage::AddModule(
),
)
);
?>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.4">
<classes>
<class id="Change" _delta="define">
<parent>Ticket</parent>
@@ -7,7 +7,7 @@
<comment><![CDATA[/**
* Persistent classes for a CMDB
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @copyright Copyright (C) 2010-2017 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/]]></comment>
<category>bizmodel,searchable,changemgmt</category>

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2014 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-change-mgmt-itil/2.3.0',
'itop-change-mgmt-itil/2.4.0',
array(
// Identification
//
@@ -42,5 +42,3 @@ SetupWebPage::AddModule(
),
)
);
?>

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2014 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-change-mgmt/2.3.0',
'itop-change-mgmt/2.4.0',
array(
// Identification
//
@@ -91,5 +91,3 @@ class ChangeManagementInstaller extends ModuleInstallerAPI
}
}
}
?>

File diff suppressed because one or more lines are too long

View File

@@ -1663,6 +1663,8 @@
<attribute id="name"/>
<attribute id="org_id"/>
<attribute id="organization_name"/>
<attribute id="location_id"/>
<attribute id="location_name"/>
<attribute id="finalclass"/>
</attributes>
</reconciliation>

View File

@@ -395,8 +395,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Class:Group/Attribute:status+' => '',
'Class:Group/Attribute:status/Value:implementation' => 'Implementation',
'Class:Group/Attribute:status/Value:implementation+' => 'Implementation',
'Class:Group/Attribute:status/Value:obsolete' => 'Veraltet',
'Class:Group/Attribute:status/Value:obsolete+' => 'Veraltet',
'Class:Group/Attribute:status/Value:obsolete' => 'Obsolet (Veraltet)',
'Class:Group/Attribute:status/Value:obsolete+' => 'Obsolet (Veraltet)',
'Class:Group/Attribute:status/Value:production' => 'Produktion',
'Class:Group/Attribute:status/Value:production+' => 'Produktion',
'Class:Group/Attribute:org_id' => 'Organisation',
@@ -489,7 +489,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Class:Document/Attribute:status+' => '',
'Class:Document/Attribute:status/Value:draft' => 'Entwurf',
'Class:Document/Attribute:status/Value:draft+' => '',
'Class:Document/Attribute:status/Value:obsolete' => 'Veraltet',
'Class:Document/Attribute:status/Value:obsolete' => 'Obsolet (Veraltet)',
'Class:Document/Attribute:status/Value:obsolete+' => '',
'Class:Document/Attribute:status/Value:published' => 'Veröffentlicht',
'Class:Document/Attribute:status/Value:published+' => '',
@@ -1184,4 +1184,4 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Class:Subnet/Tab:FreeIPs-count' => 'Freie IPs: %1$s',
'Class:Subnet/Tab:FreeIPs-explain' => 'Hier ist eine Aufstellung von 10 freien IP Adressen',
));
?>
?>

View File

@@ -685,7 +685,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Class:SoftwareInstance/Attribute:softwarelicence_id+' => '',
'Class:SoftwareInstance/Attribute:softwarelicence_name' => 'Nom Licence logiciel',
'Class:SoftwareInstance/Attribute:softwarelicence_name+' => '',
'Class:SoftwareInstance/Attribute:path' => 'Chemin d`installation',
'Class:SoftwareInstance/Attribute:path' => 'Chemin d\'installation',
'Class:SoftwareInstance/Attribute:path+' => '',
'Class:SoftwareInstance/Attribute:status' => 'Statut',
'Class:SoftwareInstance/Attribute:status+' => '',

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-config/1.0.2',
'itop-config/2.4.0',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.4">
<classes>
<class id="Rack" _delta="define">
<parent>PhysicalDevice</parent>
@@ -20,6 +20,10 @@
<reconciliation>
<attributes>
<attribute id="name"/>
<attribute id="org_id"/>
<attribute id="organization_name"/>
<attribute id="location_id"/>
<attribute id="location_name"/>
</attributes>
</reconciliation>
</properties>

View File

@@ -18,7 +18,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-datacenter-mgmt/2.2.0',
'itop-datacenter-mgmt/2.4.0',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.4">
<classes>
<class id="TelephonyCI" _delta="define">
<parent>PhysicalDevice</parent>

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2014 Combodo SARL
// Copyright (C) 2010-2017 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-endusers-devices/2.2.0',
'itop-endusers-devices/2.4.0',
array(
// Identification
//

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.3">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.4">
<classes>
<class id="Ticket">
<methods>

View File

@@ -6,7 +6,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-full-itil/1.0.0', array(
'itop-full-itil/2.4.0', array(
// Identification
//
'label' => 'Bridge - Request management ITIL + Incident management ITIL',

View File

@@ -38,7 +38,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Class:Incident/Attribute:status/Value:assigned+' => '',
'Class:Incident/Attribute:status/Value:escalated_ttr' => 'Escalate ttr',
'Class:Incident/Attribute:status/Value:escalated_ttr+' => '',
'Class:Incident/Attribute:status/Value:waiting_for_approval' => 'En attente d`approbation',
'Class:Incident/Attribute:status/Value:waiting_for_approval' => 'En attente d\'approbation',
'Class:Incident/Attribute:status/Value:waiting_for_approval+' => '',
'Class:Incident/Attribute:status/Value:pending' => 'En attente',
'Class:Incident/Attribute:status/Value:pending+' => '',

View File

@@ -105,7 +105,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Class:Incident/Attribute:servicesubcategory_id+' => 'Подкатегория услуги',
'Class:Incident/Attribute:servicesubcategory_name' => 'Подкатегория услуги',
'Class:Incident/Attribute:servicesubcategory_name+' => '',
'Class:Incident/Attribute:escalation_flag' => '«Флаг эскалации',
'Class:Incident/Attribute:escalation_flag' => 'Флаг эскалации',
'Class:Incident/Attribute:escalation_flag+' => 'Флаг повышенного приоритета',
'Class:Incident/Attribute:escalation_flag/Value:no' => 'Нет',
'Class:Incident/Attribute:escalation_flag/Value:no+' => 'Нет',

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.3">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.4">
<classes>
<class id="KnownError" _delta="define">
<parent>cmdbAbstractObject</parent>

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-knownerror-mgmt/2.3.0',
'itop-knownerror-mgmt/2.4.0',
array(
// Identification
//

View File

@@ -2,7 +2,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-portal-base/1.1.0', array(
'itop-portal-base/2.4.0', array(
// Identification
'label' => 'Portal Development Library',
'category' => 'Portal',
@@ -40,4 +40,3 @@ SetupWebPage::AddModule(
),
)
);

View File

@@ -714,15 +714,18 @@ class ObjectFormManager extends FormManager
// 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
/** @var DBObjectSearch $oValuesScope */
$oValuesScope = $oField->GetSearch()->DeepClone();
$oBinaryExp = new BinaryExpression(new FieldExpression('id', $oValuesScope->GetClassAlias()), '=', new ScalarExpression( $oField->GetCurrentValue() ));
$oValuesScope->AddConditionExpression($oBinaryExp);
$oValuesSet = new DBObjectSet($oValuesScope);
if( $oValuesSet->Count() === 0 )
if(!$oField->GetReadOnly())
{
$oField->SetCurrentValue(null);
/** @var DBObjectSearch $oValuesScope */
$oValuesScope = $oField->GetSearch()->DeepClone();
$oBinaryExp = new BinaryExpression(new FieldExpression('id', $oValuesScope->GetClassAlias()), '=', new ScalarExpression($oField->GetCurrentValue()));
$oValuesScope->AddConditionExpression($oBinaryExp);
$oValuesSet = new DBObjectSet($oValuesScope);
if($oValuesSet->Count() === 0)
{
$oField->SetCurrentValue(null);
}
}
}
// - Field that require processing on their subfields

View File

@@ -23,12 +23,9 @@ use \Exception;
use \DOMNodeList;
use \DOMFormatException;
use \utils;
use \UserRights;
use \ProfilesConfig;
use \MetaModel;
use \DBSearch;
use \DBUnionSearch;
use \Combodo\iTop\DesignElement;
class LifecycleValidatorHelper
{
@@ -161,10 +158,10 @@ class LifecycleValidatorHelper
}
// Retrieving profiles for the stimulus
$oProfilesNode = $oStimulusNode->GetOptionalElement('allowed_profiles');
$oProfilesNode = $oStimulusNode->GetOptionalElement('denied_profiles');
$aProfilesNames = array();
// If no profile is specified, we consider that it's for ALL the profiles
if (($oProfilesNode === null) || ($oProfilesNode->GetNodes('./allowed_profile')->length === 0))
if (($oProfilesNode === null) || ($oProfilesNode->GetNodes('./denied_profile')->length === 0))
{
foreach (ProfilesConfig::GetProfilesValues() as $iKey => $aValue)
{
@@ -173,13 +170,13 @@ class LifecycleValidatorHelper
}
else
{
foreach ($oProfilesNode->GetNodes('./allowed_profile') as $oProfileNode)
foreach ($oProfilesNode->GetNodes('./denied_profile') as $oProfileNode)
{
// Retrieving mandatory profile id attribute
$sProfileId = $oProfileNode->getAttribute('id');
if ($sProfileId === '')
{
throw new DOMFormatException('Stimulus tag must have an id attribute.', null, null, $oProfileNode);
throw new DOMFormatException('Profile tag must have an id attribute.', null, null, $oProfileNode);
}
$aProfilesNames[] = $sProfileId;
}
@@ -287,6 +284,12 @@ class LifecycleValidatorHelper
{
$aStimuli = array();
// Preparing available stimuli
foreach(MetaModel::EnumStimuli($sClass) as $sStimulusCode => $aData)
{
$aStimuli[$sStimulusCode] = true;
}
// Iterating on profiles to retrieving the different OQLs parts
foreach ($aProfiles as $sProfile)
{
@@ -297,19 +300,16 @@ class LifecycleValidatorHelper
$sLifecycleValuesClass = $this->sGeneratedClass;
$aProfileMatrix = $sLifecycleValuesClass::GetProfileStimuli($iProfileId, $sClass);
// If the profile / class tuple is not present (null), it means that all stimuli are allowed
if($aProfileMatrix === null)
foreach($aProfileMatrix as $sStimulusCode)
{
$aImplicitStimuli = array_keys(MetaModel::EnumStimuli($sClass));
$aStimuli = array_merge_recursive($aStimuli, $aImplicitStimuli);
}
else
{
$aStimuli = array_merge_recursive($aStimuli, $aProfileMatrix);
if(array_key_exists($sStimulusCode, $aStimuli))
{
unset($aStimuli[$sStimulusCode]);
}
}
}
return $aStimuli;
return array_keys($aStimuli);
}
/**
@@ -374,7 +374,7 @@ class LifecycleValidatorHelper
// File generated by LifeCycleValidatorHelper
//
// Please do not edit manually
// List of constant lifecycles
// List of denied stimuli by profiles in the lifecycles
// - used by the portal LifecycleValidatorHelper
//
class $sClassName
@@ -382,12 +382,14 @@ class $sClassName
protected static \$aPROFILES = $sProfiles;
/**
* Returns the denied stimuli for a profile / class
*
* @param integer \$iProfileId
* @param string \$sClass
*/
public static function GetProfileStimuli(\$iProfileId, \$sClass)
{
\$aStimuli = null;
\$aStimuli = array();
\$sLifecycleKey = \$iProfileId.'_'.\$sClass;
if (isset(self::\$aPROFILES[\$sLifecycleKey]))

View File

@@ -186,8 +186,11 @@
var iItemFlags = 0;
// - Adding stub div
var textElem = $('<div></div>').addClass('mosaic-item-text');
// - Adding wrapper to textElem to easily control text's subnodes flow
var textWrapperElem = $('<div></div>').addClass('mosaic-item-text-wrapper');
textWrapperElem.appendTo(textElem);
// - Adding image
if( (item.image !== undefined) && (item.image !== '') )
if( (item.image !== undefined) && (item.image !== '') && (item.image !== null) )
{
iItemFlags += 4;
aElem.append( $('<div></div>').addClass('mosaic-item-image').append( $('<img />').attr('src', item.image) ) );
@@ -196,13 +199,13 @@
if( (item.name !== undefined) && (item.name !== '') )
{
iItemFlags += 1;
textElem.append( $('<div></div>').addClass('mosaic-item-name').html(item.name) );
textWrapperElem.append( $('<div></div>').addClass('mosaic-item-name').html(item.name) );
}
// - Adding description
if( (item.description !== undefined) && (item.description !== '') )
{
iItemFlags += 2;
textElem.append( $('<div></div>').addClass('mosaic-item-description').html(item.description) );
textWrapperElem.append( $('<div></div>').addClass('mosaic-item-description').html(item.description) );
}
aElem.append( textElem );
// - Adding CSS class to adjust the layout regarding which properties are available
@@ -408,6 +411,7 @@
registerFilterListeners();
// Open first level if only one item
// TODO: We must disable opening of first level when pre-filtering when filtering will be implemented
if($('#brick_content_mosaic > .mosaic-group[data-level-id="L"] > .mosaic-group-item').length == 1)
{
setTimeout(function(){

View File

@@ -411,8 +411,8 @@
registerFilterListeners();
collapseAll();
// Open first level if only one item
if($('#brick_content_tree > .list-group-item').length == 1)
// Open first level if only one item and not pre-filtering
if( ($('#brick_content_tree > .list-group-item').length == 1) && ($('#brick_search_field').val() === '') )
{
setTimeout(function(){
$('#brick_content_tree > .list-group-item > .tree-toggle').trigger('click');

View File

@@ -37,9 +37,11 @@
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/scroller.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/select.bootstrap.min.css'|add_itop_version }}" rel="stylesheet">
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/datatables/css/select.dataTables.min.css'|add_itop_version }}" rel="stylesheet">
{# - Font Combodo #}
{# - Font OpenSans #}
<link href="{{ app['combodo.absolute_url'] ~ 'css/font-open-sans/font-open-sans.css'|add_itop_version }}" rel="stylesheet">
{# - Font Combodo #}
<link href="{{ app['combodo.absolute_url'] ~ 'css/font-combodo/font-combodo.css'|add_itop_version }}" rel="stylesheet">
{# - Font awesome #}
{# - Font awesome #}
<link href="{{ app['combodo.absolute_url'] ~ 'css/font-awesome/css/font-awesome.min.css'|add_itop_version }}" rel="stylesheet">
{# - Misc libs #}
<link href="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/typeahead/css/typeaheadjs.bootstrap.css'|add_itop_version }}" rel="stylesheet">
@@ -104,9 +106,7 @@
{# Date-time picker for Bootstrap #}
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js'|add_itop_version }}"></script>
{# Typeahead files for autocomplete #}
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/typeahead/js/bloodhound.min.js'|add_itop_version }}"></script>
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/typeahead/js/typeahead.bundle.min.js'|add_itop_version }}"></script>
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/typeahead/js/typeahead.jquery.min.js'|add_itop_version }}"></script>
<script type="text/javascript" src="{{ app['combodo.portal.base.absolute_url'] ~ 'lib/handlebars/js/handlebars.min-768ddbd.js'|add_itop_version }}"></script>
{# Form files #}
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/form_handler.js'|add_itop_version }}"></script>

View File

@@ -1,4 +1,3 @@
@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,700");
/*!
* Combodo portal theme v1.0.0
* Based on Bootswatch Simplex
@@ -2745,6 +2744,10 @@ textarea.input-group-sm > .form-control, textarea.input-group-sm > .input-group-
/* To mask border from previous li item */
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.8) inset;
}
.navbar-nav > li:last-child.active > a {
margin-top: 0px;
/* Overflow hack */
}
.navbar-nav > li > a {
padding-top: 11px;
padding-bottom: 11px;

View File

@@ -1,5 +1,4 @@
@import 'variables.scss';
@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,700");
/*!
* Combodo portal theme v1.0.0
@@ -3471,10 +3470,13 @@ select[multiple].input-group-sm>.input-group-btn>.btn {
border-right-width: 20px;
border-right-color: $body-bg;
}
.navbar-nav>li.active>a{
margin-top: -1px; /* To mask border from previous li item */
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.8) inset;
}
.navbar-nav>li.active>a{
margin-top: -1px; /* To mask border from previous li item */
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.8) inset;
}
.navbar-nav>li:last-child.active>a{
margin-top: 0px; /* Overflow hack */
}
.navbar-nav>li>a {
padding-top: 11px;
padding-bottom: 11px;

View File

@@ -628,10 +628,19 @@ table .group-actions {
border-radius: 0px 0px 4px 4px;
font-size: 1em;
}
/****************/
/* - Mosaic mode */
/* Note: Some of the CSS is factorised in the "Tree mode" part */
/****************/
/****************************************************************/
/* - Mosaic mode */
/* */
/* Note: Some of the CSS is factorised in the "Tree mode" part */
/* */
/* Note: .mosaic-item-layout-x classes are for different */
/* presentation modes. Like in binary, add the values to know */
/* which class to use. */
/* - 1 is for name */
/* - 2 is for description */
/* - 4 is for image */
/* eg. .mosaic-item-layout-5 when just name and image */
/****************************************************************/
#brick_content_mosaic {
position: relative;
padding: 10px 10px 1px 10px;
@@ -685,6 +694,11 @@ table .group-actions {
.mosaic-item-image > img {
max-width: 85%;
}
.mosaic-item-text {
max-width: 1px;
/* This is an arbitrary value. It is just here to make .mosaic-item-name wrap when there is a very long word in it. */
overflow: hidden;
}
.mosaic-group-item > .mosaic-group-item-actions {
position: absolute;
top: 5px;
@@ -698,7 +712,7 @@ table .group-actions {
color: #eee;
}
@media (max-width: 768px) {
/* All layout */
/* All layouts */
/* Layout 2 */
/* Layout 5/7 */
.mosaic-group-item > .mosaic-group-item-actions {
@@ -720,6 +734,8 @@ table .group-actions {
}
.mosaic-item-name {
font-size: 14px;
max-height: 50px;
overflow: hidden;
}
.mosaic-item-description {
display: none;
@@ -732,7 +748,10 @@ table .group-actions {
}
}
@media (min-width: 768px) {
/* All layout */
/* All layouts */
/* .mosaic-item-image{
vertical-align: inherit; Note: This was introduced to avoid image from going down the tile when .mosaic-item-name was way too long, but the .mosaic-item-image glitched by being a little too high. As a very long .mosaic-item-name is extremely rare, we decided that it was not worth it.
}*/
/* Layout 1 */
/* Layout 7 */
.mosaic-group-item {
@@ -741,6 +760,7 @@ table .group-actions {
height: 120px;
margin-right: 1.95%;
/* We don't put 2% to keep a margin in case of a bad browser rendering */
word-break: break-word;
}
.mosaic-item {
padding: 10px;
@@ -749,7 +769,14 @@ table .group-actions {
background-color: #ea7d1e;
box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.20);
}
.mosaic-item-text .mosaic-item-text-wrapper {
max-height: 100px;
/* Must be .mosaic-item absolute height (in px) */
}
.mosaic-item-name {
max-height: 100%;
/* It's ok if description is pushed down and not visible; but we truncate before it flows out of the tile */
overflow: hidden;
font-weight: 600;
font-size: 12px;
}
@@ -770,32 +797,39 @@ table .group-actions {
}
}
@media (min-width: 992px) {
/* Layout 7 */
/* Layout 5 & 7 */
.mosaic-item {
padding: 10px 15px;
}
.mosaic-group-back {
font-size: 40px;
}
.mosaic-item-layout-7 .mosaic-item-image {
.mosaic-item-layout-5 .mosaic-item-image, .mosaic-item-layout-7 .mosaic-item-image {
display: table-cell;
width: 105px;
padding-left: 5px;
padding-right: 18px;
}
.mosaic-item-layout-7 .mosaic-item-image > img {
max-width: 100%;
.mosaic-item-layout-5 .mosaic-item-image > img, .mosaic-item-layout-7 .mosaic-item-image > img {
max-width: 105px;
/* Equals parent element width */
}
.mosaic-item-layout-7 .mosaic-item-name {
.mosaic-item-layout-5 .mosaic-item-name, .mosaic-item-layout-7 .mosaic-item-name {
font-size: 12px;
}
}
@media (min-width: 1200px) {
/* All layouts */
.mosaic-group-item {
width: 24%;
height: 140px;
margin-right: 1.3%;
}
.mosaic-item-text .mosaic-item-text-wrapper {
max-height: 120px;
/* Must be .mosaic-item absolute height (in px) */
/* overflow hidden inherited */
}
}
/* Helper classes to remove margin depending on the screen size */
@media (min-width: 768px) and (max-width: 992px) {

Some files were not shown because too many files have changed in this diff Show More