Compare commits

...

170 Commits

Author SHA1 Message Date
Denis Flaven
06e389f14c Fixed a potential XSS vulnerability.
SVN:2.0.1[3667]
2015-07-30 09:27:23 +00:00
Denis Flaven
e90f4e1232 #966 Prevent duplication of attachments when the form gets reloaded.
SVN:2.0.1[3294]
2014-07-30 08:24:35 +00:00
Denis Flaven
474df98dfa #966 (continue'd): Allow attachments of several files to the same ticket (the previous fix breaks after attaching 1 file)
SVN:2.0.1[3289]
2014-07-25 15:21:07 +00:00
Denis Flaven
ce88d10766 #966 Fix for a bug caused by Google Chrome version 36: the selected attachment was added several times (up to 10 or more!).
SVN:2.0.1[3283]
2014-07-21 15:43:57 +00:00
Denis Flaven
225eab9bd3 #966 Fix for a bug caused by Google Chrome version 36: the selected attachment was added several times (up to 10 or more!).
SVN:2.0.1[3282]
2014-07-21 15:43:34 +00:00
Denis Flaven
42b0a8c3cb Bug fix : missing semicolons were causing an error with IE9.
SVN:2.0.1[3109]
2014-03-26 15:01:44 +00:00
Denis Flaven
484fa42113 #870: when a user deletes all her/his shortcuts at once, this was deleting all the shortcuts for all users.
SVN:2.0.1[3101]
2014-03-12 14:09:15 +00:00
Denis Flaven
5c1149ac68 Protect the initialization with a try ... catch, in order to protect that rest of the page in case of trouble.
SVN:2.0.1[3076]
2014-02-05 17:11:55 +00:00
Romain Quetiez
1dbb94a2e1 Fix for the validation of mandatory fields in the portal (reintegrated from trunk)
SVN:2.0.1[3053]
2014-01-07 14:10:39 +00:00
Romain Quetiez
df1869dfe3 PHP Mail transport to allow 100% of recipients in BCC (proposed on github) -reintegrated from trunk
SVN:2.0.1[3046]
2013-12-13 10:30:21 +00:00
Denis Flaven
22ee1cd6f4 #856: allow asynchronous emails to have an empty 'to' recipient... (not used anyway)
SVN:2.0.1[3045]
2013-12-12 18:06:16 +00:00
Denis Flaven
0b14bf605c #795 Issue when using the actual (id) value of an external key as a reconciliation field
SVN:2.0.1[2917]
2013-10-16 08:49:53 +00:00
Denis Flaven
02717360d0 Show all types of Actions from the "Notifications/Actions" tab.
SVN:2.0.1[2912]
2013-10-15 12:01:20 +00:00
Denis Flaven
230710eb04 #791 Protect against single quotes in localized strings...
SVN:2.0.1[2910]
2013-10-14 17:11:30 +00:00
Denis Flaven
6581c02301 #793 provide the default '=' and '!=' operators for all types of Computed Fields.
SVN:2.0.1[2904]
2013-10-14 14:20:24 +00:00
Romain Quetiez
f925a21735 retrofit Change in the Notifications panel: show/create all types of Action (not only ActionEmail)
SVN:2.0.1[2897]
2013-10-11 14:22:17 +00:00
Denis Flaven
8796e5fa74 Retrofit the useful DoPostRequest function which was used (and defined) in several extensions.
SVN:2.0.1[2887]
2013-10-11 08:41:22 +00:00
Denis Flaven
249dd03b18 New pattern accepting the new global Top Level Domains (gTLD)
SVN:2.0.1[2868]
2013-09-27 07:31:21 +00:00
Denis Flaven
94ba2c3c1c Protect the deletion of objects with very long friendly names
SVN:2.0.1[2862]
2013-09-24 16:23:26 +00:00
Denis Flaven
7ec9022bd7 Allow for comparisons of the module's versions in the expression of dependencies. For example one can now say "itop-config-mgmt/>=2.0.2" for a dependency.
SVN:2.0.1[2854]
2013-09-23 13:22:02 +00:00
Romain Quetiez
7ba2cf59de Shortest fix ever!!!! Sort icons based on the class name (ksort => asort)
SVN:2.0.1[2851]
2013-09-13 10:53:19 +00:00
Romain Quetiez
fdacbf6d0f #763 Could not use "configure this list" once a stop watch has been added to the list, which is a pitty because such attributes are not aimed at being displayed in lists!
SVN:2.0.1[2849]
2013-09-11 09:59:23 +00:00
Romain Quetiez
580de372e0 #752 Notifications sent several times (or too late) when MySQL is hosted on another server
SVN:2.0.1[2830]
2013-08-23 07:36:20 +00:00
Denis Flaven
0faa33a0e5 Allow "Support Agents" to put an Incident in "Pending" state.
SVN:2.0.1[2815]
2013-08-01 08:28:41 +00:00
Denis Flaven
1aff819f8f #747 protect against the non-existence of UserRequest (since the module is not always installed)
SVN:2.0.1[2812]
2013-07-30 16:28:26 +00:00
Denis Flaven
0ac9fce207 #746 allow adding an AttributeBlob with is_null_allowed = true to an existing Data Model. (same issue fixed also for AttributeOneWayPassword).
SVN:2.0.1[2809]
2013-07-25 09:24:18 +00:00
Denis Flaven
8a8de2bcc3 Export the content of the CaseLogs in "spreadsheet" format, with some tricks to preserve the formatting in Excel.
SVN:2.0.1[2805]
2013-07-17 17:12:52 +00:00
Denis Flaven
3b4ff79ea3 Make the portal (slightly) more configurable
SVN:2.0.1[2798]
2013-07-12 14:02:13 +00:00
Romain Quetiez
0fcbc040fd Cosmetics on the user portal -reintegrated from trunk
SVN:2.0.1[2777]
2013-06-14 15:40:58 +00:00
Romain Quetiez
ae6e0c5242 #736 Could not delete objects unless you are authorized to bulk delete -reintegrated from trunk
SVN:2.0.1[2770]
2013-06-07 07:32:38 +00:00
Denis Flaven
1ce8046c46 #734 Fixed a regression on reconciliation keys during CSV import.
SVN:2.0.1[2762]
2013-05-29 08:57:35 +00:00
Romain Quetiez
56eba6de4c Created branch 2.0.1
SVN:2.0.1[2759]
2013-05-22 12:33:48 +00:00
Denis Flaven
2fe407967b Preparing for the 2.0.1 release... update of the readme file.
SVN:trunk[2758]
2013-05-22 09:55:29 +00:00
Denis Flaven
703be73c95 #689: Logoff / Change Pwd buttons not visible in the portal if the window is too small: now allow line wrapping...
SVN:trunk[2757]
2013-05-22 09:43:26 +00:00
Denis Flaven
3060462edc #732: Change password: exit after building the page in case of wrong "old" password
SVN:trunk[2756]
2013-05-22 08:43:48 +00:00
Romain Quetiez
263acaf4e4 Missing localized label for some problem management menus, when the Known Error Management module is installed without the Problem Management module
SVN:trunk[2755]
2013-05-21 13:13:44 +00:00
Denis Flaven
db1be8f500 Add "Employee number" to the list of possible reconciliation keys for the class Person.
SVN:trunk[2754]
2013-05-21 11:04:01 +00:00
Romain Quetiez
452eca5288 The ticket class must be abstract!
SVN:trunk[2753]
2013-05-21 10:49:22 +00:00
Romain Quetiez
a728dfcf48 All the overloads of DisplayBareProperties must return an array (otherwise a warning is issued and field validation will not work as expected)
SVN:trunk[2752]
2013-05-21 10:44:13 +00:00
Denis Flaven
2027dc4a3d Make icons transparent...
SVN:trunk[2751]
2013-05-17 12:12:19 +00:00
Denis Flaven
1bc4e1431c Preparing for the 2.0.1 release... update of the readme file.
SVN:trunk[2750]
2013-05-17 08:34:42 +00:00
Denis Flaven
9afe28be20 Support non scalar posted parameters...
SVN:trunk[2749]
2013-05-16 15:45:57 +00:00
Denis Flaven
8073120351 JS syntax cleanup...
SVN:trunk[2748]
2013-05-16 15:44:05 +00:00
Denis Flaven
86c5b3e258 Typo...
SVN:trunk[2747]
2013-05-16 15:42:34 +00:00
Denis Flaven
b971faecda Cleanup of the log output. No need for such verbosity now that we are approaching the release.
SVN:trunk[2746]
2013-05-16 15:41:52 +00:00
Denis Flaven
2708b0de0e #728: the ticket's title is now an (external) attribute of the link between a ticket and a CI.
SVN:trunk[2745]
2013-05-16 14:28:23 +00:00
Romain Quetiez
8dd9893202 Readme: Documented the known issue #730 Leaving the backup temp files on disk
SVN:trunk[2744]
2013-05-16 14:23:35 +00:00
Denis Flaven
48d740da25 #727: prevent a crash in cron.php
SVN:trunk[2743]
2013-05-16 14:05:38 +00:00
Romain Quetiez
7ba5526fda #725 Specify a port for mySQL server
#729 Backup fails on Windows IIS

SVN:trunk[2742]
2013-05-16 13:57:52 +00:00
Denis Flaven
58dfa3335a Spanish localization enhancements, thanks to Miguel Turrubiates
SVN:trunk[2741]
2013-05-16 12:41:10 +00:00
Denis Flaven
deec1aa2a2 Fix the auto-resize (fit) of the dialog's content.
SVN:trunk[2740]
2013-05-16 12:13:18 +00:00
Romain Quetiez
a62c1946a6 #721 Unmet dependencies not detected
SVN:trunk[2739]
2013-05-16 08:54:50 +00:00
Romain Quetiez
a194308486 #726 Missing string in german dictionary
SVN:trunk[2738]
2013-05-16 07:41:36 +00:00
Denis Flaven
2e442dbaa0 #704: preserve the content of a "linkedset" when changing the initial state of the object being created !
SVN:trunk[2737]
2013-05-15 15:56:42 +00:00
Romain Quetiez
ad9ed96960 #673 Could not create a physical interface with default value for the speed (+ definitive corruption of the DB for the device on which the interface is being created!)
SVN:trunk[2735]
2013-05-15 10:23:06 +00:00
Romain Quetiez
efc3b4df07 Silently discard unknown attributes in object templates (in case some modules have not been installed)
SVN:trunk[2733]
2013-05-15 10:18:55 +00:00
Romain Quetiez
d6da043a32 #722 Document preview disappeared since 2.0 (not in 1.x)
SVN:trunk[2732]
2013-05-14 15:43:22 +00:00
Romain Quetiez
10a7a5aa38 Fix for reconciliation by id (Advanced Mode) -reintegrated from branch 2.0
SVN:trunk[2731]
2013-05-14 15:19:12 +00:00
Romain Quetiez
5684f1e196 #713 URL format reviewed:
- more formats allowed by default
- aligned between the wiki formatting and the URL attribute
- configurable globally with 'url_validation_pattern'
- can be defined at the attribute level with tag validation_pattern


SVN:trunk[2730]
2013-05-14 14:20:00 +00:00
Romain Quetiez
2376a63d18 #711 Audit error drill-down not working when zero error (requires to bookmark the link when there are some errors, then use it later when there is no error anymore)
SVN:trunk[2729]
2013-05-14 10:41:44 +00:00
Romain Quetiez
744b821d03 #710 Query phrase book "fields list" is too small
SVN:trunk[2728]
2013-05-14 10:19:33 +00:00
Romain Quetiez
f3eb6b5cb3 #705 Typo in the english dictionary
SVN:trunk[2727]
2013-05-14 10:09:42 +00:00
Romain Quetiez
d973f64576 #708 Cosmetics for the english dictionary
SVN:trunk[2726]
2013-05-14 10:07:20 +00:00
Denis Flaven
a6c9bcf780 #717: prevent flicker of unstyled content: make the pane visible only when their content is ready... + watchdog in case of error.
SVN:trunk[2725]
2013-05-14 10:03:23 +00:00
Romain Quetiez
7cae338e6d #723 Cron locking is too restrictive
SVN:trunk[2724]
2013-05-14 09:34:08 +00:00
Denis Flaven
ed344650c5 Prevent logoff problems depending on PHP's session.cache_limiter setting...
SVN:trunk[2723]
2013-05-13 15:45:10 +00:00
Romain Quetiez
2d03e95ece Fixed typos in the sample data for the service subcategories
SVN:trunk[2722]
2013-05-13 14:50:56 +00:00
Denis Flaven
69179f5d25 #707: oops, prevent a warning when no dict entry...
SVN:trunk[2721]
2013-05-13 14:50:26 +00:00
Romain Quetiez
27cf82b270 #693 Portal user cannot choose services linked via customer contract
SVN:trunk[2720]
2013-05-13 14:46:06 +00:00
Denis Flaven
d28891eaf4 #707: Make sure that DOCTYPE is the first statement of the page
- Enhancement: support for "target" in PopupMenuItems.. which was ignored before

SVN:trunk[2719]
2013-05-13 14:43:16 +00:00
Erwan Taloc
b1c1e5f9f2 Limit rack according to location for PDU (see track #638)
SVN:trunk[2718]
2013-05-13 10:56:55 +00:00
Erwan Taloc
8a86c6a637 change path for incident icon trac #699
SVN:trunk[2717]
2013-05-13 10:50:00 +00:00
Denis Flaven
631811145f Experimental support of icon uploads...
SVN:trunk[2716]
2013-05-07 17:27:37 +00:00
Denis Flaven
78ff062787 Proper reset of APC cache upon compilation !
SVN:trunk[2715]
2013-05-07 17:25:24 +00:00
Denis Flaven
427f50b390 Allow filtering of the languages to install
SVN:trunk[2713]
2013-05-02 08:09:10 +00:00
Romain Quetiez
21f0d96146 New way to compile the dictionaries, allowing for incremental modification via XML
SVN:trunk[2712]
2013-04-30 16:14:37 +00:00
Romain Quetiez
7fcf922ee0 Updated the unit test for the OQL parser
SVN:trunk[2711]
2013-04-29 09:01:06 +00:00
Denis Flaven
22dc44c9e5 Typo
SVN:trunk[2710]
2013-04-29 08:55:22 +00:00
Denis Flaven
6feb62d728 #383: support negative numbers in OQL
Enhancements: support MySQL bitwise operators (&, |, ^, <<, >>) and hexadecimal numbers (up to 64-bit).

SVN:trunk[2709]
2013-04-29 08:51:01 +00:00
Denis Flaven
29060f7b5e Enhancement: the expression of dependencies between modules can now use a complex boolean expression with a combination of "logical or" (||) and "logical and" (&&) instead of just a module name.
SVN:trunk[2708]
2013-04-29 08:39:23 +00:00
Denis Flaven
6df6af0df0 #663: Fix for emptying a directory which contains broken symbolic links
SVN:trunk[2707]
2013-04-29 08:34:19 +00:00
Romain Quetiez
d433a45200 #692 Compensate the effect of this fix committed as 2705
SVN:trunk[2706]
2013-04-26 10:32:11 +00:00
Romain Quetiez
d5e57ba0ba #692 Allow to set a default value for AttributeDuration (was forced to 0 anytime)
SVN:trunk[2705]
2013-04-26 10:24:44 +00:00
Romain Quetiez
d69236cb25 #701 Portal customization : enabled the calendar widget for input of a date+time type of attribute (it was only available for pure DATE attributes)
SVN:trunk[2704]
2013-04-26 10:07:13 +00:00
Romain Quetiez
422aa5b407 #715 Finalized the fix (added the year for group by day, but it is not displayed)
SVN:trunk[2703]
2013-04-26 09:54:39 +00:00
Romain Quetiez
f97f51b895 #715 Group by day -> month+day, group by month -> year+month, months are shown as a localized label
SVN:trunk[2702]
2013-04-26 09:46:31 +00:00
Denis Flaven
4ea0093f12 Enhancements to the Japanese localization, thanks to Shoji Seki
SVN:trunk[2701]
2013-04-25 09:24:35 +00:00
Romain Quetiez
2e35bb97d0 Compiler: added the capability to redefine icons in xml
SVN:trunk[2700]
2013-04-24 16:02:24 +00:00
Romain Quetiez
519b9f1a73 Needed => define if not exists
SVN:trunk[2699]
2013-04-24 15:50:44 +00:00
Denis Flaven
85c1f0d1aa New internal flag for generating the delta.
SVN:trunk[2698]
2013-04-23 15:33:40 +00:00
Romain Quetiez
f2738a79a0 User Portal:
- Portal power users can see ALL the tickets of the current customer
- Reopen and Close are done in a separate dialog box where the user will input requested data
- On closed tickets, the user satisfaction and comments are displayed

SVN:trunk[2697]
2013-04-18 15:23:43 +00:00
Romain Quetiez
4ae69372d4 User rights:
- for link classes, if no grant has been given explicitely, then check if one of the remote class has a grant (mix of compile-time and run-time changes)
- fixed an issue: when looking for a grant into the hierarchy, the most explicit declaration (aka the deepest class) must be found first -> reorder the parent classes (new flag on MetaModel::EnumParentClasses

SVN:trunk[2696]
2013-04-18 09:03:08 +00:00
Romain Quetiez
cce2509b2e #702 The second implementation of this fix was still incomplete (not compatible with some constraint queries)
SVN:trunk[2694]
2013-04-17 16:11:45 +00:00
Romain Quetiez
aa4d396960 #702 The first implementation of this fiw was not incomplete (not compatible with some constraint queries)
SVN:trunk[2692]
2013-04-17 15:53:34 +00:00
Romain Quetiez
5f11cc4cf8 #703 HTML entities not escaped in history tab
SVN:trunk[2690]
2013-04-16 13:23:10 +00:00
Denis Flaven
956ecda77e Fix for the "Notifications" tab: use the polymorphism to let each trigger determine which object is "In Scope" and thus can potentially have notifications related to it
SVN:trunk[2688]
2013-04-16 12:52:43 +00:00
Erwan Taloc
bb554b1271 define correct file name for en , es_cr, fr dictionnaries
Remove obsolete dictionaries

SVN:trunk[2685]
2013-04-16 11:44:51 +00:00
Erwan Taloc
15000ff48a remove unused dictionaries
SVN:trunk[2684]
2013-04-16 11:38:52 +00:00
Erwan Taloc
14d0ebdd71 define correct file name for en , es_cr, fr dictionnaries
SVN:trunk[2683]
2013-04-16 11:36:52 +00:00
Romain Quetiez
c95b8cf939 #702 Ignoring the class when looking up for a polymorphic ext key
SVN:trunk[2681]
2013-04-16 11:24:34 +00:00
Denis Flaven
74575440d7 Bug fix: properly serialize Emails with binary Attachments. Previously asynchronous emails with binary attachements were not working (they were queued but never sent).
SVN:trunk[2679]
2013-04-16 09:05:56 +00:00
Erwan Taloc
fcb7798e9e Remove dictionaries from module definition
SVN:trunk[2677]
2013-04-11 15:16:10 +00:00
Erwan Taloc
b0a054ada7 Remove dictionaries from module definition
SVN:trunk[2676]
2013-04-11 15:15:09 +00:00
Denis Flaven
b83d42efee Bug fix: allow printing lists fully expanded without the "pager" navigation.
Also try to completely hide the main menu on the left when printing.

SVN:trunk[2675]
2013-04-08 11:57:07 +00:00
Romain Quetiez
2e18c96328 Reviewed the readme file
SVN:trunk[2673]
2013-04-02 14:23:42 +00:00
Denis Flaven
2daccbe29d One more bug fix listed.
SVN:trunk[2672]
2013-04-02 14:13:09 +00:00
Denis Flaven
51d9c30315 #696: the message "Please fill all mandatory fields" is now localized (done in English, French and German)
SVN:trunk[2671]
2013-04-02 13:51:05 +00:00
Romain Quetiez
3d79e3fe8f #472 REST API: finalized the implementation of core/get_related + added the support for AttributeBlob (to manage documents and attachments)
SVN:trunk[2669]
2013-04-02 13:31:52 +00:00
Denis Flaven
57b34d2d91 Preparing for the 2.0.1-beta release...
SVN:trunk[2668]
2013-04-02 10:04:57 +00:00
Denis Flaven
a5a8863b52 Fixed transparent background issues...
SVN:trunk[2667]
2013-04-02 09:48:01 +00:00
Denis Flaven
d92b0aabee First (draft) version of the get_related verb for the REST API.
SVN:trunk[2666]
2013-04-02 09:42:26 +00:00
Denis Flaven
48472b6150 - Added support for creating symbolic links via the toolkit
- Added more debug info in the setup.log about the detection of the previously installed modules

SVN:trunk[2665]
2013-03-29 15:44:06 +00:00
Denis Flaven
fc29424600 #698 SeparatorPopupMenuItem was not working.
SVN:trunk[2664]
2013-03-29 13:53:51 +00:00
Denis Flaven
c4942dd747 #697: properly export NULL dates in "spreadsheet" format.
SVN:trunk[2662]
2013-03-29 13:32:47 +00:00
Denis Flaven
30b9afe165 REST API bug fix: properly handle key->finalclass
SVN:trunk[2661]
2013-03-29 10:54:23 +00:00
Denis Flaven
6d66969ff3 Better display of empty dates in the status report
SVN:trunk[2660]
2013-03-28 10:01:21 +00:00
Denis Flaven
667f258ec2 Preserve POSted parameters on the login web page (useful when the session expires)
SVN:trunk[2659]
2013-03-28 09:59:49 +00:00
Denis Flaven
badff05995 More readable edition for AttributeDuration (number are right justified)
SVN:trunk[2658]
2013-03-28 09:58:28 +00:00
Denis Flaven
052128da81 #694: make $__comp_menus__ really global !
SVN:trunk[2655]
2013-03-25 13:31:51 +00:00
Romain Quetiez
57629051bd #691 Notifications not sent if some recicipients have an empty address
SVN:trunk[2653]
2013-03-21 14:42:34 +00:00
Romain Quetiez
2cc89ad167 #690 XML export broken
SVN:trunk[2651]
2013-03-20 17:26:40 +00:00
Romain Quetiez
387ab05fd2 #674 request_type:servicerequest changed into service_request - added the DB update to allow an upgrade
SVN:trunk[2650]
2013-03-20 15:51:13 +00:00
Romain Quetiez
5de85c9d97 #688 ... regression in the search forms when the autocomplete is active
SVN:trunk[2648]
2013-03-20 15:10:18 +00:00
Romain Quetiez
d7fa2ca5b9 #688 When the autocomplete is activated, and the allowed values depend on another value, then it is possible to set a wrong value
SVN:trunk[2646]
2013-03-20 14:47:52 +00:00
Romain Quetiez
3d2866a2a0 #687 Finalized the bug fixed started in [2632], about attributes/hierarchies/labels (dictionary)
SVN:trunk[2644]
2013-03-20 10:00:19 +00:00
Denis Flaven
5d805a123e #683 : allow installation on a DB which names begins with numbers
+ directory cleanup for supporting symblinks

SVN:trunk[2639]
2013-03-19 11:38:53 +00:00
Erwan Taloc
584e1fade0 Add reconciliation keys for SLT in order to allow import for SLT having the same name
SVN:trunk[2638]
2013-03-18 17:49:27 +00:00
Erwan Taloc
98fa1fd071 Add reconciliation keys for SLT in order to allow import for SLT having the same name
SVN:trunk[2637]
2013-03-18 17:48:43 +00:00
Erwan Taloc
2b0b34a3a6 Remove wrong dependency to service_id on parent_request_id
SVN:trunk[2636]
2013-03-18 17:47:31 +00:00
Erwan Taloc
a3213bba43 Remove wrong dependency to service_id on parent_request_id
SVN:trunk[2635]
2013-03-18 17:46:56 +00:00
Erwan Taloc
1fc6b945f6 Add reconciliation key for Software (Fix Trac #666)
SVN:trunk[2634]
2013-03-18 17:46:02 +00:00
Denis Flaven
58aaed567f Bug fix: Data model alternate options were not properly checked when upgrading (especially when selecting ITIL tickets)
SVN:trunk[2633]
2013-03-18 17:39:26 +00:00
Romain Quetiez
51628604bf #687 Label for attribute Person:name always shown in english (Last Name)
SVN:trunk[2632]
2013-03-18 17:38:28 +00:00
Romain Quetiez
a35ff29363 #677 Cosmetics in the german localization (and a few other languages): first header of the config mgmt overview
SVN:trunk[2631]
2013-03-18 17:00:14 +00:00
Romain Quetiez
b52be60776 #684 CSV import / reconciliation using an enum does not take the translation into account
SVN:trunk[2630]
2013-03-18 10:26:14 +00:00
Romain Quetiez
d60d634208 #682 Order notifications (last first).
SVN:trunk[2629]
2013-03-15 16:25:02 +00:00
Romain Quetiez
b112597df8 Compiler: typo preventing from setting the property 'min_autocomplete_chars' on an external key
SVN:trunk[2628]
2013-03-15 10:07:50 +00:00
Romain Quetiez
a965bbd39f #626 Fixed missing translation in dictionaries (Tickets: "relations", and Contacts overview / count)
SVN:trunk[2627]
2013-03-14 17:37:19 +00:00
Romain Quetiez
cc70570e65 #657 JavaScript error when modifying UserLDAP object with Sync
SVN:trunk[2626]
2013-03-14 14:46:51 +00:00
Romain Quetiez
c1fae7fd24 #659 exception handling producing notices, hence causing confusion
SVN:trunk[2625]
2013-03-14 14:22:27 +00:00
Romain Quetiez
d620516055 #675 Error when drilling down on graph/pie/table with group by on a field that can be null (this case has been excluded)
SVN:trunk[2624]
2013-03-14 13:00:28 +00:00
Romain Quetiez
0918c81d58 #680 Setup failing to display the check report when DOM extension not enabled (php-xml not installed on redhat distributions)
SVN:trunk[2623]
2013-03-14 10:14:53 +00:00
Romain Quetiez
39b79e2a05 #660 Warning raised with ZendServer (with APC cache enabled) causing the setup to fail
SVN:trunk[2622]
2013-03-14 10:12:05 +00:00
Romain Quetiez
3340ca2b10 #679 Improved the reporting in case of an error while loading a module: 1) the list of already loaded modules is given, 2) the full path of the searched node is given
SVN:trunk[2621]
2013-03-14 09:07:35 +00:00
Denis Flaven
67dc148069 Better error reporting when loading a module fails.
SVN:trunk[2620]
2013-03-13 16:54:32 +00:00
Denis Flaven
c6ba656f1d Sort the modules before processing them for dependencies, in order to obtain a predictable result independent from the order of the modules in the file system... hopefully... (should fix Trac#679)
SVN:trunk[2619]
2013-03-13 16:52:10 +00:00
Romain Quetiez
acf4c7a28a #664 Could not login after upgrade of an iTop 1.x with a DB prefix
SVN:trunk[2618]
2013-03-13 14:37:46 +00:00
Romain Quetiez
b38dea4bba #634 Detection of HTTPS not working with nginx (iTop always considering the current connection as being secure)
SVN:trunk[2617]
2013-03-13 13:57:51 +00:00
Romain Quetiez
3cf398618e #472 REST Services: added core/delete (to bulk delete, full-featured), and validated the operation core/apply_stimulus
SVN:trunk[2616]
2013-03-13 11:01:16 +00:00
Romain Quetiez
462f163d8a #661 and #662 Could not create a user request (or ?) as soon as the autocomplete feature gets active
SVN:trunk[2615]
2013-03-12 16:09:03 +00:00
Erwan Taloc
96b3e9a891 Fix issue for creation of Logical Interface
SVN:trunk[2614]
2013-03-10 09:08:04 +00:00
Erwan Taloc
b56242808d Fix bug TTO / TTR computation for Service request (Trac 674)
SVN:trunk[2613]
2013-03-10 08:50:42 +00:00
Erwan Taloc
793f94d302 Correction to display IP field for Physical Device :
Network Device
Server
Storage System
NAS
Tape Library
SAN switch

SVN:trunk[2612]
2013-03-10 08:46:57 +00:00
Romain Quetiez
a23569e0c4 Fixed issue with the new CRON execution pattern
SVN:trunk[2611]
2013-03-08 14:03:55 +00:00
Romain Quetiez
80a8b63498 Modified the mechanism to display object dedicated messages (allows the plugin to add their message or replace standard ones)
Factorized the code to bulk update / bulk delete objects in an interactive way.

SVN:trunk[2610]
2013-03-08 13:36:31 +00:00
Denis Flaven
eee8d71381 Enhancement: take into account the "periodicity" of the background processes.
Bug fix: fixed a warning in CheckStopWatchThresholds

SVN:trunk[2609]
2013-03-01 17:14:54 +00:00
Denis Flaven
9013910cec Protect against unwanted output that may corrupt the JSON results
SVN:trunk[2607]
2013-02-27 16:14:16 +00:00
Denis Flaven
ddff9180ac Added 'core/apply_stimulus' as a possible operation for the REST web services.
SVN:trunk[2605]
2013-02-27 15:58:16 +00:00
Denis Flaven
4988d6eb04 Allow retrieving of the Filter used by a DisplayBlock (useful for extending search forms)
SVN:trunk[2603]
2013-02-27 14:31:27 +00:00
Denis Flaven
5ff86a40d9 Fix for making iUIPageExtension usable !
SVN:trunk[2600]
2013-02-27 13:37:12 +00:00
Denis Flaven
05133aa319 Fix for supporting the CSV export of big audit results.
SVN:trunk[2598]
2013-02-06 15:44:59 +00:00
Denis Flaven
626e2a1db1 Enable support of databases which name either is a reserved word or contains non-alphanumeric characters (i.e. itop-production).
SVN:trunk[2595]
2013-01-31 15:14:23 +00:00
Romain Quetiez
59e1a64f2d REST services: fixed issue with returned external keys
SVN:trunk[2594]
2013-01-30 14:09:32 +00:00
Denis Flaven
a9ac7d9e10 Added support for GET/JSON-P
SVN:trunk[2593]
2013-01-30 13:49:12 +00:00
Romain Quetiez
7b2789479d REST services: alpha2. It is now extensible (implement iRestServiceProvider). Still lacks two verbs: apply_stimulus and delete.
SVN:trunk[2592]
2013-01-30 09:46:55 +00:00
Denis Flaven
4e8db37060 Added credits to Stephan Rickauer about security.
SVN:trunk[2591]
2013-01-22 17:55:20 +00:00
Denis Flaven
80b0a8b942 Fix for Trac #670: XSS vulnerability issue.
SVN:trunk[2589]
2013-01-22 17:39:16 +00:00
Romain Quetiez
32924bc054 REST services: an alpha version. It is already possible to create/update/get objects. An example illustrates the possibilities.
SVN:trunk[2586]
2013-01-16 13:57:51 +00:00
Romain Quetiez
96530a5bdf Auto-documentation: first step => the extension APIs
SVN:trunk[2585]
2013-01-04 13:43:52 +00:00
Denis Flaven
18eee44ee6 Bug fix: properly record history of Hierarchical Keys
SVN:trunk[2584]
2012-12-21 15:37:45 +00:00
184 changed files with 9651 additions and 7174 deletions

View File

@@ -17,34 +17,248 @@
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Class iPlugin
* Management of application plugin
* Management of application plugins
*
* Definition of interfaces that can be implemented to customize iTop.
* You may implement such interfaces in a module file (e.g. main.mymodule.php)
*
* @package Extensibility
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
* @api
*/
/**
* Implement this interface to change the behavior of the GUI for some objects.
*
* All methods are invoked by iTop for a given object. There are basically two usages:
*
* 1) To tweak the form of an object, you will have to implement a specific behavior within:
*
* * OnDisplayProperties (bEditMode = true)
* * OnFormSubmit
* * OnFormCancel
*
* 2) To tune the display of the object details, you can use:
*
* * OnDisplayProperties
* * OnDisplayRelations
* * GetIcon
* * GetHilightClass
*
* Please note that some of the APIs can be called several times for a single page displayed.
* Therefore it is not recommended to perform too many operations, such as querying the database.
* A recommended pattern is to cache data by the mean of static members.
*
* @package Extensibility
* @api
*/
interface iApplicationUIExtension
{
/**
* Invoked when an object is being displayed (wiew or edit)
*
* The method is called right after the main tab has been displayed.
* You can add output to the page, either to change the display, or to add a form input
*
* Example:
* <code>
* if ($bEditMode)
* {
* $oPage->p('Age of the captain: &lt;input type="text" name="captain_age"/&gt;');
* }
* else
* {
* $oPage->p('Age of the captain: '.$iCaptainAge);
* }
* </code>
*
* @param DBObject $oObject The object being displayed
* @param WebPage $oPage The output context
* @param boolean $bEditMode True if the edition form is being displayed
* @return void
*/
public function OnDisplayProperties($oObject, WebPage $oPage, $bEditMode = false);
public function OnDisplayRelations($oObject, WebPage $oPage, $bEditMode = false);
public function OnFormSubmit($oObject, $sFormPrefix = '');
public function OnFormCancel($sTempId); // temp id is made of session_id and transaction_id, it identifies the object in a unique way
/**
* Invoked when an object is being displayed (wiew or edit)
*
* The method is called rigth after all the tabs have been displayed
*
* @param DBObject $oObject The object being displayed
* @param WebPage $oPage The output context
* @param boolean $bEditMode True if the edition form is being displayed
* @return void
*/
public function OnDisplayRelations($oObject, WebPage $oPage, $bEditMode = false);
/**
* Invoked when the end-user clicks on Modify from the object edition form
*
* The method is called after the changes from the standard form have been
* taken into account, and before saving the changes into the database.
*
* @param DBObject $oObject The object being edited
* @param string $sFormPrefix Prefix given to the HTML form inputs
* @return void
*/
public function OnFormSubmit($oObject, $sFormPrefix = '');
/**
* Invoked when the end-user clicks on Cancel from the object edition form
*
* Implement here any cleanup. This is necessary when you have injected some
* javascript into the edition form, and if that code requires to store temporary data
* (this is the case when a file must be uploaded).
*
* @param string $sTempId Unique temporary identifier made of session_id and transaction_id. It identifies the object in a unique way.
* @return void
*/
public function OnFormCancel($sTempId);
/**
* Not yet called by the framework!
*
* Sorry, the verb has been reserved. You must implement it, but it is not called as of now.
*
* @param DBObject $oObject The object being displayed
* @return type desc
*/
public function EnumUsedAttributes($oObject); // Not yet implemented
/**
* Not yet called by the framework!
*
* Sorry, the verb has been reserved. You must implement it, but it is not called as of now.
*
* @param DBObject $oObject The object being displayed
* @return string Path of the icon, relative to the modules directory.
*/
public function GetIcon($oObject); // Not yet implemented
/**
* Invoked when the object is displayed alone or within a list
*
* Returns a value influencing the appearance of the object depending on its
* state.
*
* Possible values are:
*
* * HILIGHT_CLASS_CRITICAL
* * HILIGHT_CLASS_WARNING
* * HILIGHT_CLASS_OK
* * HILIGHT_CLASS_NONE
*
* @param DBObject $oObject The object being displayed
* @return integer The value representing the mood of the object
*/
public function GetHilightClass($oObject);
/**
* Called when building the Actions menu for a single object or a list of objects
*
* Use this to add items to the Actions menu. You will have to specify a label and an URL.
*
* Example:
* <code>
* $oObject = $oSet->fetch();
* if ($oObject instanceof Sheep)
* {
* return array('View in my app' => 'http://myserver/view_sheeps?id='.$oObject->Get('name'));
* }
* else
* {
* return array();
* }
* </code>
*
* See also iPopupMenuExtension for greater flexibility
*
* @param DBObjectSet $oSet A set of persistent objects (DBObject)
* @return string[string]
*/
public function EnumAllowedActions(DBObjectSet $oSet);
}
/**
* Implement this interface to perform specific things when objects are manipulated
*
* Note that those methods will be called when objects are manipulated, either in a programmatic way
* or through the GUI.
*
* @package Extensibility
* @api
*/
interface iApplicationObjectExtension
{
/**
* Invoked to determine wether an object has been modified in memory
*
* The GUI calls this verb to determine the message that will be displayed to the end-user.
* Anyhow, this API can be called in other contexts such as the CSV import tool.
*
* If the extension returns false, then the framework will perform the usual evaluation.
* Otherwise, the answer is definitively "yes, the object has changed".
*
* @param DBObject $oObject The target object
* @return boolean True if something has changed for the target object
*/
public function OnIsModified($oObject);
/**
* Invoked to determine wether an object can be written to the database
*
* The GUI calls this verb and reports any issue.
* Anyhow, this API can be called in other contexts such as the CSV import tool.
*
* @param DBObject $oObject The target object
* @return string[] A list of errors message. An error message is made of one line and it can be displayed to the end-user.
*/
public function OnCheckToWrite($oObject);
/**
* Invoked to determine wether an object can be deleted from the database
*
* The GUI calls this verb and stops the deletion process if any issue is reported.
*
* Please not that it is not possible to cascade deletion by this mean: only stopper issues can be handled.
*
* @param DBObject $oObject The target object
* @return string[] A list of errors message. An error message is made of one line and it can be displayed to the end-user.
*/
public function OnCheckToDelete($oObject);
/**
* Invoked when an object is updated into the database
*
* The method is called right <b>after</b> the object has been written to the database.
*
* @param DBObject $oObject The target object
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information once for all the changes made within the current page
* @return void
*/
public function OnDBUpdate($oObject, $oChange = null);
/**
* Invoked when an object is created into the database
*
* The method is called right <b>after</b> the object has been written to the database.
*
* @param DBObject $oObject The target object
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information once for all the changes made within the current page
* @return void
*/
public function OnDBInsert($oObject, $oChange = null);
/**
* Invoked when an object is deleted from the database
*
* The method is called right <b>before</b> the object will be deleted from the database.
*
* @param DBObject $oObject The target object
* @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information once for all the changes made within the current page
* @return void
*/
public function OnDBDelete($oObject, $oChange = null);
}
@@ -54,46 +268,102 @@ interface iApplicationObjectExtension
*
* To add some menus into iTop, declare a class that implements this interface, it will be called automatically
* by the application, as long as the class definition is included somewhere in the code
*
* @package Extensibility
* @api
* @since 2.0
*/
interface iPopupMenuExtension
{
// Possible types of menu into which new items can be added
const MENU_OBJLIST_ACTIONS = 1; // $param is a DBObjectSet containing the list of objects
const MENU_OBJLIST_TOOLKIT = 2; // $param is a DBObjectSet containing the list of objects
const MENU_OBJDETAILS_ACTIONS = 3; // $param is a DBObject instance: the object currently displayed
const MENU_DASHBOARD_ACTIONS = 4; // $param is a Dashboard instance: the dashboard currently displayed
const MENU_USER_ACTIONS = 5; // $param is a null ??
/**
* Insert an item into the Actions menu of a list
*
* $param is a DBObjectSet containing the list of objects
*/
const MENU_OBJLIST_ACTIONS = 1;
/**
* Insert an item into the Toolkit menu of a list
*
* $param is a DBObjectSet containing the list of objects
*/
const MENU_OBJLIST_TOOLKIT = 2;
/**
* Insert an item into the Actions menu on an object details page
*
* $param is a DBObject instance: the object currently displayed
*/
const MENU_OBJDETAILS_ACTIONS = 3;
/**
* Insert an item into the Dashboard menu
*
* The dashboad menu is shown on the top right corner when a dashboard
* is being displayed.
*
* $param is a Dashboard instance: the dashboard currently displayed
*/
const MENU_DASHBOARD_ACTIONS = 4;
/**
* Insert an item into the User menu (upper right corner)
*
* $param is null
*/
const MENU_USER_ACTIONS = 5;
/**
* Get the list of items to be added to a menu. The items will be inserted in the menu in the order of the returned array
* @param int $iMenuId The identifier of the type of menu, as listed by the constants MENU_xxx above
* Get the list of items to be added to a menu.
*
* This method is called by the framework for each menu.
* The items will be inserted in the menu in the order of the returned array.
* @param int $iMenuId The identifier of the type of menu, as listed by the constants MENU_xxx
* @param mixed $param Depends on $iMenuId, see the constants defined above
* @return Array An array of ApplicationPopupMenuItem or an empty array if no action is to be added to the menu
* @return object[] An array of ApplicationPopupMenuItem or an empty array if no action is to be added to the menu
*/
public static function EnumItems($iMenuId, $param);
}
/**
* Each menu items is defined by an instance of an object derived from the class
* ApplicationPopupMenu below
*
* Base class for the various types of custom menus
*
* @package Extensibility
* @internal
* @since 2.0
*/
abstract class ApplicationPopupMenuItem
{
/** @ignore */
protected $sUID;
/** @ignore */
protected $sLabel;
/**
* Constructor
*
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
* @param string $sLabel The display label of the menu (must be localized)
*/
public function __construct($sUID, $sLabel)
{
$this->sUID = $sUID;
$this->sLabel = $sLabel;
}
/**
* Get the UID
*
* @return string The unique identifier
* @ignore
*/
public function GetUID()
{
return $this->sUID;
}
/**
* Get the label
*
* @return string The label
* @ignore
*/
public function GetLabel()
{
return $this->sLabel;
@@ -102,9 +372,11 @@ abstract class ApplicationPopupMenuItem
/**
* Returns the components to create a popup menu item in HTML
* @return Hash A hash array: array('label' => , 'url' => , 'target' => , 'onclick' => )
* @ignore
*/
abstract public function GetMenuItem();
/** @ignore */
public function GetLinkedScripts()
{
return array();
@@ -113,14 +385,21 @@ abstract class ApplicationPopupMenuItem
/**
* Class for adding an item into a popup menu that browses to the given URL
*
* @package Extensibility
* @api
* @since 2.0
*/
class URLPopupMenuItem extends ApplicationPopupMenuItem
{
/** @ignore */
protected $sURL;
/** @ignore */
protected $sTarget;
/**
* Class for adding an item that browses to the given URL
* Constructor
*
* @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough
* @param string $sLabel The display label of the menu (must be localized)
* @param string $sURL If the menu is an hyperlink, provide the absolute hyperlink here
@@ -133,6 +412,7 @@ class URLPopupMenuItem extends ApplicationPopupMenuItem
$this->sTarget = $sTarget;
}
/** @ignore */
public function GetMenuItem()
{
return array ('label' => $this->GetLabel(), 'url' => $this->sURL, 'target' => $this->sTarget);
@@ -141,10 +421,16 @@ class URLPopupMenuItem extends ApplicationPopupMenuItem
/**
* Class for adding an item into a popup menu that triggers some Javascript code
*
* @package Extensibility
* @api
* @since 2.0
*/
class JSPopupMenuItem extends ApplicationPopupMenuItem
{
/** @ignore */
protected $sJSCode;
/** @ignore */
protected $aIncludeJSFiles;
/**
@@ -161,11 +447,13 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
$this->aIncludeJSFiles = $aIncludeJSFiles;
}
/** @ignore */
public function GetMenuItem()
{
return array ('label' => $this->GetLabel(), 'onclick' => $this->sJSCode, 'url' => '#');
}
/** @ignore */
public function GetLinkedScripts()
{
return $this->aIncludeJSFiles;
@@ -175,17 +463,23 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
/**
* Class for adding a separator (horizontal line, not selectable) the output
* will automatically reduce several consecutive separators to just one
*
* @package Extensibility
* @api
* @since 2.0
*/
class SeparatorPopupMenuItem extends ApplicationPopupMenuItem
{
static $idx = 0;
/**
* Class for inserting a separator into a popup menu
* Constructor
*/
public function __construct()
{
parent::__construct('', '');
parent::__construct('_separator_'.(self::$idx++), '');
}
/** @ignore */
public function GetMenuItem()
{
return array ('label' => '<hr class="menu-separator">', 'url' => '');
@@ -194,36 +488,476 @@ class SeparatorPopupMenuItem extends ApplicationPopupMenuItem
/**
* Implement this interface to add content to any iTopWebPage
*
* There are 3 places where content can be added:
* - The north pane: (normaly empty/hidden) at the top of the page, spanning the whole
*
* * The north pane: (normaly empty/hidden) at the top of the page, spanning the whole
* width of the page
* - The south pane: (normaly empty/hidden) at the bottom of the page, spanning the whole
* * The south pane: (normaly empty/hidden) at the bottom of the page, spanning the whole
* width of the page
* - The admin banner (two tones gray background) at the left of the global search.
* * The admin banner (two tones gray background) at the left of the global search.
* Limited space, use it for short messages
*
* Each of the methods of this interface is supposed to return the HTML to be inserted at
* the specified place and can use the passed iTopWebPage object to add javascript or CSS definitions
*
* @package Extensibility
* @api
* @since 2.0
*/
interface iPageUIExtension
{
/**
* Add content to the North pane
* @param WebPage $oPage The page to insert stuff into.
* @param iTopWebPage $oPage The page to insert stuff into.
* @return string The HTML content to add into the page
*/
public function GetNorthPaneHtml(iTopWebPage $oPage);
/**
* Add content to the South pane
* @param WebPage $oPage The page to insert stuff into.
* @param iTopWebPage $oPage The page to insert stuff into.
* @return string The HTML content to add into the page
*/
public function GetSouthPaneHtml(iTopWebPage $oPage);
/**
* Add content to the "admin banner"
* @param WebPage $oPage The page to insert stuff into.
* @param iTopWebPage $oPage The page to insert stuff into.
* @return string The HTML content to add into the page
*/
public function GetBannerHtml(iTopWebPage $oPage);
}
/**
* Implement this interface to add new operations to the REST/JSON web service
*
* @package Extensibility
* @api
* @since 2.0.1
*/
interface iRestServiceProvider
{
/**
* Enumerate services delivered by this class
* @param string $sVersion The version (e.g. 1.0) supported by the services
* @return array An array of hash 'verb' => verb, 'description' => description
*/
public function ListOperations($sVersion);
/**
* Enumerate services delivered by this class
* @param string $sVersion The version (e.g. 1.0) supported by the services
* @return RestResult The standardized result structure (at least a message)
* @throws Exception in case of internal failure.
*/
public function ExecOperation($sVersion, $sVerb, $aParams);
}
/**
* Minimal REST response structure. Derive this structure to add response data and error codes.
*
* @package Extensibility
* @api
* @since 2.0.1
*/
class RestResult
{
/**
* Result: no issue has been encountered
*/
const OK = 0;
/**
* Result: missing/wrong credentials or the user does not have enough rights to perform the requested operation
*/
const UNAUTHORIZED = 1;
/**
* Result: the parameter 'version' is missing
*/
const MISSING_VERSION = 2;
/**
* Result: the parameter 'json_data' is missing
*/
const MISSING_JSON = 3;
/**
* Result: the input structure is not a valid JSON string
*/
const INVALID_JSON = 4;
/**
* Result: no operation is available for the specified version
*/
const UNSUPPORTED_VERSION = 10;
/**
* Result: the requested operation is not valid for the specified version
*/
const UNKNOWN_OPERATION = 11;
/**
* Result: the requested operation cannot be performed because it can cause data (integrity) loss
*/
const UNSAFE = 12;
/**
* Result: the operation could not be performed, see the message for troubleshooting
*/
const INTERNAL_ERROR = 100;
/**
* Default constructor - ok!
*
* @param DBObject $oObject The object being reported
* @param string $sAttCode The attribute code (must be valid)
* @return string A scalar representation of the value
*/
public function __construct()
{
$this->code = RestResult::OK;
}
public $code;
public $message;
}
/**
* Helpers for implementing REST services
*
* @package Extensibility
* @api
*/
class RestUtils
{
/**
* Registering tracking information. Any further object modification be associated with the given comment, when the modification gets recorded into the DB
*
* @param StdClass $oData Structured input data. Must contain 'comment'.
* @return void
* @throws Exception
* @api
*/
public static function InitTrackingComment($oData)
{
$sComment = self::GetMandatoryParam($oData, 'comment');
CMDBObject::SetTrackInfo($sComment);
}
/**
* Read a mandatory parameter from from a Rest/Json structure.
*
* @param StdClass $oData Structured input data. Must contain the entry defined by sParamName.
* @param string $sParamName Name of the parameter to fetch from the input data
* @return void
* @throws Exception If the parameter is missing
* @api
*/
public static function GetMandatoryParam($oData, $sParamName)
{
if (isset($oData->$sParamName))
{
return $oData->$sParamName;
}
else
{
throw new Exception("Missing parameter '$sParamName'");
}
}
/**
* Read an optional parameter from from a Rest/Json structure.
*
* @param StdClass $oData Structured input data.
* @param string $sParamName Name of the parameter to fetch from the input data
* @param mixed $default Default value if the parameter is not found in the input data
* @return void
* @throws Exception
* @api
*/
public static function GetOptionalParam($oData, $sParamName, $default)
{
if (isset($oData->$sParamName))
{
return $oData->$sParamName;
}
else
{
return $default;
}
}
/**
* Read a class from a Rest/Json structure.
*
* @param StdClass $oData Structured input data. Must contain the entry defined by sParamName.
* @param string $sParamName Name of the parameter to fetch from the input data
* @return void
* @throws Exception If the parameter is missing or the class is unknown
* @api
*/
public static function GetClass($oData, $sParamName)
{
$sClass = self::GetMandatoryParam($oData, $sParamName);
if (!MetaModel::IsValidClass($sClass))
{
throw new Exception("$sParamName: '$sClass' is not a valid class'");
}
return $sClass;
}
/**
* Read a list of attribute codes from a Rest/Json structure.
*
* @param string $sClass Name of the class
* @param StdClass $oData Structured input data.
* @param string $sParamName Name of the parameter to fetch from the input data
* @return void
* @throws Exception
* @api
*/
public static function GetFieldList($sClass, $oData, $sParamName)
{
$sFields = self::GetOptionalParam($oData, $sParamName, '*');
$aShowFields = array();
if ($sFields == '*')
{
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
$aShowFields[] = $sAttCode;
}
}
else
{
foreach(explode(',', $sFields) as $sAttCode)
{
$sAttCode = trim($sAttCode);
if (($sAttCode != 'id') && (!MetaModel::IsValidAttCode($sClass, $sAttCode)))
{
throw new Exception("$sParamName: invalid attribute code '$sAttCode'");
}
$aShowFields[] = $sAttCode;
}
}
return $aShowFields;
}
/**
* Read and interpret object search criteria from a Rest/Json structure
*
* @param string $sClass Name of the class
* @param StdClass $oCriteria Hash of attribute code => value (can be a substructure or a scalar, depending on the nature of the attriute)
* @return object The object found
* @throws Exception If the input structure is not valid or it could not find exactly one object
*/
protected static function FindObjectFromCriteria($sClass, $oCriteria)
{
$aCriteriaReport = array();
if (isset($oCriteria->finalclass))
{
$sClass = $oCriteria->finalclass;
if (!MetaModel::IsValidClass($sClass))
{
throw new Exception("finalclass: Unknown class '$sClass'");
}
}
$oSearch = new DBObjectSearch($sClass);
foreach ($oCriteria as $sAttCode => $value)
{
$realValue = self::MakeValue($sClass, $sAttCode, $value);
$oSearch->AddCondition($sAttCode, $realValue);
$aCriteriaReport[] = "$sAttCode: $value ($realValue)";
}
$oSet = new DBObjectSet($oSearch);
$iCount = $oSet->Count();
if ($iCount == 0)
{
throw new Exception("No item found with criteria: ".implode(', ', $aCriteriaReport));
}
elseif ($iCount > 1)
{
throw new Exception("Several items found ($iCount) with criteria: ".implode(', ', $aCriteriaReport));
}
$res = $oSet->Fetch();
return $res;
}
/**
* Find an object from a polymorph search specification (Rest/Json)
*
* @param string $sClass Name of the class
* @param mixed $key Either search criteria (substructure), or an object or an OQL string.
* @return DBObject The object found
* @throws Exception If the input structure is not valid or it could not find exactly one object
* @api
*/
public static function FindObjectFromKey($sClass, $key)
{
if (is_object($key))
{
$res = self::FindObjectFromCriteria($sClass, $key);
}
elseif (is_numeric($key))
{
$res = MetaModel::GetObject($sClass, $key, false);
if (is_null($res))
{
throw new Exception("Invalid object $sClass::$key");
}
}
elseif (is_string($key))
{
// OQL
$oSearch = DBObjectSearch::FromOQL($key);
$oSet = new DBObjectSet($oSearch);
$iCount = $oSet->Count();
if ($iCount == 0)
{
throw new Exception("No item found for query: $key");
}
elseif ($iCount > 1)
{
throw new Exception("Several items found ($iCount) for query: $key");
}
$res = $oSet->Fetch();
}
else
{
throw new Exception("Wrong format for key");
}
return $res;
}
/**
* Search objects from a polymorph search specification (Rest/Json)
*
* @param string $sClass Name of the class
* @param mixed $key Either search criteria (substructure), or an object or an OQL string.
* @return DBObjectSet The search result set
* @throws Exception If the input structure is not valid
*/
public static function GetObjectSetFromKey($sClass, $key)
{
if (is_object($key))
{
if (isset($key->finalclass))
{
$sClass = $key->finalclass;
if (!MetaModel::IsValidClass($sClass))
{
throw new Exception("finalclass: Unknown class '$sClass'");
}
}
$oSearch = new DBObjectSearch($sClass);
foreach ($key as $sAttCode => $value)
{
$realValue = self::MakeValue($sClass, $sAttCode, $value);
$oSearch->AddCondition($sAttCode, $realValue);
}
}
elseif (is_numeric($key))
{
$oSearch = new DBObjectSearch($sClass);
$oSearch->AddCondition('id', $key);
}
elseif (is_string($key))
{
// OQL
$oSearch = DBObjectSearch::FromOQL($key);
$oObjectSet = new DBObjectSet($oSearch);
}
else
{
throw new Exception("Wrong format for key");
}
$oObjectSet = new DBObjectSet($oSearch);
return $oObjectSet;
}
/**
* Interpret the Rest/Json value and get a valid attribute value
*
* @param string $sClass Name of the class
* @param string $sAttCode Attribute code
* @param mixed $value Depending on the type of attribute (a scalar, or search criteria, or list of related objects...)
* @return mixed The value that can be used with DBObject::Set()
* @throws Exception If the specification of the value is not valid.
* @api
*/
public static function MakeValue($sClass, $sAttCode, $value)
{
try
{
if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
{
throw new Exception("Unknown attribute");
}
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef instanceof AttributeExternalKey)
{
$oExtKeyObject = self::FindObjectFromKey($oAttDef->GetTargetClass(), $value);
$value = $oExtKeyObject->GetKey();
}
elseif ($oAttDef instanceof AttributeLinkedSet)
{
if (!is_array($value))
{
throw new Exception("A link set must be defined by an array of objects");
}
$sLnkClass = $oAttDef->GetLinkedClass();
$aLinks = array();
foreach($value as $oValues)
{
$oLnk = self::MakeObjectFromFields($sLnkClass, $oValues);
$aLinks[] = $oLnk;
}
$value = DBObjectSet::FromArray($sLnkClass, $aLinks);
}
else
{
$value = $oAttDef->FromJSONToValue($value);
}
}
catch (Exception $e)
{
throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode());
}
return $value;
}
/**
* Interpret a Rest/Json structure that defines attribute values, and build an object
*
* @param string $sClass Name of the class
* @param array $aFields A hash of attribute code => value specification.
* @return DBObject The newly created object
* @throws Exception If the specification of the values is not valid
* @api
*/
public static function MakeObjectFromFields($sClass, $aFields)
{
$oObject = MetaModel::NewObject($sClass);
foreach ($aFields as $sAttCode => $value)
{
$realValue = self::MakeValue($sClass, $sAttCode, $value);
$oObject->Set($sAttCode, $realValue);
}
return $oObject;
}
/**
* Interpret a Rest/Json structure that defines attribute values, and update the given object
*
* @param DBObject $oObject The object being modified
* @param array $aFields A hash of attribute code => value specification.
* @return DBObject The object modified
* @throws Exception If the specification of the values is not valid
* @api
*/
public static function UpdateObjectFromFields($oObject, $aFields)
{
$sClass = get_class($oObject);
foreach ($aFields as $sAttCode => $value)
{
$realValue = self::MakeValue($sClass, $sAttCode, $value);
$oObject->Set($sAttCode, $realValue);
}
return $oObject;
}
}

View File

@@ -80,6 +80,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
{
protected $m_iFormId; // The ID of the form used to edit the object (when in edition mode !)
static $iGlobalFormId = 1;
protected $aFieldsMap;
/**
* returns what will be the next ID for the forms
@@ -92,7 +93,38 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
{
return 'UI.php';
}
/**
* Set a message diplayed to the end-user next time this object will be displayed
* Messages are uniquely identified so that plugins can override standard messages (the final work is given to the last plugin to set the message for a given message id)
* In practice, standard messages are recorded at the end but they will not overwrite existing messages
*
* @param string $sClass The class of the object (must be the final class)
* @param int $iKey The identifier of the object
* @param string $sMessageId Your id or one of the well-known ids: 'create', 'update' and 'apply_stimulus'
* @param string $sMessage The HTML message (must be correctly escaped)
* @param string $sSeverity Any of the following: ok, info, error.
* @param float $fRank Ordering of the message: smallest displayed first (can be negative)
* @param bool $bMustNotExist Do not alter any existing message (considering the id)
*
*/
public static function SetSessionMessage($sClass, $iKey, $sMessageId, $sMessage, $sSeverity, $fRank, $bMustNotExist = false)
{
$sMessageKey = $sClass.'::'.$iKey;
if (!isset($_SESSION['obj_messages'][$sMessageKey]))
{
$_SESSION['obj_messages'][$sMessageKey] = array();
}
if (!$bMustNotExist || !array_key_exists($sMessageId, $_SESSION['obj_messages'][$sMessageKey]))
{
$_SESSION['obj_messages'][$sMessageKey][$sMessageId] = array(
'rank' => $fRank,
'severity' => $sSeverity,
'message' => $sMessage
);
}
}
function DisplayBareHeader(WebPage $oPage, $bEditMode = false)
{
// Standard Header with name, actions menu and history block
@@ -102,8 +134,19 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
$sMessageKey = get_class($this).'::'.$this->GetKey();
if (array_key_exists('obj_messages', $_SESSION) && array_key_exists($sMessageKey, $_SESSION['obj_messages']))
{
$sMsgClass = 'message_'.$_SESSION['obj_messages'][$sMessageKey]['severity'];
$oPage->add("<div class=\"header_message $sMsgClass\">".$_SESSION['obj_messages'][$sMessageKey]['message']."</div>");
$aMessages = array();
$aRanks = array();
foreach ($_SESSION['obj_messages'][$sMessageKey] as $sMessageId => $aMessageData)
{
$sMsgClass = 'message_'.$aMessageData['severity'];
$aMessages[] = "<div class=\"header_message $sMsgClass\">".$aMessageData['message']."</div>";
$aRanks[] = $aMessageData['rank'];
}
array_multisort($aRanks, $aMessages);
foreach ($aMessages as $sMessage)
{
$oPage->add($sMessage);
}
unset($_SESSION['obj_messages'][$sMessageKey]);
}
@@ -197,6 +240,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
$sTip .= Dict::S('Core:Synchro:LastSynchro').'<br/>'.$aStruct['last_synchro']."</p>";
}
$sSynchroIcon = '&nbsp;<img style="vertical-align:middle;" id="synchro_icon" src="../images/locked.png"/>';
$sTip = addslashes($sTip);
$oPage->add_ready_script("$('#synchro_icon').qtip( { content: '$sTip', show: 'mouseover', hide: { fixed: true }, style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );");
}
@@ -247,6 +291,16 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
return $aFieldsMap;
}
/**
* Add a field to the map: attcode => id used when building a form
* @param string $sAttCode The attribute code of the field being edited
* @param string $sInputId The unique ID of the control/widget in the page
*/
protected function AddToFieldsMap($sAttCode, $sInputId)
{
$this->aFieldsMap[$sAttCode] = $sInputId;
}
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
{
@@ -303,7 +357,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
$sDisplayValue = ''; // not used
$aArgs = array('this' => $this);
$sHTMLValue = "<span id=\"field_{$sInputId}\">".self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $oValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs).'</span>';
$aFieldsMap[$sAttCode] = $sInputId;
$this->AddToFieldsMap($sAttCode, $sInputId);
$oPage->add($sHTMLValue);
}
else
@@ -364,23 +418,42 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
// Display Notifications after the other tabs since this tab disappears in edition
if (!$bEditMode)
{
// Get the actual class of the current object
// And look for triggers referring to it
// Look for any trigger that considers this object as "In Scope"
// If any trigger has been found then display a tab with notifications
//
$sClass = get_class($this);
$sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
$oTriggerSet = new CMDBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObject AS T WHERE T.target_class IN ('$sClassList')"));
if ($oTriggerSet->Count() > 0)
$oTriggerSet = new CMDBObjectSet(new DBObjectSearch('Trigger'));
$aTriggers = array();
while($oTrigger = $oTriggerSet->Fetch())
{
if($oTrigger->IsInScope($this))
{
$aTriggers[] = $oTrigger->GetKey();
}
}
if (count($aTriggers) > 0)
{
// Display notifications regarding the object
$iId = $this->GetKey();
$oNotifSearch = DBObjectSearch::FromOQL("SELECT EventNotificationEmail AS Ev JOIN TriggerOnObject AS T ON Ev.trigger_id = T.id WHERE T.target_class IN ('$sClassList') AND Ev.object_id = $iId");
$oNotifSet = new DBObjectSet($oNotifSearch);
$sCount = ($oNotifSet->Count() > 0) ? ' ('.$oNotifSet->Count().')' : '';
$sTriggersList = implode(',', $aTriggers);
$aNotifSearches = array();
$iNotifsCount = 0;
$aNotificationClasses = MetaModel::EnumChildClasses('EventNotification', ENUM_CHILD_CLASSES_EXCLUDETOP);
foreach($aNotificationClasses as $sNotifClass)
{
$aNotifSearches[$sNotifClass] = DBObjectSearch::FromOQL("SELECT $sNotifClass AS Ev JOIN Trigger AS T ON Ev.trigger_id = T.id WHERE T.id IN ($sTriggersList) AND Ev.object_id = $iId");
$oNotifSet = new DBObjectSet($aNotifSearches[$sNotifClass]);
$iNotifsCount += $oNotifSet->Count();
}
// Display notifications regarding the object: on block per subclass to have the intersting columns
$sCount = ($iNotifsCount > 0) ? ' ('.$iNotifsCount.')' : '';
$oPage->SetCurrentTab(Dict::S('UI:NotificationsTab').$sCount);
$oBlock = new DisplayBlock($oNotifSearch, 'list', false);
$oBlock->Display($oPage, 'notifications', array('menu' => false));
foreach($aNotificationClasses as $sNotifClass)
{
$oPage->p(MetaModel::GetClassIcon($sNotifClass, true).'&nbsp;'.MetaModel::GetName($sNotifClass));
$oBlock = new DisplayBlock($aNotifSearches[$sNotifClass], 'list', false);
$oBlock->Display($oPage, 'notifications_'.$sNotifClass, array('menu' => false));
}
}
}
}
@@ -504,6 +577,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
{
$sTip .= "<p>Synchronized with {$aRow['name']} - {$aRow['description']}</p>";
}
$sTip = addslashes($sTip);
$oPage->add_ready_script("$('#synchro_$sInputId').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );");
}
@@ -757,7 +831,10 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
$iDefaultPageSize = appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit());
$oSettings->iDefaultPageSize = $iDefaultPageSize;
}
else
{
$oSettings->iDefaultPageSize = 0;
}
$oSettings->aSortOrder = MetaModel::GetOrderByDefault($sClassName);
return $oDataTable->Display($oPage, $oSettings, $bDisplayMenu, $sSelectMode, $bViewLink, $aExtraParams);
@@ -1143,9 +1220,25 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
$oFinalAttDef = $oAttDef->GetFinalAttDef();
if (get_class($oFinalAttDef) == 'AttributeDateTime')
{
$iDate = AttributeDateTime::GetAsUnixSeconds($oObj->Get($sAttCodeEx));
$aRow[] = '<td>'.date('Y-m-d', $iDate).'</td>';
$aRow[] = '<td>'.date('H:i:s', $iDate).'</td>';
$sDate = $oObj->Get($sAttCodeEx);
if ($sDate === null)
{
$aRow[] = '<td></td>';
$aRow[] = '<td></td>';
}
else
{
$iDate = AttributeDateTime::GetAsUnixSeconds($sDate);
$aRow[] = '<td>'.date('Y-m-d', $iDate).'</td>';
$aRow[] = '<td>'.date('H:i:s', $iDate).'</td>';
}
}
else if($oAttDef instanceof AttributeCaseLog)
{
$rawValue = $oObj->Get($sAttCodeEx);
$outputValue = str_replace("\n", "<br/>", htmlentities($rawValue->__toString(), ENT_QUOTES, 'UTF-8'));
// Trick for Excel: treat the content as text even if it begins with an equal sign
$aRow[] = '<td x:str>'.$outputValue.'</td>';
}
else
{
@@ -1539,10 +1632,10 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
$oPage->add_ready_script("$('#{$iId}_m').bind('keyup change', function(evt, sFormId) { return UpdateDuration('$iId'); });");
$oPage->add_ready_script("$('#{$iId}_s').bind('keyup change', function(evt, sFormId) { return UpdateDuration('$iId'); });");
$aVal = AttributeDuration::SplitDuration($value);
$sDays = "<input title=\"$sHelpText\" type=\"text\" size=\"3\" name=\"attr_{$sFieldPrefix}{$sAttCode}[d]{$sNameSuffix}\" value=\"{$aVal['days']}\" id=\"{$iId}_d\"/>";
$sHours = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[h]{$sNameSuffix}\" value=\"{$aVal['hours']}\" id=\"{$iId}_h\"/>";
$sMinutes = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[m]{$sNameSuffix}\" value=\"{$aVal['minutes']}\" id=\"{$iId}_m\"/>";
$sSeconds = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[s]{$sNameSuffix}\" value=\"{$aVal['seconds']}\" id=\"{$iId}_s\"/>";
$sDays = "<input title=\"$sHelpText\" type=\"text\" style=\"text-align:right\" size=\"3\" name=\"attr_{$sFieldPrefix}{$sAttCode}[d]{$sNameSuffix}\" value=\"{$aVal['days']}\" id=\"{$iId}_d\"/>";
$sHours = "<input title=\"$sHelpText\" type=\"text\" style=\"text-align:right\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[h]{$sNameSuffix}\" value=\"{$aVal['hours']}\" id=\"{$iId}_h\"/>";
$sMinutes = "<input title=\"$sHelpText\" type=\"text\" style=\"text-align:right\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[m]{$sNameSuffix}\" value=\"{$aVal['minutes']}\" id=\"{$iId}_m\"/>";
$sSeconds = "<input title=\"$sHelpText\" type=\"text\" style=\"text-align:right\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[s]{$sNameSuffix}\" value=\"{$aVal['seconds']}\" id=\"{$iId}_s\"/>";
$sHidden = "<input type=\"hidden\" id=\"{$iId}\" value=\"".htmlentities($value, ENT_QUOTES, 'UTF-8')."\"/>";
$sHTMLValue = Dict::Format('UI:DurationForm_Days_Hours_Minutes_Seconds', $sDays, $sHours, $sMinutes, $sSeconds).$sHidden."&nbsp;".$sValidationField;
$oPage->add_ready_script("$('#{$iId}').bind('update', function(evt, sFormId) { return ToggleDurationField('$iId'); });");
@@ -1754,10 +1847,11 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
}
return "<div>{$sHTMLValue}</div>";
}
public function DisplayModifyForm(WebPage $oPage, $aExtraParams = array())
{
self::$iGlobalFormId++;
$this->aFieldsMap = array();
$sPrefix = '';
if (isset($aExtraParams['formPrefix']))
{
@@ -1902,7 +1996,8 @@ EOF
// Now display the relations, one tab per relation
if (!isset($aExtraParams['noRelations']))
{
$this->DisplayBareRelations($oPage, true); // Edit mode
$this->DisplayBareRelations($oPage, true); // Edit mode, will fill $this->aFieldsMap
$aFieldsMap = array_merge($aFieldsMap, $this->aFieldsMap);
}
$oPage->SetCurrentTab('');
@@ -2790,6 +2885,7 @@ EOF
{
$sTip .= "<p>Synchronized with {$aRow['name']} - {$aRow['description']}</p>";
}
$sTip = addslashes($sTip);
$oPage->add_ready_script("$('#synchro_$sInputId').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );");
}
@@ -2868,5 +2964,579 @@ EOF
}
return $aComputedAttributes;
}
/**
* Display a form for modifying several objects at once
* The form will be submitted to the current page, with the specified additional values
*/
public static function DisplayBulkModifyForm($oP, $sClass, $aSelectedObj, $sCustomOperation, $sCancelUrl, $aExcludeAttributes = array(), $aContextData = array())
{
if (count($aSelectedObj) > 0)
{
$iAllowedCount = count($aSelectedObj);
$sSelectedObj = implode(',', $aSelectedObj);
$sOQL = "SELECT $sClass WHERE id IN (".$sSelectedObj.")";
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL));
// Compute the distribution of the values for each field to determine which of the "scalar" fields are homogenous
$aList = MetaModel::ListAttributeDefs($sClass);
$aValues = array();
foreach($aList as $sAttCode => $oAttDef)
{
if ($oAttDef->IsScalar())
{
$aValues[$sAttCode] = array();
}
}
while($oObj = $oSet->Fetch())
{
foreach($aList as $sAttCode => $oAttDef)
{
if ($oAttDef->IsScalar() && $oAttDef->IsWritable())
{
$currValue = $oObj->Get($sAttCode);
if ($oAttDef instanceof AttributeCaseLog)
{
$currValue = ' '; // Don't put an empty string, in case the field would be considered as mandatory...
}
if (is_object($currValue)) continue; // Skip non scalar values...
if(!array_key_exists($currValue, $aValues[$sAttCode]))
{
$aValues[$sAttCode][$currValue] = array('count' => 1, 'display' => $oObj->GetAsHTML($sAttCode));
}
else
{
$aValues[$sAttCode][$currValue]['count']++;
}
}
}
}
// Now create an object that has values for the homogenous values only
$oDummyObj = new $sClass(); // @@ What if the class is abstract ?
$aComments = array();
function MyComparison($a, $b) // Sort descending
{
if ($a['count'] == $b['count'])
{
return 0;
}
return ($a['count'] > $b['count']) ? -1 : 1;
}
$iFormId = cmdbAbstractObject::GetNextFormId(); // Identifier that prefixes all the form fields
$sReadyScript = '';
$aDependsOn = array();
$sFormPrefix = '2_';
foreach($aList as $sAttCode => $oAttDef)
{
$aPrerequisites = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode); // List of attributes that are needed for the current one
if (count($aPrerequisites) > 0)
{
// When 'enabling' a field, all its prerequisites must be enabled too
$sFieldList = "['{$sFormPrefix}".implode("','{$sFormPrefix}", $aPrerequisites)."']";
$oP->add_ready_script("$('#enable_{$sFormPrefix}{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, $sFieldList, true); } );\n");
}
$aDependents = MetaModel::GetDependentAttributes($sClass, $sAttCode); // List of attributes that are needed for the current one
if (count($aDependents) > 0)
{
// When 'disabling' a field, all its dependent fields must be disabled too
$sFieldList = "['{$sFormPrefix}".implode("','{$sFormPrefix}", $aDependents)."']";
$oP->add_ready_script("$('#enable_{$sFormPrefix}{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, $sFieldList, false); } );\n");
}
if ($oAttDef->IsScalar() && $oAttDef->IsWritable())
{
if ($oAttDef->GetEditClass() == 'One Way Password')
{
$sTip = "Unknown values";
$sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
$oDummyObj->Set($sAttCode, null);
$aComments[$sAttCode] = '<input type="checkbox" id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToogleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
$aComments[$sAttCode] .= '<div class="multi_values" id="multi_values_'.$sAttCode.'"> ? </div>';
$sReadyScript .= 'ToogleField(false, \''.$iFormId.'_'.$sAttCode.'\');'."\n";
}
else
{
$iCount = count($aValues[$sAttCode]);
if ($iCount == 1)
{
// Homogenous value
reset($aValues[$sAttCode]);
$aKeys = array_keys($aValues[$sAttCode]);
$currValue = $aKeys[0]; // The only value is the first key
//echo "<p>current value for $sAttCode : $currValue</p>";
$oDummyObj->Set($sAttCode, $currValue);
$aComments[$sAttCode] = '<input type="checkbox" checked id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToogleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
$aComments[$sAttCode] .= '<div class="mono_value">1</div>';
}
else
{
// Non-homogenous value
$aMultiValues = $aValues[$sAttCode];
uasort($aMultiValues, 'MyComparison');
$iMaxCount = 5;
$sTip = "<p><b>".Dict::Format('UI:BulkModify_Count_DistinctValues', $iCount)."</b><ul>";
$index = 0;
foreach($aMultiValues as $sCurrValue => $aVal)
{
$sDisplayValue = empty($aVal['display']) ? '<i>'.Dict::S('Enum:Undefined').'</i>' : str_replace(array("\n", "\r"), " ", $aVal['display']);
$sTip .= "<li>".Dict::Format('UI:BulkModify:Value_Exists_N_Times', $sDisplayValue, $aVal['count'])."</li>";
$index++;
if ($iMaxCount == $index)
{
$sTip .= "<li>".Dict::Format('UI:BulkModify:N_MoreValues', count($aMultiValues) - $iMaxCount)."</li>";
break;
}
}
$sTip .= "</ul></p>";
$sTip = addslashes($sTip);
$sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
$oDummyObj->Set($sAttCode, null);
$aComments[$sAttCode] = '<input type="checkbox" id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToogleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
$aComments[$sAttCode] .= '<div class="multi_values" id="multi_values_'.$sAttCode.'">'.$iCount.'</div>';
}
$sReadyScript .= 'ToogleField('.(($iCount == 1) ? 'true': 'false').', \''.$iFormId.'_'.$sAttCode.'\');'."\n";
}
}
}
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
if (($sStateAttCode != '') && ($oDummyObj->GetState() == ''))
{
// Hmmm, it's not gonna work like this ! Set a default value for the "state"
// Maybe we should use the "state" that is the most common among the objects...
$aMultiValues = $aValues[$sStateAttCode];
uasort($aMultiValues, 'MyComparison');
foreach($aMultiValues as $sCurrValue => $aVal)
{
$oDummyObj->Set($sStateAttCode, $sCurrValue);
break;
}
//$oStateAtt = MetaModel::GetAttributeDef($sClass, $sStateAttCode);
//$oDummyObj->Set($sStateAttCode, $oStateAtt->GetDefaultValue());
}
$oP->add("<div class=\"page_header\">\n");
$oP->add("<h1>".$oDummyObj->GetIcon()."&nbsp;".Dict::Format('UI:Modify_M_ObjectsOf_Class_OutOf_N', $iAllowedCount, $sClass, $iAllowedCount)."</h1>\n");
$oP->add("</div>\n");
$oP->add("<div class=\"wizContainer\">\n");
$sDisableFields = json_encode($aExcludeAttributes);
$aParams = array
(
'fieldsComments' => $aComments,
'noRelations' => true,
'custom_operation' => $sCustomOperation,
'custom_button' => Dict::S('UI:Button:PreviewModifications'),
'selectObj' => $sSelectedObj,
'preview_mode' => true,
'disabled_fields' => $sDisableFields,
'disable_plugins' => true
);
$aParams = $aParams + $aContextData; // merge keeping associations
$oDummyObj->DisplayModifyForm($oP, $aParams);
$oP->add("</div>\n");
$oP->add_ready_script($sReadyScript);
$oP->add_ready_script(
<<<EOF
$('.wizContainer button.cancel').unbind('click');
$('.wizContainer button.cancel').click( function() { window.location.href = '$sCancelUrl'; } );
EOF
);
} // Else no object selected ???
else
{
$oP->p("No object selected !, nothing to do");
}
}
/**
* Process the reply made from a form built with DisplayBulkModifyForm
*/
public static function DoBulkModify($oP, $sClass, $aSelectedObj, $sCustomOperation, $bPreview, $sCancelUrl, $aContextData = array())
{
$aHeaders = array(
'form::select' => array('label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList:not(:disabled)', this.checked);\"></input>", 'description' => Dict::S('UI:SelectAllToggle+')),
'object' => array('label' => MetaModel::GetName($sClass), 'description' => Dict::S('UI:ModifiedObject')),
'status' => array('label' => Dict::S('UI:BulkModifyStatus'), 'description' => Dict::S('UI:BulkModifyStatus+')),
'errors' => array('label' => Dict::S('UI:BulkModifyErrors'), 'description' => Dict::S('UI:BulkModifyErrors+')),
);
$aRows = array();
$oP->add("<div class=\"page_header\">\n");
$oP->add("<h1>".MetaModel::GetClassIcon($sClass)."&nbsp;".Dict::Format('UI:Modify_N_ObjectsOf_Class', count($aSelectedObj), $sClass)."</h1>\n");
$oP->add("</div>\n");
$oP->set_title(Dict::Format('UI:Modify_N_ObjectsOf_Class', count($aSelectedObj), $sClass));
if (!$bPreview)
{
// Not in preview mode, do the update for real
$sTransactionId = utils::ReadPostedParam('transaction_id', '');
if (!utils::IsTransactionValid($sTransactionId, false))
{
throw new Exception(Dict::S('UI:Error:ObjectAlreadyUpdated'));
}
utils::RemoveTransaction($sTransactionId);
}
foreach($aSelectedObj as $iId)
{
$oObj = MetaModel::GetObject($sClass, $iId);
$aErrors = $oObj->UpdateObjectFromPostedForm('');
$bResult = (count($aErrors) == 0);
if ($bResult)
{
list($bResult, $aErrors) = $oObj->CheckToWrite(true /* Enforce Read-only fields */);
}
if ($bPreview)
{
$sStatus = $bResult ? Dict::S('UI:BulkModifyStatusOk') : Dict::S('UI:BulkModifyStatusError');
}
else
{
$sStatus = $bResult ? Dict::S('UI:BulkModifyStatusModified') : Dict::S('UI:BulkModifyStatusSkipped');
}
$sCSSClass = $bResult ? HILIGHT_CLASS_NONE : HILIGHT_CLASS_CRITICAL;
$sChecked = $bResult ? 'checked' : '';
$sDisabled = $bResult ? '' : 'disabled';
$aRows[] = array(
'form::select' => "<input type=\"checkbox\" class=\"selectList\" $sChecked $sDisabled\"></input>",
'object' => $oObj->GetHyperlink(),
'status' => $sStatus,
'errors' => '<p>'.($bResult ? '': implode('</p><p>', $aErrors)).'</p>',
'@class' => $sCSSClass,
);
if ($bResult && (!$bPreview))
{
$oObj->DBUpdate();
}
}
$oP->Table($aHeaders, $aRows);
if ($bPreview)
{
$sFormAction = $_SERVER['SCRIPT_NAME']; // No parameter in the URL, the only parameter will be the ones passed through the form
// Form to submit:
$oP->add("<form method=\"post\" action=\"$sFormAction\" enctype=\"multipart/form-data\">\n");
$aDefaults = utils::ReadParam('default', array());
$oAppContext = new ApplicationContext();
$oP->add($oAppContext->GetForForm());
foreach ($aContextData as $sKey => $value)
{
$oP->add("<input type=\"hidden\" name=\"{$sKey}\" value=\"$value\">\n");
}
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"$sCustomOperation\">\n");
$oP->add("<input type=\"hidden\" name=\"class\" value=\"$sClass\">\n");
$oP->add("<input type=\"hidden\" name=\"preview_mode\" value=\"0\">\n");
$oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\">\n");
$oP->add("<button type=\"button\" class=\"action cancel\" onClick=\"window.location.href='$sCancelUrl'\">".Dict::S('UI:Button:Cancel')."</button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oP->add("<button type=\"submit\" class=\"action\"><span>".Dict::S('UI:Button:ModifyAll')."</span></button>\n");
foreach($_POST as $sKey => $value)
{
if (preg_match('/attr_(.+)/', $sKey, $aMatches))
{
// Beware: some values (like durations) are passed as arrays
if (is_array($value))
{
foreach($value as $vKey => $vValue)
{
$oP->add("<input type=\"hidden\" name=\"{$sKey}[$vKey]\" value=\"$vValue\">\n");
}
}
else
{
$oP->add("<input type=\"hidden\" name=\"$sKey\" value=\"$value\">\n");
}
}
}
$oP->add("</form>\n");
}
else
{
$oP->add("<button type=\"button\" onClick=\"window.location.href='$sCancelUrl'\" class=\"action\"><span>".Dict::S('UI:Button:Done')."</span></button>\n");
}
}
/**
* Perform all the needed checks to delete one (or more) objects
*/
public static function DeleteObjects(WebPage $oP, $sClass, $aObjects, $bPreview, $sCustomOperation, $aContextData = array())
{
$oDeletionPlan = new DeletionPlan();
foreach($aObjects as $oObj)
{
if ($bPreview)
{
$oObj->CheckToDelete($oDeletionPlan);
}
else
{
$oObj->DBDeleteTracked(CMDBObject::GetCurrentChange(), null, $oDeletionPlan);
}
}
if ($bPreview)
{
if (count($aObjects) == 1)
{
$oObj = $aObjects[0];
$oP->add("<h1>".Dict::Format('UI:Delete:ConfirmDeletionOf_Name', $oObj->GetName())."</h1>\n");
}
else
{
$oP->add("<h1>".Dict::Format('UI:Delete:ConfirmDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass))."</h1>\n");
}
// Explain what should be done
//
$aDisplayData = array();
foreach ($oDeletionPlan->ListDeletes() as $sTargetClass => $aDeletes)
{
foreach ($aDeletes as $iId => $aData)
{
$oToDelete = $aData['to_delete'];
$bAutoDel = (($aData['mode'] == DEL_SILENT) || ($aData['mode'] == DEL_AUTO));
if (array_key_exists('issue', $aData))
{
if ($bAutoDel)
{
if (isset($aData['requested_explicitely']))
{
$sConsequence = Dict::Format('UI:Delete:CannotDeleteBecause', $aData['issue']);
}
else
{
$sConsequence = Dict::Format('UI:Delete:ShouldBeDeletedAtomaticallyButNotPossible', $aData['issue']);
}
}
else
{
$sConsequence = Dict::Format('UI:Delete:MustBeDeletedManuallyButNotPossible', $aData['issue']);
}
}
else
{
if ($bAutoDel)
{
if (isset($aData['requested_explicitely']))
{
$sConsequence = ''; // not applicable
}
else
{
$sConsequence = Dict::S('UI:Delete:WillBeDeletedAutomatically');
}
}
else
{
$sConsequence = Dict::S('UI:Delete:MustBeDeletedManually');
}
}
$aDisplayData[] = array(
'class' => MetaModel::GetName(get_class($oToDelete)),
'object' => $oToDelete->GetHyperLink(),
'consequence' => $sConsequence,
);
}
}
foreach ($oDeletionPlan->ListUpdates() as $sRemoteClass => $aToUpdate)
{
foreach ($aToUpdate as $iId => $aData)
{
$oToUpdate = $aData['to_reset'];
if (array_key_exists('issue', $aData))
{
$sConsequence = Dict::Format('UI:Delete:CannotUpdateBecause_Issue', $aData['issue']);
}
else
{
$sConsequence = Dict::Format('UI:Delete:WillAutomaticallyUpdate_Fields', $aData['attributes_list']);
}
$aDisplayData[] = array(
'class' => MetaModel::GetName(get_class($oToUpdate)),
'object' => $oToUpdate->GetHyperLink(),
'consequence' => $sConsequence,
);
}
}
$iImpactedIndirectly = $oDeletionPlan->GetTargetCount() - count($aObjects);
if ($iImpactedIndirectly > 0)
{
if (count($aObjects) == 1)
{
$oObj = $aObjects[0];
$oP->p(Dict::Format('UI:Delete:Count_Objects/LinksReferencing_Object', $iImpactedIndirectly, $oObj->GetName()));
}
else
{
$oP->p(Dict::Format('UI:Delete:Count_Objects/LinksReferencingTheObjects', $iImpactedIndirectly));
}
$oP->p(Dict::S('UI:Delete:ReferencesMustBeDeletedToEnsureIntegrity'));
}
if (($iImpactedIndirectly > 0) || $oDeletionPlan->FoundStopper())
{
$aDisplayConfig = array();
$aDisplayConfig['class'] = array('label' => 'Class', 'description' => '');
$aDisplayConfig['object'] = array('label' => 'Object', 'description' => '');
$aDisplayConfig['consequence'] = array('label' => 'Consequence', 'description' => Dict::S('UI:Delete:Consequence+'));
$oP->table($aDisplayConfig, $aDisplayData);
}
if ($oDeletionPlan->FoundStopper())
{
if ($oDeletionPlan->FoundSecurityIssue())
{
$oP->p(Dict::S('UI:Delete:SorryDeletionNotAllowed'));
}
elseif ($oDeletionPlan->FoundManualOperation())
{
$oP->p(Dict::S('UI:Delete:PleaseDoTheManualOperations'));
}
else // $bFoundManualOp
{
$oP->p(Dict::S('UI:Delete:PleaseDoTheManualOperations'));
}
$oAppContext = new ApplicationContext();
$oP->add("<form method=\"post\">\n");
$oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::ReadParam('transaction_id')."\">\n");
$oP->add("<input type=\"button\" onclick=\"window.history.back();\" value=\"".Dict::S('UI:Button:Back')."\">\n");
$oP->add("<input DISABLED type=\"submit\" name=\"\" value=\"".Dict::S('UI:Button:Delete')."\">\n");
$oP->add($oAppContext->GetForForm());
$oP->add("</form>\n");
}
else
{
if (count($aObjects) == 1)
{
$oObj = $aObjects[0];
$id = $oObj->GetKey();
$oP->p('<h1>'.Dict::Format('UI:Delect:Confirm_Object', $oObj->GetHyperLink()).'</h1>');
}
else
{
$oP->p('<h1>'.Dict::Format('UI:Delect:Confirm_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)).'</h1>');
}
foreach($aObjects as $oObj)
{
$aKeys[] = $oObj->GetKey();
}
$oFilter = new DBObjectSearch($sClass);
$oFilter->AddCondition('id', $aKeys, 'IN');
$oSet = new CMDBobjectSet($oFilter);
$oP->add('<div id="0">');
CMDBAbstractObject::DisplaySet($oP, $oSet, array('display_limit' => false, 'menu' => false));
$oP->add("</div>\n");
$oP->add("<form method=\"post\">\n");
foreach ($aContextData as $sKey => $value)
{
$oP->add("<input type=\"hidden\" name=\"{$sKey}\" value=\"$value\">\n");
}
$oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\">\n");
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"$sCustomOperation\">\n");
$oP->add("<input type=\"hidden\" name=\"filter\" value=\"".$oFilter->Serialize()."\">\n");
$oP->add("<input type=\"hidden\" name=\"class\" value=\"$sClass\">\n");
foreach($aObjects as $oObj)
{
$oP->add("<input type=\"hidden\" name=\"selectObject[]\" value=\"".$oObj->GetKey()."\">\n");
}
$oP->add("<input type=\"button\" onclick=\"window.history.back();\" value=\"".Dict::S('UI:Button:Back')."\">\n");
$oP->add("<input type=\"submit\" name=\"\" value=\"".Dict::S('UI:Button:Delete')."\">\n");
$oAppContext = new ApplicationContext();
$oP->add($oAppContext->GetForForm());
$oP->add("</form>\n");
}
}
else // if ($bPreview)...
{
// Execute the deletion
//
if (count($aObjects) == 1)
{
$oObj = $aObjects[0];
$oP->add("<h1>".Dict::Format('UI:Title:DeletionOf_Object', $oObj->GetName())."</h1>\n");
}
else
{
$oP->add("<h1>".Dict::Format('UI:Title:BulkDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass))."</h1>\n");
}
// Security - do not allow the user to force a forbidden delete by the mean of page arguments...
if ($oDeletionPlan->FoundSecurityIssue())
{
throw new CoreException(Dict::S('UI:Error:NotEnoughRightsToDelete'));
}
if ($oDeletionPlan->FoundManualOperation())
{
throw new CoreException(Dict::S('UI:Error:CannotDeleteBecauseManualOpNeeded'));
}
if ($oDeletionPlan->FoundManualDelete())
{
throw new CoreException(Dict::S('UI:Error:CannotDeleteBecauseOfDepencies'));
}
// Report deletions
//
$aDisplayData = array();
foreach ($oDeletionPlan->ListDeletes() as $sTargetClass => $aDeletes)
{
foreach ($aDeletes as $iId => $aData)
{
$oToDelete = $aData['to_delete'];
if (isset($aData['requested_explicitely']))
{
$sMessage = Dict::S('UI:Delete:Deleted');
}
else
{
$sMessage = Dict::S('UI:Delete:AutomaticallyDeleted');
}
$aDisplayData[] = array(
'class' => MetaModel::GetName(get_class($oToDelete)),
'object' => $oToDelete->GetName(),
'consequence' => $sMessage,
);
}
}
// Report updates
//
foreach ($oDeletionPlan->ListUpdates() as $sTargetClass => $aToUpdate)
{
foreach ($aToUpdate as $iId => $aData)
{
$oToUpdate = $aData['to_reset'];
$aDisplayData[] = array(
'class' => MetaModel::GetName(get_class($oToUpdate)),
'object' => $oToUpdate->GetHyperLink(),
'consequence' => Dict::Format('UI:Delete:AutomaticResetOf_Fields', $aData['attributes_list']),
);
}
}
// Report automatic jobs
//
if ($oDeletionPlan->GetTargetCount() > 0)
{
if (count($aObjects) == 1)
{
$oObj = $aObjects[0];
$oP->p(Dict::Format('UI:Delete:CleaningUpRefencesTo_Object', $oObj->GetName()));
}
else
{
$oP->p(Dict::Format('UI:Delete:CleaningUpRefencesTo_Several_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)));
}
$aDisplayConfig = array();
$aDisplayConfig['class'] = array('label' => 'Class', 'description' => '');
$aDisplayConfig['object'] = array('label' => 'Object', 'description' => '');
$aDisplayConfig['consequence'] = array('label' => 'Done', 'description' => Dict::S('UI:Delete:Done+'));
$oP->table($aDisplayConfig, $aDisplayData);
}
}
}
}
?>

View File

@@ -231,7 +231,7 @@ abstract class Dashboard
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
{
$oPage->add('<h1>'.Dict::S($this->sTitle).'</h1>');
$oPage->add('<h1>'.htmlentities(Dict::S($this->sTitle), ENT_QUOTES, 'UTF-8', false).'</h1>');
$oLayout = new $this->sLayoutClass;
$oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
if (!$bEditMode)

View File

@@ -458,7 +458,7 @@ abstract class DashletGroupBy extends Dashlet
case 'month':
$sGroupByLabel = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Month', $sAttLabel);
$sGroupByExpr = "DATE_FORMAT($sClassAlias.$sAttCode, '%m')"; // 0 -> 31
$sGroupByExpr = "DATE_FORMAT($sClassAlias.$sAttCode, '%Y-%m')"; // yyyy-mm
break;
case 'day_of_week':
@@ -468,7 +468,7 @@ abstract class DashletGroupBy extends Dashlet
case 'day_of_month':
$sGroupByLabel = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:DayOfMonth', $sAttLabel);
$sGroupByExpr = "DATE_FORMAT($sClassAlias.$sAttCode, '%e')"; // 0 -> 31
$sGroupByExpr = "DATE_FORMAT($sClassAlias.$sAttCode, '%Y-%m-%d')"; // mm-dd
break;
default:
@@ -1059,7 +1059,7 @@ class DashletBadge extends Dashlet
$oField = new DesignerIconSelectionField('class', Dict::S('UI:DashletBadge:Prop-Class'), $this->aProperties['class']);
ksort($aClasses);
asort($aClasses);
$aValues = array();
foreach($aClasses as $sClass => $sClass)
{

View File

@@ -60,6 +60,10 @@ class DataTable
{
// Custom settings overload the default ones
$this->bUseCustomSettings = true;
if ($this->oDefaultSettings->iDefaultPageSize == 0)
{
$oCustomSettings->iDefaultPageSize = 0;
}
}
else
{
@@ -176,6 +180,8 @@ class DataTable
if ($iPageSize < 1) // Display all
{
$sPagerStyle = 'style="display:none"'; // no limit: display the full table, so hide the "pager" UI
// WARNING: mPDF does not take the "display" style into account
// when applied to a <td> or a <table> tag, so make sure you apply this to a div
}
else
{
@@ -226,7 +232,8 @@ class DataTable
$sSelectionMode = ($iNbPages == 1) ? '' : 'positive';
$sHtml =
<<<EOF
<td $sPagerStyle colspan="2">
<td colspan="2">
<div $sPagerStyle>
<table id="pager{$this->iListId}" class="pager"><tr>
<td>$sPages</td>
<td><img src="../images/first.png" class="first"/></td>
@@ -239,6 +246,7 @@ class DataTable
</td>
</tr>
</table>
</div>
</td>
EOF;
return $sHtml;

View File

@@ -59,6 +59,11 @@ class DisplayBlock
$this->m_aParams = $aParams;
$this->m_oSet = $oSet;
}
public function GetFilter()
{
return $this->m_oFilter;
}
/**
* Constructs a DisplayBlock object from a DBObjectSet already in memory
* @param $oSet DBObjectSet
@@ -73,7 +78,14 @@ class DisplayBlock
$aKeys[] = $oObject->GetKey();
}
$oSet->Rewind();
$oDummyFilter->AddCondition('id', $aKeys, 'IN');
if (count($aKeys) > 0)
{
$oDummyFilter->AddCondition('id', $aKeys, 'IN');
}
else
{
$oDummyFilter->AddCondition('id', 0, '=');
}
$oBlock = new DisplayBlock($oDummyFilter, $sStyle, false, $aParams); // DisplayBlocks built this way are synchronous
return $oBlock;
}
@@ -390,7 +402,7 @@ class DisplayBlock
$aGroupBy = array();
$aGroupBy['grouped_by_1'] = $oGroupByExp;
$sSql = MetaModel::MakeGroupByQuery($this->m_oFilter, $aQueryParams, $aGroupBy);
$sSql = MetaModel::MakeGroupByQuery($this->m_oFilter, $aQueryParams, $aGroupBy, true);
$aRes = CMDBSource::QueryToArray($sSql);
$aGroupBy = array();
@@ -888,7 +900,7 @@ EOF
$aGroupBy = array();
$aGroupBy['grouped_by_1'] = $oGroupByExp;
$sSql = MetaModel::MakeGroupByQuery($this->m_oFilter, $aQueryParams, $aGroupBy);
$sSql = MetaModel::MakeGroupByQuery($this->m_oFilter, $aQueryParams, $aGroupBy, true);
$aRes = CMDBSource::QueryToArray($sSql);
$aGroupBy = array();
@@ -963,7 +975,7 @@ EOF
$aGroupBy = array();
$aGroupBy['grouped_by_1'] = $oGroupByExp;
$sSql = MetaModel::MakeGroupByQuery($this->m_oFilter, $aQueryParams, $aGroupBy);
$sSql = MetaModel::MakeGroupByQuery($this->m_oFilter, $aQueryParams, $aGroupBy, true);
$aRes = CMDBSource::QueryToArray($sSql);
$aGroupBy = array();
@@ -1044,7 +1056,8 @@ EOF
$aGroupBy = array();
$aGroupBy['grouped_by_1'] = $oGroupByExp;
$sSql = MetaModel::MakeGroupByQuery($this->m_oFilter, $aQueryParams, $aGroupBy);
$sSql = MetaModel::MakeGroupByQuery($this->m_oFilter, $aQueryParams, $aGroupBy, true);
$aRes = CMDBSource::QueryToArray($sSql);
$aGroupBy = array();

View File

@@ -82,6 +82,7 @@ class iTopWebPage extends NiceWebPage
$sSearchAny = addslashes(Dict::S('UI:SearchValue:Any'));
$sSearchNbSelected = addslashes(Dict::S('UI:SearchValue:NbSelected'));
$this->add_dict_entry('UI:FillAllMandatoryFields');
$bForceMenuPane = utils::ReadParam('force_menu_pane', null);
$sInitClosed = '';
@@ -140,6 +141,7 @@ class iTopWebPage extends NiceWebPage
}
});
window.clearTimeout(iPaneVisWatchDog);
myLayout.addPinBtn( "#tPinMenu", "west" );
//myLayout.open( "west" );
$('.ui-layout-resizer-west .ui-layout-toggler').css({background: 'transparent'});
@@ -390,6 +392,11 @@ EOF
});
function FixPaneVis()
{
$('.ui-layout-center, .ui-layout-north, .ui-layout-south').css({display: 'block'});
}
EOF
);
}
@@ -480,6 +487,25 @@ EOF
$sForm = $this->GetSiloSelectionForm();
$this->DisplayMenu(); // Compute the menu
// Call the extensions to add content to the page, so that they can also add styles or scripts
$sBannerExtraHtml = '';
foreach (MetaModel::EnumPlugins('iPageUIExtension') as $oExtensionInstance)
{
$sBannerExtraHtml .= $oExtensionInstance->GetBannerHtml($this);
}
$sNorthPane = '';
foreach (MetaModel::EnumPlugins('iPageUIExtension') as $oExtensionInstance)
{
$sNorthPane .= $oExtensionInstance->GetNorthPaneHtml($this);
}
$sSouthPane = '';
foreach (MetaModel::EnumPlugins('iPageUIExtension') as $oExtensionInstance)
{
$sSouthPane .= $oExtensionInstance->GetSouthPaneHtml($this);
}
// Put here the 'ready scripts' that must be executed after all others
$this->add_ready_script(
<<<EOF
@@ -527,6 +553,7 @@ EOF
if ($this->GetOutputFormat() == 'html')
{
$sHtml .= $this->output_dict_entries(true); // before any script so that they can benefit from the translations
foreach($this->a_linked_scripts as $s_script)
{
// Make sure that the URL to the script contains the application's version number
@@ -541,7 +568,7 @@ EOF
}
$sHtml .= "<script type=\"text/javascript\" src=\"$s_script\"></script>\n";
}
$this->add_script("\$(document).ready(function() {\n{$this->m_sInitScript};\nwindow.setTimeout('onDelayedReady()',10)\n});");
$this->add_script("var iPaneVisWatchDog = window.setTimeout('FixPaneVis()',5000);\n\$(document).ready(function() {\n{$this->m_sInitScript};\nwindow.setTimeout('onDelayedReady()',10)\n});");
if (count($this->m_aReadyScripts)>0)
{
$this->add_script("\nonDelayedReady = function() {\n".implode("\n", $this->m_aReadyScripts)."\n}\n");
@@ -555,7 +582,6 @@ EOF
}
$sHtml .= "</script>\n";
}
$this->output_dict_entries();
}
if (count($this->a_styles)>0)
@@ -711,26 +737,13 @@ EOF
$sApplicationBanner .= '<div id="admin-banner"><span style="padding:5px;">'.Dict::Format('UI:ApplicationEnvironment', $sEnvLabel).$sBackButton.'<span></div>';
}
foreach (MetaModel::EnumPlugins('iPageUIExtension') as $oExtensionInstance)
{
$sApplicationBanner .= $oExtensionInstance->GetBannerHtml($this);
}
$sApplicationBanner .= $sBannerExtraHtml;
$sNorthPane = '';
foreach (MetaModel::EnumPlugins('iPageUIExtension') as $oExtensionInstance)
{
$sNorthPane .= $oExtensionInstance->GetNorthPaneHtml($this);
}
if (!empty($sNorthPane))
{
$sNorthPane = '<div id="bottom-pane" class="ui-layout-south">'.$sNorthPane.'</div>';
$sNorthPane = '<div id="bottom-pane" class="ui-layout-north">'.$sNorthPane.'</div>';
}
$sSouthPane = '';
foreach (MetaModel::EnumPlugins('iPageUIExtension') as $oExtensionInstance)
{
$sSouthPane .= $oExtensionInstance->GetSouthPaneHtml($this);
}
if (!empty($sSouthPane))
{
$sSouthPane = '<div id="bottom-pane" class="ui-layout-south">'.$sSouthPane.'</div>';
@@ -761,7 +774,7 @@ EOF
$sHtml .= ' </div>';
$sHtml .= ' </div> <!-- /inner menu -->';
$sHtml .= ' </div> <!-- /menu -->';
$sHtml .= ' <div class="footer ui-layout-south"><a href="http://www.combodo.com" title="www.combodo.com" target="_blank"><img src="../images/logo-combodo.png"/></a></div>';
$sHtml .= ' <div class="footer ui-layout-south"><div id="combodo_logo"><a href="http://www.combodo.com" title="www.combodo.com" target="_blank"><img src="../images/logo-combodo.png"/></a></div></div>';
$sHtml .= '<!-- End of the left pane -->';
$sHtml .= '</div>';

View File

@@ -148,6 +148,26 @@ EOF
$this->add("<tr><td colspan=\"2\" class=\"center v-spacer\"> <input type=\"submit\" value=\"".Dict::S('UI:Button:Login')."\" /></td></tr>\n");
$this->add("</table>\n");
$this->add("<input type=\"hidden\" name=\"loginop\" value=\"login\" />\n");
// Keep the OTHER parameters posted
foreach($_POST as $sPostedKey => $postedValue)
{
if (!in_array($sPostedKey, array('auth_user', 'auth_pwd')))
{
if (is_array($postedValue))
{
foreach($postedValue as $sKey => $sValue)
{
$this->add("<input type=\"hidden\" name=\"".htmlentities($sPostedKey, ENT_QUOTES, 'UTF-8')."[".htmlentities($sKey, ENT_QUOTES, 'UTF-8')."]\" value=\"".htmlentities($sValue, ENT_QUOTES, 'UTF-8')."\" />\n");
}
}
else
{
$this->add("<input type=\"hidden\" name=\"".htmlentities($sPostedKey, ENT_QUOTES, 'UTF-8')."\" value=\"".htmlentities($postedValue, ENT_QUOTES, 'UTF-8')."\" />\n");
}
}
}
$this->add("</form>\n");
$this->add(Dict::S('UI:Login:About'));
$this->add("</div>\n");
@@ -220,20 +240,9 @@ EOF
return MetaModel::GetConfig()->GetSecureConnectionRequired();
}
static function IsConnectionSecure()
{
$bSecured = false;
if (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS']!='off'))
{
$bSecured = true;
}
return $bSecured;
}
protected static function Login()
{
if (self::SecureConnectionRequired() && !self::IsConnectionSecure())
if (self::SecureConnectionRequired() && !utils::IsConnectionSecure())
{
// Non secured URL... request for a secure connection
throw new Exception('Secure connection required!');
@@ -427,6 +436,7 @@ EOF
$oPage = new LoginWebPage();
$oPage->DisplayChangePwdForm(true); // old pwd was wrong
$oPage->output();
exit;
}
$sMessage = Dict::S('UI:Login:PasswordChanged');
}

View File

@@ -64,6 +64,7 @@ class PortalWebPage extends NiceWebPage
$sAbsURLModulesRoot = addslashes(utils::GetAbsoluteUrlModulesRoot()); // Pass it to Javascript scripts
$oAppContext = new ApplicationContext();
$sAppContext = addslashes($oAppContext->GetForLink());
$this->add_dict_entry('UI:FillAllMandatoryFields');
if ($sAlternateStyleSheet != '')
{
$this->add_linked_stylesheet("../portal/$sAlternateStyleSheet/portal.css");
@@ -138,6 +139,17 @@ try
changeMonth: true,
changeYear: true
});
$(".datetime-pick").datepicker({
showOn: 'button',
buttonImage: '../images/calendar.png',
buttonImageOnly: true,
dateFormat: 'yy-mm-dd 00:00:00',
constrainInput: false,
changeMonth: true,
changeYear: true
});
//$('.resizable').resizable(); // Make resizable everything that claims to be resizable !
$('.caselog_header').click( function () { $(this).toggleClass('open').next('.caselog_entry').toggle(); });
}

View File

@@ -47,7 +47,7 @@ abstract class Query extends cmdbAbstractObject
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("fields", array("allowed_values"=>null, "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("fields", array("allowed_values"=>null, "sql"=>"fields", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'fields')); // Attributes to be displayed for the complete details
@@ -88,7 +88,7 @@ class QueryOQL extends Query
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
{
parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams);
$aFieldsMap = parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams);
if (!$bEditMode)
{
@@ -102,6 +102,7 @@ class QueryOQL extends Query
}
$oPage->p(Dict::S('UI:Query:UrlForExcel').':<br/><textarea cols="80" rows="3" READONLY>'.$sUrl.'</textarea>');
}
return $aFieldsMap;
}
}

View File

@@ -142,6 +142,7 @@ EOF
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
{
return array();
}
// End of the minimal implementation of iDisplay
}

View File

@@ -283,9 +283,29 @@ class ObjectDetailsTemplate extends DisplayTemplate
$sStateAttCode = MetaModel :: GetStateAttributeCode(get_class($this->m_oObj));
$aTemplateFields = array();
preg_match_all('/\\$this->([a-z0-9_]+)\\$/', $this->m_sTemplate, $aMatches);
$aTemplateFields = $aMatches[1];
foreach ($aMatches[1] as $sAttCode)
{
if (MetaModel::IsValidAttCode(get_class($this->m_oObj), $sAttCode))
{
$aTemplateFields[] = $sAttCode;
}
else
{
$aParams['this->'.$sAttCode] = "<!--Unknown attribute: $sAttCode-->";
}
}
preg_match_all('/\\$this->field\\(([a-z0-9_]+)\\)\\$/', $this->m_sTemplate, $aMatches);
$aTemplateFields = array_merge($aTemplateFields, $aMatches[1]);
foreach ($aMatches[1] as $sAttCode)
{
if (MetaModel::IsValidAttCode(get_class($this->m_oObj), $sAttCode))
{
$aTemplateFields[] = $sAttCode;
}
else
{
$aParams['this->field('.$sAttCode.')'] = "<!--Unknown attribute: $sAttCode-->";
}
}
$aFieldsComments = (isset($aParams['fieldsComments'])) ? $aParams['fieldsComments'] : array();
$aFieldsMap = array();

View File

@@ -15,6 +15,6 @@
</itoptab>
<itoptab name="UI:NotificationsMenu:Actions">
<h2><itopstring>UI:NotificationsMenu:AvailableActions</itopstring></h2>
<itopblock BlockClass="DisplayBlock" type="list" asynchronous="false" encoding="text/oql">SELECT ActionEmail</itopblock>
<itopblock BlockClass="DisplayBlock" type="list" asynchronous="false" encoding="text/oql">SELECT Action</itopblock>
</itoptab>
</itoptabs>

View File

@@ -96,7 +96,7 @@ class UIExtKeyWidget
}
/**
* Get the HTML fragment corresponding to the linkset editing widget
* Get the HTML fragment corresponding to the ext key editing widget
* @param WebPage $oP The web page used for all the output
* @param Hash $aArgs Extra context arguments
* @return string The HTML fragment to be inserted into the page
@@ -225,6 +225,15 @@ EOF
// Too many choices, use an autocomplete
$sSelectMode = 'false';
// Check that the given value is allowed
$oSearch = $oAllowedValues->GetFilter();
$oSearch->AddCondition('id', $value);
$oSet = new DBObjectSet($oSearch);
if ($oSet->Count() == 0)
{
$value = null;
}
if (is_null($value) || ($value == 0)) // Null values are displayed as ''
{
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : '';
@@ -346,6 +355,10 @@ EOF
}
$oFilter = DBObjectSearch::FromOQL($sFilter);
if (strlen($sRemoteClass) > 0)
{
$oFilter->ChangeClass($sRemoteClass);
}
$oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
$oBlock = new DisplayBlock($oFilter, 'list', false, array('query_params' => array('this' => $oObj)));
$oBlock->Display($oP, $this->iId.'_results', array('this' => $oObj, 'cssCount'=> '#count_'.$this->iId, 'menu' => false, 'selection_mode' => true, 'selection_type' => 'single', 'table_id' => 'select_'.$this->sAttCode)); // Don't display the 'Actions' menu on the results

View File

@@ -106,7 +106,7 @@ class UILinksWidget
$sPrefix = "$this->m_sAttCode{$this->m_sNameSuffix}";
$aRow = array();
$aFieldsMap = array();
if(is_object($linkObjOrId))
if(is_object($linkObjOrId) && (!$linkObjOrId->IsNew()))
{
$key = $linkObjOrId->GetKey();
$iRemoteObjKey = $linkObjOrId->Get($this->m_sExtKeyToRemote);
@@ -130,12 +130,24 @@ class UILinksWidget
else
{
// form for creating a new record
if (is_object($linkObjOrId))
{
// New link existing only in memory
$oNewLinkObj = $linkObjOrId;
$iRemoteObjKey = $oNewLinkObj->Get($this->m_sExtKeyToRemote);
$oRemoteObj = MetaModel::GetObject($this->m_sRemoteClass, $iRemoteObjKey);
$oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object also fills the related external fields
$linkObjOrId = -$iRemoteObjKey;
}
else
{
$iRemoteObjKey = -$linkObjOrId;
$oNewLinkObj = MetaModel::NewObject($this->m_sLinkedClass);
$oRemoteObj = MetaModel::GetObject($this->m_sRemoteClass, -$linkObjOrId);
$oNewLinkObj->Set($this->m_sExtKeyToRemote, $oRemoteObj); // Setting the extkey with the object alsoo fills the related external fields
$oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object also fills the related external fields
}
$sPrefix .= "[$linkObjOrId][";
$iRemoteObjKey = -$linkObjOrId;
$oNewLinkObj = MetaModel::NewObject($this->m_sLinkedClass);
$oRemoteObj = MetaModel::GetObject($this->m_sRemoteClass, -$linkObjOrId);
$oNewLinkObj->Set($this->m_sExtKeyToRemote, $oRemoteObj); // Setting the extkey with the object alsoo fills the related external fields
$oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object also fills the related external fields
$sNameSuffix = "]"; // To make a tabular form
$aArgs['prefix'] = $sPrefix;
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}_".(-$linkObjOrId);
@@ -275,6 +287,7 @@ EOF
$sHtmlValue = '';
$sTargetClass = self::GetTargetClass($this->m_sClass, $this->m_sAttCode);
$sHtmlValue .= "<div id=\"linkedset_{$this->m_sAttCode}{$this->m_sNameSuffix}\">\n";
$sHtmlValue .= "<input type=\"hidden\" id=\"{$sFormPrefix}{$this->m_iInputId}\">\n";
$oValue->Rewind();
$aForm = array();
while($oCurrentLink = $oValue->Fetch())
@@ -284,7 +297,7 @@ EOF
if ($oCurrentLink->IsNew())
{
$key = -$oLinkedObj->GetKey();
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $key, $aArgs, $oCurrentObj);
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj);
}
else
{
@@ -297,8 +310,9 @@ EOF
$sDuplicates = ($this->m_bDuplicatesAllowed) ? 'true' : 'false';
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
$oPage->add_ready_script(<<<EOF
oWidget{$this->m_iInputId} = new LinksWidget('{$this->m_sAttCode}{$this->m_sNameSuffix}', '{$this->m_sClass}', '{$this->m_sAttCode}', '{$this->m_iInputId}', '{$this->m_sNameSuffix}', $sDuplicates, $sWizHelper);
oWidget{$this->m_iInputId} = new LinksWidget('{$this->m_sAttCode}{$this->m_sNameSuffix}', '{$this->m_sClass}', '{$this->m_sAttCode}', '{$this->m_iInputId}', '{$this->m_sNameSuffix}', $sDuplicates, $sWizHelper, '{$this->m_sExtKeyToRemote}');
oWidget{$this->m_iInputId}.Init();
$('#{$this->m_iInputId}').bind('update_value', function() { $(this).val(oWidget{$this->m_iInputId}.GetUpdatedValue()); })
EOF
);
$sHtmlValue .= "<span style=\"float:left;\">&nbsp;&nbsp;&nbsp;<img src=\"../images/tv-item-last.gif\">&nbsp;&nbsp;<input id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_btnRemove\" type=\"button\" value=\"".Dict::S('UI:RemoveLinkedObjectsOf_Class')."\" onClick=\"oWidget{$this->m_iInputId}.RemoveSelected();\" >";

View File

@@ -508,7 +508,7 @@ class utils
{
// Build an absolute URL to this page on this server/port
$sServerName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
$sProtocol = (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS']!="off")) ? 'https' : 'http';
$sProtocol = self::IsConnectionSecure() ? 'https' : 'http';
$iPort = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : 80;
if ($sProtocol == 'http')
{
@@ -571,6 +571,25 @@ class utils
return $sAppRootUrl;
}
/**
* Helper to handle the variety of HTTP servers
* See #286 (fixed in [896]), and #634 (this fix)
*
* Though the official specs says 'a non empty string', some servers like IIS do set it to 'off' !
* nginx set it to an empty string
* Others might leave it unset (no array entry)
*/
static public function IsConnectionSecure()
{
$bSecured = false;
if (!empty($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off'))
{
$bSecured = true;
}
return $bSecured;
}
/**
* Tells whether or not log off operation is supported.
* Actually in only one case:
@@ -850,6 +869,60 @@ class utils
static public function GetSafeId($sId)
{
return str_replace(array(':', '[', ']', '+', '-'), '_', $sId);
}
}
/**
* Helper to execute an HTTP POST request
* Source: http://netevil.org/blog/2006/nov/http-post-from-php-without-curl
* originaly named after do_post_request
* Does not require cUrl but requires openssl for performing https POSTs.
*
* @param string $sUrl The URL to POST the data to
* @param hash $aData The data to POST as an array('param_name' => value)
* @param string $sOptionnalHeaders Additional HTTP headers as a string with newlines between headers
* @return string The result of the POST request
* @throws Exception
*/
static public function DoPostRequest($sUrl, $aData, $sOptionnalHeaders = null)
{
// $sOptionnalHeaders is a string containing additional HTTP headers that you would like to send in your request.
$sData = http_build_query($aData);
$aParams = array('http' => array(
'method' => 'POST',
'content' => $sData,
'header'=> "Content-type: application/x-www-form-urlencoded\r\nContent-Length: ".strlen($sData)."\r\n",
));
if ($sOptionnalHeaders !== null)
{
$aParams['http']['header'] .= $sOptionnalHeaders;
}
$ctx = stream_context_create($aParams);
$fp = @fopen($sUrl, 'rb', false, $ctx);
if (!$fp)
{
global $php_errormsg;
if (isset($php_errormsg))
{
throw new Exception("Wrong URL: $sUrl, $php_errormsg");
}
elseif ((strtolower(substr($sUrl, 0, 5)) == 'https') && !extension_loaded('openssl'))
{
throw new Exception("Cannot connect to $sUrl: missing module 'openssl'");
}
else
{
throw new Exception("Wrong URL: $sUrl");
}
}
$response = @stream_get_contents($fp);
if ($response === false)
{
throw new Exception("Problem reading data from $sUrl, $php_errormsg");
}
return $response;
}
}
?>

View File

@@ -651,6 +651,7 @@ class WebPage implements Page
{
$sClass = isset($aAction['class']) ? " class=\"{$aAction['class']}\"" : "";
$sOnClick = isset($aAction['onclick']) ? " onclick=\"{$aAction['onclick']}\"" : "";
$sTarget = isset($aAction['target']) ? " target=\"{$aAction['target']}\"" : "";
if (empty($aAction['url']))
{
if ($sPrevUrl != '') // Don't output consecutively two separators...
@@ -661,41 +662,52 @@ class WebPage implements Page
}
else
{
$sHtml .= "<li><a href=\"{$aAction['url']}\"$sClass $sOnClick>{$aAction['label']}</a></li>";
$sHtml .= "<li><a $sTarget href=\"{$aAction['url']}\"$sClass $sOnClick>{$aAction['label']}</a></li>";
$sPrevUrl = $aAction['url'];
}
}
$sHtml .= "</ul></li></ul></div>";
foreach(array_reverse($aFavoriteActions) as $aAction)
{
$sHtml .= "<div class=\"actions_button\"><a href='{$aAction['url']}'>{$aAction['label']}</a></div>";
$sTarget = isset($aAction['target']) ? " target=\"{$aAction['target']}\"" : "";
$sHtml .= "<div class=\"actions_button\"><a $sTarget href='{$aAction['url']}'>{$aAction['label']}</a></div>";
}
return $sHtml;
}
protected function output_dict_entries()
protected function output_dict_entries($bReturnOutput = false)
{
$sHtml = '';
if (count($this->a_dict_entries)>0)
{
echo "<script type=\"text/javascript\">\n";
echo "var Dict = {};\n";
echo "Dict._entries = {};\n";
echo "Dict.S = function(sEntry) {\n";
echo " if (sEntry in Dict._entries)\n";
echo " {\n";
echo " return Dict._entries[sEntry];\n";
echo " }\n";
echo " else\n";
echo " {\n";
echo " return sEntry;\n";
echo " }\n";
echo "};\n";
$sHtml .= "<script type=\"text/javascript\">\n";
$sHtml .= "var Dict = {};\n";
$sHtml .= "Dict._entries = {};\n";
$sHtml .= "Dict.S = function(sEntry) {\n";
$sHtml .= " if (sEntry in Dict._entries)\n";
$sHtml .= " {\n";
$sHtml .= " return Dict._entries[sEntry];\n";
$sHtml .= " }\n";
$sHtml .= " else\n";
$sHtml .= " {\n";
$sHtml .= " return sEntry;\n";
$sHtml .= " }\n";
$sHtml .= "};\n";
foreach($this->a_dict_entries as $s_entry => $s_value)
{
echo "Dict._entries['$s_entry'] = '".addslashes($s_value)."';\n";
$sHtml .= "Dict._entries['$s_entry'] = '".addslashes($s_value)."';\n";
}
echo "</script>\n";
$sHtml .= "</script>\n";
}
if ($bReturnOutput)
{
return $sHtml;
}
else
{
echo $sHtml;
}
}
}

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2012 Combodo SARL
// Copyright (C) 2010-2013 Combodo SARL
//
// This file is part of iTop.
//
@@ -37,69 +37,77 @@ class XMLPage extends WebPage
var $m_bPassThrough;
var $m_bHeaderSent;
function __construct($s_title, $bPassThrough = false)
{
parent::__construct($s_title);
$this->m_bPassThrough = $bPassThrough;
$this->m_bHeaderSent = false;
$this->add_header("Content-type: text/xml; charset=utf-8");
function __construct($s_title, $bPassThrough = false)
{
parent::__construct($s_title);
$this->m_bPassThrough = $bPassThrough;
$this->m_bHeaderSent = false;
$this->add_header("Content-type: text/xml; charset=utf-8");
$this->add_header("Cache-control: no-cache");
$this->add_header("Content-location: export.xml");
}
}
public function output()
{
if (!$this->m_bPassThrough)
{
$this->add("<?xml version=\"1.0\" encoding=\"UTF-8\"?".">\n");
$this->add_header("Content-Length: ".strlen(trim($this->s_content)));
foreach($this->a_headers as $s_header)
{
header($s_header);
}
echo trim($this->s_content);
}
if (class_exists('MetaModel'))
{
MetaModel::RecordQueryTrace();
}
}
public function add($sText)
{
if (!$this->m_bPassThrough)
{
parent::add($sText);
}
else
{
if ($this->m_bHeaderSent)
{
echo $sText;
}
else
{
$s_captured_output = ob_get_contents();
ob_end_clean();
foreach($this->a_headers as $s_header)
{
header($s_header);
}
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?".">\n";
echo trim($s_captured_output);
echo trim($this->s_content);
echo $sText;
$this->m_bHeaderSent = true;
}
}
}
public function small_p($sText)
{
public function output()
{
if (!$this->m_bPassThrough)
{
$this->s_content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?".">\n".trim($this->s_content);
$this->add_header("Content-Length: ".strlen($this->s_content));
foreach($this->a_headers as $s_header)
{
header($s_header);
}
echo $this->s_content;
}
if (class_exists('MetaModel'))
{
MetaModel::RecordQueryTrace();
}
}
public function add($sText)
{
if (!$this->m_bPassThrough)
{
parent::add($sText);
}
else
{
if ($this->m_bHeaderSent)
{
echo $sText;
}
else
{
$s_captured_output = ob_get_contents();
ob_end_clean();
foreach($this->a_headers as $s_header)
{
header($s_header);
}
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?".">\n";
echo trim($s_captured_output);
echo trim($this->s_content);
echo $sText;
$this->m_bHeaderSent = true;
}
}
}
public function small_p($sText)
{
}
public function table($aConfig, $aData, $aParams = array())
{
}
public function TrashUnexpectedOutput()
{
if (!$this->m_bPassThrough)
{
parent::TrashUnexpectedOutput();
}
}
}
?>

View File

@@ -213,8 +213,12 @@ class ActionEmail extends ActionNotification
$aRecipients = array();
while ($oObj = $oSet->Fetch())
{
$aRecipients[] = $oObj->Get($sEmailAttCode);
$this->m_iRecipients++;
$sAddress = trim($oObj->Get($sEmailAttCode));
if (strlen($sAddress) > 0)
{
$aRecipients[] = $sAddress;
$this->m_iRecipients++;
}
}
return implode(', ', $aRecipients);
}

View File

@@ -139,7 +139,8 @@ class AsyncSendEmail extends AsyncTask
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeText("to", array("allowed_values"=>null, "sql"=>"to", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("version", array("allowed_values"=>null, "sql"=>"version", "default_value"=>Email::ORIGINAL_FORMAT, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("to", array("allowed_values"=>null, "sql"=>"to", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("subject", array("allowed_values"=>null, "sql"=>"subject", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLongText("message", array("allowed_values"=>null, "sql"=>"message", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
@@ -161,7 +162,10 @@ class AsyncSendEmail extends AsyncTask
$oNew->Set('to', $oEMail->GetRecipientTO(true /* string */));
$oNew->Set('subject', $oEMail->GetSubject());
$sMessage = serialize($oEMail);
// $oNew->Set('version', 1);
// $sMessage = serialize($oEMail);
$oNew->Set('version', 2);
$sMessage = $oEMail->SerializeV2();
$oNew->Set('message', $sMessage);
$oNew->DBInsert();
}
@@ -169,7 +173,20 @@ class AsyncSendEmail extends AsyncTask
public function DoProcess()
{
$sMessage = $this->Get('message');
$oEMail = unserialize($sMessage);
$iVersion = (int) $this->Get('version');
switch($iVersion)
{
case Email::FORMAT_V2:
$oEMail = Email::UnSerializeV2($sMessage);
break;
case Email::ORIGINAL_FORMAT:
$oEMail = unserialize($sMessage);
break;
default:
return 'Unknown version of the serialization format: '.$iVersion;
}
$iRes = $oEMail->Send($aIssues, true /* force synchro !!!!! */);
switch ($iRes)
{

View File

@@ -212,15 +212,12 @@ abstract class AttributeDefinition
public function IsNullAllowed() {return true;}
public function GetCode() {return $this->m_sCode;}
public function GetLabel($sDefault = null)
/**
* Helper to browse the hierarchy of classes, searching for a label
*/
protected function SearchLabel($sDictEntrySuffix, $sDefault, $bUserLanguageOnly)
{
// If no default value is specified, let's define the most relevant one for developping purposes
if (is_null($sDefault))
{
$sDefault = str_replace('_', ' ', $this->m_sCode);
}
$sLabel = Dict::S('Class:'.$this->m_sHostClass.'/Attribute:'.$this->m_sCode, '');
$sLabel = Dict::S('Class:'.$this->m_sHostClass.$sDictEntrySuffix, '', $bUserLanguageOnly);
if (strlen($sLabel) == 0)
{
// Nothing found: go higher in the hierarchy (if possible)
@@ -232,13 +229,29 @@ abstract class AttributeDefinition
if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode))
{
$oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode);
$sLabel = $oAttDef->GetLabel($sDefault);
$sLabel = $oAttDef->SearchLabel($sDictEntrySuffix, $sDefault, $bUserLanguageOnly);
}
}
}
return $sLabel;
}
public function GetLabel($sDefault = null)
{
$sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode, null, true /*user lang*/);
if (is_null($sLabel))
{
// If no default value is specified, let's define the most relevant one for developping purposes
if (is_null($sDefault))
{
$sDefault = str_replace('_', ' ', $this->m_sCode);
}
// Browse the hierarchy again, accepting default (english) translations
$sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode, $sDefault, false);
}
return $sLabel;
}
/**
* Get the label corresponding to the given value (in plain text)
* To be overloaded for localized enums
@@ -272,52 +285,32 @@ abstract class AttributeDefinition
public function GetDescription($sDefault = null)
{
// If no default value is specified, let's define the most relevant one for developping purposes
if (is_null($sDefault))
$sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'+', null, true /*user lang*/);
if (is_null($sLabel))
{
$sDefault = '';
}
$sLabel = Dict::S('Class:'.$this->m_sHostClass.'/Attribute:'.$this->m_sCode.'+', '');
if (strlen($sLabel) == 0)
{
// Nothing found: go higher in the hierarchy (if possible)
//
$sLabel = $sDefault;
$sParentClass = MetaModel::GetParentClass($this->m_sHostClass);
if ($sParentClass)
// If no default value is specified, let's define the most relevant one for developping purposes
if (is_null($sDefault))
{
if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode))
{
$oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode);
$sLabel = $oAttDef->GetDescription($sDefault);
}
$sDefault = '';
}
// Browse the hierarchy again, accepting default (english) translations
$sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'+', $sDefault, false);
}
return $sLabel;
}
}
public function GetHelpOnEdition($sDefault = null)
{
// If no default value is specified, let's define the most relevant one for developping purposes
if (is_null($sDefault))
$sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'?', null, true /*user lang*/);
if (is_null($sLabel))
{
$sDefault = '';
}
$sLabel = Dict::S('Class:'.$this->m_sHostClass.'/Attribute:'.$this->m_sCode.'?', '');
if (strlen($sLabel) == 0)
{
// Nothing found: go higher in the hierarchy (if possible)
//
$sLabel = $sDefault;
$sParentClass = MetaModel::GetParentClass($this->m_sHostClass);
if ($sParentClass)
// If no default value is specified, let's define the most relevant one for developping purposes
if (is_null($sDefault))
{
if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode))
{
$oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode);
$sLabel = $oAttDef->GetHelpOnEdition($sDefault);
}
$sDefault = '';
}
// Browse the hierarchy again, accepting default (english) translations
$sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'?', $sDefault, false);
}
return $sLabel;
}
@@ -433,6 +426,26 @@ abstract class AttributeDefinition
return (string)$sValue;
}
/**
* Helper to get a value that will be JSON encoded
* The operation is the opposite to FromJSONToValue
*/
public function GetForJSON($value)
{
// In most of the cases, that will be the expected behavior...
return $this->GetEditValue($value);
}
/**
* Helper to form a value, given JSON decoded data
* The operation is the opposite to GetForJSON
*/
public function FromJSONToValue($json)
{
// Passthrough in most of the cases
return $json;
}
/**
* Override to display the value in the GUI
*/
@@ -471,11 +484,14 @@ abstract class AttributeDefinition
$sLabel = $this->GetLabel();
}
$sNewValueHtml = $this->GetAsHTML($sNewValue);
$sOldValueHtml = $this->GetAsHTML($sOldValue);
if($this->IsExternalKey())
{
$sTargetClass = $this->GetTargetClass();
$sOldValue = (int)$sOldValue ? MetaModel::GetHyperLink($sTargetClass, (int)$sOldValue) : null;
$sNewValue = (int)$sNewValue ? MetaModel::GetHyperLink($sTargetClass, (int)$sNewValue) : null;
$sOldValueHtml = (int)$sOldValue ? MetaModel::GetHyperLink($sTargetClass, (int)$sOldValue) : null;
$sNewValueHtml = (int)$sNewValue ? MetaModel::GetHyperLink($sTargetClass, (int)$sNewValue) : null;
}
if ( (($this->GetType() == 'String') || ($this->GetType() == 'Text')) &&
(strlen($sNewValue) > strlen($sOldValue)) )
@@ -483,27 +499,27 @@ abstract class AttributeDefinition
// Check if some text was not appended to the field
if (substr($sNewValue,0, strlen($sOldValue)) == $sOldValue) // Text added at the end
{
$sDelta = substr($sNewValue, strlen($sOldValue));
$sDelta = $this->GetAsHTML(substr($sNewValue, strlen($sOldValue)));
$sResult = Dict::Format('Change:Text_AppendedTo_AttName', $sDelta, $sLabel);
}
else if (substr($sNewValue, -strlen($sOldValue)) == $sOldValue) // Text added at the beginning
{
$sDelta = substr($sNewValue, 0, strlen($sNewValue) - strlen($sOldValue));
$sDelta = $this->GetAsHTML(substr($sNewValue, 0, strlen($sNewValue) - strlen($sOldValue)));
$sResult = Dict::Format('Change:Text_AppendedTo_AttName', $sDelta, $sLabel);
}
else
{
if (strlen($sOldValue) == 0)
{
$sResult = Dict::Format('Change:AttName_SetTo', $sLabel, $sNewValue);
$sResult = Dict::Format('Change:AttName_SetTo', $sLabel, $sNewValueHtml);
}
else
{
if (is_null($sNewValue))
{
$sNewValue = Dict::S('UI:UndefinedObject');
$sNewValueHtml = Dict::S('UI:UndefinedObject');
}
$sResult = Dict::Format('Change:AttName_SetTo_NewValue_PreviousValue_OldValue', $sLabel, $sNewValue, $sOldValue);
$sResult = Dict::Format('Change:AttName_SetTo_NewValue_PreviousValue_OldValue', $sLabel, $sNewValueHtml, $sOldValueHtml);
}
}
}
@@ -511,15 +527,15 @@ abstract class AttributeDefinition
{
if (strlen($sOldValue) == 0)
{
$sResult = Dict::Format('Change:AttName_SetTo', $sLabel, $sNewValue);
$sResult = Dict::Format('Change:AttName_SetTo', $sLabel, $sNewValueHtml);
}
else
{
if (is_null($sNewValue))
{
$sNewValue = Dict::S('UI:UndefinedObject');
$sNewValueHtml = Dict::S('UI:UndefinedObject');
}
$sResult = Dict::Format('Change:AttName_SetTo_NewValue_PreviousValue_OldValue', $sLabel, $sNewValue, $sOldValue);
$sResult = Dict::Format('Change:AttName_SetTo_NewValue_PreviousValue_OldValue', $sLabel, $sNewValueHtml, $sOldValueHtml);
}
}
return $sResult;
@@ -1214,14 +1230,14 @@ class AttributeDecimal extends AttributeDBField
public function MakeRealValue($proposedValue, $oHostObj)
{
if (is_null($proposedValue)) return null;
if ($proposedValue == '') return null;
if ($proposedValue === '') return null;
return (string)$proposedValue;
}
public function ScalarToSQL($value)
{
assert(is_null($value) || preg_match('/'.$this->GetValidationPattern().'/', $value));
return (string)$value; // treated as a string
return $value; // null or string
}
}
@@ -1677,12 +1693,6 @@ class AttributeEncryptedString extends AttributeString
// Example: [[Server:db1.tnut.com]]
define('WIKI_OBJECT_REGEXP', '/\[\[(.+):(.+)\]\]/U');
// <url>
// Example: http://romain:trustno1@127.0.0.1:8888/iTop-trunk/modules/itop-caches/itop-caches.php?agument=machin%20#monAncre
define('WIKI_URL', "/(https?|ftp)\:\/\/([a-z0-9+!*(),;?&=\$_.-]+(\:[a-z0-9+!*(),;?&=\$_.-]+)?@)?([a-z0-9-.]{3,})(\:[0-9]{2,5})?(\/([a-z0-9+\$_-]\.?)+)*\/?(\?[a-z+&\$_.-][a-z0-9;:@&%=+\/\$_.-]*)?(#[a-z_.-][a-z0-9+\$_.-]*)?/i");
// SHEME............. USER.................... PASSWORD...................... HOST/IP......... PORT.......... PATH...................... GET................................... ANCHOR....................
// Origin of this regexp: http://www.php.net/manual/fr/function.preg-match.php#93824
/**
* Map a text column (size > ?) to an attribute
@@ -1703,7 +1713,8 @@ class AttributeText extends AttributeString
static public function RenderWikiHtml($sText)
{
if (preg_match_all(WIKI_URL, $sText, $aAllMatches, PREG_SET_ORDER /* important !*/ |PREG_OFFSET_CAPTURE /* important ! */))
$sPattern = '/'.str_replace('/', '\/', utils::GetConfig()->Get('url_validation_pattern')).'/i';
if (preg_match_all($sPattern, $sText, $aAllMatches, PREG_SET_ORDER /* important !*/ |PREG_OFFSET_CAPTURE /* important ! */))
{
$aUrls = array();
$i = count($aAllMatches);
@@ -2067,7 +2078,7 @@ class AttributeEmailAddress extends AttributeString
public function GetValidationPattern()
{
// return "^([0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\\.)+[a-zA-Z]{2,9})$";
return "^[a-zA-Z0-9._&-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$";
return "^[a-zA-Z0-9._&-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,}$";
}
public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true)
@@ -2224,19 +2235,12 @@ class AttributeEnum extends AttributeString
}
else
{
$sLabel = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue, '');
if (strlen($sLabel) == 0)
$sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'/Value:'.$sValue, null, true /*user lang*/);
if (is_null($sLabel))
{
$sLabel = str_replace('_', ' ', $sValue);
$sParentClass = MetaModel::GetParentClass($this->m_sHostClass);
if ($sParentClass)
{
if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode))
{
$oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode);
$sLabel = $oAttDef->GetValueLabel($sValue);
}
}
$sDefault = str_replace('_', ' ', $sValue);
// Browse the hierarchy again, accepting default (english) translations
$sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'/Value:'.$sValue, $sDefault, false);
}
}
return $sLabel;
@@ -2251,7 +2255,7 @@ class AttributeEnum extends AttributeString
}
else
{
$sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+', '');
$sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+', '', true /* user language only */);
if (strlen($sDescription) == 0)
{
$sParentClass = MetaModel::GetParentClass($this->m_sHostClass);
@@ -2333,14 +2337,6 @@ class AttributeEnum extends AttributeString
}
}
public function GetAsHTMLForHistory($sOldValue, $sNewValue, $sLabel = null)
{
$sOldValue = is_null($sOldValue) ? null : $this->GetAsHTML($sOldValue);
$sNewValue = is_null($sNewValue) ? null : $this->GetAsHTML($sNewValue);
$sResult = parent::GetAsHTMLForHistory($sOldValue, $sNewValue, $sLabel);
return $sResult;
}
public function GetAllowedValues($aArgs = array(), $sContains = '')
{
$aRawValues = parent::GetAllowedValues($aArgs, $sContains);
@@ -2648,10 +2644,6 @@ class AttributeDuration extends AttributeInteger
protected function GetSQLCol() {return "INT(11) UNSIGNED";}
public function GetNullValue() {return '0';}
public function GetDefaultValue()
{
return 0;
}
public function MakeRealValue($proposedValue, $oHostObj)
{
@@ -3302,17 +3294,17 @@ class AttributeURL extends AttributeString
$sTarget = $this->Get("target");
if (empty($sTarget)) $sTarget = "_blank";
$sLabel = Str::pure2html($sValue);
if (strlen($sLabel) > 40)
if (strlen($sLabel) > 255)
{
// Truncate the length to about 40 characters, by removing the middle
$sLabel = substr($sLabel, 0, 25).'...'.substr($sLabel, -15);
// Truncate the length to 128 characters, by removing the middle
$sLabel = substr($sLabel, 0, 100).'.....'.substr($sLabel, -20);
}
return "<a target=\"$sTarget\" href=\"$sValue\">$sLabel</a>";
}
public function GetValidationPattern()
{
return "^(http|https|ftp)\://[a-zA-Z0-9\-\.]+(:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\\+&amp;%\$#\=~])*$";
return $this->GetOptional('validation_pattern', '^'.utils::GetConfig()->Get('url_validation_pattern').'$');
}
}
@@ -3336,6 +3328,11 @@ class AttributeBlob extends AttributeDefinition
public function GetDefaultValue() {return "";}
public function IsNullAllowed() {return $this->GetOptional("is_null_allowed", false);}
public function GetEditValue($sValue, $oHostObj = null)
{
return '';
}
// Facilitate things: allow the user to Set the value from a string
public function MakeRealValue($proposedValue, $oHostObj)
@@ -3363,26 +3360,26 @@ class AttributeBlob extends AttributeDefinition
public function FromSQLToValue($aCols, $sPrefix = '')
{
if (!isset($aCols[$sPrefix]))
if (!array_key_exists($sPrefix, $aCols))
{
$sAvailable = implode(', ', array_keys($aCols));
throw new MissingColumnException("Missing column '$sPrefix' from {$sAvailable}");
}
$sMimeType = $aCols[$sPrefix];
$sMimeType = isset($aCols[$sPrefix]) ? $aCols[$sPrefix] : '';
if (!isset($aCols[$sPrefix.'_data']))
if (!array_key_exists($sPrefix.'_data', $aCols))
{
$sAvailable = implode(', ', array_keys($aCols));
throw new MissingColumnException("Missing column '".$sPrefix."_data' from {$sAvailable}");
}
$data = $aCols[$sPrefix.'_data'];
$data = isset($aCols[$sPrefix.'_data']) ? $aCols[$sPrefix.'_data'] : null;
if (!isset($aCols[$sPrefix.'_filename']))
if (!array_key_exists($sPrefix.'_filename', $aCols))
{
$sAvailable = implode(', ', array_keys($aCols));
throw new MissingColumnException("Missing column '".$sPrefix."_filename' from {$sAvailable}");
}
$sFileName = $aCols[$sPrefix.'_filename'];
$sFileName = isset($aCols[$sPrefix.'_filename']) ? $aCols[$sPrefix.'_filename'] : '';
$value = new ormDocument($data, $sMimeType, $sFileName);
return $value;
@@ -3464,6 +3461,44 @@ class AttributeBlob extends AttributeDefinition
{
return ''; // Not exportable in XML, or as CDATA + some subtags ??
}
/**
* Helper to get a value that will be JSON encoded
* The operation is the opposite to FromJSONToValue
*/
public function GetForJSON($value)
{
if ($value instanceOf ormDocument)
{
$aValues = array();
$aValues['data'] = base64_encode($value->GetData());
$aValues['mimetype'] = $value->GetMimeType();
$aValues['filename'] = $value->GetFileName();
}
else
{
$aValues = null;
}
return $aValues;
}
/**
* Helper to form a value, given JSON decoded data
* The operation is the opposite to GetForJSON
*/
public function FromJSONToValue($json)
{
if (isset($json->data))
{
$data = base64_decode($json->data);
$value = new ormDocument($data, $json->mimetype, $json->filename);
}
else
{
$value = null;
}
return $value;
}
}
/**
@@ -4092,19 +4127,19 @@ class AttributeOneWayPassword extends AttributeDefinition
public function FromSQLToValue($aCols, $sPrefix = '')
{
if (!isset($aCols[$sPrefix]))
if (!array_key_exists($sPrefix, $aCols))
{
$sAvailable = implode(', ', array_keys($aCols));
throw new MissingColumnException("Missing column '$sPrefix' from {$sAvailable}");
}
$hashed = $aCols[$sPrefix];
$hashed = isset($aCols[$sPrefix]) ? $aCols[$sPrefix] : '';
if (!isset($aCols[$sPrefix.'_salt']))
if (!array_key_exists($sPrefix.'_salt', $aCols))
{
$sAvailable = implode(', ', array_keys($aCols));
throw new MissingColumnException("Missing column '".$sPrefix."_salt' from {$sAvailable}");
}
$sSalt = $aCols[$sPrefix.'_salt'];
$sSalt = isset($aCols[$sPrefix.'_salt']) ? $aCols[$sPrefix.'_salt'] : '';
$value = new ormPassword($hashed, $sSalt);
return $value;
@@ -4429,7 +4464,7 @@ class AttributeComputedFieldVoid extends AttributeDefinition
public function GetEditClass() {return "";}
public function GetValuesDef() {return null;}
public function GetPrerequisiteAttributes() {return $this->Get("depends_on");}
public function GetPrerequisiteAttributes() {return $this->GetOptional("depends_on", array());}
public function IsDirectField() {return true;}
public function IsScalar() {return true;}
@@ -4471,7 +4506,7 @@ class AttributeComputedFieldVoid extends AttributeDefinition
public function GetBasicFilterOperators()
{
return array();
return array("="=>"equals", "!="=>"differs from");
}
public function GetBasicFilterLooseOperator()
{

View File

@@ -18,7 +18,7 @@
/**
* Class BackgroundProcess
* interface iBackgroundProcess
* Any extension that must be called regularly to be executed in the background
*
* @copyright Copyright (C) 2010-2012 Combodo SARL

View File

@@ -0,0 +1,76 @@
<?php
// Copyright (C) 2013 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 BackgroundTask
* A class to record information about the execution of background processes
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class BackgroundTask extends DBObject
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"key_type" => "autoincrement",
"name_attcode" => "class_name",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_backgroundtask",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeString("class_name", array("allowed_values"=>null, "sql"=>"class_name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("first_run_date", array("allowed_values"=>null, "sql"=>"first_run_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("latest_run_date", array("allowed_values"=>null, "sql"=>"latest_run_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("next_run_date", array("allowed_values"=>null, "sql"=>"next_run_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("total_exec_count", array("allowed_values"=>null, "sql"=>"total_exec_count", "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDecimal("latest_run_duration", array("allowed_values"=>null, "sql"=>"latest_run_duration", "digits"=> 8, "decimals"=> 3, "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDecimal("min_run_duration", array("allowed_values"=>null, "sql"=>"min_run_duration", "digits"=> 8, "decimals"=> 3, "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDecimal("max_run_duration", array("allowed_values"=>null, "sql"=>"max_run_duration", "digits"=> 8, "decimals"=> 3, "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDecimal("average_run_duration", array("allowed_values"=>null, "sql"=>"average_run_duration", "digits"=> 8, "decimals"=> 3, "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeBoolean("running", array("allowed_values"=>null, "sql"=>"running", "default_value"=>false, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values"=>new ValueSetEnum('active,paused'), "sql"=>"status", "default_value"=>'active', "is_null_allowed"=>false, "depends_on"=>array())));
}
public function ComputeDurations($fLatestDuration)
{
$iTotalRun = $this->Get('total_exec_count');
$fAverageDuration = ($this->Get('average_run_duration') * $iTotalRun + $fLatestDuration) / (1+$iTotalRun);
$this->Set('average_run_duration', sprintf('%.3f',$fAverageDuration));
$this->Set('total_exec_count', 1+$iTotalRun);
if ($fLatestDuration < $this->Get('min_run_duration'))
{
$this->Set('min_run_duration', sprintf('%.3f',$fLatestDuration));
}
if ($fLatestDuration > $this->Get('max_run_duration'))
{
$this->Set('max_run_duration', sprintf('%.3f',$fLatestDuration));
}
$this->Set('latest_run_duration', sprintf('%.3f',$fLatestDuration));
}
}

View File

@@ -296,8 +296,17 @@ class BulkChange
$oReconFilter = new CMDBSearchFilter($oExtKey->GetTargetClass());
foreach ($this->m_aExtKeys[$sAttCode] as $sForeignAttCode => $iCol)
{
// The foreign attribute is one of our reconciliation key
$oReconFilter->AddCondition($sForeignAttCode, $aRowData[$iCol], '=');
if ($sForeignAttCode == 'id')
{
$value = (int) $aRowData[$iCol];
}
else
{
// The foreign attribute is one of our reconciliation key
$oForeignAtt = MetaModel::GetAttributeDef($oExtKey->GetTargetClass(), $sForeignAttCode);
$value = $oForeignAtt->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
}
$oReconFilter->AddCondition($sForeignAttCode, $value, '=');
$aResults[$iCol] = new CellStatus_Void($aRowData[$iCol]);
}
@@ -359,7 +368,16 @@ class BulkChange
foreach ($aKeyConfig as $sForeignAttCode => $iCol)
{
// The foreign attribute is one of our reconciliation key
$oReconFilter->AddCondition($sForeignAttCode, $aRowData[$iCol], '=');
if ($sForeignAttCode == 'id')
{
$value = $aRowData[$iCol];
}
else
{
$oForeignAtt = MetaModel::GetAttributeDef($oExtKey->GetTargetClass(), $sForeignAttCode);
$value = $oForeignAtt->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
}
$oReconFilter->AddCondition($sForeignAttCode, $value, '=');
$aResults[$iCol] = new CellStatus_Void($aRowData[$iCol]);
}
$oExtObjects = new CMDBObjectSet($oReconFilter);
@@ -824,7 +842,15 @@ class BulkChange
{
// The value is given in the data row
$iCol = $this->m_aAttList[$sAttCode];
$valuecondition = $aRowData[$iCol];
if ($sAttCode == 'id')
{
$valuecondition = $aRowData[$iCol];
}
else
{
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
$valuecondition = $oAttDef->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
}
}
if (is_null($valuecondition))
{

View File

@@ -176,7 +176,7 @@ abstract class CMDBObject extends DBObject
$oMyChangeOp->Set("objclass", MetaModel::GetRootClass(get_class($this)));
$oMyChangeOp->Set("objkey", $objkey);
$oMyChangeOp->Set("fclass", get_class($this));
$oMyChangeOp->Set("fname", $this->GetRawName());
$oMyChangeOp->Set("fname", substr($this->GetRawName(), 0, 255)); // Protect against very long friendly names
$iId = $oMyChangeOp->DBInsertNoReload();
}
@@ -322,6 +322,18 @@ abstract class CMDBObject extends DBObject
$oMyChangeOp->Set("newvalue", $value ? 1 : 0);
$iId = $oMyChangeOp->DBInsertNoReload();
}
elseif ($oAttDef instanceOf AttributeHierarchicalKey)
{
// Hierarchical keys
//
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeScalar");
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
$oMyChangeOp->Set("oldvalue", $original);
$oMyChangeOp->Set("newvalue", $value[$sAttCode]);
$iId = $oMyChangeOp->DBInsertNoReload();
}
else
{
// Scalars

View File

@@ -58,15 +58,29 @@ class CMDBSource
self::$m_sDBUser = $sUser;
self::$m_sDBPwd = $sPwd;
self::$m_sDBName = $sSource;
if (!self::$m_resDBLink = @mysqli_connect($sServer, $sUser, $sPwd))
$aConnectInfo = explode(':', self::$m_sDBHost);
if (count($aConnectInfo) > 1)
{
throw new MySQLException('Could not connect to the DB server', array('host'=>$sServer, 'user'=>$sUser));
// Override the default port
$sServer = $aConnectInfo[0];
$iPort = $aConnectInfo[1];
self::$m_resDBLink = @mysqli_connect($sServer, self::$m_sDBUser, self::$m_sDBPwd, '', $iPort);
}
else
{
self::$m_resDBLink = @mysqli_connect(self::$m_sDBHost, self::$m_sDBUser, self::$m_sDBPwd);
}
if (!self::$m_resDBLink)
{
throw new MySQLException('Could not connect to the DB server', array('host'=>self::$m_sDBHost, 'user'=>self::$m_sDBUser));
}
if (!empty($sSource))
{
if (!((bool)mysqli_query(self::$m_resDBLink, "USE $sSource")))
if (!((bool)mysqli_query(self::$m_resDBLink, "USE `$sSource`")))
{
throw new MySQLException('Could not select DB', array('host'=>$sServer, 'user'=>$sUser, 'db_name'=>$sSource));
throw new MySQLException('Could not select DB', array('host'=>self::$m_sDBHost, 'user'=>self::$m_sDBUser, 'db_name'=>self::$m_sDBName));
}
}
}
@@ -120,7 +134,7 @@ class CMDBSource
{
// In case we don't have rights to enumerate the databases
// Let's try to connect directly
return @((bool)mysqli_query(self::$m_resDBLink, "USE $sSource"));
return @((bool)mysqli_query(self::$m_resDBLink, "USE `$sSource`"));
}
}
@@ -133,7 +147,7 @@ class CMDBSource
public static function SelectDB($sSource)
{
if (!((bool)mysqli_query(self::$m_resDBLink, "USE $sSource")))
if (!((bool)mysqli_query(self::$m_resDBLink, "USE `$sSource`")))
{
throw new MySQLException('Could not select DB', array('db_name'=>$sSource));
}

View File

@@ -606,6 +606,17 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'url_validation_pattern' => array(
'type' => 'string',
'description' => 'Regular expression to validate/detect the format of an URL (URL attributes and Wiki formatting for Text attributes)',
'default' => '(https?|ftp)\://([a-zA-Z0-9+!*(),;?&=\$_.-]+(\:[a-zA-Z0-9+!*(),;?&=\$_.-]+)?@)?([a-zA-Z0-9-.]{3,})(\:[0-9]{2,5})?(/([a-zA-Z0-9+\$_-]\.?)+)*/?(\?[a-zA-Z+&\$_.-][a-zA-Z0-9;:[\]@&%=+/\$_.-]*)?(#[a-zA-Z_.-][a-zA-Z0-9+\$_.-]*)?',
// SHEME.......... USER....................... PASSWORD.......................... HOST/IP........... PORT.......... PATH....................... GET......................................... ANCHOR............................
// Example: http://User:passWord@127.0.0.1:8888/patH/Page.php?arrayArgument[2]=something:blah20#myAnchor
// Origin of this regexp: http://www.php.net/manual/fr/function.preg-match.php#93824
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
),
);
public function IsProperty($sPropCode)
@@ -747,6 +758,7 @@ class Config
'core/action.class.inc.php',
'core/trigger.class.inc.php',
'synchro/synchrodatasource.class.inc.php',
'core/backgroundtask.class.inc.php',
);
$this->m_aDataModels = array();
$this->m_aWebServiceCategories = array(
@@ -1569,10 +1581,6 @@ class Config
{
$aWebServiceCategories = array_unique(array_merge($aWebServiceCategories, $aModuleInfo['webservice']));
}
if (isset($aModuleInfo['dictionary']))
{
$aDictionaries = array_unique(array_merge($aDictionaries, $aModuleInfo['dictionary']));
}
if (isset($aModuleInfo['settings']))
{
list($sName, $sVersion) = ModuleDiscovery::GetModuleName($sModuleId);
@@ -1608,6 +1616,17 @@ class Config
$this->SetAppModules($aAppModules);
$this->SetDataModels($aDataModels);
$this->SetWebServiceCategories($aWebServiceCategories);
// Scan dictionaries
//
if (!is_null($sModulesDir))
{
foreach(glob(APPROOT.$sModulesDir.'/dictionaries/*.dict.php') as $sFilePath)
{
$sFile = basename($sFilePath);
$aDictionaries[] = $sModulesDir.'/dictionaries/'.$sFile;
}
}
$this->SetDictionaries($aDictionaries);
}
}

View File

@@ -455,7 +455,10 @@ abstract class DBObject
if (($iRemote = $this->Get($sExtKeyAttCode)) && ($iRemote > 0)) // Objects in memory have negative IDs
{
$oExtKeyAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyAttCode);
$oRemote = MetaModel::GetObject($oExtKeyAttDef->GetTargetClass(), $iRemote);
// Note: "allow all data" must be enabled because the external fields are always visible
// to the current user even if this is not the case for the remote object
// This is consistent with the behavior of the lists
$oRemote = MetaModel::GetObject($oExtKeyAttDef->GetTargetClass(), $iRemote, true, true);
}
else
{
@@ -509,6 +512,9 @@ abstract class DBObject
/**
* Updates the value of an external field by (re)loading the object
* corresponding to the external key and getting the value from it
*
* UNUSED ?
*
* @param string $sAttCode Attribute code of the external field to update
* @return void
*/
@@ -519,7 +525,10 @@ abstract class DBObject
{
$sTargetClass = $oAttDef->GetTargetClass();
$objkey = $this->Get($oAttDef->GetKeyAttCode());
$oObj = MetaModel::GetObject($sTargetClass, $objkey);
// Note: "allow all data" must be enabled because the external fields are always visible
// to the current user even if this is not the case for the remote object
// This is consistent with the behavior of the lists
$oObj = MetaModel::GetObject($sTargetClass, $objkey, true, true);
if (is_object($oObj))
{
$value = $oObj->Get($oAttDef->GetExtAttCode());
@@ -1776,6 +1785,11 @@ abstract class DBObject
MyHelpers::CheckKeyInArray('object lifecycle stimulus', $sStimulusCode, MetaModel::EnumStimuli(get_class($this)));
$aStateTransitions = $this->EnumTransitions();
if (!array_key_exists($sStimulusCode, $aStateTransitions))
{
// This simulus has no effect in the current state... do nothing
return;
}
$aTransitionDef = $aStateTransitions[$sStimulusCode];
// Change the state before proceeding to the actions, this is necessary because an action might

View File

@@ -118,6 +118,60 @@ class DBObjectSearch
return key($this->m_aClasses);
}
/**
* Change the class (only subclasses are supported as of now, because the conditions must fit the new class)
* Defaults to the first selected class (most of the time it is also the first joined class
*/
public function ChangeClass($sNewClass, $sAlias = null)
{
if (is_null($sAlias))
{
$sAlias = $this->GetClassAlias();
}
else
{
if (!array_key_exists($sAlias, $this->m_aClasses))
{
// discard silently - necessary when recursing on the related nodes (see code below)
return;
}
}
$sCurrClass = $this->GetClassName($sAlias);
if (!MetaModel::IsParentClass($sCurrClass, $sNewClass))
{
throw new Exception("Could not change the search class from '$sCurrClass' to '$sNewClass'. Only child classes are permitted.");
}
// Change for this node
//
$this->m_aSelectedClasses[$sAlias] = $sNewClass;
$this->m_aClasses[$sAlias] = $sNewClass;
// Change for all the related node (yes, this was necessary with some queries - strange effects otherwise)
//
foreach($this->m_aRelatedTo as $aRelatedTo)
{
$aRelatedTo['flt']->ChangeClass($sNewClass, $sAlias);
}
foreach($this->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo)
{
foreach($aPointingTo as $iOperatorCode => $aFilter)
{
foreach($aFilter as $oExtFilter)
{
$oExtFilter->ChangeClass($sNewClass, $sAlias);
}
}
}
foreach($this->m_aReferencedBy as $sForeignClass => $aReferences)
{
foreach($aReferences as $sForeignExtKeyAttCode => $oForeignFilter)
{
$oForeignFilter->ChangeClass($sNewClass, $sAlias);
}
}
}
public function SetSelectedClasses($aNewSet)
{
$this->m_aSelectedClasses = array();

View File

@@ -272,7 +272,9 @@ class DBObjectSet
{
// Make sure that we carry on the parameters of the set with the filter
$oFilter = $this->m_oFilter->DeepClone();
$oFilter->SetInternalParams(array_merge($oFilter->GetInternalParams(), $this->m_aArgs));
// Note: the arguments found within a set can be object (but not in a filter)
// That's why PrepareQueryArguments must be invoked there
$oFilter->SetInternalParams(array_merge($oFilter->GetInternalParams(), MetaModel::PrepareQueryArguments($this->m_aArgs)));
if (count($this->m_aAddedIds) == 0)
{

View File

@@ -82,6 +82,9 @@ class DeletionPlan
public function ComputeResults()
{
$this->m_iToDelete = 0;
$this->m_iToUpdate = 0;
foreach($this->m_aToDelete as $sClass => $aToDelete)
{
foreach($aToDelete as $iId => $aData)

View File

@@ -120,7 +120,7 @@ class Dict
}
public static function S($sStringCode, $sDefault = null)
public static function S($sStringCode, $sDefault = null, $bUserLanguageOnly = false)
{
// Attempt to find the string in the user language
//
@@ -134,19 +134,22 @@ class Dict
{
return $aCurrentDictionary[$sStringCode];
}
// Attempt to find the string in the default language
//
$aDefaultDictionary = self::$m_aData[self::$m_sDefaultLanguage];
if (array_key_exists($sStringCode, $aDefaultDictionary))
if (!$bUserLanguageOnly)
{
return $aDefaultDictionary[$sStringCode];
}
// Attempt to find the string in english
//
$aDefaultDictionary = self::$m_aData['EN US'];
if (array_key_exists($sStringCode, $aDefaultDictionary))
{
return $aDefaultDictionary[$sStringCode];
// Attempt to find the string in the default language
//
$aDefaultDictionary = self::$m_aData[self::$m_sDefaultLanguage];
if (array_key_exists($sStringCode, $aDefaultDictionary))
{
return $aDefaultDictionary[$sStringCode];
}
// Attempt to find the string in english
//
$aDefaultDictionary = self::$m_aData['EN US'];
if (array_key_exists($sStringCode, $aDefaultDictionary))
{
return $aDefaultDictionary[$sStringCode];
}
}
// Could not find the string...
//

View File

@@ -33,10 +33,15 @@ define ('EMAIL_SEND_OK', 0);
define ('EMAIL_SEND_PENDING', 1);
define ('EMAIL_SEND_ERROR', 2);
class EMail
{
// Serialization formats
const ORIGINAL_FORMAT = 1; // Original format, consisting in serializing the whole object, inculding the Swift Mailer's object.
// Did not work with attachements since their binary representation cannot be stored as a valid UTF-8 string
const FORMAT_V2 = 2; // New format, only the raw data are serialized (base64 encoded if needed)
protected static $m_oConfig = null;
protected $m_aData; // For storing data to serialize
public function LoadConfig($sConfigFile = ITOP_DEFAULT_CONFIG_FILE)
{
@@ -46,17 +51,95 @@ class EMail
}
}
protected $m_oMessage;
public function __construct()
{
$this->m_aData = array();
$this->m_oMessage = Swift_Message::newInstance();
$oEncoder = new Swift_Mime_ContentEncoder_PlainContentEncoder('8bit');
$this->m_oMessage->setEncoder($oEncoder);
}
/**
* Custom serialization method
* No longer use the brute force "serialize" method since
* 1) It does not work with binary attachments (since they cannot be stored in a UTF-8 text field)
* 2) The size tends to be quite big (sometimes ten times the size of the email)
*/
public function SerializeV2()
{
return serialize($this->m_aData);
}
/**
* Custom de-serialization method
* @param string $sSerializedMessage The serialized representation of the message
*/
static public function UnSerializeV2($sSerializedMessage)
{
$aData = unserialize($sSerializedMessage);
$oMessage = new Email();
if (array_key_exists('body', $aData))
{
$oMessage->SetBody($aData['body']['body'], $aData['body']['mimeType']);
}
if (array_key_exists('message_id', $aData))
{
$oMessage->SetMessageId($aData['message_id']);
}
if (array_key_exists('bcc', $aData))
{
$oMessage->SetRecipientBCC($aData['bcc']);
}
if (array_key_exists('cc', $aData))
{
$oMessage->SetRecipientCC($aData['cc']);
}
if (array_key_exists('from', $aData))
{
$oMessage->SetRecipientFrom($aData['from']['address'], $aData['from']['label']);
}
if (array_key_exists('reply_to', $aData))
{
$oMessage->SetRecipientReplyTo($aData['reply_to']);
}
if (array_key_exists('to', $aData))
{
$oMessage->SetRecipientTO($aData['to']);
}
if (array_key_exists('subject', $aData))
{
$oMessage->SetSubject($aData['subject']);
}
if (array_key_exists('headers', $aData))
{
foreach($aData['headers'] as $sKey => $sValue)
{
$oMessage->AddToHeader($sKey, $sValue);
}
}
if (array_key_exists('parts', $aData))
{
foreach($aData['parts'] as $aPart)
{
$oMessage->AddPart($aPart['text'], $aPart['mimeType']);
}
}
if (array_key_exists('attachments', $aData))
{
foreach($aData['attachments'] as $aAttachment)
{
$oMessage->AddAttachment(base64_decode($aAttachment['data']), $aAttachment['filename'], $aAttachment['mimeType']);
}
}
return $oMessage;
}
protected function SendAsynchronous(&$aIssues, $oLog = null)
{
try
@@ -102,9 +185,9 @@ class EMail
$oMailer = Swift_Mailer::newInstance($oTransport);
$iSent = $oMailer->send($this->m_oMessage);
if ($iSent === false)
if ($iSent === 0)
{
$aIssues = 'une erreur s\'est produite... mais quoi !!!';
$aIssues = array('No valid recipient for this message.');
return EMAIL_SEND_ERROR;
}
else
@@ -136,6 +219,12 @@ class EMail
public function AddToHeader($sKey, $sValue)
{
if (!array_key_exists('headers', $this->m_aData))
{
$this->m_aData['headers'] = array();
}
$this->m_aData['headers'][$sKey] = $sValue;
if (strlen($sValue) > 0)
{
$oHeaders = $this->m_oMessage->getHeaders();
@@ -149,6 +238,8 @@ class EMail
public function SetMessageId($sId)
{
$this->m_aData['message_id'] = $sId;
// Note: Swift will add the angle brackets for you
// so let's remove the angle brackets if present, for historical reasons
$sId = str_replace(array('<', '>'), '', $sId);
@@ -164,22 +255,34 @@ class EMail
public function SetBody($sBody, $sMimeType = 'text/html')
{
$this->m_aData['body'] = array('body' => $sBody, 'mimeType' => $sMimeType);
$this->m_oMessage->setBody($sBody, $sMimeType);
}
public function AddPart($sText, $sMimeType = 'text/html')
{
if (!array_key_exists('parts', $this->m_aData))
{
$this->m_aData['parts'] = array();
}
$this->m_aData['parts'][] = array('text' => $sText, 'mimeType' => $sMimeType);
$this->m_oMessage->addPart($sText, $sMimeType);
}
public function AddAttachment($data, $sFileName, $sMimeType)
{
if (!array_key_exists('attachments', $this->m_aData))
{
$this->m_aData['attachments'] = array();
}
$this->m_aData['attachments'][] = array('data' => base64_encode($data), 'filename' => $sFileName, 'mimeType' => $sMimeType);
$this->m_oMessage->attach(Swift_Attachment::newInstance($data, $sFileName, $sMimeType));
}
public function SetSubject($aSubject)
public function SetSubject($sSubject)
{
$this->m_oMessage->setSubject($aSubject);
$this->m_aData['subject'] = $sSubject;
$this->m_oMessage->setSubject($sSubject);
}
public function GetSubject()
@@ -187,11 +290,30 @@ class EMail
return $this->m_oMessage->getSubject();
}
/**
* Helper to transform and sanitize addresses
* - get rid of empty addresses
*/
protected function AddressStringToArray($sAddressCSVList)
{
$aAddresses = array();
foreach(explode(',', $sAddressCSVList) as $sAddress)
{
$sAddress = trim($sAddress);
if (strlen($sAddress) > 0)
{
$aAddresses[] = $sAddress;
}
}
return $aAddresses;
}
public function SetRecipientTO($sAddress)
{
$this->m_aData['to'] = $sAddress;
if (!empty($sAddress))
{
$aAddresses = explode(', ', $sAddress);
$aAddresses = $this->AddressStringToArray($sAddress);
$this->m_oMessage->setTo($aAddresses);
}
}
@@ -224,24 +346,27 @@ class EMail
public function SetRecipientCC($sAddress)
{
$this->m_aData['cc'] = $sAddress;
if (!empty($sAddress))
{
$aAddresses = explode(', ', $sAddress);
$aAddresses = $this->AddressStringToArray($sAddress);
$this->m_oMessage->setCc($aAddresses);
}
}
public function SetRecipientBCC($sAddress)
{
$this->m_aData['bcc'] = $sAddress;
if (!empty($sAddress))
{
$aAddresses = explode(', ', $sAddress);
$aAddresses = $this->AddressStringToArray($sAddress);
$this->m_oMessage->setBcc($aAddresses);
}
}
public function SetRecipientFrom($sAddress, $sLabel = '')
{
$this->m_aData['from'] = array('address' => $sAddress, 'label' => $sLabel);
if ($sLabel != '')
{
$this->m_oMessage->setFrom(array($sAddress => $sLabel));
@@ -254,6 +379,7 @@ class EMail
public function SetRecipientReplyTo($sAddress)
{
$this->m_aData['reply_to'] = $sAddress;
if (!empty($sAddress))
{
$this->m_oMessage->setReplyTo($sAddress);

View File

@@ -41,6 +41,7 @@ class Event extends DBObject implements iDisplay
"db_key_field" => "id",
"db_finalclass_field" => "realclass",
"display_template" => "",
"order_by_default" => array('date' => false)
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
@@ -106,7 +107,7 @@ class Event extends DBObject implements iDisplay
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
{
if ($bEditMode) return; // Not editable
if ($bEditMode) return array(); // Not editable
$aDetails = array();
$sClass = get_class($this);
@@ -117,6 +118,7 @@ class Event extends DBObject implements iDisplay
$aDetails[] = array('label' => '<span title="'.MetaModel::GetDescription($sClass, $sAttCode).'">'.MetaModel::GetLabel($sClass, $sAttCode).'</span>', 'value' => $sDisplayValue);
}
$oPage->Details($aDetails);
return array();
}
}
@@ -135,6 +137,7 @@ class EventNotification extends Event
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
"order_by_default" => array('date' => false)
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
@@ -167,6 +170,7 @@ class EventNotificationEmail extends EventNotification
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
"order_by_default" => array('date' => false)
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
@@ -204,6 +208,7 @@ class EventIssue extends Event
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
"order_by_default" => array('date' => false)
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
@@ -303,6 +308,7 @@ class EventWebService extends Event
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
"order_by_default" => array('date' => false)
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
@@ -337,6 +343,7 @@ class EventLoginUsage extends Event
"db_table" => "priv_event_loginusage",
"db_key_field" => "id",
"db_finalclass_field" => "",
"order_by_default" => array('date' => false)
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();

View File

@@ -383,7 +383,7 @@ class ScalarExpression extends UnaryExpression
{
public function __construct($value)
{
if (!is_scalar($value) && !is_null($value))
if (!is_scalar($value) && !is_null($value) && (!$value instanceof OqlHexValue))
{
throw new CoreException('Attempt to create a scalar expression from a non scalar', array('var_type'=>gettype($value)));
}
@@ -618,7 +618,7 @@ class VariableExpression extends UnaryExpression
}
else
{
throw new MissingQueryArgument('Missing query argument', array('expecting'=>$this->m_sName, 'available'=>$aArgs));
throw new MissingQueryArgument('Missing query argument', array('expecting'=>$this->m_sName, 'available'=>array_keys($aArgs)));
}
}
@@ -879,31 +879,63 @@ class FunctionExpression extends Expression
*/
public function MakeValueLabel($oFilter, $sValue, $sDefault)
{
static $aWeekDayToString = null;
if (is_null($aWeekDayToString))
{
// Init the correspondance table
$aWeekDayToString = array(
0 => Dict::S('DayOfWeek-Sunday'),
1 => Dict::S('DayOfWeek-Monday'),
2 => Dict::S('DayOfWeek-Tuesday'),
3 => Dict::S('DayOfWeek-Wednesday'),
4 => Dict::S('DayOfWeek-Thursday'),
5 => Dict::S('DayOfWeek-Friday'),
6 => Dict::S('DayOfWeek-Saturday')
);
}
static $aMonthToString = null;
if (is_null($aMonthToString))
{
// Init the correspondance table
$aMonthToString = array(
1 => Dict::S('Month-01'),
2 => Dict::S('Month-02'),
3 => Dict::S('Month-03'),
4 => Dict::S('Month-04'),
5 => Dict::S('Month-05'),
6 => Dict::S('Month-06'),
7 => Dict::S('Month-07'),
8 => Dict::S('Month-08'),
9 => Dict::S('Month-09'),
10 => Dict::S('Month-10'),
11 => Dict::S('Month-11'),
12 => Dict::S('Month-12'),
);
}
$sRes = $sDefault;
if (strtolower($this->m_sVerb) == 'date_format')
{
$oFormatExpr = $this->m_aArgs[1];
if ($oFormatExpr->Render() == "'%w'")
{
static $aWeekDayToString = null;
if (is_null($aWeekDayToString))
{
// Init the correspondance table
$aWeekDayToString = array(
0 => Dict::S('DayOfWeek-Sunday'),
1 => Dict::S('DayOfWeek-Monday'),
2 => Dict::S('DayOfWeek-Tuesday'),
3 => Dict::S('DayOfWeek-Wednesday'),
4 => Dict::S('DayOfWeek-Thursday'),
5 => Dict::S('DayOfWeek-Friday'),
6 => Dict::S('DayOfWeek-Saturday')
);
}
if (isset($aWeekDayToString[(int)$sValue]))
{
$sRes = $aWeekDayToString[(int)$sValue];
}
}
elseif ($oFormatExpr->Render() == "'%Y-%m'")
{
// yyyy-mm => "yyyy month"
$iMonth = (int) substr($sValue, -2); // the two last chars
$sRes = substr($sValue, 0, 4).' '.$aMonthToString[$iMonth];
}
elseif ($oFormatExpr->Render() == "'%Y-%m-%d'")
{
// yyyy-mm-dd => "month d"
$iMonth = (int) substr($sValue, 5, 2);
$sRes = $aMonthToString[$iMonth].' '.(int)substr($sValue, -2);
}
}
return $sRes;
}

View File

@@ -1967,15 +1967,30 @@ abstract class MetaModel
{
return array_unique(self::$m_aRootClasses);
}
public static function EnumParentClasses($sClass, $iOption = ENUM_PARENT_CLASSES_EXCLUDELEAF)
public static function EnumParentClasses($sClass, $iOption = ENUM_PARENT_CLASSES_EXCLUDELEAF, $bRootFirst = true)
{
self::_check_subclass($sClass);
if ($iOption == ENUM_PARENT_CLASSES_EXCLUDELEAF)
if ($bRootFirst)
{
return self::$m_aParentClasses[$sClass];
$aRes = self::$m_aParentClasses[$sClass];
}
else
{
$aRes = array_reverse(self::$m_aParentClasses[$sClass], true);
}
if ($iOption != ENUM_PARENT_CLASSES_EXCLUDELEAF)
{
if ($bRootFirst)
{
// Leaf class at the end
$aRes[] = $sClass;
}
else
{
// Leaf class on top
array_unshift($aRes, $sClass);
}
}
$aRes = self::$m_aParentClasses[$sClass];
$aRes[] = $sClass;
return $aRes;
}
public static function EnumChildClasses($sClass, $iOption = ENUM_CHILD_CLASSES_EXCLUDETOP)
@@ -2076,10 +2091,27 @@ abstract class MetaModel
return $aScalarArgs;
}
public static function MakeGroupByQuery(DBObjectSearch $oFilter, $aArgs, $aGroupByExpr)
public static function MakeGroupByQuery(DBObjectSearch $oFilter, $aArgs, $aGroupByExpr, $bExcludeNullValues = false)
{
$aAttToLoad = array();
$oSelect = self::MakeSelectStructure($oFilter, array(), $aArgs, $aAttToLoad, null, 0, 0, false, $aGroupByExpr);
if ($bExcludeNullValues)
{
// Null values are not handled (though external keys set to 0 are allowed)
$oQueryFilter = $oFilter->DeepClone();
foreach ($aGroupByExpr as $oGroupByExp)
{
$oNull = new FunctionExpression('ISNULL', array($oGroupByExp));
$oNotNull = new BinaryExpression($oNull, '!=', new TrueExpression());
$oQueryFilter->AddConditionExpression($oNotNull);
}
}
else
{
$oQueryFilter = $oFilter;
}
$oSelect = self::MakeSelectStructure($oQueryFilter, array(), $aArgs, $aAttToLoad, null, 0, 0, false, $aGroupByExpr);
$aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams());
try
@@ -5148,7 +5180,7 @@ abstract class MetaModel
}
$aEntries = array();
$aCacheUserData = @apc_cache_info('user');
if (is_array($aCacheUserData))
if (is_array($aCacheUserData) && isset($aCacheUserData['cache_list']))
{
$sPrefix = 'itop-'.$sEnvironment.'-';

View File

@@ -17,6 +17,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/>
/**
* OQL syntax analyzer, to be used prior to run the lexical analyzer
*
@@ -119,6 +120,11 @@ class OQLLexerRaw
'/\G-/ ',
'/\GAND/ ',
'/\GOR/ ',
'/\G\\|/ ',
'/\G&/ ',
'/\G\\^/ ',
'/\G<</ ',
'/\G>>/ ',
'/\G,/ ',
'/\G\\(/ ',
'/\G\\)/ ',
@@ -168,7 +174,8 @@ class OQLLexerRaw
'/\GABOVE STRICT/ ',
'/\GNOT ABOVE/ ',
'/\GNOT ABOVE STRICT/ ',
'/\G(0x[0-9a-fA-F]+|[0-9]+)/ ',
'/\G(0x[0-9a-fA-F]+)/ ',
'/\G([0-9]+)/ ',
'/\G\"([^\\\\\"]|\\\\\"|\\\\\\\\)*\"|'.chr(94).chr(39).'([^\\\\'.chr(39).']|\\\\'.chr(39).'|\\\\\\\\)*'.chr(39).'/ ',
'/\G([_a-zA-Z][_a-zA-Z0-9]*|`[^`]+`)/ ',
'/\G:([_a-zA-Z][_a-zA-Z0-9]*->[_a-zA-Z][_a-zA-Z0-9]*|[_a-zA-Z][_a-zA-Z0-9]*)/ ',
@@ -333,269 +340,299 @@ class OQLLexerRaw
function yy_r1_13($yy_subpatterns)
{
$this->token = OQLParser::COMA;
$this->token = OQLParser::BITWISE_OR;
}
function yy_r1_14($yy_subpatterns)
{
$this->token = OQLParser::PAR_OPEN;
$this->token = OQLParser::BITWISE_AND;
}
function yy_r1_15($yy_subpatterns)
{
$this->token = OQLParser::PAR_CLOSE;
$this->token = OQLParser::BITWISE_XOR;
}
function yy_r1_16($yy_subpatterns)
{
$this->token = OQLParser::REGEXP;
$this->token = OQLParser::BITWISE_LEFT_SHIFT;
}
function yy_r1_17($yy_subpatterns)
{
$this->token = OQLParser::EQ;
$this->token = OQLParser::BITWISE_RIGHT_SHIFT;
}
function yy_r1_18($yy_subpatterns)
{
$this->token = OQLParser::NOT_EQ;
$this->token = OQLParser::COMA;
}
function yy_r1_19($yy_subpatterns)
{
$this->token = OQLParser::GT;
$this->token = OQLParser::PAR_OPEN;
}
function yy_r1_20($yy_subpatterns)
{
$this->token = OQLParser::LT;
$this->token = OQLParser::PAR_CLOSE;
}
function yy_r1_21($yy_subpatterns)
{
$this->token = OQLParser::GE;
$this->token = OQLParser::REGEXP;
}
function yy_r1_22($yy_subpatterns)
{
$this->token = OQLParser::LE;
$this->token = OQLParser::EQ;
}
function yy_r1_23($yy_subpatterns)
{
$this->token = OQLParser::LIKE;
$this->token = OQLParser::NOT_EQ;
}
function yy_r1_24($yy_subpatterns)
{
$this->token = OQLParser::NOT_LIKE;
$this->token = OQLParser::GT;
}
function yy_r1_25($yy_subpatterns)
{
$this->token = OQLParser::IN;
$this->token = OQLParser::LT;
}
function yy_r1_26($yy_subpatterns)
{
$this->token = OQLParser::NOT_IN;
$this->token = OQLParser::GE;
}
function yy_r1_27($yy_subpatterns)
{
$this->token = OQLParser::INTERVAL;
$this->token = OQLParser::LE;
}
function yy_r1_28($yy_subpatterns)
{
$this->token = OQLParser::F_IF;
$this->token = OQLParser::LIKE;
}
function yy_r1_29($yy_subpatterns)
{
$this->token = OQLParser::F_ELT;
$this->token = OQLParser::NOT_LIKE;
}
function yy_r1_30($yy_subpatterns)
{
$this->token = OQLParser::F_COALESCE;
$this->token = OQLParser::IN;
}
function yy_r1_31($yy_subpatterns)
{
$this->token = OQLParser::F_ISNULL;
$this->token = OQLParser::NOT_IN;
}
function yy_r1_32($yy_subpatterns)
{
$this->token = OQLParser::F_CONCAT;
$this->token = OQLParser::INTERVAL;
}
function yy_r1_33($yy_subpatterns)
{
$this->token = OQLParser::F_SUBSTR;
$this->token = OQLParser::F_IF;
}
function yy_r1_34($yy_subpatterns)
{
$this->token = OQLParser::F_TRIM;
$this->token = OQLParser::F_ELT;
}
function yy_r1_35($yy_subpatterns)
{
$this->token = OQLParser::F_DATE;
$this->token = OQLParser::F_COALESCE;
}
function yy_r1_36($yy_subpatterns)
{
$this->token = OQLParser::F_DATE_FORMAT;
$this->token = OQLParser::F_ISNULL;
}
function yy_r1_37($yy_subpatterns)
{
$this->token = OQLParser::F_CURRENT_DATE;
$this->token = OQLParser::F_CONCAT;
}
function yy_r1_38($yy_subpatterns)
{
$this->token = OQLParser::F_NOW;
$this->token = OQLParser::F_SUBSTR;
}
function yy_r1_39($yy_subpatterns)
{
$this->token = OQLParser::F_TIME;
$this->token = OQLParser::F_TRIM;
}
function yy_r1_40($yy_subpatterns)
{
$this->token = OQLParser::F_TO_DAYS;
$this->token = OQLParser::F_DATE;
}
function yy_r1_41($yy_subpatterns)
{
$this->token = OQLParser::F_FROM_DAYS;
$this->token = OQLParser::F_DATE_FORMAT;
}
function yy_r1_42($yy_subpatterns)
{
$this->token = OQLParser::F_YEAR;
$this->token = OQLParser::F_CURRENT_DATE;
}
function yy_r1_43($yy_subpatterns)
{
$this->token = OQLParser::F_MONTH;
$this->token = OQLParser::F_NOW;
}
function yy_r1_44($yy_subpatterns)
{
$this->token = OQLParser::F_DAY;
$this->token = OQLParser::F_TIME;
}
function yy_r1_45($yy_subpatterns)
{
$this->token = OQLParser::F_HOUR;
$this->token = OQLParser::F_TO_DAYS;
}
function yy_r1_46($yy_subpatterns)
{
$this->token = OQLParser::F_MINUTE;
$this->token = OQLParser::F_FROM_DAYS;
}
function yy_r1_47($yy_subpatterns)
{
$this->token = OQLParser::F_SECOND;
$this->token = OQLParser::F_YEAR;
}
function yy_r1_48($yy_subpatterns)
{
$this->token = OQLParser::F_DATE_ADD;
$this->token = OQLParser::F_MONTH;
}
function yy_r1_49($yy_subpatterns)
{
$this->token = OQLParser::F_DATE_SUB;
$this->token = OQLParser::F_DAY;
}
function yy_r1_50($yy_subpatterns)
{
$this->token = OQLParser::F_ROUND;
$this->token = OQLParser::F_HOUR;
}
function yy_r1_51($yy_subpatterns)
{
$this->token = OQLParser::F_FLOOR;
$this->token = OQLParser::F_MINUTE;
}
function yy_r1_52($yy_subpatterns)
{
$this->token = OQLParser::F_INET_ATON;
$this->token = OQLParser::F_SECOND;
}
function yy_r1_53($yy_subpatterns)
{
$this->token = OQLParser::F_INET_NTOA;
$this->token = OQLParser::F_DATE_ADD;
}
function yy_r1_54($yy_subpatterns)
{
$this->token = OQLParser::BELOW;
$this->token = OQLParser::F_DATE_SUB;
}
function yy_r1_55($yy_subpatterns)
{
$this->token = OQLParser::BELOW_STRICT;
$this->token = OQLParser::F_ROUND;
}
function yy_r1_56($yy_subpatterns)
{
$this->token = OQLParser::NOT_BELOW;
$this->token = OQLParser::F_FLOOR;
}
function yy_r1_57($yy_subpatterns)
{
$this->token = OQLParser::NOT_BELOW_STRICT;
$this->token = OQLParser::F_INET_ATON;
}
function yy_r1_58($yy_subpatterns)
{
$this->token = OQLParser::ABOVE;
$this->token = OQLParser::F_INET_NTOA;
}
function yy_r1_59($yy_subpatterns)
{
$this->token = OQLParser::ABOVE_STRICT;
$this->token = OQLParser::BELOW;
}
function yy_r1_60($yy_subpatterns)
{
$this->token = OQLParser::NOT_ABOVE;
$this->token = OQLParser::BELOW_STRICT;
}
function yy_r1_61($yy_subpatterns)
{
$this->token = OQLParser::NOT_ABOVE_STRICT;
$this->token = OQLParser::NOT_BELOW;
}
function yy_r1_62($yy_subpatterns)
{
$this->token = OQLParser::NUMVAL;
$this->token = OQLParser::NOT_BELOW_STRICT;
}
function yy_r1_63($yy_subpatterns)
{
$this->token = OQLParser::STRVAL;
$this->token = OQLParser::ABOVE;
}
function yy_r1_64($yy_subpatterns)
{
$this->token = OQLParser::NAME;
$this->token = OQLParser::ABOVE_STRICT;
}
function yy_r1_65($yy_subpatterns)
{
$this->token = OQLParser::VARNAME;
$this->token = OQLParser::NOT_ABOVE;
}
function yy_r1_66($yy_subpatterns)
{
$this->token = OQLParser::NOT_ABOVE_STRICT;
}
function yy_r1_67($yy_subpatterns)
{
$this->token = OQLParser::HEXVAL;
}
function yy_r1_68($yy_subpatterns)
{
$this->token = OQLParser::NUMVAL;
}
function yy_r1_69($yy_subpatterns)
{
$this->token = OQLParser::STRVAL;
}
function yy_r1_70($yy_subpatterns)
{
$this->token = OQLParser::NAME;
}
function yy_r1_71($yy_subpatterns)
{
$this->token = OQLParser::VARNAME;
}
function yy_r1_72($yy_subpatterns)
{
$this->token = OQLParser::DOT;

View File

@@ -95,6 +95,11 @@ math_plus = "+"
math_minus = "-"
log_and = "AND"
log_or = "OR"
bitwise_and = "&"
bitwise_or = "|"
bitwise_xor = "^"
bitwise_leftshift = "<<"
bitwise_rightshift = ">>"
regexp = "REGEXP"
eq = "="
not_eq = "!="
@@ -156,8 +161,11 @@ not_above_strict = "NOT ABOVE STRICT"
//
// numval = /([0-9]+|0x[0-9a-fA-F]+)/
// Does not work either, the hexadecimal numbers are not matched properly
// The following seems to work...
numval = /(0x[0-9a-fA-F]+|[0-9]+)/
// Anyhow let's distinguish the hexadecimal values from decimal integers, hex numbers will be stored as strings
// and passed as-is to MySQL which enables us to pass 64-bit values without messing with them in PHP
//
hexval = /(0x[0-9a-fA-F]+)/
numval = /([0-9]+)/
strval = /"([^\\"]|\\"|\\\\)*"|'.chr(94).chr(39).'([^\\'.chr(39).']|\\'.chr(39).'|\\\\)*'.chr(39).'/
name = /([_a-zA-Z][_a-zA-Z0-9]*|`[^`]+`)/
varname = /:([_a-zA-Z][_a-zA-Z0-9]*->[_a-zA-Z][_a-zA-Z0-9]*|[_a-zA-Z][_a-zA-Z0-9]*)/
@@ -204,6 +212,21 @@ log_and {
log_or {
$this->token = OQLParser::LOG_OR;
}
bitwise_or {
$this->token = OQLParser::BITWISE_OR;
}
bitwise_and {
$this->token = OQLParser::BITWISE_AND;
}
bitwise_xor {
$this->token = OQLParser::BITWISE_XOR;
}
bitwise_leftshift {
$this->token = OQLParser::BITWISE_LEFT_SHIFT;
}
bitwise_rightshift {
$this->token = OQLParser::BITWISE_RIGHT_SHIFT;
}
coma {
$this->token = OQLParser::COMA;
}
@@ -351,6 +374,9 @@ not_above {
not_above_strict {
$this->token = OQLParser::NOT_ABOVE_STRICT;
}
hexval {
$this->token = OQLParser::HEXVAL;
}
numval {
$this->token = OQLParser::NUMVAL;
}

File diff suppressed because it is too large Load Diff

View File

@@ -164,19 +164,23 @@ name(A) ::= NAME(X). {
}
A = new OqlName($name, $this->m_iColPrev);
}
num_value(A) ::= NUMVAL(X). {A=X;}
num_value(A) ::= NUMVAL(X). {A=(int)X;}
num_value(A) ::= MATH_MINUS NUMVAL(X). {A=(int)-X;}
num_value(A) ::= HEXVAL(X). {A=new OqlHexValue(X);}
str_value(A) ::= STRVAL(X). {A=stripslashes(substr(X, 1, strlen(X) - 2));}
operator1(A) ::= num_operator1(X). {A=X;}
operator1(A) ::= bitwise_operator1(X). {A=X;}
operator2(A) ::= num_operator2(X). {A=X;}
operator2(A) ::= str_operator(X). {A=X;}
operator2(A) ::= REGEXP(X). {A=X;}
operator2(A) ::= EQ(X). {A=X;}
operator2(A) ::= NOT_EQ(X). {A=X;}
operator3(A) ::= LOG_AND(X). {A=X;}
operator3(A) ::= bitwise_operator3(X). {A=X;}
operator4(A) ::= LOG_OR(X). {A=X;}
operator4(A) ::= bitwise_operator4(X). {A=X;}
num_operator1(A) ::= MATH_DIV(X). {A=X;}
num_operator1(A) ::= MATH_MULT(X). {A=X;}
@@ -190,6 +194,12 @@ num_operator2(A) ::= LE(X). {A=X;}
str_operator(A) ::= LIKE(X). {A=X;}
str_operator(A) ::= NOT_LIKE(X). {A=X;}
bitwise_operator1(A) ::= BITWISE_LEFT_SHIFT(X). {A=X;}
bitwise_operator1(A) ::= BITWISE_RIGHT_SHIFT(X). {A=X;}
bitwise_operator3(A) ::= BITWISE_AND(X). {A=X;}
bitwise_operator4(A) ::= BITWISE_OR(X). {A=X;}
bitwise_operator4(A) ::= BITWISE_XOR(X). {A=X;}
list_operator(A) ::= IN(X). {A=X;}
list_operator(A) ::= NOT_IN(X). {A=X;}

View File

@@ -54,6 +54,27 @@ class OqlName
}
}
/**
*
* Store hexadecimal values as strings so that we can support 64-bit values
*
*/
class OqlHexValue
{
protected $m_sValue;
public function __construct($sValue)
{
$this->m_sValue = $sValue;
}
public function __toString()
{
return $this->m_sValue;
}
}
class OqlJoinSpec
{
protected $m_oClass;

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2012 Combodo SARL
// Copyright (C) 2010-2013 Combodo SARL
//
// This file is part of iTop.
//
@@ -162,8 +162,7 @@ class ormStopWatch
}
else
{
$iElapsedTemp = ''; //$this->ComputeDuration($oHostObject, $oAttDef, $this->iLastStart, time());
$aProperties['Elapsed'] = $this->iTimeSpent.' + '.$iElapsedTemp.' s + <img src="../images/indicator.gif">';
$aProperties['Elapsed'] = 'running <img src="../images/indicator.gif">';
}
$aProperties['Started'] = $oAttDef->SecondsToDate($this->iStarted);
@@ -183,7 +182,7 @@ class ormStopWatch
}
$aProperties[$iPercent.'%'] = $sThresholdDesc;
}
$sRes = "<TABLE class=\"listResults\">";
$sRes = "<TABLE>";
$sRes .= "<TBODY>";
foreach ($aProperties as $sProperty => $sValue)
{
@@ -387,6 +386,7 @@ class CheckStopWatchThresholds implements iBackgroundProcess
public function Process($iTimeLimit)
{
$aList = array();
foreach (MetaModel::GetClasses() as $sClass)
{
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
@@ -397,17 +397,15 @@ class CheckStopWatchThresholds implements iBackgroundProcess
{
$iPercent = $aThresholdData['percent']; // could be different than the index !
$sExpression = "SELECT $sClass WHERE {$sAttCode}_laststart AND {$sAttCode}_{$iThreshold}_triggered = 0 AND {$sAttCode}_{$iThreshold}_deadline < NOW()";
//echo $sExpression."<br/>\n";
$sNow = date('Y-m-d H:i:s');
$sExpression = "SELECT $sClass WHERE {$sAttCode}_laststart AND {$sAttCode}_{$iThreshold}_triggered = 0 AND {$sAttCode}_{$iThreshold}_deadline < '$sNow'";
$oFilter = DBObjectSearch::FromOQL($sExpression);
$aList = array();
$oSet = new DBObjectSet($oFilter);
while ((time() < $iTimeLimit) && ($oObj = $oSet->Fetch()))
{
$sClass = get_class($oObj);
$aList[] = $sClass.'::'.$oObj->GetKey().' '.$sAttCode.' '.$iThreshold;
//echo $sClass.'::'.$oObj->GetKey().' '.$sAttCode.' '.$iThreshold."\n";
// Execute planned actions
//
@@ -416,7 +414,6 @@ class CheckStopWatchThresholds implements iBackgroundProcess
$sVerb = $aActionData['verb'];
$aParams = $aActionData['params'];
$sParams = implode(', ', $aParams);
//echo "Calling: $sVerb($sParams)<br/>\n";
$aCallSpec = array($oObj, $sVerb);
call_user_func_array($aCallSpec, $aParams);
}
@@ -438,12 +435,12 @@ class CheckStopWatchThresholds implements iBackgroundProcess
// Activate any existing trigger
//
$sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
$oSet = new DBObjectSet(
$oTriggerSet = new DBObjectSet(
DBObjectSearch::FromOQL("SELECT TriggerOnThresholdReached AS t WHERE t.target_class IN ('$sClassList') AND stop_watch_code=:stop_watch_code AND threshold_index = :threshold_index"),
array(), // order by
array('stop_watch_code' => $sAttCode, 'threshold_index' => $iThreshold)
);
while ($oTrigger = $oSet->Fetch())
while ($oTrigger = $oTriggerSet->Fetch())
{
$oTrigger->DoActivate($oObj->ToArgs('this'));
}
@@ -454,9 +451,6 @@ class CheckStopWatchThresholds implements iBackgroundProcess
}
$iProcessed = count($aList);
return "Triggered $iProcessed threshold(s)";
return "Triggered $iProcessed threshold(s):".implode(", ", $aList);
}
}
?>

View File

@@ -0,0 +1,595 @@
<?php
// Copyright (C) 2013 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/>
/**
* REST/json services
*
* Definition of common structures + the very minimum service provider (manage objects)
*
* @package REST Services
* @copyright Copyright (C) 2013 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
* @api
*/
/**
* Element of the response formed by RestResultWithObjects
*
* @package REST Services
*/
class ObjectResult
{
public $code;
public $message;
public $fields;
/**
* Default constructor
*/
public function __construct()
{
$this->code = RestResult::OK;
$this->message = '';
$this->fields = array();
}
/**
* Helper to make an output value for a given attribute
*
* @param DBObject $oObject The object being reported
* @param string $sAttCode The attribute code (must be valid)
* @return string A scalar representation of the value
*/
protected function MakeResultValue(DBObject $oObject, $sAttCode)
{
if ($sAttCode == 'id')
{
$value = $oObject->GetKey();
}
else
{
$sClass = get_class($oObject);
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef instanceof AttributeLinkedSet)
{
$value = array();
// Make the list of required attributes
// - Skip attributes pointing to the current object (redundant data)
// - Skip link sets refering to the current data (infinite recursion!)
$aRelevantAttributes = array();
$sLnkClass = $oAttDef->GetLinkedClass();
foreach (MetaModel::ListAttributeDefs($sLnkClass) as $sLnkAttCode => $oLnkAttDef)
{
// Skip any attribute of the link that points to the current object
//
if ($sLnkAttCode == $oAttDef->GetExtKeyToMe()) continue;
if (method_exists($oLnkAttDef, 'GetKeyAttCode'))
{
if ($oLnkAttDef->GetKeyAttCode() ==$oAttDef->GetExtKeyToMe()) continue;
}
$aRelevantAttributes[] = $sLnkAttCode;
}
// Iterate on the set and build an array of array of attcode=>value
$oSet = $oObject->Get($sAttCode);
while ($oLnk = $oSet->Fetch())
{
$aLnkValues = array();
foreach ($aRelevantAttributes as $sLnkAttCode)
{
$aLnkValues[$sLnkAttCode] = $this->MakeResultValue($oLnk, $sLnkAttCode);
}
$value[] = $aLnkValues;
}
}
else
{
$value = $oAttDef->GetForJSON($oObject->Get($sAttCode));
}
}
return $value;
}
/**
* Report the value for the given object attribute
*
* @param DBObject $oObject The object being reported
* @param string $sAttCode The attribute code (must be valid)
* @return void
*/
public function AddField(DBObject $oObject, $sAttCode)
{
$this->fields[$sAttCode] = $this->MakeResultValue($oObject, $sAttCode);
}
}
/**
* REST response for services managing objects. Derive this structure to add information and/or constants
*
* @package Extensibility
* @package REST Services
* @api
*/
class RestResultWithObjects extends RestResult
{
public $objects;
/**
* Report the given object
*
* @param int An error code (RestResult::OK is no issue has been found)
* @param string $sMessage Description of the error if any, an empty string otherwise
* @param DBObject $oObject The object being reported
* @param array $aFields An array of attribute codes. List of the attributes to be reported.
* @return void
*/
public function AddObject($iCode, $sMessage, $oObject, $aFields)
{
$oObjRes = new ObjectResult();
$oObjRes->code = $iCode;
$oObjRes->message = $sMessage;
$oObjRes->class = get_class($oObject);
foreach ($aFields as $sAttCode)
{
$oObjRes->AddField($oObject, $sAttCode);
}
$sObjKey = get_class($oObject).'::'.$oObject->GetKey();
$this->objects[$sObjKey] = $oObjRes;
}
}
class RestResultWithRelations extends RestResultWithObjects
{
public $relations;
public function __construct()
{
parent::__construct();
$this->relations = array();
}
public function AddRelation($sSrcKey, $sDestKey)
{
if (!array_key_exists($sSrcKey, $this->relations))
{
$this->relations[$sSrcKey] = array();
}
$this->relations[$sSrcKey][] = array('key' => $sDestKey);
}
}
/**
* Deletion result codes for a target object (either deleted or updated)
*
* @package Extensibility
* @api
* @since 2.0.1
*/
class RestDelete
{
/**
* Result: Object deleted as per the initial request
*/
const OK = 0;
/**
* Result: general issue (user rights or ... ?)
*/
const ISSUE = 1;
/**
* Result: Must be deleted to preserve database integrity
*/
const AUTO_DELETE = 2;
/**
* Result: Must be deleted to preserve database integrity, but that is NOT possible
*/
const AUTO_DELETE_ISSUE = 3;
/**
* Result: Must be deleted to preserve database integrity, but this must be requested explicitely
*/
const REQUEST_EXPLICITELY = 4;
/**
* Result: Must be updated to preserve database integrity
*/
const AUTO_UPDATE = 5;
/**
* Result: Must be updated to preserve database integrity, but that is NOT possible
*/
const AUTO_UPDATE_ISSUE = 6;
}
/**
* Implementation of core REST services (create/get/update... objects)
*
* @package Core
*/
class CoreServices implements iRestServiceProvider
{
/**
* Enumerate services delivered by this class
*
* @param string $sVersion The version (e.g. 1.0) supported by the services
* @return array An array of hash 'verb' => verb, 'description' => description
*/
public function ListOperations($sVersion)
{
$aOps = array();
if ($sVersion == '1.0')
{
$aOps[] = array(
'verb' => 'core/create',
'description' => 'Create an object'
);
$aOps[] = array(
'verb' => 'core/update',
'description' => 'Update an object'
);
$aOps[] = array(
'verb' => 'core/apply_stimulus',
'description' => 'Apply a stimulus to change the state of an object'
);
$aOps[] = array(
'verb' => 'core/get',
'description' => 'Search for objects'
);
$aOps[] = array(
'verb' => 'core/delete',
'description' => 'Delete objects'
);
$aOps[] = array(
'verb' => 'core/get_related',
'description' => 'Get related objects through the specified relation'
);
}
return $aOps;
}
/**
* Enumerate services delivered by this class
* @param string $sVersion The version (e.g. 1.0) supported by the services
* @return RestResult The standardized result structure (at least a message)
* @throws Exception in case of internal failure.
*/
public function ExecOperation($sVersion, $sVerb, $aParams)
{
$oResult = new RestResultWithObjects();
switch ($sVerb)
{
case 'core/create':
RestUtils::InitTrackingComment($aParams);
$sClass = RestUtils::GetClass($aParams, 'class');
$aFields = RestUtils::GetMandatoryParam($aParams, 'fields');
$aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields');
$oObject = RestUtils::MakeObjectFromFields($sClass, $aFields);
$oObject->DBInsert();
$oResult->AddObject(0, 'created', $oObject, $aShowFields);
break;
case 'core/update':
RestUtils::InitTrackingComment($aParams);
$sClass = RestUtils::GetClass($aParams, 'class');
$key = RestUtils::GetMandatoryParam($aParams, 'key');
$aFields = RestUtils::GetMandatoryParam($aParams, 'fields');
$aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields');
$oObject = RestUtils::FindObjectFromKey($sClass, $key);
RestUtils::UpdateObjectFromFields($oObject, $aFields);
$oObject->DBUpdate();
$oResult->AddObject(0, 'updated', $oObject, $aShowFields);
break;
case 'core/apply_stimulus':
RestUtils::InitTrackingComment($aParams);
$sClass = RestUtils::GetClass($aParams, 'class');
$key = RestUtils::GetMandatoryParam($aParams, 'key');
$aFields = RestUtils::GetMandatoryParam($aParams, 'fields');
$aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields');
$sStimulus = RestUtils::GetMandatoryParam($aParams, 'stimulus');
$oObject = RestUtils::FindObjectFromKey($sClass, $key);
RestUtils::UpdateObjectFromFields($oObject, $aFields);
$aTransitions = $oObject->EnumTransitions();
$aStimuli = MetaModel::EnumStimuli(get_class($oObject));
if (!isset($aTransitions[$sStimulus]))
{
// Invalid stimulus
$oResult->code = RestResult::INTERNAL_ERROR;
$oResult->message = "Invalid stimulus: '$sStimulus' on the object ".$oObject->GetName()." in state '".$oObject->GetState()."'";
}
else
{
$aTransition = $aTransitions[$sStimulus];
$sTargetState = $aTransition['target_state'];
$aStates = MetaModel::EnumStates($sClass);
$aTargetStateDef = $aStates[$sTargetState];
$aExpectedAttributes = $aTargetStateDef['attribute_list'];
$aMissingMandatory = array();
foreach($aExpectedAttributes as $sAttCode => $iExpectCode)
{
if ( ($iExpectCode & OPT_ATT_MANDATORY) && ($oObject->Get($sAttCode) == ''))
{
$aMissingMandatory[] = $sAttCode;
}
}
if (count($aMissingMandatory) == 0)
{
// If all the mandatory fields are already present, just apply the transition silently...
if ($oObject->ApplyStimulus($sStimulus))
{
$oObject->DBUpdate();
$oResult->AddObject(0, 'updated', $oObject, $aShowFields);
}
}
else
{
// Missing mandatory attributes for the transition
$oResult->code = RestResult::INTERNAL_ERROR;
$oResult->message = 'Missing mandatory attribute(s) for applying the stimulus: '.implode(', ', $aMissingMandatory).'.';
}
}
break;
case 'core/get':
$sClass = RestUtils::GetClass($aParams, 'class');
$key = RestUtils::GetMandatoryParam($aParams, 'key');
$aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields');
$oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key);
while ($oObject = $oObjectSet->Fetch())
{
$oResult->AddObject(0, '', $oObject, $aShowFields);
}
$oResult->message = "Found: ".$oObjectSet->Count();
break;
case 'core/delete':
$sClass = RestUtils::GetClass($aParams, 'class');
$key = RestUtils::GetMandatoryParam($aParams, 'key');
$bSimulate = RestUtils::GetOptionalParam($aParams, 'simulate', false);
$oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key);
$aObjects = $oObjectSet->ToArray();
$this->DeleteObjects($oResult, $aObjects, $bSimulate);
break;
case 'core/get_related':
$oResult = new RestResultWithRelations();
$sClass = RestUtils::GetClass($aParams, 'class');
$key = RestUtils::GetMandatoryParam($aParams, 'key');
$sRelation = RestUtils::GetMandatoryParam($aParams, 'relation');
$iMaxRecursionDepth = RestUtils::GetOptionalParam($aParams, 'depth', 20 /* = MAX_RECURSION_DEPTH */);
$aShowFields = array('id', 'friendlyname');
$oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key);
$aIndexByClass = array();
while ($oObject = $oObjectSet->Fetch())
{
$aRelated = array();
$aGraph = array();
$aIndexByClass[get_class($oObject)][$oObject->GetKey()] = null;
$oResult->AddObject(0, '', $oObject, $aShowFields);
$this->GetRelatedObjects($oObject, $sRelation, $iMaxRecursionDepth, $aRelated, $aGraph);
foreach($aRelated as $sClass => $aObjects)
{
foreach($aObjects as $oRelatedObj)
{
$aIndexByClass[get_class($oRelatedObj)][$oRelatedObj->GetKey()] = null;
$oResult->AddObject(0, '', $oRelatedObj, $aShowFields);
}
}
foreach($aGraph as $sSrcKey => $aDestinations)
{
foreach ($aDestinations as $sDestKey)
{
$oResult->AddRelation($sSrcKey, $sDestKey);
}
}
}
if (count($aIndexByClass) > 0)
{
$aStats = array();
foreach ($aIndexByClass as $sClass => $aIds)
{
$aStats[] = $sClass.'= '.count($aIds);
}
$oResult->message = "Scope: ".$oObjectSet->Count()."; Related objects: ".implode(', ', $aStats);
}
else
{
$oResult->message = "Nothing found";
}
break;
default:
// unknown operation: handled at a higher level
}
return $oResult;
}
/**
* Helper for object deletion
*/
public function DeleteObjects($oResult, $aObjects, $bSimulate)
{
$oDeletionPlan = new DeletionPlan();
foreach($aObjects as $oObj)
{
if ($bSimulate)
{
$oObj->CheckToDelete($oDeletionPlan);
}
else
{
$oObj->DBDelete($oDeletionPlan);
}
}
foreach ($oDeletionPlan->ListDeletes() as $sTargetClass => $aDeletes)
{
foreach ($aDeletes as $iId => $aData)
{
$oToDelete = $aData['to_delete'];
$bAutoDel = (($aData['mode'] == DEL_SILENT) || ($aData['mode'] == DEL_AUTO));
if (array_key_exists('issue', $aData))
{
if ($bAutoDel)
{
if (isset($aData['requested_explicitely'])) // i.e. in the initial list of objects to delete
{
$iCode = RestDelete::ISSUE;
$sPlanned = 'Cannot be deleted: '.$aData['issue'];
}
else
{
$iCode = RestDelete::AUTO_DELETE_ISSUE;
$sPlanned = 'Should be deleted automatically... but: '.$aData['issue'];
}
}
else
{
$iCode = RestDelete::REQUEST_EXPLICITELY;
$sPlanned = 'Must be deleted explicitely... but: '.$aData['issue'];
}
}
else
{
if ($bAutoDel)
{
if (isset($aData['requested_explicitely']))
{
$iCode = RestDelete::OK;
$sPlanned = '';
}
else
{
$iCode = RestDelete::AUTO_DELETE;
$sPlanned = 'Deleted automatically';
}
}
else
{
$iCode = RestDelete::REQUEST_EXPLICITELY;
$sPlanned = 'Must be deleted explicitely';
}
}
$oResult->AddObject($iCode, $sPlanned, $oToDelete, array('id', 'friendlyname'));
}
}
foreach ($oDeletionPlan->ListUpdates() as $sRemoteClass => $aToUpdate)
{
foreach ($aToUpdate as $iId => $aData)
{
$oToUpdate = $aData['to_reset'];
if (array_key_exists('issue', $aData))
{
$iCode = RestDelete::AUTO_UPDATE_ISSUE;
$sPlanned = 'Should be updated automatically... but: '.$aData['issue'];
}
else
{
$iCode = RestDelete::AUTO_UPDATE;
$sPlanned = 'Reset external keys: '.$aData['attributes_list'];
}
$oResult->AddObject($iCode, $sPlanned, $oToUpdate, array('id', 'friendlyname'));
}
}
if ($oDeletionPlan->FoundStopper())
{
if ($oDeletionPlan->FoundSecurityIssue())
{
$iRes = RestResult::UNAUTHORIZED;
$sRes = 'Deletion not allowed on some objects';
}
elseif ($oDeletionPlan->FoundManualOperation())
{
$iRes = RestResult::UNSAFE;
$sRes = 'The deletion requires that other objects be deleted/updated, and those operations must be requested explicitely';
}
else
{
$iRes = RestResult::INTERNAL_ERROR;
$sRes = 'Some issues have been encountered. See the list of planned changes for more information about the issue(s).';
}
}
else
{
$iRes = RestResult::OK;
$sRes = 'Deleted: '.count($aObjects);
$iIndirect = $oDeletionPlan->GetTargetCount() - count($aObjects);
if ($iIndirect > 0)
{
$sRes .= ' plus (for DB integrity) '.$iIndirect;
}
}
$oResult->code = $iRes;
if ($bSimulate)
{
$oResult->message = 'SIMULATING: '.$sRes;
}
else
{
$oResult->message = $sRes;
}
}
/**
* Helper function to get the related objects up to the given depth along with the "graph" of the relation
* @param DBObject $oObject Starting point of the computation
* @param string $sRelation Code of the relation (i.e; 'impact', 'depends on'...)
* @param integer $iMaxRecursionDepth Maximum level of recursion
* @param Hash $aRelated Two dimensions hash of the already related objects: array( 'class' => array(key => ))
* @param Hash $aGraph Hash array for the topology of the relation: source => related: array('class:key' => array( DBObjects ))
* @param integer $iRecursionDepth Current level of recursion
*/
protected function GetRelatedObjects(DBObject $oObject, $sRelation, $iMaxRecursionDepth, &$aRelated, &$aGraph, $iRecursionDepth = 1)
{
// Avoid loops
if ((array_key_exists(get_class($oObject), $aRelated)) && (array_key_exists($oObject->GetKey(), $aRelated[get_class($oObject)]))) return;
// Stop at maximum recursion level
if ($iRecursionDepth > $iMaxRecursionDepth) return;
$sSrcKey = get_class($oObject).'::'.$oObject->GetKey();
$aNewRelated = array();
$oObject->GetRelatedObjects($sRelation, 1, $aNewRelated);
foreach($aNewRelated as $sClass => $aObjects)
{
if (!array_key_exists($sSrcKey, $aGraph))
{
$aGraph[$sSrcKey] = array();
}
foreach($aObjects as $oRelatedObject)
{
$aRelated[$sClass][$oRelatedObject->GetKey()] = $oRelatedObject;
$aGraph[$sSrcKey][] = get_class($oRelatedObject).'::'.$oRelatedObject->GetKey();
$this->GetRelatedObjects($oRelatedObject, $sRelation, $iMaxRecursionDepth, $aRelated, $aGraph, $iRecursionDepth+1);
}
}
}
}

View File

@@ -76,6 +76,19 @@ abstract class Trigger extends cmdbAbstractObject
}
}
}
/**
* Check whether the given object is in the scope of this trigger
* and can potentially be the subject of notifications
* @param DBObject $oObject The object to check
* @return bool
*/
public function IsInScope(DBObject $oObject)
{
// By default the answer is no
// Overload this function in your own derived class for a different behavior
return false;
}
}
abstract class TriggerOnObject extends Trigger
@@ -105,6 +118,18 @@ abstract class TriggerOnObject extends Trigger
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
/**
* Check whether the given object is in the scope of this trigger
* and can potentially be the subject of notifications
* @param DBObject $oObject The object to check
* @return bool
*/
public function IsInScope(DBObject $oObject)
{
$sRootClass = $this->Get('target_class');
return ($oObject instanceof $sRootClass);
}
}
/**
* To trigger notifications when a ticket is updated from the portal

View File

@@ -8,6 +8,11 @@ body {
overflow: hidden; /* Remove scroll bars on browser window */
}
/* to prevent flicker, hide the pane's content until it's ready */
.ui-layout-center, .ui-layout-north, .ui-layout-south {
display: none;
}
.raw_output {
font-family: Courier-New, Courier, Arial, Helvetica;
font-size: 8pt;
@@ -1102,9 +1107,6 @@ table.pagination tr td {
.pagination_container {
padding-left: 3px;
}
.pager {
display:inline-block;
}
.pager p {
margin-top: 0;
margin-bottom: 0;

View File

@@ -1,15 +1,15 @@
@CHARSET "UTF-8";
#left-pane { display: none; }
span.ui-layout-resizer { display: none; }
#header-logo { display: none; }
#logo { display: none; }
div.header-menu { display:none; }
div.footer { display:none; }
#top-bar { display: none; }
#menu { display: none; }
#inner_menu { display: none; }
div.actions_button { display:none; }
div.itop_popup { display:none; }
div.HRDrawer { display:none; }
div.DrawerHandle { display:none; }
a.tab { display:none; }
div.itop-tab { border: #ccc 1px solid; margin-top: 1em; padding-bottom:1em; }
div.itop-tab { border: #ccc 1px solid; margin-top: 1em; padding-bottom:1em; }
#combodo_logo { display:none; };

View File

@@ -350,7 +350,8 @@ EOF
$oPage->add('</span>');
$oPage->add('<div style="clear:both"></div>');
$sMaxUpload = $this->GetMaxUpload();
$oPage->p(Dict::S('Attachments:AddAttachment').'<input type="file" name="file" id="file" onChange="ajaxFileUpload();"><span style="display:none;" id="attachment_loading">&nbsp;<img src="../images/indicator.gif"></span> '.$sMaxUpload);
$oPage->p(Dict::S('Attachments:AddAttachment').'<input type="file" name="file" id="file"><span style="display:none;" id="attachment_loading">&nbsp;<img src="../images/indicator.gif"></span> '.$sMaxUpload);
$oPage->add_ready_script('$("#file").off("change.itop-attachments").on("change.itop-attachments", function() {ajaxFileUpload();});'); // Workaround for a Chrome 36 bug causing multiple (12!) times the same upload. See http://www.redmine.org/issues/17151
$oPage->p('<span style="display:none;" id="attachment_loading">Loading, please wait...</span>');
$oPage->p('<input type="hidden" id="attachment_plugin" name="attachment_plugin"/>');
$oPage->add('</fieldset>');

View File

@@ -45,8 +45,7 @@ SetupWebPage::AddModule(
),
'dictionary' => array(
'en.dict.attachments.php',
'fr.dict.attachments.php',
),
'data.struct' => array(
// add your 'structure' definition XML files here,

View File

@@ -1277,14 +1277,15 @@
<type>Overload-cmdbAbstractObject</type>
<code><![CDATA[ public function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
{
$aFieldsMap = parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams);
if (!$bEditMode)
{
$oPage->SetCurrentTab(Dict::S('Class:Document:PreviewTab'));
$oPage->add('<fieldset>');
$oPage->add('<legend>'.Dict::S('Class:Document:PreviewTab').'</legend>');
$oPage->add($this->DisplayDocumentInline($oPage, 'contents'));
$oPage->SetCurrentTab(Dict::S('UI:PropertiesTab'));
$oPage->add('</fieldset>');
}
parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams);
return $aFieldsMap;
}]]></code>
</method>
</methods>

View File

@@ -553,7 +553,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Class:Document/Attribute:service_list+' => 'Services liés à ce document',
'Class:Document/Attribute:ticket_list' => 'Tickets',
'Class:Document/Attribute:ticket_list+' => 'Tickets liés à ce document',
'Class:Document:PreviewTab' => 'Entrevue',
'Class:Document:PreviewTab' => 'Aperçu',
'Class:Subnet/Name' => '%1$s / %2$s',
'Class:Software' => 'Logiciel',
'Class:Software+' => '',

View File

@@ -571,6 +571,11 @@
</group>
</groups>
</profile>
<profile id="12" _delta="define">
<name>Portal power user</name>
<description>Users having this profile will have the rights to see all the tickets for a customer in the portal. This profile must be used in conjunction with other profiles (e.g. Portal User or Administrator).</description>
<groups/>
</profile>
</profiles>
</user_rights>
</itop_design>

View File

@@ -16,6 +16,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('PORTAL_POWER_USER_PROFILE', 'Portal power user');
define('PORTAL_SERVICECATEGORY_QUERY', 'SELECT Service AS s JOIN SLA AS sla ON sla.service_id=s.id JOIN lnkContractToSLA AS ln ON ln.sla_id=sla.id JOIN CustomerContract AS cc ON ln.contract_id=cc.id WHERE cc.org_id = :org_id');
define('PORTAL_SERVICE_SUBCATEGORY_QUERY', 'SELECT ServiceSubcategory WHERE service_id = :svc_id');
@@ -32,4 +33,11 @@ define('PORTAL_REQUEST_FORM_ATTRIBUTES', 'title,description,impact,urgency,workg
define('PORTAL_ATTCODE_TYPE', ''); // optional if the type has to be set
define('PORTAL_SET_TYPE_FROM', ''); // The attribute to get the type from (Subcategory)
define('PORTAL_TICKETS_LIST_ZLIST', 'finalclass,title,start_date,status,servicesubcategory_id,priority,caller_id');
define('PORTAL_TICKETS_SEARCH_CRITERIA','ref,start_date,close_date,service_id,caller_id');
define('PORTAL_TICKETS_CLOSED_ZLIST', 'title,start_date,close_date,servicesubcategory_id');
// json encoded lists for the portal...
define('PORTAL_TICKET_DETAILS_ZLIST', '{"col:left":["ref","caller_id","servicesubcategory_id","title","description","solution"],"col:right":["status","priority","start_date","resolution_date","last_update","agent_id"]}');
?>

View File

@@ -39,7 +39,7 @@
//
Dict::Add('ES CR', 'Spanish', 'Español, Castellaño', array(
'Class:UserExternal' => 'Usuario Externo (Webserver)',
'Class:UserExternal' => 'Usuario Externo',
'Class:UserExternal+' => 'Usuario Autenticado fuera de iTop',
));

View File

@@ -39,8 +39,7 @@
//
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:UserInternal' => 'Usuario Interno',
'Class:UserLDAP' => 'Usuario LDAP',
'Class:UserLDAP' => 'Usuario LDAP',
'Class:UserLDAP+' => 'Usuario Autenticado vía LDAP',
'Class:UserLDAP/Attribute:password' => 'Contrase&ntilde;a',
'Class:UserLDAP/Attribute:password+' => 'Contrase&ntilde;a',

View File

@@ -22,8 +22,6 @@
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
// Dictionnay conventions
@@ -41,7 +39,6 @@
//
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:UserInternal' => 'Usuario Interno',
'Class:UserLocal' => 'Usuario de iTop',
'Class:UserLocal+' => 'Usuario Autenticado vía iTop',
'Class:UserLocal/Attribute:password' => 'Contrase&ntilde;a',

View File

@@ -1,42 +0,0 @@
<?php
// Copyright (C) 2010-2012 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/>
/**
* Localized data
*
* @author Stephan Rosenke <stephan.rosenke@itomig.de>
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('DE DE', 'German', 'Deutsch', array(
'Attachments:TabTitle_Count' => 'Attachments (%1$d)',
'Attachments:EmptyTabTitle' => 'Attachments',
'Attachments:FieldsetTitle' => 'Attachments',
'Attachments:DeleteBtn' => 'Löschen',
'Attachments:History_File_Added' => 'Attachment %1$s hinzugefügt.',
'Attachments:History_File_Removed' => 'Attachment %1$s entfernt.',
'Attachments:AddAttachment' => 'Attachment hinzufügen: ',
'Attachments:UploadNotAllowedOnThisSystem' => 'Datei-Upload auf diesem System NICHT erlaubt.',
'Attachment:Max_Go' => '(Maximale Datei-Größe: %1$s Go)',
'Attachment:Max_Mo' => '(Maximale Datei-Größe: %1$s Mo)',
'Attachment:Max_Ko' => '(Maximale Datei-Größe: %1$s Ko)',
'Attachments:NoAttachment' => 'Kein Attachment.',
));
?>

View File

@@ -1,38 +0,0 @@
<?php
// Copyright (C) 2010-2012 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/>
/**
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @licence http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Attachments:TabTitle_Count' => '添付 (%1$d)',
'Attachments:EmptyTabTitle' => '添付',
'Attachments:FieldsetTitle' => '添付',
'Attachments:DeleteBtn' => '削除',
'Attachments:History_File_Added' => '添付 %1$s を追加しました。',
'Attachments:History_File_Removed' => '添付 %1$s を削除しました。',
'Attachments:AddAttachment' => '添付追加: ',
'Attachments:UploadNotAllowedOnThisSystem' => 'このシステムでは、ファイルのアップロードは許可されていません。',
'Attachment:Max_Go' => '(最大ファイルサイズ: %1$s GB)',
'Attachment:Max_Mo' => '(最大ファイルサイズ: %1$s MB)',
'Attachment:Max_Ko' => '(最大ファイルサイズ: %1$s KB)',
'Attachments:NoAttachment' => '添付はありません。',
));
?>

View File

@@ -35,4 +35,4 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'Attachment:Max_Ko' => '(最大ファイルサイズ: %1$s KB)',
'Attachments:NoAttachment' => '添付はありません。',
));
?>
?>

View File

@@ -350,7 +350,8 @@ EOF
$oPage->add('</span>');
$oPage->add('<div style="clear:both"></div>');
$sMaxUpload = $this->GetMaxUpload();
$oPage->p(Dict::S('Attachments:AddAttachment').'<input type="file" name="file" id="file" onChange="ajaxFileUpload();"><span style="display:none;" id="attachment_loading">&nbsp;<img src="../images/indicator.gif"></span> '.$sMaxUpload);
$oPage->p(Dict::S('Attachments:AddAttachment').'<input type="file" name="file" id="file"><span style="display:none;" id="attachment_loading">&nbsp;<img src="../images/indicator.gif"></span> '.$sMaxUpload);
$oPage->add_ready_script('$("#file").off("change.itop-attachments").on("change.itop-attachments", function() {ajaxFileUpload();});'); // Workaround for a Chrome 36 bug causing multiple (12!) times the same upload. See http://www.redmine.org/issues/17151
$oPage->p('<span style="display:none;" id="attachment_loading">Loading, please wait...</span>');
$oPage->p('<input type="hidden" id="attachment_plugin" name="attachment_plugin"/>');
$oPage->add('</fieldset>');

View File

@@ -45,8 +45,7 @@ SetupWebPage::AddModule(
),
'dictionary' => array(
'en.dict.attachments.php',
'fr.dict.attachments.php',
),
'data.struct' => array(
// add your 'structure' definition XML files here,

View File

@@ -1102,7 +1102,7 @@
</item>
</items>
</item>
<item id="fieldset:Relations">
<item id="fieldset:Ticket:relation">
<rank>20</rank>
<items>
<item id="parent_id">
@@ -2093,7 +2093,7 @@
</item>
</items>
</item>
<item id="fieldset:Relations">
<item id="fieldset:Ticket:relation">
<rank>20</rank>
<items>
<item id="parent_id">
@@ -3082,7 +3082,7 @@
</item>
</items>
</item>
<item id="fieldset:Relations">
<item id="fieldset:Ticket:relation">
<rank>20</rank>
<items>
<item id="parent_id">
@@ -4215,7 +4215,7 @@
</item>
</items>
</item>
<item id="fieldset:Relations">
<item id="fieldset:Ticket:relation">
<rank>20</rank>
<items>
<item id="parent_id">
@@ -5290,7 +5290,7 @@
</item>
</items>
</item>
<item id="fieldset:Relations">
<item id="fieldset:Ticket:relation">
<rank>20</rank>
<items>
<item id="parent_id">

View File

@@ -32,8 +32,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Menu:NewChange+' => 'Crear Ticket de Cambio',
'Menu:SearchChanges' => 'Búsqueda de Cambios',
'Menu:SearchChanges+' => 'Búsqueda de Tickets de Cambios',
'Menu:Change:Shortcuts' => 'Acceso Rápido',
'Menu:Change:Shortcuts+' => 'Acceso Rápido',
'Menu:Change:Shortcuts' => 'Accesos Rápidos',
'Menu:Change:Shortcuts+' => 'Accesos Rápidos',
'Menu:WaitingAcceptance' => 'Cambios Esperando ser Aceptados',
'Menu:WaitingAcceptance+' => 'Cambios Esperando ser Aceptados',
'Menu:WaitingApproval' => 'Cambios Esperando ser Aprobados',
@@ -134,8 +134,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Change/Attribute:related_incident_list+' => 'Incidentes Relacionados',
'Class:Change/Attribute:child_changes_list' => 'Cambios Hijo',
'Class:Change/Attribute:child_changes_list+' => 'Cambios Hijo',
'Class:Change/Attribute:parent_id_friendlyname' => 'Parent friendly name',
'Class:Change/Attribute:parent_id_friendlyname+' => 'Parent friendly name',
'Class:Change/Attribute:parent_id_friendlyname' => 'Nombre del Padre',
'Class:Change/Attribute:parent_id_friendlyname+' => 'Nombre del Padre',
'Class:Change/Attribute:parent_id_finalclass_recall' => 'Tipo de Cambio',
'Class:Change/Attribute:parent_id_finalclass_recall+' => 'Tipo de Cambio',
'Class:Change/Stimulus:ev_validate' => 'Validar',

View File

@@ -1,295 +1,245 @@
<?php
// Copyright (C) 2010-2012 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/>
/**
* Localized data
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('JA JP', 'Japanese', '日本語', array (
'Menu:ChangeManagement' => '変更管理',
'Menu:Change:Overview' => '概要',
'Menu:Change:Overview+' => '',
'Menu:NewChange' => '新規変更',
'Menu:NewChange+' => '新規変更のチケット作成',
'Menu:SearchChanges' => '変更検索',
'Menu:SearchChanges+' => '変更チケット検索',
'Menu:Change:Shortcuts' => 'ショートカット',
'Menu:Change:Shortcuts+' => '',
'Menu:WaitingAcceptance' => '受理待ちの変更',
'Menu:WaitingAcceptance+' => '',
'Menu:WaitingApproval' => '承認待ちの変更',
'Menu:WaitingApproval+' => '',
'Menu:Changes' => 'オープン状態の変更',
'Menu:Changes+' => '',
'Menu:MyChanges' => '担当している変更',
'Menu:MyChanges+' => '担当している変更(エージェントとして)',
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => '最近7日間のカテゴリ別の変更',
'UI-ChangeManagementOverview-Last-7-days' => '最近7日間の変更数',
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => '最近7日間のドメイン別変更',
'UI-ChangeManagementOverview-ChangeByStatus-last-7-days' => '最近7日間の状態別変更',
));
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
// Class:<class_name>/Attribute:<attribute_code>
// Class:<class_name>/Attribute:<attribute_code>+
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//
// Class: Change
//
Dict::Add('JA JP', 'Japanese', '日本語', array (
'Class:Change' => '変更',
'Class:Change+' => '',
'Class:Change/Attribute:status' => '状態',
'Class:Change/Attribute:status+' => '',
'Class:Change/Attribute:status/Value:new' => '新規',
'Class:Change/Attribute:status/Value:new+' => '',
'Class:Change/Attribute:status/Value:validated' => '受け付け済み',
'Class:Change/Attribute:status/Value:validated+' => '',
'Class:Change/Attribute:status/Value:rejected' => '却下済み',
'Class:Change/Attribute:status/Value:rejected+' => '',
'Class:Change/Attribute:status/Value:assigned' => '割り当て済み',
'Class:Change/Attribute:status/Value:assigned+' => '',
'Class:Change/Attribute:status/Value:plannedscheduled' => '計画・予定された',
'Class:Change/Attribute:status/Value:plannedscheduled+' => '',
'Class:Change/Attribute:status/Value:approved' => '承認済み',
'Class:Change/Attribute:status/Value:approved+' => '',
'Class:Change/Attribute:status/Value:notapproved' => '未承認',
'Class:Change/Attribute:status/Value:notapproved+' => '',
'Class:Change/Attribute:status/Value:implemented' => '実施済み',
'Class:Change/Attribute:status/Value:implemented+' => '',
'Class:Change/Attribute:status/Value:monitored' => '経過観察',
'Class:Change/Attribute:status/Value:monitored+' => '',
'Class:Change/Attribute:status/Value:closed' => 'クローズ',
'Class:Change/Attribute:status/Value:closed+' => '',
'Class:Change/Attribute:reason' => '理由',
'Class:Change/Attribute:reason+' => '',
'Class:Change/Attribute:requestor_id' => '依頼者',
'Class:Change/Attribute:requestor_id+' => '',
'Class:Change/Attribute:requestor_email' => '依頼者',
'Class:Change/Attribute:requestor_email+' => '',
'Class:Change/Attribute:creation_date' => '作成',
'Class:Change/Attribute:creation_date+' => '',
'Class:Change/Attribute:impact' => 'インパクト',
'Class:Change/Attribute:impact+' => '',
'Class:Change/Attribute:supervisor_group_id' => '監督者チーム',
'Class:Change/Attribute:supervisor_group_id+' => '',
'Class:Change/Attribute:supervisor_group_name' => '監督者チーム名',
'Class:Change/Attribute:supervisor_group_name+' => '',
'Class:Change/Attribute:supervisor_id' => '監督者',
'Class:Change/Attribute:supervisor_id+' => '',
'Class:Change/Attribute:supervisor_email' => '監督者電子メール',
'Class:Change/Attribute:supervisor_email+' => '',
'Class:Change/Attribute:manager_group_id' => 'マネジャーチーム',
'Class:Change/Attribute:manager_group_id+' => '',
'Class:Change/Attribute:manager_group_name' => 'マネジャーチーム名',
'Class:Change/Attribute:manager_group_name+' => '',
'Class:Change/Attribute:manager_id' => 'マネジャー',
'Class:Change/Attribute:manager_id+' => '',
'Class:Change/Attribute:manager_email' => 'マネジャー電子メール',
'Class:Change/Attribute:manager_email+' => '',
'Class:Change/Attribute:outage' => '停止',
'Class:Change/Attribute:outage+' => '',
'Class:Change/Attribute:outage/Value:yes' => 'はい',
'Class:Change/Attribute:outage/Value:yes+' => '',
'Class:Change/Attribute:outage/Value:no' => 'いいえ',
'Class:Change/Attribute:outage/Value:no+' => '',
'Class:Change/Attribute:fallback' => 'フォールバック',
'Class:Change/Attribute:fallback+' => '',
'Class:Change/Attribute:parent_id' => '親変更',
'Class:Change/Attribute:parent_id+' => '',
'Class:Change/Attribute:parent_name' => '親変更参照',
'Class:Change/Attribute:parent_name+' => '',
'Class:Change/Attribute:related_request_list' => '関連要求',
'Class:Change/Attribute:related_request_list+' => '',
'Class:Change/Attribute:related_problems_list' => '関連問題',
'Class:Change/Attribute:related_problems_list+' => '',
'Class:Change/Attribute:child_changes_list' => '子変更',
'Class:Change/Attribute:child_changes_list+' => '',
'Class:Change/Attribute:parent_id_friendlyname' => '親のフレンドリー名',
'Class:Change/Attribute:parent_id_friendlyname+' => '',
'Class:Change/Attribute:parent_id_finalclass_recall' => '変更タイプ',
'Class:Change/Attribute:parent_id_finalclass_recall+' => '',
'Class:Change/Stimulus:ev_validate' => '受け付け',
'Class:Change/Stimulus:ev_validate+' => '',
'Class:Change/Stimulus:ev_reject' => '却下',
'Class:Change/Stimulus:ev_reject+' => '',
'Class:Change/Stimulus:ev_assign' => '割り当て',
'Class:Change/Stimulus:ev_assign+' => '',
'Class:Change/Stimulus:ev_reopen' => '再開',
'Class:Change/Stimulus:ev_reopen+' => '',
'Class:Change/Stimulus:ev_plan' => '計画',
'Class:Change/Stimulus:ev_plan+' => '',
'Class:Change/Stimulus:ev_approve' => '承認',
'Class:Change/Stimulus:ev_approve+' => '',
'Class:Change/Stimulus:ev_replan' => '再計画',
'Class:Change/Stimulus:ev_replan+' => '',
'Class:Change/Stimulus:ev_notapprove' => '否認',
'Class:Change/Stimulus:ev_notapprove+' => '',
'Class:Change/Stimulus:ev_implement' => '実施',
'Class:Change/Stimulus:ev_implement+' => '',
'Class:Change/Stimulus:ev_monitor' => '経過観察',
'Class:Change/Stimulus:ev_monitor+' => '',
'Class:Change/Stimulus:ev_finish' => '終了',
'Class:Change/Stimulus:ev_finish+' => '',
));
//
// Class: RoutineChange
//
Dict::Add('JA JP', 'Japanese', '日本語', array (
'Class:RoutineChange' => 'ルーチン変更',
'Class:RoutineChange+' => '',
'Class:RoutineChange/Stimulus:ev_validate' => '受け付け',
'Class:RoutineChange/Stimulus:ev_validate+' => '',
'Class:RoutineChange/Stimulus:ev_reject' => '却下',
'Class:RoutineChange/Stimulus:ev_reject+' => '',
'Class:RoutineChange/Stimulus:ev_assign' => '割り当て',
'Class:RoutineChange/Stimulus:ev_assign+' => '',
'Class:RoutineChange/Stimulus:ev_reopen' => '再オープン',
'Class:RoutineChange/Stimulus:ev_reopen+' => '',
'Class:RoutineChange/Stimulus:ev_plan' => '計画',
'Class:RoutineChange/Stimulus:ev_plan+' => '',
'Class:RoutineChange/Stimulus:ev_approve' => '承認',
'Class:RoutineChange/Stimulus:ev_approve+' => '',
'Class:RoutineChange/Stimulus:ev_replan' => '再計画',
'Class:RoutineChange/Stimulus:ev_replan+' => '',
'Class:RoutineChange/Stimulus:ev_notapprove' => '否認',
'Class:RoutineChange/Stimulus:ev_notapprove+' => '',
'Class:RoutineChange/Stimulus:ev_implement' => '実施',
'Class:RoutineChange/Stimulus:ev_implement+' => '',
'Class:RoutineChange/Stimulus:ev_monitor' => '経過観察',
'Class:RoutineChange/Stimulus:ev_monitor+' => '',
'Class:RoutineChange/Stimulus:ev_finish' => '終了',
'Class:RoutineChange/Stimulus:ev_finish+' => '',
));
//
// Class: ApprovedChange
//
Dict::Add('JA JP', 'Japanese', '日本語', array (
'Class:ApprovedChange' => '承認済の変更',
'Class:ApprovedChange+' => '',
'Class:ApprovedChange/Attribute:approval_date' => '承認日',
'Class:ApprovedChange/Attribute:approval_date+' => '',
'Class:ApprovedChange/Attribute:approval_comment' => '承認時のコメント',
'Class:ApprovedChange/Attribute:approval_comment+' => '',
'Class:ApprovedChange/Stimulus:ev_validate' => '受け付け',
'Class:ApprovedChange/Stimulus:ev_validate+' => '',
'Class:ApprovedChange/Stimulus:ev_reject' => '却下',
'Class:ApprovedChange/Stimulus:ev_reject+' => '',
'Class:ApprovedChange/Stimulus:ev_assign' => '割り当て',
'Class:ApprovedChange/Stimulus:ev_assign+' => '',
'Class:ApprovedChange/Stimulus:ev_reopen' => '再オープン',
'Class:ApprovedChange/Stimulus:ev_reopen+' => '',
'Class:ApprovedChange/Stimulus:ev_plan' => '計画',
'Class:ApprovedChange/Stimulus:ev_plan+' => '',
'Class:ApprovedChange/Stimulus:ev_approve' => '承認',
'Class:ApprovedChange/Stimulus:ev_approve+' => '',
'Class:ApprovedChange/Stimulus:ev_replan' => '再計画',
'Class:ApprovedChange/Stimulus:ev_replan+' => '',
'Class:ApprovedChange/Stimulus:ev_notapprove' => '否認',
'Class:ApprovedChange/Stimulus:ev_notapprove+' => '',
'Class:ApprovedChange/Stimulus:ev_implement' => '実施',
'Class:ApprovedChange/Stimulus:ev_implement+' => '',
'Class:ApprovedChange/Stimulus:ev_monitor' => '経過観察',
'Class:ApprovedChange/Stimulus:ev_monitor+' => '',
'Class:ApprovedChange/Stimulus:ev_finish' => '終了',
'Class:ApprovedChange/Stimulus:ev_finish+' => '',
));
//
// Class: NormalChange
//
Dict::Add('JA JP', 'Japanese', '日本語', array (
'Class:NormalChange' => '通常変更',
'Class:NormalChange+' => '',
'Class:NormalChange/Attribute:acceptance_date' => '受理日',
'Class:NormalChange/Attribute:acceptance_date+' => '',
'Class:NormalChange/Attribute:acceptance_comment' => '受理コメント',
'Class:NormalChange/Attribute:acceptance_comment+' => '',
'Class:NormalChange/Stimulus:ev_validate' => '受け付け',
'Class:NormalChange/Stimulus:ev_validate+' => '',
'Class:NormalChange/Stimulus:ev_reject' => '却下',
'Class:NormalChange/Stimulus:ev_reject+' => '',
'Class:NormalChange/Stimulus:ev_assign' => '割り当て',
'Class:NormalChange/Stimulus:ev_assign+' => '',
'Class:NormalChange/Stimulus:ev_reopen' => '再オープン',
'Class:NormalChange/Stimulus:ev_reopen+' => '',
'Class:NormalChange/Stimulus:ev_plan' => '計画',
'Class:NormalChange/Stimulus:ev_plan+' => '',
'Class:NormalChange/Stimulus:ev_approve' => '承認',
'Class:NormalChange/Stimulus:ev_approve+' => '',
'Class:NormalChange/Stimulus:ev_replan' => '再計画',
'Class:NormalChange/Stimulus:ev_replan+' => '',
'Class:NormalChange/Stimulus:ev_notapprove' => '否認',
'Class:NormalChange/Stimulus:ev_notapprove+' => '',
'Class:NormalChange/Stimulus:ev_implement' => '実施',
'Class:NormalChange/Stimulus:ev_implement+' => '',
'Class:NormalChange/Stimulus:ev_monitor' => '経過観察',
'Class:NormalChange/Stimulus:ev_monitor+' => '',
'Class:NormalChange/Stimulus:ev_finish' => '終了',
'Class:NormalChange/Stimulus:ev_finish+' => '',
));
//
// Class: EmergencyChange
//
Dict::Add('JA JP', 'Japanese', '日本語', array (
'Class:EmergencyChange' => '緊急変更',
'Class:EmergencyChange+' => '',
'Class:EmergencyChange/Stimulus:ev_validate' => '受け付け',
'Class:EmergencyChange/Stimulus:ev_validate+' => '',
'Class:EmergencyChange/Stimulus:ev_reject' => '却下',
'Class:EmergencyChange/Stimulus:ev_reject+' => '',
'Class:EmergencyChange/Stimulus:ev_assign' => '割り当て',
'Class:EmergencyChange/Stimulus:ev_assign+' => '',
'Class:EmergencyChange/Stimulus:ev_reopen' => '再オープン',
'Class:EmergencyChange/Stimulus:ev_reopen+' => '',
'Class:EmergencyChange/Stimulus:ev_plan' => '計画',
'Class:EmergencyChange/Stimulus:ev_plan+' => '',
'Class:EmergencyChange/Stimulus:ev_approve' => '承認',
'Class:EmergencyChange/Stimulus:ev_approve+' => '',
'Class:EmergencyChange/Stimulus:ev_replan' => '再計画',
'Class:EmergencyChange/Stimulus:ev_replan+' => '',
'Class:EmergencyChange/Stimulus:ev_notapprove' => '否認',
'Class:EmergencyChange/Stimulus:ev_notapprove+' => '',
'Class:EmergencyChange/Stimulus:ev_implement' => '実施',
'Class:EmergencyChange/Stimulus:ev_implement+' => '',
'Class:EmergencyChange/Stimulus:ev_monitor' => '経過観察',
'Class:EmergencyChange/Stimulus:ev_monitor+' => '',
'Class:EmergencyChange/Stimulus:ev_finish' => '終了',
'Class:EmergencyChange/Stimulus:ev_finish+' => '',
));
?>
<?php
// Copyright (C) 2010-2012 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/>
/**
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @licence http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:RoutineChange' => 'ルーチン変更',
'Class:RoutineChange+' => '',
'Class:RoutineChange/Stimulus:ev_assign' => '割り当て',
'Class:RoutineChange/Stimulus:ev_assign+' => '',
'Class:RoutineChange/Stimulus:ev_reopen' => '再オープン',
'Class:RoutineChange/Stimulus:ev_reopen+' => '',
'Class:RoutineChange/Stimulus:ev_plan' => '計画',
'Class:RoutineChange/Stimulus:ev_plan+' => '',
'Class:RoutineChange/Stimulus:ev_approve' => '承認',
'Class:RoutineChange/Stimulus:ev_approve+' => '',
'Class:RoutineChange/Stimulus:ev_replan' => '再計画',
'Class:RoutineChange/Stimulus:ev_replan+' => '',
'Class:RoutineChange/Stimulus:ev_notapprove' => '否認',
'Class:RoutineChange/Stimulus:ev_notapprove+' => '',
'Class:RoutineChange/Stimulus:ev_implement' => '実施',
'Class:RoutineChange/Stimulus:ev_implement+' => '',
'Class:RoutineChange/Stimulus:ev_monitor' => '経過観察',
'Class:RoutineChange/Stimulus:ev_monitor+' => '',
'Class:RoutineChange/Stimulus:ev_finish' => '終了',
'Class:RoutineChange/Stimulus:ev_finish+' => '',
'Class:NormalChange' => '通常変更',
'Class:NormalChange+' => '',
'Class:NormalChange/Attribute:acceptance_date' => '受理日',
'Class:NormalChange/Attribute:acceptance_date+' => '',
'Class:NormalChange/Attribute:acceptance_comment' => '受理コメント',
'Class:NormalChange/Attribute:acceptance_comment+' => '',
'Class:NormalChange/Stimulus:ev_validate' => '受け付け',
'Class:NormalChange/Stimulus:ev_validate+' => '',
'Class:NormalChange/Stimulus:ev_reject' => '却下',
'Class:NormalChange/Stimulus:ev_reject+' => '',
'Class:NormalChange/Stimulus:ev_assign' => '割り当て',
'Class:NormalChange/Stimulus:ev_assign+' => '',
'Class:NormalChange/Stimulus:ev_reopen' => '再オープン',
'Class:NormalChange/Stimulus:ev_reopen+' => '',
'Class:NormalChange/Stimulus:ev_plan' => '計画',
'Class:NormalChange/Stimulus:ev_plan+' => '',
'Class:NormalChange/Stimulus:ev_approve' => '承認',
'Class:NormalChange/Stimulus:ev_approve+' => '',
'Class:NormalChange/Stimulus:ev_replan' => '再計画',
'Class:NormalChange/Stimulus:ev_replan+' => '',
'Class:NormalChange/Stimulus:ev_notapprove' => '否認',
'Class:NormalChange/Stimulus:ev_notapprove+' => '',
'Class:NormalChange/Stimulus:ev_implement' => '実施',
'Class:NormalChange/Stimulus:ev_implement+' => '',
'Class:NormalChange/Stimulus:ev_monitor' => '経過観察',
'Class:NormalChange/Stimulus:ev_monitor+' => '',
'Class:NormalChange/Stimulus:ev_finish' => '終了',
'Class:NormalChange/Stimulus:ev_finish+' => '',
'Class:EmergencyChange' => '緊急変更',
'Class:EmergencyChange+' => '',
'Class:EmergencyChange/Stimulus:ev_assign' => '割り当て',
'Class:EmergencyChange/Stimulus:ev_assign+' => '',
'Class:EmergencyChange/Stimulus:ev_reopen' => '再オープン',
'Class:EmergencyChange/Stimulus:ev_reopen+' => '',
'Class:EmergencyChange/Stimulus:ev_plan' => '計画',
'Class:EmergencyChange/Stimulus:ev_plan+' => '',
'Class:EmergencyChange/Stimulus:ev_approve' => '承認',
'Class:EmergencyChange/Stimulus:ev_approve+' => '',
'Class:EmergencyChange/Stimulus:ev_replan' => '再計画',
'Class:EmergencyChange/Stimulus:ev_replan+' => '',
'Class:EmergencyChange/Stimulus:ev_notapprove' => '否認',
'Class:EmergencyChange/Stimulus:ev_notapprove+' => '',
'Class:EmergencyChange/Stimulus:ev_implement' => '実施',
'Class:EmergencyChange/Stimulus:ev_implement+' => '',
'Class:EmergencyChange/Stimulus:ev_monitor' => '経過観察',
'Class:EmergencyChange/Stimulus:ev_monitor+' => '',
'Class:EmergencyChange/Stimulus:ev_finish' => '終了',
'Class:EmergencyChange/Stimulus:ev_finish+' => '',
'Menu:ChangeManagement' => '変更管理',
'Menu:Change:Overview' => '概要',
'Menu:Change:Overview+' => '',
'Menu:NewChange' => '新規変更',
'Menu:NewChange+' => '新規変更のチケット作成',
'Menu:SearchChanges' => '変更検索',
'Menu:SearchChanges+' => '変更チケット検索',
'Menu:Change:Shortcuts' => 'ショートカット',
'Menu:Change:Shortcuts+' => '',
'Menu:WaitingAcceptance' => '受理待ちの変更',
'Menu:WaitingAcceptance+' => '',
'Menu:WaitingApproval' => '承認待ちの変更',
'Menu:WaitingApproval+' => '',
'Menu:Changes' => 'オープン状態の変更',
'Menu:Changes+' => '',
'Menu:MyChanges' => '担当している変更',
'Menu:MyChanges+' => '担当している変更(エージェントとして)',
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => '最近7日間のカテゴリ別の変更',
'UI-ChangeManagementOverview-Last-7-days' => '最近7日間の変更数',
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => '最近7日間のドメイン別変更',
'UI-ChangeManagementOverview-ChangeByStatus-last-7-days' => '最近7日間の状態別変更',
'Class:Change' => '変更',
'Class:Change+' => '',
'Class:Change/Attribute:status' => '状態',
'Class:Change/Attribute:status+' => '',
'Class:Change/Attribute:status/Value:new' => '新規',
'Class:Change/Attribute:status/Value:new+' => '',
'Class:Change/Attribute:status/Value:validated' => '受け付け済み',
'Class:Change/Attribute:status/Value:validated+' => '',
'Class:Change/Attribute:status/Value:rejected' => '却下済み',
'Class:Change/Attribute:status/Value:rejected+' => '',
'Class:Change/Attribute:status/Value:assigned' => '割り当て済み',
'Class:Change/Attribute:status/Value:assigned+' => '',
'Class:Change/Attribute:status/Value:plannedscheduled' => '計画・予定された',
'Class:Change/Attribute:status/Value:plannedscheduled+' => '',
'Class:Change/Attribute:status/Value:approved' => '承認済み',
'Class:Change/Attribute:status/Value:approved+' => '',
'Class:Change/Attribute:status/Value:notapproved' => '未承認',
'Class:Change/Attribute:status/Value:notapproved+' => '',
'Class:Change/Attribute:status/Value:implemented' => '実施済み',
'Class:Change/Attribute:status/Value:implemented+' => '',
'Class:Change/Attribute:status/Value:monitored' => '経過観察',
'Class:Change/Attribute:status/Value:monitored+' => '',
'Class:Change/Attribute:status/Value:closed' => 'クローズ',
'Class:Change/Attribute:status/Value:closed+' => '',
'Class:Change/Attribute:reason' => '理由',
'Class:Change/Attribute:reason+' => '',
'Class:Change/Attribute:requestor_id' => '依頼者',
'Class:Change/Attribute:requestor_id+' => '',
'Class:Change/Attribute:requestor_email' => '依頼者',
'Class:Change/Attribute:requestor_email+' => '',
'Class:Change/Attribute:creation_date' => '作成日',
'Class:Change/Attribute:creation_date+' => '',
'Class:Change/Attribute:impact' => 'インパクト',
'Class:Change/Attribute:impact+' => '',
'Class:Change/Attribute:supervisor_group_id' => '監督者チーム',
'Class:Change/Attribute:supervisor_group_id+' => '',
'Class:Change/Attribute:supervisor_group_name' => '監督者チーム名',
'Class:Change/Attribute:supervisor_group_name+' => '',
'Class:Change/Attribute:supervisor_id' => '監督者',
'Class:Change/Attribute:supervisor_id+' => '',
'Class:Change/Attribute:supervisor_email' => '監督者電子メール',
'Class:Change/Attribute:supervisor_email+' => '',
'Class:Change/Attribute:manager_group_id' => 'マネジャーチーム',
'Class:Change/Attribute:manager_group_id+' => '',
'Class:Change/Attribute:manager_group_name' => 'マネジャーチーム名',
'Class:Change/Attribute:manager_group_name+' => '',
'Class:Change/Attribute:manager_id' => 'マネジャー',
'Class:Change/Attribute:manager_id+' => '',
'Class:Change/Attribute:manager_email' => 'マネジャー電子メール',
'Class:Change/Attribute:manager_email+' => '',
'Class:Change/Attribute:outage' => '停止',
'Class:Change/Attribute:outage+' => '',
'Class:Change/Attribute:outage/Value:no' => 'いいえ',
'Class:Change/Attribute:outage/Value:no+' => '',
'Class:Change/Attribute:outage/Value:yes' => 'はい',
'Class:Change/Attribute:outage/Value:yes+' => '',
'Class:Change/Attribute:fallback' => 'フォールバック',
'Class:Change/Attribute:fallback+' => '',
'Class:Change/Attribute:parent_id' => '親変更',
'Class:Change/Attribute:parent_id+' => '',
'Class:Change/Attribute:parent_name' => '親変更参照',
'Class:Change/Attribute:parent_name+' => '',
'Class:Change/Attribute:related_request_list' => '関連要求',
'Class:Change/Attribute:related_request_list+' => '',
'Class:Change/Attribute:related_problems_list' => '関連問題',
'Class:Change/Attribute:related_problems_list+' => '',
'Class:Change/Attribute:child_changes_list' => '子変更',
'Class:Change/Attribute:child_changes_list+' => '',
'Class:Change/Attribute:parent_id_friendlyname' => '親のフレンドリー名',
'Class:Change/Attribute:parent_id_friendlyname+' => '',
'Class:Change/Attribute:parent_id_finalclass_recall' => '変更タイプ',
'Class:Change/Attribute:parent_id_finalclass_recall+' => '',
'Class:Change/Stimulus:ev_validate' => '受け付け',
'Class:Change/Stimulus:ev_validate+' => '',
'Class:Change/Stimulus:ev_reject' => '却下',
'Class:Change/Stimulus:ev_reject+' => '',
'Class:Change/Stimulus:ev_assign' => '割り当て',
'Class:Change/Stimulus:ev_assign+' => '',
'Class:Change/Stimulus:ev_reopen' => '再開',
'Class:Change/Stimulus:ev_reopen+' => '',
'Class:Change/Stimulus:ev_plan' => '計画',
'Class:Change/Stimulus:ev_plan+' => '',
'Class:Change/Stimulus:ev_approve' => '承認',
'Class:Change/Stimulus:ev_approve+' => '',
'Class:Change/Stimulus:ev_replan' => '再計画',
'Class:Change/Stimulus:ev_replan+' => '',
'Class:Change/Stimulus:ev_notapprove' => '否認',
'Class:Change/Stimulus:ev_notapprove+' => '',
'Class:Change/Stimulus:ev_implement' => '実施',
'Class:Change/Stimulus:ev_implement+' => '',
'Class:Change/Stimulus:ev_monitor' => '経過観察',
'Class:Change/Stimulus:ev_monitor+' => '',
'Class:Change/Stimulus:ev_finish' => '終了',
'Class:Change/Stimulus:ev_finish+' => '',
'Class:RoutineChange/Stimulus:ev_validate' => '受け付け',
'Class:RoutineChange/Stimulus:ev_validate+' => '',
'Class:RoutineChange/Stimulus:ev_reject' => '却下',
'Class:RoutineChange/Stimulus:ev_reject+' => '',
'Class:ApprovedChange' => '承認済の変更',
'Class:ApprovedChange+' => '',
'Class:ApprovedChange/Attribute:approval_date' => '承認日',
'Class:ApprovedChange/Attribute:approval_date+' => '',
'Class:ApprovedChange/Attribute:approval_comment' => '承認時のコメント',
'Class:ApprovedChange/Attribute:approval_comment+' => '',
'Class:ApprovedChange/Stimulus:ev_validate' => '受け付け',
'Class:ApprovedChange/Stimulus:ev_validate+' => '',
'Class:ApprovedChange/Stimulus:ev_reject' => '却下',
'Class:ApprovedChange/Stimulus:ev_reject+' => '',
'Class:ApprovedChange/Stimulus:ev_assign' => '割り当て',
'Class:ApprovedChange/Stimulus:ev_assign+' => '',
'Class:ApprovedChange/Stimulus:ev_reopen' => '再オープン',
'Class:ApprovedChange/Stimulus:ev_reopen+' => '',
'Class:ApprovedChange/Stimulus:ev_plan' => '計画',
'Class:ApprovedChange/Stimulus:ev_plan+' => '',
'Class:ApprovedChange/Stimulus:ev_approve' => '承認',
'Class:ApprovedChange/Stimulus:ev_approve+' => '',
'Class:ApprovedChange/Stimulus:ev_replan' => '再計画',
'Class:ApprovedChange/Stimulus:ev_replan+' => '',
'Class:ApprovedChange/Stimulus:ev_notapprove' => '否認',
'Class:ApprovedChange/Stimulus:ev_notapprove+' => '',
'Class:ApprovedChange/Stimulus:ev_implement' => '実施',
'Class:ApprovedChange/Stimulus:ev_implement+' => '',
'Class:ApprovedChange/Stimulus:ev_monitor' => '経過観察',
'Class:ApprovedChange/Stimulus:ev_monitor+' => '',
'Class:ApprovedChange/Stimulus:ev_finish' => '終了',
'Class:ApprovedChange/Stimulus:ev_finish+' => '',
'Class:EmergencyChange/Stimulus:ev_validate' => '受け付け',
'Class:EmergencyChange/Stimulus:ev_validate+' => '',
'Class:EmergencyChange/Stimulus:ev_reject' => '却下',
'Class:EmergencyChange/Stimulus:ev_reject+' => '',
));
?>

View File

@@ -765,7 +765,7 @@
</item>
</items>
</item>
<item id="fieldset:Relations">
<item id="fieldset:Ticket:relation">
<rank>20</rank>
<items>
<item id="parent_id">

View File

@@ -32,8 +32,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Menu:NewChange+' => 'Crear Ticket de Cambio',
'Menu:SearchChanges' => 'Búsqueda de Cambios',
'Menu:SearchChanges+' => 'Búsqueda de Tickets de Cambios',
'Menu:Change:Shortcuts' => 'Acceso Rápido',
'Menu:Change:Shortcuts+' => 'Acceso Rápido',
'Menu:Change:Shortcuts' => 'Accesos Rápidos',
'Menu:Change:Shortcuts+' => 'Accesos Rápidos',
'Menu:WaitingAcceptance' => 'Cambios Esperando ser Aceptados',
'Menu:WaitingAcceptance+' => 'Cambios Esperando ser Aceptados',
'Menu:WaitingApproval' => 'Cambios Esperando ser Aprobados',
@@ -114,10 +114,12 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Change/Attribute:related_request_list+' => 'Requerimientos Relacionados',
'Class:Change/Attribute:related_incident_list' => 'Incidentes Relacionados',
'Class:Change/Attribute:related_incident_list+' => 'Incidentes Relacionados',
'Class:Change/Attribute:related_problems_list' => 'Problemas Relacionados',
'Class:Change/Attribute:related_problems_list+' => 'Problemas Relacionados',
'Class:Change/Attribute:child_changes_list' => 'Cambios Hijo',
'Class:Change/Attribute:child_changes_list+' => 'Cambios Hijo',
'Class:Change/Attribute:parent_id_friendlyname' => 'Parent change friendly name',
'Class:Change/Attribute:parent_id_friendlyname+' => 'Parent change friendly name',
'Class:Change/Attribute:parent_id_friendlyname' => 'Nombre del Cambio Padre',
'Class:Change/Attribute:parent_id_friendlyname+' => 'Nombre del Cambio Padre',
'Class:Change/Stimulus:ev_assign' => 'Asignar',
'Class:Change/Stimulus:ev_assign+' => 'Asignar',
'Class:Change/Stimulus:ev_plan' => 'Planificar',

View File

@@ -470,6 +470,7 @@
<attribute id="org_id"/>
<attribute id="org_name"/>
<attribute id="email"/>
<attribute id="employee_number"/>
</attributes>
</reconciliation>
</properties>
@@ -970,7 +971,30 @@
<fields>
<field id="file" xsi:type="AttributeBlob"/>
</fields>
<methods/>
<methods>
<method id="DisplayBareRelations">
<static>false</static>
<access>public</access>
<type>Overload-cmdbAbstractObject</type>
<comment><![CDATA[/**
* Overload the display of the properties to add a tab (the first one)
* with the preview of the document
*/
]]></comment>
<code><![CDATA[public function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
{
$aFieldsMap = parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams);
if (!$bEditMode)
{
$oPage->add('<fieldset>');
$oPage->add('<legend>'.Dict::S('Class:Document:PreviewTab').'</legend>');
$oPage->add($this->DisplayDocumentInline($oPage, 'file'));
$oPage->add('</fieldset>');
}
return $aFieldsMap;
}]]></code>
</method>
</methods>
<presentation>
<details>
<items>
@@ -2327,6 +2351,9 @@
<item id="iosversion_id">
<rank>40</rank>
</item>
<item id="managementip">
<rank>45</rank>
</item>
<item id="ram">
<rank>50</rank>
</item>
@@ -2395,6 +2422,9 @@
<item id="location_id">
<rank>50</rank>
</item>
<item id="managementip">
<rank>55</rank>
</item>
<item id="brand_id">
<rank>60</rank>
</item>
@@ -2647,6 +2677,9 @@
<item id="osversion_id">
<rank>40</rank>
</item>
<item id="managementip">
<rank>45</rank>
</item>
<item id="oslicence_id">
<rank>50</rank>
</item>
@@ -2721,6 +2754,9 @@
<item id="location_id">
<rank>50</rank>
</item>
<item id="managementip">
<rank>55</rank>
</item>
<item id="brand_id">
<rank>60</rank>
</item>
@@ -4409,6 +4445,8 @@
<reconciliation>
<attributes>
<attribute id="name"/>
<attribute id="version"/>
<attribute id="vendor"/>
</attributes>
</reconciliation>
</properties>

View File

@@ -1037,6 +1037,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Menu:ConfigManagementOverview+' => 'Übersicht',
'Menu:Contact' => 'Kontakte',
'Menu:Contact+' => 'Kontakte',
'Menu:Contact:Count' => '%1$d kontakten',
'Menu:Person' => 'Personen',
'Menu:Person+' => 'Alle Personen',
'Menu:Team' => 'Teams',
@@ -1080,7 +1081,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Menu:SearchCIs' => 'Nach CIs suchen',
'Menu:SearchCIs+' => 'Nach CIs suchen',
'Menu:ConfigManagement:Devices' => 'Geräte',
'Menu:ConfigManagement:AllDevices' => 'Anzahl der Geräte: %1$d',
'Menu:ConfigManagement:AllDevices' => 'Infrastruktur',
'Menu:ConfigManagement:virtualization' => 'Virtualisierung',
'Menu:ConfigManagement:EndUsers' => 'Endbenutzer-Geräte',
'Menu:ConfigManagement:SWAndApps' => 'Software und Anwendungen',
@@ -1097,5 +1098,6 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Menu:Software+' => '',
'UI_WelcomeMenu_AllConfigItems' => 'Zusammenfassung',
'Menu:ConfigManagement:Typology' => 'Typologie-Konfiguration',
'Class:Document:PreviewTab' => 'Vorschau',
));
?>

View File

@@ -312,7 +312,7 @@ Dict::Add('EN US', 'English', 'English', array(
'Class:FunctionalCI/Attribute:move2production' => 'Move to production date',
'Class:FunctionalCI/Attribute:move2production+' => '',
'Class:FunctionalCI/Attribute:contacts_list' => 'Contacts',
'Class:FunctionalCI/Attribute:contacts_list+' => 'All the contracts for this configuration item',
'Class:FunctionalCI/Attribute:contacts_list+' => 'All the contacts for this configuration item',
'Class:FunctionalCI/Attribute:documents_list' => 'Documents',
'Class:FunctionalCI/Attribute:documents_list+' => 'All the documents linked to this configuration item',
'Class:FunctionalCI/Attribute:applicationsolution_list' => 'Application solutions',
@@ -375,7 +375,7 @@ Dict::Add('EN US', 'English', 'English', array(
Dict::Add('EN US', 'English', 'English', array(
'Class:Rack' => 'Rack',
'Class:Rack+' => '',
'Class:Rack/Attribute:nb_u' => 'NB U',
'Class:Rack/Attribute:nb_u' => 'Rack units',
'Class:Rack/Attribute:nb_u+' => '',
'Class:Rack/Attribute:device_list' => 'Devices',
'Class:Rack/Attribute:device_list+' => 'All the physical devices racked into this rack',
@@ -462,7 +462,7 @@ Dict::Add('EN US', 'English', 'English', array(
'Class:DatacenterDevice/Attribute:enclosure_id+' => '',
'Class:DatacenterDevice/Attribute:enclosure_name' => 'Enclosure name',
'Class:DatacenterDevice/Attribute:enclosure_name+' => '',
'Class:DatacenterDevice/Attribute:nb_u' => 'NB U',
'Class:DatacenterDevice/Attribute:nb_u' => 'Rack units',
'Class:DatacenterDevice/Attribute:nb_u+' => '',
'Class:DatacenterDevice/Attribute:managementip' => 'Management ip',
'Class:DatacenterDevice/Attribute:managementip+' => '',
@@ -665,7 +665,7 @@ Dict::Add('EN US', 'English', 'English', array(
'Class:Enclosure/Attribute:rack_id+' => '',
'Class:Enclosure/Attribute:rack_name' => 'Rack name',
'Class:Enclosure/Attribute:rack_name+' => '',
'Class:Enclosure/Attribute:nb_u' => 'NB U',
'Class:Enclosure/Attribute:nb_u' => 'Rack units',
'Class:Enclosure/Attribute:nb_u+' => '',
'Class:Enclosure/Attribute:device_list' => 'Devices',
'Class:Enclosure/Attribute:device_list+' => 'All the devices in this enclosure',
@@ -1714,6 +1714,7 @@ Dict::Add('EN US', 'English', 'English', array(
'Menu:ConfigManagementOverview+' => 'Overview',
'Menu:Contact' => 'Contacts',
'Menu:Contact+' => 'Contacts',
'Menu:Contact:Count' => '%1$d contacts',
'Menu:Person' => 'Persons',
'Menu:Person+' => 'All persons',
'Menu:Team' => 'Teams',
@@ -1781,16 +1782,17 @@ Dict::Add('EN US', 'English', 'English', array(
// Add translation for Fieldsets
Dict::Add('EN US', 'English', 'English', array(
'Server:baseinfo' => 'General informations',
'Server:baseinfo' => 'General information',
'Server:Date' => 'Date',
'Server:moreinfo' => 'More informations',
'Server:otherinfo' => 'Other informations',
'Person:info' => 'General informations',
'Server:moreinfo' => 'More information',
'Server:otherinfo' => 'Other information',
'Person:info' => 'General information',
'Person:notifiy' => 'Notification',
'Class:Subnet/Tab:IPUsage' => 'IP Usage',
'Class:Subnet/Tab:IPUsage-explain' => 'Interfaces having an IP in the range: <em>%1$s</em> to <em>%2$s</em>',
'Class:Subnet/Tab:FreeIPs' => 'Free IPs',
'Class:Subnet/Tab:FreeIPs-count' => 'Free IPs: %1$s',
'Class:Subnet/Tab:FreeIPs-explain' => 'Here is an extract of 10 free IP addresses',
'Class:Document:PreviewTab' => 'Preview',
));
?>

View File

@@ -33,7 +33,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Relation:impacts/Description' => 'Elementos Impactados por',
'Relation:impacts/VerbUp' => 'Impacto...',
'Relation:impacts/VerbDown' => 'Elementos Impactados por...',
'Relation:depends on/Description' => 'Elementos de los cuales este elemento depende',
'Relation:depends on/Description' => 'Elementos de los cuales depende',
'Relation:depends on/VerbUp' => 'Depende de...',
'Relation:depends on/VerbDown' => 'Impactos...',
));
@@ -81,7 +81,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Organization' => 'Organización',
'Class:Organization+' => 'Organización',
'Class:Organization/Attribute:name' => 'Nombre',
'Class:Organization/Attribute:name+' => 'Nombre',
'Class:Organization/Attribute:name+' => 'Nombre de la Organización',
'Class:Organization/Attribute:code' => 'Código',
'Class:Organization/Attribute:code+' => 'Código de Organización (RFC, DUNS, Siret, etc.)',
'Class:Organization/Attribute:status' => 'Estatus',
@@ -98,7 +98,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Organization/Attribute:deliverymodel_id+' => 'Modelo de Entrega',
'Class:Organization/Attribute:deliverymodel_name' => 'Nombre del Modelo de Entrega',
'Class:Organization/Attribute:deliverymodel_name+' => 'Nombre del Modelo de Entrega',
'Class:Organization/Attribute:parent_id_friendlyname' => 'Padre',
'Class:Organization/Attribute:parent_id_friendlyname' => 'Organización Padre',
'Class:Organization/Attribute:parent_id_friendlyname+' => 'Organización Padre',
));
@@ -142,8 +142,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Contact' => 'Contacto',
'Class:Contact+' => 'Contacto',
'Class:Contact/Attribute:name' => 'Apellidos',
'Class:Contact/Attribute:name+' => 'Apellidos',
'Class:Contact/Attribute:name' => 'Nombre',
'Class:Contact/Attribute:name+' => 'Nombre del Contacto',
'Class:Contact/Attribute:status' => 'Estatus',
'Class:Contact/Attribute:status+' => 'Estatus',
'Class:Contact/Attribute:status/Value:active' => 'Activo',
@@ -179,12 +179,14 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Person' => 'Persona',
'Class:Person+' => 'Persona',
'Class:Person/Attribute:first_name' => 'Nombre',
'Class:Person/Attribute:first_name+' => 'Nombre',
'Class:Person/Attribute:name' => 'Nombre',
'Class:Person/Attribute:name+' => 'Nombre de la Persona',
'Class:Person/Attribute:first_name' => 'Apellidos',
'Class:Person/Attribute:first_name+' => 'Apellidos',
'Class:Person/Attribute:employee_number' => 'Número de Empleado',
'Class:Person/Attribute:employee_number+' => 'Número de Empleado',
'Class:Person/Attribute:mobile_phone' => 'Celular',
'Class:Person/Attribute:mobile_phone+' => 'Celular',
'Class:Person/Attribute:mobile_phone' => 'Móvil',
'Class:Person/Attribute:mobile_phone+' => 'Móvil',
'Class:Person/Attribute:location_id' => 'Localidad',
'Class:Person/Attribute:location_id+' => 'Localidad',
'Class:Person/Attribute:location_name' => 'Nombre de Localidad',
@@ -222,7 +224,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Document' => 'Documento',
'Class:Document+' => 'Documento',
'Class:Document/Attribute:name' => 'Nombre',
'Class:Document/Attribute:name+' => 'Nombre',
'Class:Document/Attribute:name+' => 'Nombre del Documento',
'Class:Document/Attribute:org_id' => 'Organización',
'Class:Document/Attribute:org_id+' => 'Organización',
'Class:Document/Attribute:org_name' => 'Nombre de la Organización',
@@ -292,7 +294,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:FunctionalCI' => 'EC Funcional',
'Class:FunctionalCI+' => 'Elemento de Configuración Funcional',
'Class:FunctionalCI/Attribute:name' => 'Nombre',
'Class:FunctionalCI/Attribute:name+' => 'Nombre',
'Class:FunctionalCI/Attribute:name+' => 'Nombre del Elemento de Configuración',
'Class:FunctionalCI/Attribute:description' => 'Descripción',
'Class:FunctionalCI/Attribute:description+' => 'Descripción',
'Class:FunctionalCI/Attribute:org_id' => 'Organización',
@@ -472,8 +474,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:DatacenterDevice/Attribute:powerB_id+' => 'Fuente de Poder B',
'Class:DatacenterDevice/Attribute:powerB_name' => 'Fuente de Poder B',
'Class:DatacenterDevice/Attribute:powerB_name+' => 'Fuente de Poder B',
'Class:DatacenterDevice/Attribute:fiberinterfacelist_list' => 'Puertos de Fibra',
'Class:DatacenterDevice/Attribute:fiberinterfacelist_list+' => 'Puertos de Fibra',
'Class:DatacenterDevice/Attribute:fiberinterfacelist_list' => 'Puertos de Fibra Óptica',
'Class:DatacenterDevice/Attribute:fiberinterfacelist_list+' => 'Puertos de Fibra Óptica',
'Class:DatacenterDevice/Attribute:san_list' => 'SANs',
'Class:DatacenterDevice/Attribute:san_list+' => 'SANs',
));
@@ -929,7 +931,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:LogicalVolume' => 'Volumen Lógico',
'Class:LogicalVolume+' => 'Volumen Lógico',
'Class:LogicalVolume/Attribute:name' => 'Nombre',
'Class:LogicalVolume/Attribute:name+' => 'Nombre',
'Class:LogicalVolume/Attribute:name+' => 'Nombre del Volumen Lógico',
'Class:LogicalVolume/Attribute:lun_id' => 'LUN',
'Class:LogicalVolume/Attribute:lun_id+' => 'LUN',
'Class:LogicalVolume/Attribute:description' => 'Descripción',
@@ -1015,7 +1017,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Tape' => 'Cinta',
'Class:Tape+' => 'Cinta',
'Class:Tape/Attribute:name' => 'Nombre',
'Class:Tape/Attribute:name+' => 'Nombre',
'Class:Tape/Attribute:name+' => 'Nombre de la Cinta',
'Class:Tape/Attribute:description' => 'Descriptción',
'Class:Tape/Attribute:description+' => 'Descriptción',
'Class:Tape/Attribute:size' => 'Tama&ntilde;o',
@@ -1034,7 +1036,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:NASFileSystem' => 'Filesysten en NAS',
'Class:NASFileSystem+' => 'Filesysten en NAS',
'Class:NASFileSystem/Attribute:name' => 'Nombre',
'Class:NASFileSystem/Attribute:name+' => 'Nombre',
'Class:NASFileSystem/Attribute:name+' => 'Nombre del Filesystem de Red',
'Class:NASFileSystem/Attribute:description' => 'Descripción',
'Class:NASFileSystem/Attribute:description+' => 'Descripción',
'Class:NASFileSystem/Attribute:raid_level' => 'Nivel de RAID',
@@ -1055,7 +1057,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Software' => 'Software',
'Class:Software+' => 'Software',
'Class:Software/Attribute:name' => 'Nombre',
'Class:Software/Attribute:name+' => 'Nombre',
'Class:Software/Attribute:name+' => 'Nombre del Software',
'Class:Software/Attribute:vendor' => 'Proveedor',
'Class:Software/Attribute:vendor+' => 'Proveedor',
'Class:Software/Attribute:version' => 'Versión',
@@ -1090,7 +1092,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Patch' => 'Parche',
'Class:Patch+' => 'Parche',
'Class:Patch/Attribute:name' => 'Nombre',
'Class:Patch/Attribute:name+' => 'Nombre',
'Class:Patch/Attribute:name+' => 'Nombre del Parche',
'Class:Patch/Attribute:documents_list' => 'Documentos',
'Class:Patch/Attribute:documents_list+' => 'Documentos',
'Class:Patch/Attribute:description' => 'Descripción',
@@ -1137,7 +1139,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Licence' => 'Licencia',
'Class:Licence+' => 'Licencia',
'Class:Licence/Attribute:name' => 'Nombre',
'Class:Licence/Attribute:name+' => 'Nombre',
'Class:Licence/Attribute:name+' => 'Nombre de la Licencia',
'Class:Licence/Attribute:documents_list' => 'Documentos',
'Class:Licence/Attribute:documents_list+' => 'Documentos',
'Class:Licence/Attribute:org_id' => 'Compañía',
@@ -1152,8 +1154,14 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Licence/Attribute:start_date+' => 'Fecha de Inicio',
'Class:Licence/Attribute:end_date' => 'Fecha de Fin',
'Class:Licence/Attribute:end_date+' => 'Fecha de Fin',
'Class:Licence/Attribute:licence_key' => 'LLave',
'Class:Licence/Attribute:licence_key+' => 'LLave',
'Class:Licence/Attribute:licence_key' => 'Llave',
'Class:Licence/Attribute:licence_key+' => 'Llave',
'Class:Licence/Attribute:perpetual' => 'Perpetuidad',
'Class:Licence/Attribute:perpetual+' => 'Licenciamiento Perpetuo',
'Class:Licence/Attribute:perpetual/Value:no' => 'No',
'Class:Licence/Attribute:perpetual/Value:no+' => 'No',
'Class:Licence/Attribute:perpetual/Value:yes' => 'Si',
'Class:Licence/Attribute:perpetual/Value:yes+' => 'Si',
'Class:Licence/Attribute:finalclass' => 'Tipo',
'Class:Licence/Attribute:finalclass+' => 'Tipo',
));
@@ -1215,7 +1223,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Typology' => 'Tipología',
'Class:Typology+' => 'Tipología',
'Class:Typology/Attribute:name' => 'Nombre',
'Class:Typology/Attribute:name+' => 'Nombre',
'Class:Typology/Attribute:name+' => 'Nombre del Tipo',
'Class:Typology/Attribute:finalclass' => 'Tipo',
'Class:Typology/Attribute:finalclass+' => 'Tipo',
));
@@ -1477,7 +1485,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:NetworkInterface' => 'Interfaz de Red',
'Class:NetworkInterface+' => 'Interfaz de Red',
'Class:NetworkInterface/Attribute:name' => 'Nombre',
'Class:NetworkInterface/Attribute:name+' => 'Nombre',
'Class:NetworkInterface/Attribute:name+' => 'Nombre de la Interfaz de Red',
'Class:NetworkInterface/Attribute:finalclass' => 'Tipo',
'Class:NetworkInterface/Attribute:finalclass+' => 'Tipo',
));
@@ -1534,8 +1542,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
//
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:FiberChannelInterface' => 'Intefaz de Fibra',
'Class:FiberChannelInterface+' => 'Intefaz de Fibra',
'Class:FiberChannelInterface' => 'Intefaz de Fibra Óptica',
'Class:FiberChannelInterface+' => 'Intefaz de Fibra Óptica',
'Class:FiberChannelInterface/Attribute:speed' => 'Velocidad',
'Class:FiberChannelInterface/Attribute:speed+' => 'Velocidad',
'Class:FiberChannelInterface/Attribute:topology' => 'Topología',
@@ -1638,7 +1646,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Group' => 'Grupo',
'Class:Group+' => 'Grupo',
'Class:Group/Attribute:name' => 'Nombre',
'Class:Group/Attribute:name+' => 'Nombre',
'Class:Group/Attribute:name+' => 'Nombre del Grupo',
'Class:Group/Attribute:status' => 'Estatus',
'Class:Group/Attribute:status+' => 'Estatus',
'Class:Group/Attribute:status/Value:implementation' => 'No Productivo',
@@ -1697,7 +1705,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Menu:Organization' => 'Organizaciones',
'Menu:Organization+' => 'Organizaciones',
'Menu:Application' => 'Aplicaciones',
'Menu:Application+' => 'Aplicaciones/Pogramas',
'Menu:Application+' => 'Aplicaciones/Programas',
'Menu:DBServer' => 'Servidores de Base de Datos',
'Menu:DBServer+' => 'Servidores de Base de Datos',
'Menu:Audit' => 'Auditoría',
@@ -1705,7 +1713,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Menu:ConfigManagement+' => 'Administración de la Configuración',
'Menu:ConfigManagementOverview' => 'Resumen de Infraestructura',
'Menu:ConfigManagementOverview+' => 'Resumen de Infraestructura',
'Menu:Contact:Count' => 'Contactos',
'Menu:Contact:Count' => '%1$d Contactos',
'Menu:Contact' => 'Contactos',
'Menu:Contact+' => 'Contactos',
'Menu:Person' => 'Personas',
@@ -1738,8 +1746,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Menu:Server+' => 'Servidores',
'Menu:Printer' => 'Impresoras',
'Menu:Printer+' => 'Impresoras',
'Menu:MobilePhone' => 'Teléfonos Celulares',
'Menu:MobilePhone+' => 'Teléfonos Celulares',
'Menu:MobilePhone' => 'Teléfonos Móviles',
'Menu:MobilePhone+' => 'Teléfonos Móviles',
'Menu:PC' => 'PCs y Laptops',
'Menu:PC+' => 'PCs y Laptops',
'Menu:NewContact' => 'Nuevo Contacto',
@@ -1781,6 +1789,10 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Server:otherinfo' => 'Otra Información',
'Person:info' => 'Información General',
'Person:notifiy' => 'Notificación',
'Class:Subnet/Tab:IPUsage' => 'Uso de IP',
'Class:Subnet/Tab:IPUsage-explain' => 'Interfases con IP en el rango: <em>%1$s</em> a <em>%2$s</em>',
'Class:Subnet/Tab:FreeIPs' => 'IPs Libres',
'Class:Subnet/Tab:FreeIPs-count' => 'IPs Libres: %1$s',
'Class:Subnet/Tab:FreeIPs-explain' => 'Aquí está un extracto de 10 direcciones IP Libres',
));
?>

View File

@@ -1669,6 +1669,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Menu:ConfigManagementOverview+' => 'Tableaux de bord',
'Menu:Contact' => 'Contacts',
'Menu:Contact+' => 'Contacts',
'Menu:Contact:Count' => '%1$d contacts',
'Menu:Person' => 'Personnes',
'Menu:Person+' => 'Toutes les personnes',
'Menu:Team' => 'Equipes',
@@ -1772,5 +1773,6 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Class:Subnet/Tab:FreeIPs' => 'IP disponibles',
'Class:Subnet/Tab:FreeIPs-count' => 'IP disponibles: %1$s',
'Class:Subnet/Tab:FreeIPs-explain' => 'Voici un échantillon de dix addresses IP disponibles',
'Class:Document:PreviewTab' => 'Aperçu',
));
?>

View File

@@ -657,6 +657,7 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Menu:ConfigManagementOverview+' => '',
'Menu:Contact' => 'Kapcsolattartók',
'Menu:Contact+' => '',
'Menu:Contact:Count' => '%1$d',
'Menu:Person' => 'Személyek',
'Menu:Person+' => '',
'Menu:Team' => 'Csoportok',
@@ -700,7 +701,7 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Menu:SearchCIs' => 'CI keresés',
'Menu:SearchCIs+' => '',
'Menu:ConfigManagement:Devices' => 'Eszközök',
'Menu:ConfigManagement:AllDevices' => 'Eszközök száma: %1$d',
'Menu:ConfigManagement:AllDevices' => 'Infrastruktúra',
'Menu:ConfigManagement:SWAndApps' => 'Szoftverek és egyedi alkalmazások',
'Menu:ConfigManagement:Misc' => 'Egyéb',
'Menu:Group' => 'CI csoportok',

View File

@@ -657,6 +657,7 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Menu:ConfigManagementOverview+' => 'Panoramica',
'Menu:Contact' => 'Contatti',
'Menu:Contact+' => 'Contatti',
'Menu:Contact:Count' => '%1$d contatti',
'Menu:Person' => 'Persone',
'Menu:Person+' => 'Tutte le persone',
'Menu:Team' => 'Teams',
@@ -700,7 +701,7 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Menu:SearchCIs' => 'Ricerca CIs',
'Menu:SearchCIs+' => 'Ricerca CIs',
'Menu:ConfigManagement:Devices' => 'Dispositvi',
'Menu:ConfigManagement:AllDevices' => 'Numero di dispositivi: %1$d',
'Menu:ConfigManagement:AllDevices' => 'Infrastrutture',
'Menu:ConfigManagement:SWAndApps' => 'Software e Applicazioni',
'Menu:ConfigManagement:Misc' => 'Varie',
'Menu:Group' => 'Gruppi di CIs',

File diff suppressed because it is too large Load Diff

View File

@@ -658,6 +658,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Menu:ConfigManagementOverview+' => 'Visão Global',
'Menu:Contact' => 'Contatos',
'Menu:Contact+' => 'Contatos',
'Menu:Contact:Count' => '%1$d contatos',
'Menu:Person' => 'Pessoas',
'Menu:Person+' => 'Todas Pessoas',
'Menu:Team' => 'Equipes',
@@ -701,7 +702,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Menu:SearchCIs' => 'Pesquisa para CIs',
'Menu:SearchCIs+' => 'Pesquisa para CIs',
'Menu:ConfigManagement:Devices' => 'Dispositivo',
'Menu:ConfigManagement:AllDevices' => 'Número de dispositivos: %1$d',
'Menu:ConfigManagement:AllDevices' => 'Infra-estrutura',
'Menu:ConfigManagement:SWAndApps' => 'Software e Aplicações',
'Menu:ConfigManagement:Misc' => 'Diversos',
'Menu:Group' => 'Grupo de CIs',

View File

@@ -1036,6 +1036,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Menu:ConfigManagementOverview+' => 'Обзор',
'Menu:Contact' => 'Контакты',
'Menu:Contact+' => 'Контакты',
'Menu:Contact:Count' => '%1$d',
'Menu:Person' => 'Лица',
'Menu:Person+' => 'Все лица',
'Menu:Team' => 'Команды',
@@ -1079,9 +1080,9 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Menu:SearchCIs' => 'Поиск КЕ',
'Menu:SearchCIs+' => 'Поиск КЕ',
'Menu:ConfigManagement:Devices' => 'Устройства',
'Menu:ConfigManagement:AllDevices' => 'Количество устройств: %1$d',
'Menu:ConfigManagement:virtualization' => 'Виртуализация~~',
'Menu:ConfigManagement:EndUsers' => 'Оконечные устройства~~',
'Menu:ConfigManagement:AllDevices' => 'Инфраструктура',
'Menu:ConfigManagement:virtualization' => 'Виртуализация',
'Menu:ConfigManagement:EndUsers' => 'Оконечные устройства',
'Menu:ConfigManagement:SWAndApps' => 'ПО и приложения',
'Menu:ConfigManagement:Misc' => 'Разное',
'Menu:Group' => 'Группы КЕ',
@@ -1096,5 +1097,6 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Menu:Software+' => '',
'UI_WelcomeMenu_AllConfigItems' => 'Общее~~',
'Menu:ConfigManagement:Typology' => 'Конфигурация топологии~~',
'Class:Document:PreviewTab' => 'Предпросмотр',
));
?>

View File

@@ -1007,6 +1007,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Menu:ConfigManagementOverview+' => 'Özet',
'Menu:Contact' => 'İrtibatlar',
'Menu:Contact+' => 'İrtibatlar',
'Menu:Contact:Count' => '%1$d',
'Menu:Person' => 'Kişiler',
'Menu:Person+' => 'Tüm Kişiler',
'Menu:Team' => 'Ekipler',
@@ -1050,7 +1051,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Menu:SearchCIs' => 'KK ara',
'Menu:SearchCIs+' => 'KK ara',
'Menu:ConfigManagement:Devices' => 'Cihazlar',
'Menu:ConfigManagement:AllDevices' => 'Cihaz sayısı: %1$d',
'Menu:ConfigManagement:AllDevices' => 'Altyapı',
'Menu:ConfigManagement:SWAndApps' => 'Yazılım ve uygulamalar',
'Menu:ConfigManagement:Misc' => 'Diğer',
'Menu:Group' => 'KK Grupları',

View File

@@ -1009,6 +1009,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Menu:ConfigManagementOverview+' => '总览',
'Menu:Contact' => '联系人',
'Menu:Contact+' => '联系人',
'Menu:Contact:Count' => '%1$d',
'Menu:Person' => '人员',
'Menu:Person+' => '所有人员',
'Menu:Team' => '团队',
@@ -1052,7 +1053,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Menu:SearchCIs' => '查找CI',
'Menu:SearchCIs+' => '查找CI',
'Menu:ConfigManagement:Devices' => '设备',
'Menu:ConfigManagement:AllDevices' => '设备数量: %1$d',
'Menu:ConfigManagement:AllDevices' => '基础架构',
'Menu:ConfigManagement:SWAndApps' => '软件和应用程序',
'Menu:ConfigManagement:Misc' => '杂项',
'Menu:Group' => 'CI族',

View File

@@ -761,6 +761,10 @@
</properties>
<fields>
<field id="rack_id" xsi:type="AttributeExternalKey">
<filter><![CDATA[SELECT Rack WHERE location_id= :this->location_id]]></filter>
<dependencies>
<attribute id="location_id"/>
</dependencies>
<sql>rack_id</sql>
<target_class>Rack</target_class>
<is_null_allowed>false</is_null_allowed>

View File

@@ -1315,7 +1315,7 @@
case 'new':
case 'approved':
$sIcon = self::MakeIconFromName('user-request.png');
$sIcon = self::MakeIconFromName('incident.png');
$iEscalationDeadline = $this->Get('tto_escalation_deadline');
if ($iEscalationDeadline != null)
{
@@ -1335,7 +1335,7 @@
break;
case 'assigned':
$sIcon = self::MakeIconFromName('user-request.png');
$sIcon = self::MakeIconFromName('incident.png');
$iEscalationDeadline = $this->Get('ttr_escalation_deadline');
if ($iEscalationDeadline != null)
{
@@ -1452,28 +1452,31 @@
$sUserString = CMDBChange::GetCurrentUserName();
$oMyChange->Set("userinfo", $sUserString."(automatic resolution)");
$iChangeId = $oMyChange->DBInsert();
$sOQL = "SELECT UserRequest WHERE parent_request_id=:ticket";
$oChildRequestSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
array(),
array(
'ticket' => $this->GetKey(),
)
);
//automatically resolve child requests
while($oRequest = $oChildRequestSet->Fetch())
{
if ( $oRequest->Get('status') != 'resolved')
{
$oRequest->set('servicesubcategory_id',$this->Get('servicesubcategory_id'));
$oRequest->set('service_id',$this->Get('service_id'));
$oRequest->set('team_id',$this->Get('team_id'));
$oRequest->set('agent_id',$this->Get('agent_id'));
$oRequest->set('resolution_code',$this->Get('resolution_code'));
$oRequest->set('solution','Automatically resolved by incident:[[Incident:'.$this->Get('ref').']]');
$oRequest->ApplyStimulus('ev_autoresolve');
$oRequest->DBUpdateTracked($oMyChange);
}
}
if (MetaModel::IsValidClass('UserRequest'))
{
$sOQL = "SELECT UserRequest WHERE parent_request_id=:ticket";
$oChildRequestSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
array(),
array(
'ticket' => $this->GetKey(),
)
);
//automatically resolve child requests
while($oRequest = $oChildRequestSet->Fetch())
{
if ( $oRequest->Get('status') != 'resolved')
{
$oRequest->set('servicesubcategory_id',$this->Get('servicesubcategory_id'));
$oRequest->set('service_id',$this->Get('service_id'));
$oRequest->set('team_id',$this->Get('team_id'));
$oRequest->set('agent_id',$this->Get('agent_id'));
$oRequest->set('resolution_code',$this->Get('resolution_code'));
$oRequest->set('solution','Automatically resolved by incident:[[Incident:'.$this->Get('ref').']]');
$oRequest->ApplyStimulus('ev_autoresolve');
$oRequest->DBUpdateTracked($oMyChange);
}
}
}
//automatically resolve child incidents
$sOQL = "SELECT Incident WHERE parent_incident_id=:ticket";
@@ -1507,6 +1510,8 @@
<type>LifecycleAction</type>
<code><![CDATA[ public function UpdateChildRequestLog()
{
if (!MetaModel::IsValidClass('UserRequest')) return true; // Do nothing
$sLogPublic = utils::ReadPostedParam('attr_public_log', null,false,'raw_data');
if ( $sLogPublic != null)
{
@@ -1795,7 +1800,7 @@
<item id="col:col3">
<rank>80</rank>
<items>
<item id="fieldset:Relations">
<item id="fieldset:Ticket:relation">
<rank>10</rank>
<items>
<item id="parent_incident_id">

View File

@@ -33,8 +33,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Menu:NewIncident+' => 'Crear Ticket de Incidente',
'Menu:SearchIncidents' => 'Búsqueda por Incidentes',
'Menu:SearchIncidents+' => 'Búsqueda por tickets de Incidente',
'Menu:Incident:Shortcuts' => 'Acceso Rápido',
'Menu:Incident:Shortcuts+' => 'Acceso Rápido',
'Menu:Incident:Shortcuts' => 'Accesos Rápidos',
'Menu:Incident:Shortcuts+' => 'Accesos Rápidos',
'Menu:Incident:MyIncidents' => 'Incidentes Asignados a Mí',
'Menu:Incident:MyIncidents+' => 'Incidentes Asignados a Mí (como Analista)',
'Menu:Incident:EscalatedIncidents' => 'Incidentes Escalados',
@@ -200,6 +200,10 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:Incident/Attribute:parent_change_ref+' => 'Ref. Cambio Padre',
'Class:Incident/Attribute:child_incidents_list' => 'Incidentes Hijos',
'Class:Incident/Attribute:child_incidents_list+' => 'Incidentes Hijos',
'Class:Incident/Attribute:related_request_list' => 'Requerimientos Relacionados',
'Class:Incident/Attribute:related_request_list+' => 'Requerimientos Relacionados',
'Class:Incident/Attribute:parent_problem_id' => 'Problema Padre',
'Class:Incident/Attribute:parent_problem_id+' => 'Problema Padre',
'Class:Incident/Attribute:public_log' => 'Bitácora Pública',
'Class:Incident/Attribute:public_log+' => 'Bitácora Pública',
'Class:Incident/Attribute:user_satisfaction' => 'Satisfacción del Usuario',

View File

@@ -1,240 +1,215 @@
<?php
// Copyright (C) 2010-2012 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/>
/**
* Localized data
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('JA JP', 'Japanese', '日本語', array (
'Menu:IncidentManagement' => 'インシデント管理',
'Menu:IncidentManagement+' => 'インシデント管理',
'Menu:Incident:Overview' => '概要',
'Menu:Incident:Overview+' => '概要',
'Menu:NewIncident' => '新規インシデント',
'Menu:NewIncident+' => 'インシデントチケット作成',
'Menu:SearchIncidents' => 'インシデント検索',
'Menu:SearchIncidents+' => 'インシデントチケット検索',
'Menu:Incident:Shortcuts' => 'ショートカット',
'Menu:Incident:Shortcuts+' => '',
'Menu:Incident:MyIncidents' => '担当しているインシデント',
'Menu:Incident:MyIncidents+' => '担当しているインシデント(エージェント)',
'Menu:Incident:EscalatedIncidents' => 'エスカレーションされたインシデント',
'Menu:Incident:EscalatedIncidents+' => 'エスカレーションされたインシデント',
'Menu:Incident:OpenIncidents' => '全オープンインシデント',
'Menu:Incident:OpenIncidents+' => '全オープンインシデント',
'Menu:Incident:UnassignedIncidents' => '未割り当てインシデント',
'Menu:Incident:UnassignedIncidents+' => '未割り当てインシデント',
'Menu:Incident:HelpdeskIncidents' => 'レベル2へ割り当てられたインシデント',
'Menu:Incident:HelpdeskIncidents+' => 'レベル2へ割り当てられたインシデント',
'UI-IncidentManagementOverview-IncidentByPriority-last-14-days' => '最近14日の優先度別インシデント',
'UI-IncidentManagementOverview-Last-14-days' => '最近14日のインシデント数',
'UI-IncidentManagementOverview-OpenIncidentByStatus' => '状態別オープンインシデント',
'UI-IncidentManagementOverview-OpenIncidentByAgent' => 'エージェント別オープンインシデント',
'UI-IncidentManagementOverview-OpenIncidentByCustomer' => '顧客別オープンインシデント',
));
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
// Class:<class_name>/Attribute:<attribute_code>
// Class:<class_name>/Attribute:<attribute_code>+
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//
// Class: Incident
//
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:Incident' => 'インシデント',
'Class:Incident+' => '',
'Class:Incident/Attribute:status' => '状態',
'Class:Incident/Attribute:status+' => '',
'Class:Incident/Attribute:status/Value:new' => '新規',
'Class:Incident/Attribute:status/Value:new+' => '',
'Class:Incident/Attribute:status/Value:escalated_tto' => 'エスカレートTTO',
'Class:Incident/Attribute:status/Value:escalated_tto+' => '',
'Class:Incident/Attribute:status/Value:assigned' => '割り当て',
'Class:Incident/Attribute:status/Value:assigned+' => '',
'Class:Incident/Attribute:status/Value:escalated_ttr' => 'エスカレートTTR',
'Class:Incident/Attribute:status/Value:escalated_ttr+' => '',
'Class:Incident/Attribute:status/Value:waiting_for_approval' => '承認待ち',
'Class:Incident/Attribute:status/Value:waiting_for_approval+' => '',
'Class:Incident/Attribute:status/Value:pending' => '保留中',
'Class:Incident/Attribute:status/Value:pending+' => '',
'Class:Incident/Attribute:status/Value:resolved' => '解決済み',
'Class:Incident/Attribute:status/Value:resolved+' => '',
'Class:Incident/Attribute:status/Value:closed' => 'クローズ',
'Class:Incident/Attribute:status/Value:closed+' => '',
'Class:Incident/Attribute:impact' => 'インパクト',
'Class:Incident/Attribute:impact+' => '',
'Class:Incident/Attribute:impact/Value:1' => '部門',
'Class:Incident/Attribute:impact/Value:1+' => '',
'Class:Incident/Attribute:impact/Value:2' => 'サービス',
'Class:Incident/Attribute:impact/Value:2+' => '',
'Class:Incident/Attribute:impact/Value:3' => '個人',
'Class:Incident/Attribute:impact/Value:3+' => '',
'Class:Incident/Attribute:priority' => '優先度',
'Class:Incident/Attribute:priority+' => '',
'Class:Incident/Attribute:priority/Value:1' => '重大',
'Class:Incident/Attribute:priority/Value:1+' => '重大',
'Class:Incident/Attribute:priority/Value:2' => '',
'Class:Incident/Attribute:priority/Value:2+' => '',
'Class:Incident/Attribute:priority/Value:3' => '中',
'Class:Incident/Attribute:priority/Value:3+' => '',
'Class:Incident/Attribute:priority/Value:4' => '低',
'Class:Incident/Attribute:priority/Value:4+' => '',
'Class:Incident/Attribute:urgency' => '緊急度',
'Class:Incident/Attribute:urgency+' => '',
'Class:Incident/Attribute:urgency/Value:1' => '至急',
'Class:Incident/Attribute:urgency/Value:1+' => '至急',
'Class:Incident/Attribute:urgency/Value:2' => '高',
'Class:Incident/Attribute:urgency/Value:2+' => '',
'Class:Incident/Attribute:urgency/Value:3' => '',
'Class:Incident/Attribute:urgency/Value:3+' => '',
'Class:Incident/Attribute:urgency/Value:4' => '',
'Class:Incident/Attribute:urgency/Value:4+' => '',
'Class:Incident/Attribute:origin' => '情報源',
'Class:Incident/Attribute:origin+' => '',
'Class:Incident/Attribute:origin/Value:mail' => 'メール',
'Class:Incident/Attribute:origin/Value:mail+' => 'メール',
'Class:Incident/Attribute:origin/Value:monitoring' => 'モニタリング',
'Class:Incident/Attribute:origin/Value:monitoring+' => 'モニタリング',
'Class:Incident/Attribute:origin/Value:phone' => '電話',
'Class:Incident/Attribute:origin/Value:phone+' => '電話',
'Class:Incident/Attribute:origin/Value:portal' => 'ポータル',
'Class:Incident/Attribute:origin/Value:portal+' => 'ポータル',
'Class:Incident/Attribute:service_id' => 'サービス',
'Class:Incident/Attribute:service_id+' => '',
'Class:Incident/Attribute:service_name' => 'サービス名',
'Class:Incident/Attribute:service_name+' => '',
'Class:Incident/Attribute:servicesubcategory_id' => 'サービス中分類',
'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/Value:no' => 'いいえ',
'Class:Incident/Attribute:escalation_flag/Value:no+' => 'いいえ',
'Class:Incident/Attribute:escalation_flag/Value:yes' => 'はい',
'Class:Incident/Attribute:escalation_flag/Value:yes+' => 'はい',
'Class:Incident/Attribute:escalation_reason' => '理由',
'Class:Incident/Attribute:escalation_reason+' => '',
'Class:Incident/Attribute:assignment_date' => '割り当て日',
'Class:Incident/Attribute:assignment_date+' => '',
'Class:Incident/Attribute:resolution_date' => '解決日',
'Class:Incident/Attribute:resolution_date+' => '',
'Class:Incident/Attribute:last_pending_date' => '最終保留日',
'Class:Incident/Attribute:last_pending_date+' => '',
'Class:Incident/Attribute:cumulatedpending' => '合計保留',
'Class:Incident/Attribute:cumulatedpending+' => '',
'Class:Incident/Attribute:tto' => 'tto',
'Class:Incident/Attribute:tto+' => '',
'Class:Incident/Attribute:ttr' => 'ttr',
'Class:Incident/Attribute:ttr+' => '',
'Class:Incident/Attribute:tto_escalation_deadline' => 'TTO 期限',
'Class:Incident/Attribute:tto_escalation_deadline+' => '',
'Class:Incident/Attribute:sla_tto_passed' => 'SLA tto 合格',
'Class:Incident/Attribute:sla_tto_passed+' => '',
'Class:Incident/Attribute:sla_tto_over' => 'SLA tto オーバー',
'Class:Incident/Attribute:sla_tto_over+' => '',
'Class:Incident/Attribute:ttr_escalation_deadline' => 'TTR 期限',
'Class:Incident/Attribute:ttr_escalation_deadline+' => '',
'Class:Incident/Attribute:sla_ttr_passed' => 'SLA ttr 合格',
'Class:Incident/Attribute:sla_ttr_passed+' => '',
'Class:Incident/Attribute:sla_ttr_over' => 'SLA ttr オーバー',
'Class:Incident/Attribute:sla_ttr_over+' => '',
'Class:Incident/Attribute:time_spent' => '解決遅れ',
'Class:Incident/Attribute:time_spent+' => '',
'Class:Incident/Attribute:resolution_code' => '解決コード',
'Class:Incident/Attribute:resolution_code+' => '',
'Class:Incident/Attribute:resolution_code/Value:assistance' => '補助',
'Class:Incident/Attribute:resolution_code/Value:assistance+' => '補助',
'Class:Incident/Attribute:resolution_code/Value:bug fixed' => 'バグ修正',
'Class:Incident/Attribute:resolution_code/Value:bug fixed+' => 'バグ修正',
'Class:Incident/Attribute:resolution_code/Value:hardware repair' => 'ハードウエア修理',
'Class:Incident/Attribute:resolution_code/Value:hardware repair+' => 'ハードウエア修理',
'Class:Incident/Attribute:resolution_code/Value:other' => 'その他',
'Class:Incident/Attribute:resolution_code/Value:other+' => 'その他',
'Class:Incident/Attribute:resolution_code/Value:software patch' => 'ソフトウエアパッチ',
'Class:Incident/Attribute:resolution_code/Value:software patch+' => 'ソフトウエアパッチ',
'Class:Incident/Attribute:resolution_code/Value:system update' => 'システム更新',
'Class:Incident/Attribute:resolution_code/Value:system update+' => 'システム更新',
'Class:Incident/Attribute:resolution_code/Value:training' => '研修',
'Class:Incident/Attribute:resolution_code/Value:training+' => '研修',
'Class:Incident/Attribute:solution' => '解決',
'Class:Incident/Attribute:solution+' => '',
'Class:Incident/Attribute:pending_reason' => '保留理由',
'Class:Incident/Attribute:pending_reason+' => '',
'Class:Incident/Attribute:parent_incident_id' => 'インシデント',
'Class:Incident/Attribute:parent_incident_id+' => '',
'Class:Incident/Attribute:parent_incident_ref' => 'インシデント参照',
'Class:Incident/Attribute:parent_incident_ref+' => '',
'Class:Incident/Attribute:parent_change_id' => '親変更',
'Class:Incident/Attribute:parent_change_id+' => '',
'Class:Incident/Attribute:parent_change_ref' => '親変更参照',
'Class:Incident/Attribute:parent_change_ref+' => '',
'Class:Incident/Attribute:child_incidents_list' => 'インシデント',
'Class:Incident/Attribute:child_incidents_list+' => '',
'Class:Incident/Attribute:public_log' => 'パブリックログ',
'Class:Incident/Attribute:public_log+' => '',
'Class:Incident/Attribute:user_satisfaction' => 'ユーザ満足度',
'Class:Incident/Attribute:user_satisfaction+' => '',
'Class:Incident/Attribute:user_satisfaction/Value:1' => '非常に満足',
'Class:Incident/Attribute:user_satisfaction/Value:1+' => '非常に満足',
'Class:Incident/Attribute:user_satisfaction/Value:2' => '十分満足',
'Class:Incident/Attribute:user_satisfaction/Value:2+' => '十分満足',
'Class:Incident/Attribute:user_satisfaction/Value:3' => '多少不満',
'Class:Incident/Attribute:user_satisfaction/Value:3+' => '多少不満',
'Class:Incident/Attribute:user_satisfaction/Value:4' => '非常に不満',
'Class:Incident/Attribute:user_satisfaction/Value:4+' => '非常に不満',
'Class:Incident/Attribute:user_comment' => 'ユーザコメント',
'Class:Incident/Attribute:user_comment+' => '',
'Class:Incident/Attribute:parent_incident_id_friendlyname' => '親インシデント名',
'Class:Incident/Attribute:parent_incident_id_friendlyname+' => '',
'Class:Incident/Stimulus:ev_assign' => '割り当て',
'Class:Incident/Stimulus:ev_assign+' => '',
'Class:Incident/Stimulus:ev_reassign' => '再割り当て',
'Class:Incident/Stimulus:ev_reassign+' => '',
'Class:Incident/Stimulus:ev_pending' => '保留',
'Class:Incident/Stimulus:ev_pending+' => '',
'Class:Incident/Stimulus:ev_timeout' => 'タイムアウト',
'Class:Incident/Stimulus:ev_timeout+' => '',
'Class:Incident/Stimulus:ev_autoresolve' => '自動解決',
'Class:Incident/Stimulus:ev_autoresolve+' => '',
'Class:Incident/Stimulus:ev_autoclose' => '自動クローズ',
'Class:Incident/Stimulus:ev_autoclose+' => '',
'Class:Incident/Stimulus:ev_resolve' => '解決とマーク',
'Class:Incident/Stimulus:ev_resolve+' => '',
'Class:Incident/Stimulus:ev_close' => 'このリクエストをクローズ',
'Class:Incident/Stimulus:ev_close+' => '',
'Class:Incident/Stimulus:ev_reopen' => '再オープン',
'Class:Incident/Stimulus:ev_reopen+' => '',
));
?>
<?php
// Copyright (C) 2010-2012 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/>
/**
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @licence http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:Incident' => 'インシデント',
'Class:Incident+' => '',
'Class:Incident/Attribute:status' => '状態',
'Class:Incident/Attribute:status+' => '',
'Class:Incident/Attribute:status/Value:new' => '新規',
'Class:Incident/Attribute:status/Value:new+' => '',
'Class:Incident/Attribute:status/Value:escalated_tto' => 'エスカレートTTO',
'Class:Incident/Attribute:status/Value:escalated_tto+' => '',
'Class:Incident/Attribute:status/Value:assigned' => '割り当て',
'Class:Incident/Attribute:status/Value:assigned+' => '',
'Class:Incident/Attribute:status/Value:escalated_ttr' => 'エスカレートTTR',
'Class:Incident/Attribute:status/Value:escalated_ttr+' => '',
'Class:Incident/Attribute:status/Value:pending' => '保留中',
'Class:Incident/Attribute:status/Value:pending+' => '',
'Class:Incident/Attribute:status/Value:resolved' => '解決済み',
'Class:Incident/Attribute:status/Value:resolved+' => '',
'Class:Incident/Attribute:status/Value:closed' => 'クローズ',
'Class:Incident/Attribute:status/Value:closed+' => '',
'Class:Incident/Attribute:impact' => 'インパクト',
'Class:Incident/Attribute:impact+' => '',
'Class:Incident/Attribute:impact/Value:1' => '部門',
'Class:Incident/Attribute:impact/Value:1+' => '',
'Class:Incident/Attribute:impact/Value:2' => 'サービス',
'Class:Incident/Attribute:impact/Value:2+' => '',
'Class:Incident/Attribute:impact/Value:3' => '個人',
'Class:Incident/Attribute:impact/Value:3+' => '',
'Class:Incident/Attribute:priority' => '優先度',
'Class:Incident/Attribute:priority+' => '',
'Class:Incident/Attribute:priority/Value:1' => '重大',
'Class:Incident/Attribute:priority/Value:1+' => '重大',
'Class:Incident/Attribute:priority/Value:2' => '高',
'Class:Incident/Attribute:priority/Value:2+' => '高',
'Class:Incident/Attribute:priority/Value:3' => '中',
'Class:Incident/Attribute:priority/Value:3+' => '中',
'Class:Incident/Attribute:priority/Value:4' => '低',
'Class:Incident/Attribute:priority/Value:4+' => '低',
'Class:Incident/Attribute:urgency' => '緊急度',
'Class:Incident/Attribute:urgency+' => '',
'Class:Incident/Attribute:urgency/Value:1' => '至急',
'Class:Incident/Attribute:urgency/Value:1+' => '至急',
'Class:Incident/Attribute:urgency/Value:2' => '高',
'Class:Incident/Attribute:urgency/Value:2+' => '高',
'Class:Incident/Attribute:urgency/Value:3' => '中',
'Class:Incident/Attribute:urgency/Value:3+' => '中',
'Class:Incident/Attribute:urgency/Value:4' => '低',
'Class:Incident/Attribute:urgency/Value:4+' => '低',
'Class:Incident/Attribute:origin' => '情報源',
'Class:Incident/Attribute:origin+' => '',
'Class:Incident/Attribute:origin/Value:mail' => 'メール',
'Class:Incident/Attribute:origin/Value:mail+' => 'メール',
'Class:Incident/Attribute:origin/Value:monitoring' => 'モニタリング',
'Class:Incident/Attribute:origin/Value:monitoring+' => 'モニタリング',
'Class:Incident/Attribute:origin/Value:phone' => '電話',
'Class:Incident/Attribute:origin/Value:phone+' => '電話',
'Class:Incident/Attribute:origin/Value:portal' => 'ポータル',
'Class:Incident/Attribute:origin/Value:portal+' => 'ポータル',
'Class:Incident/Attribute:service_id' => 'サービス',
'Class:Incident/Attribute:service_id+' => '',
'Class:Incident/Attribute:servicesubcategory_id' => 'サービス中分類',
'Class:Incident/Attribute:servicesubcategory_id+' => '',
'Class:Incident/Attribute:escalation_flag' => 'エスカレーションフラグ',
'Class:Incident/Attribute:escalation_flag+' => '',
'Class:Incident/Attribute:escalation_flag/Value:no' => 'いいえ',
'Class:Incident/Attribute:escalation_flag/Value:no+' => 'いいえ',
'Class:Incident/Attribute:escalation_flag/Value:yes' => 'はい',
'Class:Incident/Attribute:escalation_flag/Value:yes+' => 'はい',
'Class:Incident/Attribute:escalation_reason' => '理由',
'Class:Incident/Attribute:escalation_reason+' => '',
'Class:Incident/Attribute:assignment_date' => '割り当て日',
'Class:Incident/Attribute:assignment_date+' => '',
'Class:Incident/Attribute:resolution_date' => '解決日',
'Class:Incident/Attribute:resolution_date+' => '',
'Class:Incident/Attribute:last_pending_date' => '最終保留日',
'Class:Incident/Attribute:last_pending_date+' => '',
'Class:Incident/Attribute:cumulatedpending' => '合計保留',
'Class:Incident/Attribute:cumulatedpending+' => '',
'Class:Incident/Attribute:tto' => 'tto',
'Class:Incident/Attribute:tto+' => '',
'Class:Incident/Attribute:ttr' => 'ttr',
'Class:Incident/Attribute:ttr+' => '',
'Class:Incident/Attribute:tto_escalation_deadline' => 'TTO 期限',
'Class:Incident/Attribute:tto_escalation_deadline+' => '',
'Class:Incident/Attribute:sla_tto_passed' => 'SLA tto 合格',
'Class:Incident/Attribute:sla_tto_passed+' => '',
'Class:Incident/Attribute:sla_tto_over' => 'SLA tto オーバー',
'Class:Incident/Attribute:sla_tto_over+' => '',
'Class:Incident/Attribute:ttr_escalation_deadline' => 'TTR 期限',
'Class:Incident/Attribute:ttr_escalation_deadline+' => '',
'Class:Incident/Attribute:sla_ttr_passed' => 'SLA ttr 合格',
'Class:Incident/Attribute:sla_ttr_passed+' => '',
'Class:Incident/Attribute:sla_ttr_over' => 'SLA ttr オーバー',
'Class:Incident/Attribute:sla_ttr_over+' => '',
'Class:Incident/Attribute:time_spent' => '解決遅れ',
'Class:Incident/Attribute:time_spent+' => '',
'Class:Incident/Attribute:resolution_code' => '解決コード',
'Class:Incident/Attribute:resolution_code+' => '',
'Class:Incident/Attribute:resolution_code/Value:assistance' => '補助',
'Class:Incident/Attribute:resolution_code/Value:assistance+' => '補助',
'Class:Incident/Attribute:resolution_code/Value:bug fixed' => 'バグ修正',
'Class:Incident/Attribute:resolution_code/Value:bug fixed+' => 'バグ修正',
'Class:Incident/Attribute:resolution_code/Value:hardware repair' => 'ハードウエア修理',
'Class:Incident/Attribute:resolution_code/Value:hardware repair+' => 'ハードウエア修理',
'Class:Incident/Attribute:resolution_code/Value:other' => 'その他',
'Class:Incident/Attribute:resolution_code/Value:other+' => 'その他',
'Class:Incident/Attribute:resolution_code/Value:software patch' => 'ソフトウエアパッチ',
'Class:Incident/Attribute:resolution_code/Value:software patch+' => 'ソフトウエアパッチ',
'Class:Incident/Attribute:resolution_code/Value:system update' => 'システム更新',
'Class:Incident/Attribute:resolution_code/Value:system update+' => 'システム更新',
'Class:Incident/Attribute:resolution_code/Value:training' => '研修',
'Class:Incident/Attribute:resolution_code/Value:training+' => '研修',
'Class:Incident/Attribute:solution' => '解決',
'Class:Incident/Attribute:solution+' => '',
'Class:Incident/Attribute:pending_reason' => '保留理由',
'Class:Incident/Attribute:pending_reason+' => '',
'Class:Incident/Attribute:parent_incident_id' => '親インシデント',
'Class:Incident/Attribute:parent_incident_id+' => '',
'Class:Incident/Attribute:parent_change_id' => '親変更',
'Class:Incident/Attribute:parent_change_id+' => '',
'Class:Incident/Attribute:child_incidents_list' => '子インシデント',
'Class:Incident/Attribute:child_incidents_list+' => '',
'Class:Incident/Attribute:public_log' => 'パブリックログ',
'Class:Incident/Attribute:public_log+' => '',
'Class:Incident/Attribute:user_satisfaction' => 'ユーザ満足度',
'Class:Incident/Attribute:user_satisfaction+' => '',
'Class:Incident/Attribute:user_satisfaction/Value:1' => '非常に満足',
'Class:Incident/Attribute:user_satisfaction/Value:1+' => '非常に満足',
'Class:Incident/Attribute:user_satisfaction/Value:2' => '十分満足',
'Class:Incident/Attribute:user_satisfaction/Value:2+' => '十分満足',
'Class:Incident/Attribute:user_satisfaction/Value:3' => '多少不満',
'Class:Incident/Attribute:user_satisfaction/Value:3+' => '多少不満',
'Class:Incident/Attribute:user_satisfaction/Value:4' => '非常に不満',
'Class:Incident/Attribute:user_satisfaction/Value:4+' => '非常に不満',
'Class:Incident/Attribute:user_comment' => 'ユーザコメント',
'Class:Incident/Attribute:user_comment+' => '',
'Class:Incident/Stimulus:ev_assign' => '割り当て',
'Class:Incident/Stimulus:ev_assign+' => '',
'Class:Incident/Stimulus:ev_reassign' => '再割り当て',
'Class:Incident/Stimulus:ev_reassign+' => '',
'Class:Incident/Stimulus:ev_pending' => '保留',
'Class:Incident/Stimulus:ev_pending+' => '',
'Class:Incident/Stimulus:ev_timeout' => 'タイムアウト',
'Class:Incident/Stimulus:ev_timeout+' => '',
'Class:Incident/Stimulus:ev_autoresolve' => '自動解決',
'Class:Incident/Stimulus:ev_autoresolve+' => '',
'Class:Incident/Stimulus:ev_autoclose' => '自動クローズ',
'Class:Incident/Stimulus:ev_autoclose+' => '',
'Class:Incident/Stimulus:ev_resolve' => '解決とマーク',
'Class:Incident/Stimulus:ev_resolve+' => '',
'Class:Incident/Stimulus:ev_close' => 'このリクエストをクローズ',
'Class:Incident/Stimulus:ev_close+' => '',
'Class:Incident/Stimulus:ev_reopen' => '再オープン',
'Class:Incident/Stimulus:ev_reopen+' => '',
'Menu:IncidentManagement' => 'インシデント管理',
'Menu:IncidentManagement+' => 'インシデント管理',
'Menu:Incident:Overview' => '概要',
'Menu:Incident:Overview+' => '概要',
'Menu:NewIncident' => '新規インシデント',
'Menu:NewIncident+' => 'インシデントチケット作成',
'Menu:SearchIncidents' => 'インシデント検索',
'Menu:SearchIncidents+' => 'インシデントチケット検索',
'Menu:Incident:Shortcuts' => 'ショートカット',
'Menu:Incident:Shortcuts+' => '',
'Menu:Incident:MyIncidents' => '担当しているインシデント',
'Menu:Incident:MyIncidents+' => '担当しているインシデント(エージェント)',
'Menu:Incident:EscalatedIncidents' => 'エスカレーションされたインシデント',
'Menu:Incident:EscalatedIncidents+' => 'エスカレーションされたインシデント',
'Menu:Incident:OpenIncidents' => '全オープンインシデント',
'Menu:Incident:OpenIncidents+' => '全オープンインシデント',
'Menu:Incident:UnassignedIncidents' => '未割り当てインシデント',
'Menu:Incident:UnassignedIncidents+' => '未割り当てインシデント',
'Menu:Incident:HelpdeskIncidents' => 'レベル2へ割り当てられたインシデント',
'Menu:Incident:HelpdeskIncidents+' => 'レベル2へ割り当てられたインシデント',
'UI-IncidentManagementOverview-IncidentByPriority-last-14-days' => '最近14日の優先度別インシデント',
'UI-IncidentManagementOverview-Last-14-days' => '最近14日のインシデント数',
'UI-IncidentManagementOverview-OpenIncidentByStatus' => '状態別オープンインシデント',
'UI-IncidentManagementOverview-OpenIncidentByAgent' => 'エージェント別オープンインシデント',
'UI-IncidentManagementOverview-OpenIncidentByCustomer' => '顧客別オープンインシデント',
'Class:Incident/Attribute:status/Value:waiting_for_approval' => '承認待ち',
'Class:Incident/Attribute:status/Value:waiting_for_approval+' => '',
'Class:Incident/Attribute:service_name' => 'サービス名',
'Class:Incident/Attribute:service_name+' => '',
'Class:Incident/Attribute:servicesubcategory_name' => 'サービス中分類名',
'Class:Incident/Attribute:servicesubcategory_name+' => '',
'Class:Incident/Attribute:parent_incident_ref' => '親インシデント参照',
'Class:Incident/Attribute:parent_incident_ref+' => '',
'Class:Incident/Attribute:parent_change_ref' => '親変更参照',
'Class:Incident/Attribute:parent_change_ref+' => '',
'Class:Incident/Attribute:parent_incident_id_friendlyname' => '親インシデント名',
'Class:Incident/Attribute:parent_incident_id_friendlyname+' => '',
));
?>

View File

@@ -98,6 +98,9 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Class:FAQCategory/Attribute:name+' => '',
'Class:FAQCategory/Attribute:faq_list' => 'FAQs',
'Class:FAQCategory/Attribute:faq_list+' => '',
'Menu:ProblemManagement' => 'Problem Management',
'Menu:ProblemManagement+' => 'Problem Management',
'Menu:Problem:Shortcuts' => 'Shortcuts',
'Menu:NewError' => 'Neuer bekannter Fehler',
'Menu:NewError+' => '',
'Menu:SearchError' => 'Nach bekannten Fehler suchen',

View File

@@ -172,6 +172,9 @@ Dict::Add('EN US', 'English', 'English', array(
'Class:FAQCategory/Attribute:faq_list+' => 'All the frequently asked questions related to this category',
));
Dict::Add('EN US', 'English', 'English', array(
'Menu:ProblemManagement' => 'Problem Management',
'Menu:ProblemManagement+' => 'Problem Management',
'Menu:Problem:Shortcuts' => 'Shortcuts',
'Menu:NewError' => 'New known error',
'Menu:NewError+' => 'Creation of a new known error',
'Menu:SearchError' => 'Search for known errors',

View File

@@ -57,7 +57,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:KnownError' => 'Error Conocido',
'Class:KnownError+' => 'Documentación para un error conocido',
'Class:KnownError/Attribute:name' => 'Nombre',
'Class:KnownError/Attribute:name+' => 'Nombre',
'Class:KnownError/Attribute:name+' => 'Nombre del Error Conocido',
'Class:KnownError/Attribute:org_id' => 'Organización',
'Class:KnownError/Attribute:org_id+' => 'Organización',
'Class:KnownError/Attribute:cust_name' => 'Nombre',
@@ -164,14 +164,17 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
//
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Class:FAQCategory' => 'Categoría de Preguntas y Respusta Frecuentes',
'Class:FAQCategory+' => 'Categoría de Preguntas y Respusta Frecuentes',
'Class:FAQCategory' => 'Categoría de Preguntas y Respuesta Frecuentes',
'Class:FAQCategory+' => 'Categoría de Preguntas y Respuesta Frecuentes',
'Class:FAQCategory/Attribute:name' => 'Nombre',
'Class:FAQCategory/Attribute:name+' => 'Nombre',
'Class:FAQCategory/Attribute:name+' => 'Nombre de Categoría de Preguntas y Respuestas Frecuentes',
'Class:FAQCategory/Attribute:faq_list' => 'FAQs',
'Class:FAQCategory/Attribute:faq_list+' => 'FAQs',
));
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Menu:ProblemManagement' => 'Gestión de problemas',
'Menu:ProblemManagement+' => 'Gestión de problemas',
'Menu:Problem:Shortcuts' => 'Acceso Rápido',
'Menu:NewError' => 'Nuevo Error Conocido',
'Menu:NewError+' => 'Nuevo Error Conocido',
'Menu:SearchError' => 'Búsqueda de Errores Conocidos',

View File

@@ -145,6 +145,9 @@ Dict::Add('FR FR', 'French', 'Français', array(
));
Dict::Add('FR FR', 'French', 'Français', array(
'Menu:ProblemManagement' => 'Gestion des problèmes',
'Menu:ProblemManagement+' => 'Gestion des problèmes',
'Menu:Problem:Shortcuts' => 'Raccourcis',
'Menu:NewError' => 'Nouvelle erreur connue',
'Menu:NewError+' => 'Créer une erreur connue',
'Menu:SearchError' => 'Rechercher une erreur connue',

View File

@@ -90,6 +90,9 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Class:lnkDocumentError/Attribute:doc_name+' => '',
'Class:lnkDocumentError/Attribute:error_name' => 'Hiba megnevezése',
'Class:lnkDocumentError/Attribute:error_name+' => '',
'Menu:ProblemManagement' => 'Probléma menedzsment',
'Menu:ProblemManagement+' => '',
'Menu:Problem:Shortcuts' => 'Gyorsmenü',
'Menu:NewError' => 'Új ismert hiba',
'Menu:NewError+' => '',
'Menu:SearchError' => 'Ismert hiba keresés',

View File

@@ -49,102 +49,105 @@
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//
// Class: KnownError
//
Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Class:KnownError' => 'Errori conosciuti',
'Class:KnownError+' => 'Errori documentati per problemi noti',
'Class:KnownError/Attribute:name' => 'Nome',
'Class:KnownError/Attribute:name+' => '',
'Class:KnownError/Attribute:org_id' => 'Cliente ',
'Class:KnownError/Attribute:org_id+' => '',
'Class:KnownError/Attribute:cust_name' => 'Nome del cliente',
'Class:KnownError/Attribute:cust_name+' => '',
'Class:KnownError/Attribute:problem_id' => 'Problema correlato',
'Class:KnownError/Attribute:problem_id+' => '',
'Class:KnownError/Attribute:problem_ref' => 'Ref',
'Class:KnownError/Attribute:problem_ref+' => '',
'Class:KnownError/Attribute:symptom' => 'Sintomo',
'Class:KnownError/Attribute:symptom+' => '',
'Class:KnownError/Attribute:root_cause' => 'Causa principale',
'Class:KnownError/Attribute:root_cause+' => '',
'Class:KnownError/Attribute:workaround' => 'Soluzione temporanea',
'Class:KnownError/Attribute:workaround+' => '',
'Class:KnownError/Attribute:solution' => 'Solutione',
'Class:KnownError/Attribute:solution+' => '',
'Class:KnownError/Attribute:error_code' => 'Codice di errore',
'Class:KnownError/Attribute:error_code+' => '',
'Class:KnownError/Attribute:domain' => 'Dominio',
'Class:KnownError/Attribute:domain+' => '',
'Class:KnownError/Attribute:domain/Value:Application' => 'Applicazione',
'Class:KnownError/Attribute:domain/Value:Application+' => 'Applicazione',
'Class:KnownError/Attribute:domain/Value:Desktop' => 'Desktop',
'Class:KnownError/Attribute:domain/Value:Desktop+' => 'Desktop',
'Class:KnownError/Attribute:domain/Value:Network' => 'Network',
'Class:KnownError/Attribute:domain/Value:Network+' => 'Network',
'Class:KnownError/Attribute:domain/Value:Server' => 'Server',
'Class:KnownError/Attribute:domain/Value:Server+' => 'Server',
'Class:KnownError/Attribute:vendor' => 'Venditore',
'Class:KnownError/Attribute:vendor+' => '',
'Class:KnownError/Attribute:model' => 'Modello',
'Class:KnownError/Attribute:model+' => '',
'Class:KnownError/Attribute:version' => 'Versione',
'Class:KnownError/Attribute:version+' => '',
'Class:KnownError/Attribute:ci_list' => 'CIs',
'Class:KnownError/Attribute:ci_list+' => '',
'Class:KnownError/Attribute:document_list' => 'Documenti',
'Class:KnownError/Attribute:document_list+' => '',
));
//
// Class: lnkInfraError
//
Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Class:lnkInfraError' => 'InfraErrorLinks',
'Class:lnkInfraError+' => 'Infra relativi a un errore noto',
'Class:lnkInfraError/Attribute:infra_id' => 'CI',
'Class:lnkInfraError/Attribute:infra_id+' => '',
'Class:lnkInfraError/Attribute:infra_name' => 'Nome CI',
'Class:lnkInfraError/Attribute:infra_name+' => '',
'Class:lnkInfraError/Attribute:infra_status' => 'CI Stato',
'Class:lnkInfraError/Attribute:infra_status+' => '',
'Class:lnkInfraError/Attribute:error_id' => 'Errore',
'Class:lnkInfraError/Attribute:error_id+' => '',
'Class:lnkInfraError/Attribute:error_name' => 'Nome Errore',
'Class:lnkInfraError/Attribute:error_name+' => '',
'Class:lnkInfraError/Attribute:reason' => 'Motivo',
'Class:lnkInfraError/Attribute:reason+' => '',
));
//
// Class: lnkDocumentError
//
Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Class:lnkDocumentError' => 'DocumentsErrorLinks',
'Class:lnkDocumentError+' => 'Un collegamento tra un documento e un errore noto',
'Class:lnkDocumentError/Attribute:doc_id' => 'Documento',
'Class:lnkDocumentError/Attribute:doc_id+' => '',
'Class:lnkDocumentError/Attribute:doc_name' => 'Nome Documento',
'Class:lnkDocumentError/Attribute:doc_name+' => '',
'Class:lnkDocumentError/Attribute:error_id' => 'Errore',
'Class:lnkDocumentError/Attribute:error_id+' => '',
'Class:lnkDocumentError/Attribute:error_name' => 'Nome Errore',
'Class:lnkDocumentError/Attribute:error_name+' => '',
'Class:lnkDocumentError/Attribute:link_type' => 'Informazione',
'Class:lnkDocumentError/Attribute:link_type+' => '',
));
Dict::Add('IT IT', 'Italian', 'Italian', array(
'Menu:NewError' => 'Nuovo errore conosciuto',
'Menu:NewError+' => 'Creazione di un Nuovo Errore Conosciuto',
'Menu:SearchError' => 'Ricerca per Errori Conosciuti',
'Menu:SearchError+' => 'Ricerca per Errori Conosciuti',
'Menu:Problem:KnownErrors' => 'Tutti gli errori conosciuti',
'Menu:Problem:KnownErrors+' => 'Tutti gli errori conosciuti',
));
//
// Class: KnownError
//
Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Class:KnownError' => 'Errori conosciuti',
'Class:KnownError+' => 'Errori documentati per problemi noti',
'Class:KnownError/Attribute:name' => 'Nome',
'Class:KnownError/Attribute:name+' => '',
'Class:KnownError/Attribute:org_id' => 'Cliente ',
'Class:KnownError/Attribute:org_id+' => '',
'Class:KnownError/Attribute:cust_name' => 'Nome del cliente',
'Class:KnownError/Attribute:cust_name+' => '',
'Class:KnownError/Attribute:problem_id' => 'Problema correlato',
'Class:KnownError/Attribute:problem_id+' => '',
'Class:KnownError/Attribute:problem_ref' => 'Ref',
'Class:KnownError/Attribute:problem_ref+' => '',
'Class:KnownError/Attribute:symptom' => 'Sintomo',
'Class:KnownError/Attribute:symptom+' => '',
'Class:KnownError/Attribute:root_cause' => 'Causa principale',
'Class:KnownError/Attribute:root_cause+' => '',
'Class:KnownError/Attribute:workaround' => 'Soluzione temporanea',
'Class:KnownError/Attribute:workaround+' => '',
'Class:KnownError/Attribute:solution' => 'Solutione',
'Class:KnownError/Attribute:solution+' => '',
'Class:KnownError/Attribute:error_code' => 'Codice di errore',
'Class:KnownError/Attribute:error_code+' => '',
'Class:KnownError/Attribute:domain' => 'Dominio',
'Class:KnownError/Attribute:domain+' => '',
'Class:KnownError/Attribute:domain/Value:Application' => 'Applicazione',
'Class:KnownError/Attribute:domain/Value:Application+' => 'Applicazione',
'Class:KnownError/Attribute:domain/Value:Desktop' => 'Desktop',
'Class:KnownError/Attribute:domain/Value:Desktop+' => 'Desktop',
'Class:KnownError/Attribute:domain/Value:Network' => 'Network',
'Class:KnownError/Attribute:domain/Value:Network+' => 'Network',
'Class:KnownError/Attribute:domain/Value:Server' => 'Server',
'Class:KnownError/Attribute:domain/Value:Server+' => 'Server',
'Class:KnownError/Attribute:vendor' => 'Venditore',
'Class:KnownError/Attribute:vendor+' => '',
'Class:KnownError/Attribute:model' => 'Modello',
'Class:KnownError/Attribute:model+' => '',
'Class:KnownError/Attribute:version' => 'Versione',
'Class:KnownError/Attribute:version+' => '',
'Class:KnownError/Attribute:ci_list' => 'CIs',
'Class:KnownError/Attribute:ci_list+' => '',
'Class:KnownError/Attribute:document_list' => 'Documenti',
'Class:KnownError/Attribute:document_list+' => '',
));
//
// Class: lnkInfraError
//
Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Class:lnkInfraError' => 'InfraErrorLinks',
'Class:lnkInfraError+' => 'Infra relativi a un errore noto',
'Class:lnkInfraError/Attribute:infra_id' => 'CI',
'Class:lnkInfraError/Attribute:infra_id+' => '',
'Class:lnkInfraError/Attribute:infra_name' => 'Nome CI',
'Class:lnkInfraError/Attribute:infra_name+' => '',
'Class:lnkInfraError/Attribute:infra_status' => 'CI Stato',
'Class:lnkInfraError/Attribute:infra_status+' => '',
'Class:lnkInfraError/Attribute:error_id' => 'Errore',
'Class:lnkInfraError/Attribute:error_id+' => '',
'Class:lnkInfraError/Attribute:error_name' => 'Nome Errore',
'Class:lnkInfraError/Attribute:error_name+' => '',
'Class:lnkInfraError/Attribute:reason' => 'Motivo',
'Class:lnkInfraError/Attribute:reason+' => '',
));
//
// Class: lnkDocumentError
//
Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Class:lnkDocumentError' => 'DocumentsErrorLinks',
'Class:lnkDocumentError+' => 'Un collegamento tra un documento e un errore noto',
'Class:lnkDocumentError/Attribute:doc_id' => 'Documento',
'Class:lnkDocumentError/Attribute:doc_id+' => '',
'Class:lnkDocumentError/Attribute:doc_name' => 'Nome Documento',
'Class:lnkDocumentError/Attribute:doc_name+' => '',
'Class:lnkDocumentError/Attribute:error_id' => 'Errore',
'Class:lnkDocumentError/Attribute:error_id+' => '',
'Class:lnkDocumentError/Attribute:error_name' => 'Nome Errore',
'Class:lnkDocumentError/Attribute:error_name+' => '',
'Class:lnkDocumentError/Attribute:link_type' => 'Informazione',
'Class:lnkDocumentError/Attribute:link_type+' => '',
));
Dict::Add('IT IT', 'Italian', 'Italian', array(
'Menu:ProblemManagement' => 'Gestione dei Problemi',
'Menu:ProblemManagement+' => 'Gestione dei Problemi',
'Menu:Problem:Shortcuts' => 'Scorciatoia',
'Menu:NewError' => 'Nuovo errore conosciuto',
'Menu:NewError+' => 'Creazione di un Nuovo Errore Conosciuto',
'Menu:SearchError' => 'Ricerca per Errori Conosciuti',
'Menu:SearchError+' => 'Ricerca per Errori Conosciuti',
'Menu:Problem:KnownErrors' => 'Tutti gli errori conosciuti',
'Menu:Problem:KnownErrors+' => 'Tutti gli errori conosciuti',
));
?>

View File

@@ -1,187 +1,127 @@
<?php
// Copyright (C) 2010-2012 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/>
/**
* Localized data
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
// Class:<class_name>/Attribute:<attribute_code>
// Class:<class_name>/Attribute:<attribute_code>+
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//////////////////////////////////////////////////////////////////////
// Classes in 'bizmodel'
//////////////////////////////////////////////////////////////////////
//
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
// Class:<class_name>/Attribute:<attribute_code>
// Class:<class_name>/Attribute:<attribute_code>+
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//
// Class: KnownError
//
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:KnownError' => '既知のエラー',
'Class:KnownError+' => '既知の課題として文書化されたエラー',
'Class:KnownError/Attribute:name' => '名前',
'Class:KnownError/Attribute:name+' => '',
'Class:KnownError/Attribute:org_id' => '顧客',
'Class:KnownError/Attribute:org_id+' => '',
'Class:KnownError/Attribute:cust_name' => '顧客名',
'Class:KnownError/Attribute:cust_name+' => '',
'Class:KnownError/Attribute:problem_id' => '関連する問題',
'Class:KnownError/Attribute:problem_id+' => '',
'Class:KnownError/Attribute:problem_ref' => '参照',
'Class:KnownError/Attribute:problem_ref+' => '',
'Class:KnownError/Attribute:symptom' => '現象',
'Class:KnownError/Attribute:symptom+' => '',
'Class:KnownError/Attribute:root_cause' => '根本的な原因',
'Class:KnownError/Attribute:root_cause+' => '',
'Class:KnownError/Attribute:workaround' => '回避策',
'Class:KnownError/Attribute:workaround+' => '',
'Class:KnownError/Attribute:solution' => '解決策',
'Class:KnownError/Attribute:solution+' => '',
'Class:KnownError/Attribute:error_code' => 'エラーコード',
'Class:KnownError/Attribute:error_code+' => '',
'Class:KnownError/Attribute:domain' => 'ドメイン',
'Class:KnownError/Attribute:domain+' => '',
'Class:KnownError/Attribute:domain/Value:Application' => 'アプリケーション',
'Class:KnownError/Attribute:domain/Value:Application+' => 'アプリケーション',
'Class:KnownError/Attribute:domain/Value:Desktop' => 'デスクトップ',
'Class:KnownError/Attribute:domain/Value:Desktop+' => 'デスクトップ',
'Class:KnownError/Attribute:domain/Value:Network' => 'ネットワーク',
'Class:KnownError/Attribute:domain/Value:Network+' => 'ネットワーク',
'Class:KnownError/Attribute:domain/Value:Server' => 'サーバ',
'Class:KnownError/Attribute:domain/Value:Server+' => 'サーバ',
'Class:KnownError/Attribute:vendor' => 'ベンダー',
'Class:KnownError/Attribute:vendor+' => '',
'Class:KnownError/Attribute:model' => 'モデル',
'Class:KnownError/Attribute:model+' => '',
'Class:KnownError/Attribute:version' => 'バージョン',
'Class:KnownError/Attribute:version+' => '',
'Class:KnownError/Attribute:ci_list' => 'CI',
'Class:KnownError/Attribute:ci_list+' => '',
'Class:KnownError/Attribute:document_list' => '文書',
'Class:KnownError/Attribute:document_list+' => '',
));
//
// Class: lnkErrorToFunctionalCI
//
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:lnkErrorToFunctionalCI' => 'リンク エラー/機能的CI',
'Class:lnkErrorToFunctionalCI+' => '既知のエラーに関連するインフラ',
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_id' => 'CI',
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_id+' => '',
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_name' => 'CI名',
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_name+' => '',
'Class:lnkErrorToFunctionalCI/Attribute:error_id' => 'エラー',
'Class:lnkErrorToFunctionalCI/Attribute:error_id+' => '',
'Class:lnkErrorToFunctionalCI/Attribute:error_name' => 'エラー名',
'Class:lnkErrorToFunctionalCI/Attribute:error_name+' => '',
'Class:lnkErrorToFunctionalCI/Attribute:reason' => '理由',
'Class:lnkErrorToFunctionalCI/Attribute:reason+' => '',
));
//
// Class: lnkDocumentToError
//
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:lnkDocumentToError' => 'リンク 文書/エラー',
'Class:lnkDocumentToError+' => '文書と既知のエラー間のリンク',
'Class:lnkDocumentToError/Attribute:document_id' => '文書',
'Class:lnkDocumentToError/Attribute:document_id+' => '',
'Class:lnkDocumentToError/Attribute:document_name' => '文書名',
'Class:lnkDocumentToError/Attribute:document_name+' => '',
'Class:lnkDocumentToError/Attribute:error_id' => 'エラー',
'Class:lnkDocumentToError/Attribute:error_id+' => '',
'Class:lnkDocumentToError/Attribute:error_name' => 'エラー名',
'Class:lnkDocumentToError/Attribute:error_name+' => '',
'Class:lnkDocumentToError/Attribute:link_type' => 'リンクタイプ',
'Class:lnkDocumentToError/Attribute:link_type+' => '',
));
//
// Class: FAQ
//
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:FAQ' => 'FAQ',
'Class:FAQ+' => 'よくある質問',
'Class:FAQ/Attribute:title' => 'タイトル',
'Class:FAQ/Attribute:title+' => '',
'Class:FAQ/Attribute:summary' => '要約',
'Class:FAQ/Attribute:summary+' => '',
'Class:FAQ/Attribute:description' => '説明',
'Class:FAQ/Attribute:description+' => '',
'Class:FAQ/Attribute:category_id' => 'カテゴリ',
'Class:FAQ/Attribute:category_id+' => '',
'Class:FAQ/Attribute:category_name' => 'カテゴリ名',
'Class:FAQ/Attribute:category_name+' => '',
'Class:FAQ/Attribute:error_code' => 'エラーコード',
'Class:FAQ/Attribute:error_code+' => '',
'Class:FAQ/Attribute:key_words' => 'キーワード',
'Class:FAQ/Attribute:key_words+' => '',
));
//
// Class: FAQcategory
//
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:FAQCategory' => 'FAQカテゴリ',
'Class:FAQCategory+' => 'FAQのためのカテゴリ',
'Class:FAQCategory/Attribute:name' => '名前',
'Class:FAQCategory/Attribute:name+' => '',
'Class:FAQCategory/Attribute:faq_list' => 'FAQ',
'Class:FAQCategory/Attribute:faq_list+' => '',
));
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Menu:NewError' => '新規既知のエラー',
'Menu:NewError+' => '新規既知のエラーの作成',
'Menu:SearchError' => '既知のエラー検索',
'Menu:SearchError+' => '既知のエラー検索',
'Menu:Problem:KnownErrors' => '全ての既知のエラー',
'Menu:Problem:KnownErrors+' => '全ての既知のエラー',
'Menu:FAQCategory' => 'FAQカテゴリ',
'Menu:FAQCategory+' => '全てのFAQカテゴリ',
'Menu:FAQ' => 'FAQ',
'Menu:FAQ+' => '全FAQ',
));
?>
<?php
// Copyright (C) 2010-2012 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/>
/**
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @licence http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:KnownError' => '既知のエラー',
'Class:KnownError+' => '既知の課題として文書化されたエラー',
'Class:KnownError/Attribute:name' => '名前',
'Class:KnownError/Attribute:name+' => '',
'Class:KnownError/Attribute:org_id' => '顧客',
'Class:KnownError/Attribute:org_id+' => '',
'Class:KnownError/Attribute:problem_id' => '関連する問題',
'Class:KnownError/Attribute:problem_id+' => '',
'Class:KnownError/Attribute:symptom' => '現象',
'Class:KnownError/Attribute:symptom+' => '',
'Class:KnownError/Attribute:root_cause' => '根本的な原因',
'Class:KnownError/Attribute:root_cause+' => '',
'Class:KnownError/Attribute:workaround' => '回避策',
'Class:KnownError/Attribute:workaround+' => '',
'Class:KnownError/Attribute:solution' => '解決策',
'Class:KnownError/Attribute:solution+' => '',
'Class:KnownError/Attribute:error_code' => 'エラーコード',
'Class:KnownError/Attribute:error_code+' => '',
'Class:KnownError/Attribute:domain' => 'ドメイン',
'Class:KnownError/Attribute:domain+' => '',
'Class:KnownError/Attribute:domain/Value:Application' => 'アプリケーション',
'Class:KnownError/Attribute:domain/Value:Application+' => 'アプリケーション',
'Class:KnownError/Attribute:domain/Value:Desktop' => 'デスクトップ',
'Class:KnownError/Attribute:domain/Value:Desktop+' => 'デスクトップ',
'Class:KnownError/Attribute:domain/Value:Network' => 'ネットワーク',
'Class:KnownError/Attribute:domain/Value:Network+' => 'ネットワーク',
'Class:KnownError/Attribute:domain/Value:Server' => 'サーバ',
'Class:KnownError/Attribute:domain/Value:Server+' => 'サーバ',
'Class:KnownError/Attribute:vendor' => 'ベンダー',
'Class:KnownError/Attribute:vendor+' => '',
'Class:KnownError/Attribute:model' => 'モデル',
'Class:KnownError/Attribute:model+' => '',
'Class:KnownError/Attribute:version' => 'バージョン',
'Class:KnownError/Attribute:version+' => '',
'Class:KnownError/Attribute:ci_list' => 'CI',
'Class:KnownError/Attribute:ci_list+' => '',
'Class:KnownError/Attribute:document_list' => '文書',
'Class:KnownError/Attribute:document_list+' => '',
'Class:lnkErrorToFunctionalCI' => 'リンク エラー/機能的CI',
'Class:lnkErrorToFunctionalCI+' => '既知のエラーに関連するインフラ',
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_id' => 'CI',
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_id+' => '',
'Class:lnkErrorToFunctionalCI/Attribute:error_id' => 'エラー',
'Class:lnkErrorToFunctionalCI/Attribute:error_id+' => '',
'Class:lnkErrorToFunctionalCI/Attribute:reason' => '理由',
'Class:lnkErrorToFunctionalCI/Attribute:reason+' => '',
'Class:lnkDocumentToError' => 'リンク 文書/エラー',
'Class:lnkDocumentToError+' => '文書と既知のエラー間のリンク',
'Class:lnkDocumentToError/Attribute:document_id' => '文書',
'Class:lnkDocumentToError/Attribute:document_id+' => '',
'Class:lnkDocumentToError/Attribute:error_id' => 'エラー',
'Class:lnkDocumentToError/Attribute:error_id+' => '',
'Class:lnkDocumentToError/Attribute:link_type' => 'リンクタイプ',
'Class:lnkDocumentToError/Attribute:link_type+' => '',
'Class:FAQ' => 'FAQ',
'Class:FAQ+' => 'よくある質問',
'Class:FAQ/Attribute:title' => 'タイトル',
'Class:FAQ/Attribute:title+' => '',
'Class:FAQ/Attribute:summary' => '要約',
'Class:FAQ/Attribute:summary+' => '',
'Class:FAQ/Attribute:description' => '説明',
'Class:FAQ/Attribute:description+' => '',
'Class:FAQ/Attribute:category_id' => 'カテゴリ',
'Class:FAQ/Attribute:category_id+' => '',
'Class:FAQ/Attribute:error_code' => 'エラーコード',
'Class:FAQ/Attribute:error_code+' => '',
'Class:FAQ/Attribute:key_words' => 'キーワード',
'Class:FAQ/Attribute:key_words+' => '',
'Class:FAQCategory' => 'FAQカテゴリ',
'Class:FAQCategory+' => 'FAQのためのカテゴリ',
'Class:FAQCategory/Attribute:name' => '名前',
'Class:FAQCategory/Attribute:name+' => '',
'Class:FAQCategory/Attribute:faq_list' => 'FAQ',
'Class:FAQCategory/Attribute:faq_list+' => '',
'Class:KnownError/Attribute:cust_name' => '顧客名',
'Class:KnownError/Attribute:cust_name+' => '',
'Class:KnownError/Attribute:problem_ref' => '参照',
'Class:KnownError/Attribute:problem_ref+' => '',
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_name' => 'CI名',
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_name+' => '',
'Class:lnkErrorToFunctionalCI/Attribute:error_name' => 'エラー名',
'Class:lnkErrorToFunctionalCI/Attribute:error_name+' => '',
'Class:lnkDocumentToError/Attribute:document_name' => '文書名',
'Class:lnkDocumentToError/Attribute:document_name+' => '',
'Class:lnkDocumentToError/Attribute:error_name' => 'エラー名',
'Class:lnkDocumentToError/Attribute:error_name+' => '',
'Class:FAQ/Attribute:category_name' => 'カテゴリ名',
'Class:FAQ/Attribute:category_name+' => '',
'Menu:ProblemManagement' => '問題管理',
'Menu:ProblemManagement+' => '問題管理',
'Menu:Problem:Shortcuts' => 'ショートカット',
'Menu:NewError' => '新規既知のエラー',
'Menu:NewError+' => '新規既知のエラーの作成',
'Menu:SearchError' => '既知のエラー検索',
'Menu:SearchError+' => '既知のエラー検索',
'Menu:Problem:KnownErrors' => '全ての既知のエラー',
'Menu:Problem:KnownErrors+' => '全ての既知のエラー',
'Menu:FAQCategory' => 'FAQカテゴリ',
'Menu:FAQCategory+' => '全てのFAQカテゴリ',
'Menu:FAQ' => 'FAQ',
'Menu:FAQ+' => '全FAQ',
));
?>

View File

@@ -91,6 +91,9 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Class:lnkDocumentError/Attribute:doc_name+' => '',
'Class:lnkDocumentError/Attribute:error_name' => 'Nome Erro',
'Class:lnkDocumentError/Attribute:error_name+' => '',
'Menu:ProblemManagement' => 'Gerenciamento Problemas',
'Menu:ProblemManagement+' => 'Gerenciamento Problemas',
'Menu:Problem:Shortcuts' => 'Atalhos',
'Menu:NewError' => 'Novo erro conhecido',
'Menu:NewError+' => 'Criação de um novo erro conhecido',
'Menu:SearchError' => 'Pesquisar Erros Conhecidos',

View File

@@ -98,6 +98,9 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Class:FAQCategory/Attribute:name+' => '',
'Class:FAQCategory/Attribute:faq_list' => 'FAQs~~',
'Class:FAQCategory/Attribute:faq_list+' => '',
'Menu:ProblemManagement' => 'Управление проблемами',
'Menu:ProblemManagement+' => 'Управление проблемами',
'Menu:Problem:Shortcuts' => 'Ярлыки',
'Menu:NewError' => 'Новая известная ошибка',
'Menu:NewError+' => 'Создание новой известной ошибки',
'Menu:SearchError' => 'Поиск известных ошибок',

View File

@@ -50,102 +50,105 @@
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//
// Class: KnownError
//
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Class:KnownError' => 'Bilinen hata',
'Class:KnownError+' => 'Hata bilinen hatalara kaydedildi',
'Class:KnownError/Attribute:name' => 'Adı',
'Class:KnownError/Attribute:name+' => '',
'Class:KnownError/Attribute:org_id' => 'Müşteri',
'Class:KnownError/Attribute:org_id+' => '',
'Class:KnownError/Attribute:cust_name' => 'Müşteri Adı',
'Class:KnownError/Attribute:cust_name+' => '',
'Class:KnownError/Attribute:problem_id' => 'İlgili problem',
'Class:KnownError/Attribute:problem_id+' => '',
'Class:KnownError/Attribute:problem_ref' => 'Referans',
'Class:KnownError/Attribute:problem_ref+' => '',
'Class:KnownError/Attribute:symptom' => 'Belirtisi',
'Class:KnownError/Attribute:symptom+' => '',
'Class:KnownError/Attribute:root_cause' => 'Ana sebep',
'Class:KnownError/Attribute:root_cause+' => '',
'Class:KnownError/Attribute:workaround' => 'Ara çözüm',
'Class:KnownError/Attribute:workaround+' => '',
'Class:KnownError/Attribute:solution' => 'Çözüm',
'Class:KnownError/Attribute:solution+' => '',
'Class:KnownError/Attribute:error_code' => 'Hata kodu',
'Class:KnownError/Attribute:error_code+' => '',
'Class:KnownError/Attribute:domain' => 'Etki alanı',
'Class:KnownError/Attribute:domain+' => '',
'Class:KnownError/Attribute:domain/Value:Application' => 'Uygulama',
'Class:KnownError/Attribute:domain/Value:Application+' => 'Uygulama',
'Class:KnownError/Attribute:domain/Value:Desktop' => 'Masaüstü',
'Class:KnownError/Attribute:domain/Value:Desktop+' => 'Masaüstü',
'Class:KnownError/Attribute:domain/Value:Network' => 'Ağ',
'Class:KnownError/Attribute:domain/Value:Network+' => 'Ağ',
'Class:KnownError/Attribute:domain/Value:Server' => 'Sunucu',
'Class:KnownError/Attribute:domain/Value:Server+' => 'Sunucu',
'Class:KnownError/Attribute:vendor' => 'Üretici',
'Class:KnownError/Attribute:vendor+' => '',
'Class:KnownError/Attribute:model' => 'Model',
'Class:KnownError/Attribute:model+' => '',
'Class:KnownError/Attribute:version' => 'Versiyon',
'Class:KnownError/Attribute:version+' => '',
'Class:KnownError/Attribute:ci_list' => 'KKler',
'Class:KnownError/Attribute:ci_list+' => '',
'Class:KnownError/Attribute:document_list' => 'Dokümanlar',
'Class:KnownError/Attribute:document_list+' => '',
));
//
// Class: lnkInfraError
//
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Class:lnkInfraError' => 'Altyapı hata bağlantısı',
'Class:lnkInfraError+' => 'Alyapı ile ilgili bilinen hata',
'Class:lnkInfraError/Attribute:infra_id' => 'KK',
'Class:lnkInfraError/Attribute:infra_id+' => '',
'Class:lnkInfraError/Attribute:infra_name' => 'KK Adı',
'Class:lnkInfraError/Attribute:infra_name+' => '',
'Class:lnkInfraError/Attribute:infra_status' => 'KK durumu',
'Class:lnkInfraError/Attribute:infra_status+' => '',
'Class:lnkInfraError/Attribute:error_id' => 'Hata',
'Class:lnkInfraError/Attribute:error_id+' => '',
'Class:lnkInfraError/Attribute:error_name' => 'Hata adı',
'Class:lnkInfraError/Attribute:error_name+' => '',
'Class:lnkInfraError/Attribute:reason' => 'Sebep',
'Class:lnkInfraError/Attribute:reason+' => '',
));
//
// Class: lnkDocumentError
//
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Class:lnkDocumentError' => 'Bağlı Doküman hatası',
'Class:lnkDocumentError+' => 'Doküman ve bilinen hata bağlantısı',
'Class:lnkDocumentError/Attribute:doc_id' => 'Doküman',
'Class:lnkDocumentError/Attribute:doc_id+' => '',
'Class:lnkDocumentError/Attribute:doc_name' => 'Doküman Adı',
'Class:lnkDocumentError/Attribute:doc_name+' => '',
'Class:lnkDocumentError/Attribute:error_id' => 'Hata',
'Class:lnkDocumentError/Attribute:error_id+' => '',
'Class:lnkDocumentError/Attribute:error_name' => 'Hata Adı',
'Class:lnkDocumentError/Attribute:error_name+' => '',
'Class:lnkDocumentError/Attribute:link_type' => 'Bilgi',
'Class:lnkDocumentError/Attribute:link_type+' => '',
));
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Menu:NewError' => 'Yeni bilinen hata',
'Menu:NewError+' => 'Yeni bilinen hata yatarımı',
'Menu:SearchError' => 'Bilinen hataları ara',
'Menu:SearchError+' => 'Bilinen hataları ara',
'Menu:Problem:KnownErrors' => 'Tüm bilinen hatalar',
'Menu:Problem:KnownErrors+' => 'Tüm bilinen hatalar',
));
//
// Class: KnownError
//
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Class:KnownError' => 'Bilinen hata',
'Class:KnownError+' => 'Hata bilinen hatalara kaydedildi',
'Class:KnownError/Attribute:name' => 'Adı',
'Class:KnownError/Attribute:name+' => '',
'Class:KnownError/Attribute:org_id' => 'Müşteri',
'Class:KnownError/Attribute:org_id+' => '',
'Class:KnownError/Attribute:cust_name' => 'Müşteri Adı',
'Class:KnownError/Attribute:cust_name+' => '',
'Class:KnownError/Attribute:problem_id' => 'İlgili problem',
'Class:KnownError/Attribute:problem_id+' => '',
'Class:KnownError/Attribute:problem_ref' => 'Referans',
'Class:KnownError/Attribute:problem_ref+' => '',
'Class:KnownError/Attribute:symptom' => 'Belirtisi',
'Class:KnownError/Attribute:symptom+' => '',
'Class:KnownError/Attribute:root_cause' => 'Ana sebep',
'Class:KnownError/Attribute:root_cause+' => '',
'Class:KnownError/Attribute:workaround' => 'Ara çözüm',
'Class:KnownError/Attribute:workaround+' => '',
'Class:KnownError/Attribute:solution' => 'Çözüm',
'Class:KnownError/Attribute:solution+' => '',
'Class:KnownError/Attribute:error_code' => 'Hata kodu',
'Class:KnownError/Attribute:error_code+' => '',
'Class:KnownError/Attribute:domain' => 'Etki alanı',
'Class:KnownError/Attribute:domain+' => '',
'Class:KnownError/Attribute:domain/Value:Application' => 'Uygulama',
'Class:KnownError/Attribute:domain/Value:Application+' => 'Uygulama',
'Class:KnownError/Attribute:domain/Value:Desktop' => 'Masaüstü',
'Class:KnownError/Attribute:domain/Value:Desktop+' => 'Masaüstü',
'Class:KnownError/Attribute:domain/Value:Network' => 'Ağ',
'Class:KnownError/Attribute:domain/Value:Network+' => 'Ağ',
'Class:KnownError/Attribute:domain/Value:Server' => 'Sunucu',
'Class:KnownError/Attribute:domain/Value:Server+' => 'Sunucu',
'Class:KnownError/Attribute:vendor' => 'Üretici',
'Class:KnownError/Attribute:vendor+' => '',
'Class:KnownError/Attribute:model' => 'Model',
'Class:KnownError/Attribute:model+' => '',
'Class:KnownError/Attribute:version' => 'Versiyon',
'Class:KnownError/Attribute:version+' => '',
'Class:KnownError/Attribute:ci_list' => 'KKler',
'Class:KnownError/Attribute:ci_list+' => '',
'Class:KnownError/Attribute:document_list' => 'Dokümanlar',
'Class:KnownError/Attribute:document_list+' => '',
));
//
// Class: lnkInfraError
//
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Class:lnkInfraError' => 'Altyapı hata bağlantısı',
'Class:lnkInfraError+' => 'Alyapı ile ilgili bilinen hata',
'Class:lnkInfraError/Attribute:infra_id' => 'KK',
'Class:lnkInfraError/Attribute:infra_id+' => '',
'Class:lnkInfraError/Attribute:infra_name' => 'KK Adı',
'Class:lnkInfraError/Attribute:infra_name+' => '',
'Class:lnkInfraError/Attribute:infra_status' => 'KK durumu',
'Class:lnkInfraError/Attribute:infra_status+' => '',
'Class:lnkInfraError/Attribute:error_id' => 'Hata',
'Class:lnkInfraError/Attribute:error_id+' => '',
'Class:lnkInfraError/Attribute:error_name' => 'Hata adı',
'Class:lnkInfraError/Attribute:error_name+' => '',
'Class:lnkInfraError/Attribute:reason' => 'Sebep',
'Class:lnkInfraError/Attribute:reason+' => '',
));
//
// Class: lnkDocumentError
//
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Class:lnkDocumentError' => 'Bağlı Doküman hatası',
'Class:lnkDocumentError+' => 'Doküman ve bilinen hata bağlantısı',
'Class:lnkDocumentError/Attribute:doc_id' => 'Doküman',
'Class:lnkDocumentError/Attribute:doc_id+' => '',
'Class:lnkDocumentError/Attribute:doc_name' => 'Doküman Adı',
'Class:lnkDocumentError/Attribute:doc_name+' => '',
'Class:lnkDocumentError/Attribute:error_id' => 'Hata',
'Class:lnkDocumentError/Attribute:error_id+' => '',
'Class:lnkDocumentError/Attribute:error_name' => 'Hata Adı',
'Class:lnkDocumentError/Attribute:error_name+' => '',
'Class:lnkDocumentError/Attribute:link_type' => 'Bilgi',
'Class:lnkDocumentError/Attribute:link_type+' => '',
));
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Menu:ProblemManagement' => 'Problem Yönetimi',
'Menu:ProblemManagement+' => 'Problem Yönetimi',
'Menu:Problem:Shortcuts' => 'Kısayollar',
'Menu:NewError' => 'Yeni bilinen hata',
'Menu:NewError+' => 'Yeni bilinen hata yatarımı',
'Menu:SearchError' => 'Bilinen hataları ara',
'Menu:SearchError+' => 'Bilinen hataları ara',
'Menu:Problem:KnownErrors' => 'Tüm bilinen hatalar',
'Menu:Problem:KnownErrors+' => 'Tüm bilinen hatalar',
));
?>

View File

@@ -141,6 +141,9 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
));
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Menu:ProblemManagement' => '问题管理',
'Menu:ProblemManagement+' => '问题管理',
'Menu:Problem:Shortcuts' => '快捷方式',
'Menu:NewError' => '新的已知错误',
'Menu:NewError+' => '新已知错误的创建',
'Menu:SearchError' => '搜索已知错误',

View File

@@ -1,156 +1,117 @@
<?php
// Copyright (C) 2010-2012 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/>
/**
* Localized data
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
// Class:<class_name>/Attribute:<attribute_code>
// Class:<class_name>/Attribute:<attribute_code>+
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//////////////////////////////////////////////////////////////////////
// Classes in 'bizmodel'
//////////////////////////////////////////////////////////////////////
//
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
// Class:<class_name>/Attribute:<attribute_code>
// Class:<class_name>/Attribute:<attribute_code>+
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Menu:ProblemManagement' => '問題管理',
'Menu:ProblemManagement+' => '問題管理',
'Menu:Problem:Overview' => '概要',
'Menu:Problem:Overview+' => '概要',
'Menu:NewProblem' => '新規問題',
'Menu:NewProblem+' => '新規問題',
'Menu:SearchProblems' => '問題検索',
'Menu:SearchProblems+' => '問題検索',
'Menu:Problem:Shortcuts' => 'ショートカット',
'Menu:Problem:MyProblems' => '担当してる問題',
'Menu:Problem:MyProblems+' => '担当している問題',
'Menu:Problem:OpenProblems' => '全オープン問題',
'Menu:Problem:OpenProblems+' => '全オープン問題',
'UI-ProblemManagementOverview-ProblemByService' => 'サービス別問題',
'UI-ProblemManagementOverview-ProblemByService+' => 'サービス別問題',
'UI-ProblemManagementOverview-ProblemByPriority' => '優先度別問題',
'UI-ProblemManagementOverview-ProblemByPriority+' => '優先度別問題',
'UI-ProblemManagementOverview-ProblemUnassigned' => '割り当て問題',
'UI-ProblemManagementOverview-ProblemUnassigned+' => '未割り当て問題',
'UI:ProblemMgmtMenuOverview:Title' => '問題管理ダッシュボード',
'UI:ProblemMgmtMenuOverview:Title+' => '問題管理ダッシュボード',
));
//
// Class: Problem
//
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:Problem' => '問題',
'Class:Problem+' => '',
'Class:Problem/Attribute:status' => '状態',
'Class:Problem/Attribute:status+' => '',
'Class:Problem/Attribute:status/Value:new' => '新規',
'Class:Problem/Attribute:status/Value:new+' => '',
'Class:Problem/Attribute:status/Value:assigned' => '割り当て済み',
'Class:Problem/Attribute:status/Value:assigned+' => '',
'Class:Problem/Attribute:status/Value:resolved' => '解決済み',
'Class:Problem/Attribute:status/Value:resolved+' => '',
'Class:Problem/Attribute:status/Value:closed' => 'クローズ',
'Class:Problem/Attribute:status/Value:closed+' => '',
'Class:Problem/Attribute:service_id' => 'サービス',
'Class:Problem/Attribute:service_id+' => '',
'Class:Problem/Attribute:service_name' => 'サービス名',
'Class:Problem/Attribute:service_name+' => '',
'Class:Problem/Attribute:servicesubcategory_id' => 'サービスサブカテゴリ',
'Class:Problem/Attribute:servicesubcategory_id+' => '',
'Class:Problem/Attribute:servicesubcategory_name' => 'サービスサブカテゴリ',
'Class:Problem/Attribute:servicesubcategory_name+' => '',
'Class:Problem/Attribute:product' => '製品',
'Class:Problem/Attribute:product+' => '',
'Class:Problem/Attribute:impact' => 'インパクト',
'Class:Problem/Attribute:impact+' => '',
'Class:Problem/Attribute:impact/Value:1' => '部門',
'Class:Problem/Attribute:impact/Value:1+' => '',
'Class:Problem/Attribute:impact/Value:2' => 'サービス',
'Class:Problem/Attribute:impact/Value:2+' => '',
'Class:Problem/Attribute:impact/Value:3' => '人',
'Class:Problem/Attribute:impact/Value:3+' => '',
'Class:Problem/Attribute:urgency' => '緊急度',
'Class:Problem/Attribute:urgency+' => '',
'Class:Problem/Attribute:urgency/Value:1' => '至急',
'Class:Problem/Attribute:urgency/Value:1+' => '至急',
'Class:Problem/Attribute:urgency/Value:2' => '高',
'Class:Problem/Attribute:urgency/Value:2+' => '高',
'Class:Problem/Attribute:urgency/Value:3' => '中',
'Class:Problem/Attribute:urgency/Value:3+' => '中',
'Class:Problem/Attribute:urgency/Value:4' => '低',
'Class:Problem/Attribute:urgency/Value:4+' => '低',
'Class:Problem/Attribute:priority' => '優先度',
'Class:Problem/Attribute:priority+' => '',
'Class:Problem/Attribute:priority/Value:1' => '最優先',
'Class:Problem/Attribute:priority/Value:1+' => '最優先',
'Class:Problem/Attribute:priority/Value:2' => '高',
'Class:Problem/Attribute:priority/Value:2+' => '高',
'Class:Problem/Attribute:priority/Value:3' => '中',
'Class:Problem/Attribute:priority/Value:3+' => '中',
'Class:Problem/Attribute:priority/Value:4' => '低',
'Class:Problem/Attribute:priority/Value:4+' => '低',
'Class:Problem/Attribute:related_change_id' => '関連する変更',
'Class:Problem/Attribute:related_change_id+' => '',
'Class:Problem/Attribute:related_change_ref' => '関連する変更参照',
'Class:Problem/Attribute:related_change_ref+' => '',
'Class:Problem/Attribute:assignment_date' => '割り当て日',
'Class:Problem/Attribute:assignment_date+' => '',
'Class:Problem/Attribute:resolution_date' => '解決日',
'Class:Problem/Attribute:resolution_date+' => '',
'Class:Problem/Attribute:knownerrors_list' => '既知のエラー',
'Class:Problem/Attribute:knownerrors_list+' => '',
'Class:Problem/Attribute:related_request_list' => '関連する要求',
'Class:Problem/Attribute:related_request_list+' => '',
'Class:Problem/Stimulus:ev_assign' => '割り当て',
'Class:Problem/Stimulus:ev_assign+' => '',
'Class:Problem/Stimulus:ev_reassign' => '再割り当て',
'Class:Problem/Stimulus:ev_reassign+' => '',
'Class:Problem/Stimulus:ev_resolve' => '解決',
'Class:Problem/Stimulus:ev_resolve+' => '',
'Class:Problem/Stimulus:ev_close' => 'クローズ',
'Class:Problem/Stimulus:ev_close+' => '',
));
?>
<?php
// Copyright (C) 2010-2012 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/>
/**
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @licence http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:Problem' => '問題',
'Class:Problem+' => '',
'Class:Problem/Attribute:status' => '状態',
'Class:Problem/Attribute:status+' => '',
'Class:Problem/Attribute:status/Value:new' => '新規',
'Class:Problem/Attribute:status/Value:new+' => '',
'Class:Problem/Attribute:status/Value:assigned' => '割り当て済み',
'Class:Problem/Attribute:status/Value:assigned+' => '',
'Class:Problem/Attribute:status/Value:resolved' => '解決済み',
'Class:Problem/Attribute:status/Value:resolved+' => '',
'Class:Problem/Attribute:status/Value:closed' => 'クローズ',
'Class:Problem/Attribute:status/Value:closed+' => '',
'Class:Problem/Attribute:service_id' => 'サービス',
'Class:Problem/Attribute:service_id+' => '',
'Class:Problem/Attribute:servicesubcategory_id' => 'サービスサブカテゴリ',
'Class:Problem/Attribute:servicesubcategory_id+' => '',
'Class:Problem/Attribute:product' => '製品',
'Class:Problem/Attribute:product+' => '',
'Class:Problem/Attribute:impact' => 'インパクト',
'Class:Problem/Attribute:impact+' => '',
'Class:Problem/Attribute:impact/Value:1' => '部門',
'Class:Problem/Attribute:impact/Value:1+' => '',
'Class:Problem/Attribute:impact/Value:2' => 'サービス',
'Class:Problem/Attribute:impact/Value:2+' => '',
'Class:Problem/Attribute:impact/Value:3' => '人',
'Class:Problem/Attribute:impact/Value:3+' => '',
'Class:Problem/Attribute:urgency' => '緊急度',
'Class:Problem/Attribute:urgency+' => '',
'Class:Problem/Attribute:urgency/Value:1' => '至急',
'Class:Problem/Attribute:urgency/Value:1+' => '至急',
'Class:Problem/Attribute:urgency/Value:2' => '',
'Class:Problem/Attribute:urgency/Value:2+' => '',
'Class:Problem/Attribute:urgency/Value:3' => '',
'Class:Problem/Attribute:urgency/Value:3+' => '',
'Class:Problem/Attribute:urgency/Value:4' => '',
'Class:Problem/Attribute:urgency/Value:4+' => '',
'Class:Problem/Attribute:priority' => '優先度',
'Class:Problem/Attribute:priority+' => '',
'Class:Problem/Attribute:priority/Value:1' => '最優先',
'Class:Problem/Attribute:priority/Value:1+' => '最優先',
'Class:Problem/Attribute:priority/Value:2' => '',
'Class:Problem/Attribute:priority/Value:2+' => '',
'Class:Problem/Attribute:priority/Value:3' => '',
'Class:Problem/Attribute:priority/Value:3+' => '',
'Class:Problem/Attribute:priority/Value:4' => '',
'Class:Problem/Attribute:priority/Value:4+' => '',
'Class:Problem/Attribute:related_change_id' => '関連する変更',
'Class:Problem/Attribute:related_change_id+' => '',
'Class:Problem/Attribute:assignment_date' => '割り当て',
'Class:Problem/Attribute:assignment_date+' => '',
'Class:Problem/Attribute:resolution_date' => '解決日',
'Class:Problem/Attribute:resolution_date+' => '',
'Class:Problem/Attribute:knownerrors_list' => '既知のエラー',
'Class:Problem/Attribute:knownerrors_list+' => '',
'Class:Problem/Attribute:related_request_list' => '関連する要求',
'Class:Problem/Attribute:related_request_list+' => '',
'Class:Problem/Stimulus:ev_assign' => '割り当て',
'Class:Problem/Stimulus:ev_assign+' => '',
'Class:Problem/Stimulus:ev_reassign' => '再割り当て',
'Class:Problem/Stimulus:ev_reassign+' => '',
'Class:Problem/Stimulus:ev_resolve' => '解決',
'Class:Problem/Stimulus:ev_resolve+' => '',
'Class:Problem/Stimulus:ev_close' => 'クローズ',
'Class:Problem/Stimulus:ev_close+' => '',
'Menu:ProblemManagement' => '問題管理',
'Menu:ProblemManagement+' => '問題管理',
'Menu:Problem:Overview' => '概要',
'Menu:Problem:Overview+' => '概要',
'Menu:NewProblem' => '新規問題',
'Menu:NewProblem+' => '新規問題',
'Menu:SearchProblems' => '問題検索',
'Menu:SearchProblems+' => '問題検索',
'Menu:Problem:Shortcuts' => 'ショートカット',
'Menu:Problem:MyProblems' => '担当してる問題',
'Menu:Problem:MyProblems+' => '担当している問題',
'Menu:Problem:OpenProblems' => '全オープン問題',
'Menu:Problem:OpenProblems+' => '全オープン問題',
'UI-ProblemManagementOverview-ProblemByService' => 'サービス別問題',
'UI-ProblemManagementOverview-ProblemByService+' => 'サービス別問題',
'UI-ProblemManagementOverview-ProblemByPriority' => '優先度別問題',
'UI-ProblemManagementOverview-ProblemByPriority+' => '優先度別問題',
'UI-ProblemManagementOverview-ProblemUnassigned' => '未割り当て問題',
'UI-ProblemManagementOverview-ProblemUnassigned+' => '未割り当て問題',
'UI:ProblemMgmtMenuOverview:Title' => '問題管理ダッシュボード',
'UI:ProblemMgmtMenuOverview:Title+' => '問題管理ダッシュボード',
'Class:Problem/Attribute:service_name' => 'サービス',
'Class:Problem/Attribute:service_name+' => '',
'Class:Problem/Attribute:servicesubcategory_name' => 'サービスサブカテゴリ',
'Class:Problem/Attribute:servicesubcategory_name+' => '',
'Class:Problem/Attribute:related_change_ref' => '関連する変更参照',
'Class:Problem/Attribute:related_change_ref+' => '',
));
?>

View File

@@ -315,6 +315,7 @@
<action id="ev_reassign" xsi:type="stimulus">allow</action>
<action id="ev_resolve" xsi:type="stimulus">allow</action>
<action id="ev_close" xsi:type="stimulus">allow</action>
<action id="ev_pending" xsi:type="stimulus">allow</action>
</actions>
</group>
<group id="class:UserRequest">
@@ -599,6 +600,11 @@
</group>
</groups>
</profile>
<profile id="12" _delta="define">
<name>Portal power user</name>
<description>Users having this profile will have the rights to see all the tickets for a customer in the portal. Must be used in conjunction with other profiles (e.g. Portal User).</description>
<groups/>
</profile>
</profiles>
</user_rights>
</itop_design>

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