Compare commits

...

460 Commits

Author SHA1 Message Date
Romain Quetiez
a55e337757 Created tag 2.0.1
SVN:2.0.1[2760]
2013-05-22 12:34:59 +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
Denis Flaven
0d0cce9195 Icon update
SVN:trunk[2580]
2012-12-14 09:52:15 +00:00
Denis Flaven
92bf38a18e Icon update
SVN:trunk[2579]
2012-12-14 09:44:48 +00:00
Denis Flaven
08e4b306f0 Icons update
SVN:trunk[2578]
2012-12-14 09:34:04 +00:00
Denis Flaven
fcf04a4584 Added info about an IE8 patch
SVN:trunk[2577]
2012-12-14 09:03:59 +00:00
Denis Flaven
344932c063 Hide menu pane automatically if requested. Useful for automation.
SVN:trunk[2576]
2012-12-14 09:02:30 +00:00
Romain Quetiez
b8fd4014ec Update of the german dictionary by David Gumble (#654)
SVN:trunk[2575]
2012-12-14 08:47:58 +00:00
Romain Quetiez
b22eae043c #653 Document notes and FAQ: when data is longer than 64Kb, then at each modification of the text, an error is displayed and the change is not visible in the history tab (but data correctly saved).
SVN:trunk[2574]
2012-12-13 15:37:19 +00:00
Erwan Taloc
0f2815b202 change lable for simple ticket management module
SVN:trunk[2573]
2012-12-13 15:24:59 +00:00
Denis Flaven
ddc73d13c2 Don't show the CSV import history (by default) for a faster display.
SVN:trunk[2572]
2012-12-13 14:55:11 +00:00
Denis Flaven
cd82ff981f Removed the compiler's log from the overall setup log.
SVN:trunk[2571]
2012-12-13 14:51:45 +00:00
Denis Flaven
4fb7f612b1 Removed the "verbose" option from the mysqldump command.
SVN:trunk[2570]
2012-12-13 14:50:56 +00:00
Denis Flaven
58f12afdcd Restore authentication for generating the life-cycle charts in the right language.
SVN:trunk[2569]
2012-12-13 14:37:20 +00:00
Denis Flaven
8ab0b682db Patch to add the support of indexOf for IE8.
SVN:trunk[2568]
2012-12-13 14:33:32 +00:00
Erwan Taloc
646b46f2b6 Allow & inside email addresses
SVN:trunk[2567]
2012-12-13 14:23:28 +00:00
Erwan Taloc
b052ba5c59 fix typo in French dictionary
SVN:trunk[2566]
2012-12-13 14:21:26 +00:00
Erwan Taloc
2af1411a9e ConnectableCI is now an abstract class
SVN:trunk[2565]
2012-12-13 14:19:46 +00:00
Erwan Taloc
72118db350 Class VirtualDevice is now an abstract class
SVN:trunk[2564]
2012-12-13 14:18:57 +00:00
Erwan Taloc
fef19c5c99 lnkServerToVolume marked as a link in the datamodel
SVN:trunk[2563]
2012-12-13 14:16:40 +00:00
Romain Quetiez
cc8db51b33 Updated the readme for the release 2.0
SVN:trunk[2562]
2012-12-12 16:58:29 +00:00
Romain Quetiez
7245c67469 Completed missing impact/dependency rules (Datacenter device depends on power connection, and PDU depending on power connection)
SVN:trunk[2561]
2012-12-12 15:50:18 +00:00
Denis Flaven
d6a4ac64fd New icons replacing some non-free (?) ones.
SVN:trunk[2560]
2012-12-12 15:33:11 +00:00
Romain Quetiez
196826062a Typo in the data model
SVN:trunk[2559]
2012-12-12 14:57:37 +00:00
Denis Flaven
402b907c8e Fix for JS error in IE 8 (reported via the forum)
SVN:trunk[2558]
2012-12-11 13:35:43 +00:00
Romain Quetiez
b038bc3905 Cleanup in the setup manual instructions
SVN:trunk[2557]
2012-12-11 10:19:28 +00:00
Romain Quetiez
b41e7ab3db Cleanup in the setup manual instructions
SVN:trunk[2556]
2012-12-11 10:16:28 +00:00
Romain Quetiez
fd59c97ce1 Cleanup in the setup manual instructions (preliminary step)
SVN:trunk[2555]
2012-12-11 09:50:38 +00:00
Erwan Taloc
e2eb232e0f Correct wrong linkset in Change management ITIL module
SVN:trunk[2554]
2012-12-10 13:32:22 +00:00
Romain Quetiez
62b3f80a4c #629 Nested object creation (button plus) does not work if:
- PHP 5.4
- notification sent on object creation
- PHP error level allows notices

SVN:trunk[2553]
2012-12-07 13:38:14 +00:00
Romain Quetiez
4d9c632060 #560 typo for german translation of "Metric"
SVN:trunk[2552]
2012-12-07 12:32:37 +00:00
Denis Flaven
99240e997c Update of the lifecycle images
SVN:trunk[2551]
2012-12-07 12:06:16 +00:00
Romain Quetiez
bf067d4ac4 Fixed profile issue: nobody had the right to create/modify links btw VirtualDevice and LogicalVolume
SVN:trunk[2550]
2012-12-07 11:50:42 +00:00
Denis Flaven
b00b8dc05a Added some checks around the configuration of PHP sessions since it seems to cause a lot of troubles.
SVN:trunk[2549]
2012-12-07 10:57:46 +00:00
Denis Flaven
a651105675 Added some checks around the configuration of PHP sessions since it seems to cause a lot of troubles.
SVN:trunk[2548]
2012-12-07 10:33:26 +00:00
Erwan Taloc
55354389dc update French translation of menus for Change management module
SVN:trunk[2547]
2012-12-06 20:32:47 +00:00
Erwan Taloc
ce4c187fcf update Change ITIL overview
SVN:trunk[2546]
2012-12-06 20:30:22 +00:00
Erwan Taloc
25a03b4c5e update Change ITIL overview
update French translation of menus

SVN:trunk[2545]
2012-12-06 20:28:19 +00:00
Denis Flaven
f0ae02fd8e Integration of the "bridge" module and new mechanism for auto_select modules.
SVN:trunk[2544]
2012-12-06 17:51:52 +00:00
Denis Flaven
aa6cfc205e - Show only the "vsisible" parameters in the config file, or the ones already present in case of upgrade. Hide others for readability.
SVN:trunk[2543]
2012-12-06 17:33:57 +00:00
Romain Quetiez
ae1be5a53b New module to link storage and virtualization
SVN:trunk[2542]
2012-12-06 16:54:16 +00:00
Denis Flaven
d5467ca383 Remove black border around icons in the dashbaord editor (class and icon popup menus)
SVN:trunk[2541]
2012-12-06 15:09:36 +00:00
Romain Quetiez
cb4735ba6b When iTop is in read only mode, then the portal displays a banner and prevent the user from accessing the modification forms
SVN:trunk[2540]
2012-12-06 11:42:13 +00:00
Romain Quetiez
bee851155a Continuation of [2524]: fix the attachements URL issue (was not changed only on datamodel 1.x then overwritten on a more recent change)
This fixes the issue #645 for good, I hope.

SVN:trunk[2539]
2012-12-06 11:05:29 +00:00
Denis Flaven
7c13a6286e Typo causing a bug in IE8 when removing an element from a n:n linkset.
SVN:trunk[2538]
2012-12-06 10:55:23 +00:00
Denis Flaven
156993a517 - Show only the "vsisible" parameters in the config file, or the ones already present in case of upgrade. Hide others for readability.
- Properly check DB connection in case of upgrade (setup wizard)
- Cleanup old remains of the V1.x setup program.

SVN:trunk[2537]
2012-12-06 10:53:42 +00:00
Romain Quetiez
074551c506 #647: itop says "ticket updated" but nothing has been changed.
+ Do not send a notification if nothing has been changed from the portal web page
Related to #398 which seems to be fixed

SVN:trunk[2536]
2012-12-06 10:52:27 +00:00
Erwan Taloc
dead18c8fd Reset reject reason when approved
Fix display of reject reason when required

SVN:trunk[2535]
2012-12-06 10:49:29 +00:00
Erwan Taloc
0f2334052b Reset reject reason when approved
SVN:trunk[2534]
2012-12-06 10:48:40 +00:00
Erwan Taloc
7dc7b23dc3 Remove icone for Virtual Device and Virtual Host
SVN:trunk[2533]
2012-12-06 10:41:07 +00:00
Erwan Taloc
9857d9444c Fix icone issue for NASFileSystem and Fiber Channel Interface
SVN:trunk[2532]
2012-12-06 10:40:38 +00:00
Denis Flaven
4804a2994e Make auto_reload work on OQL menus
Fix for table configuration for tables resutling from an OQL menu

SVN:trunk[2531]
2012-12-06 09:47:53 +00:00
Denis Flaven
5b8dc80779 auto-reload set to fast everywhere it is used.
SVN:trunk[2530]
2012-12-06 09:40:58 +00:00
Erwan Taloc
04a037a91d update Case for Request management menu
SVN:trunk[2529]
2012-12-06 09:21:51 +00:00
Erwan Taloc
0b30cebd6a update profiles for problem manager and service manager to make sure they are allowed to manage the element they are responsible for
SVN:trunk[2528]
2012-12-06 09:17:57 +00:00
Erwan Taloc
64bc64dd95 Add icone for a work order
SVN:trunk[2527]
2012-12-06 09:09:54 +00:00
Romain Quetiez
7f45a40e5d #643 Output corrupted by characters after the PHP closing bracket (attachements get corrupted)
SVN:trunk[2526]
2012-12-06 08:56:50 +00:00
Denis Flaven
17d98c9236 Safer regexpr for DateTimes (don't let 2012-12-05 1900:00 pass through since it turns into 0000-00-00 00:00:00 in MySQL) but allow to omit the seconds (i.e. 2012-12-05 18:45 will become 2012-12-05 18:45:00 in MySQL)
SVN:trunk[2525]
2012-12-05 18:02:45 +00:00
Denis Flaven
b3e7068279 Bug fix: Incorrect URL for downloading attachments, that nobody really to noticed before since it seems to work on some web servers... weird !!!
SVN:trunk[2524]
2012-12-05 17:36:05 +00:00
Denis Flaven
5ffc5ff50a Fixed Trac #628: sort order and configurable tables
SVN:trunk[2523]
2012-12-05 14:59:51 +00:00
Erwan Taloc
cc8c034520 update Case for Service management menu
SVN:trunk[2522]
2012-12-05 14:58:33 +00:00
Erwan Taloc
b7e22f9ffe update Case for Service management menu
SVN:trunk[2521]
2012-12-05 14:58:12 +00:00
Erwan Taloc
3b1c46d13f update Case for request management menu
add transition to escalated ttr

SVN:trunk[2520]
2012-12-05 14:57:45 +00:00
Erwan Taloc
b6288aeb6b update Case for request management menu
add transition to escalated ttr

SVN:trunk[2519]
2012-12-05 14:57:14 +00:00
Erwan Taloc
0d95e11f04 update Case for Problem management menu
SVN:trunk[2518]
2012-12-05 14:56:37 +00:00
Erwan Taloc
b6c670a55b update Case for Problem management menu
SVN:trunk[2517]
2012-12-05 14:56:19 +00:00
Erwan Taloc
e4a6b37fb0 update Case for incident management menu
add transition to escalated ttr

SVN:trunk[2516]
2012-12-05 14:55:48 +00:00
Erwan Taloc
1cefd3b35f update Case for configuration management menu
SVN:trunk[2515]
2012-12-05 14:50:01 +00:00
Erwan Taloc
46cde34254 update Case for change management menu
SVN:trunk[2514]
2012-12-05 14:49:15 +00:00
Erwan Taloc
1f0acf7a0a update Case for change management menu
SVN:trunk[2513]
2012-12-05 14:48:47 +00:00
Romain Quetiez
020994c23a Russian updated (source: Shamil Khamit)
SVN:trunk[2512]
2012-12-05 14:46:18 +00:00
Denis Flaven
3e2e0be05e Set "portal" as the origin of user requests created from the portal.
SVN:trunk[2511]
2012-12-05 13:37:13 +00:00
Romain Quetiez
7561f8f8da Fixed regression due to the recent optimization of SQL queries
SVN:trunk[2510]
2012-12-05 12:43:35 +00:00
Romain Quetiez
64c9c1fead Added a comment to explain why the APIs AddCondition_PointingTo and AddCondition_ReferencedBy must be left unprotected (do not clone the passed filter). See trac #639
SVN:trunk[2509]
2012-12-05 10:32:13 +00:00
Romain Quetiez
fb8e2ce1a4 #640 Resolved requests shown in both lists (opened and resolved)
SVN:trunk[2508]
2012-12-05 09:52:19 +00:00
Denis Flaven
ed6bbe6d07 New extension API: iPageUIExtension to alter the display of *each* iTopWebPage.
SVN:trunk[2507]
2012-12-05 09:49:24 +00:00
Denis Flaven
0a0e7c01fd Perf enhancements: don't build trace information if trace is not required.
SVN:trunk[2506]
2012-12-05 09:45:53 +00:00
Denis Flaven
0221a65f82 Performance enhancement for impact analysis: avoid looping in the recursion.
SVN:trunk[2505]
2012-12-05 08:49:38 +00:00
Erwan Taloc
0e3b2a9bf1 update profile for change manager, implementor and supervisor for basic change management module
SVN:trunk[2504]
2012-12-04 18:25:07 +00:00
Denis Flaven
5808c0a8a7 Fix for a SQL error (regression) in the Portal
SVN:trunk[2503]
2012-12-04 17:25:02 +00:00
Denis Flaven
3b0e1d9a3b Prevent a crash when not authorized to see an object of a derived class.
SVN:trunk[2502]
2012-12-04 15:21:59 +00:00
Romain Quetiez
24435401a5 Fixed issue in CSV export: null enums rendered as 'undefined' whereas '' is the value expected in the import (See an export of Organization/status)
SVN:trunk[2501]
2012-12-04 15:17:22 +00:00
Denis Flaven
07d88199b4 New parameter to tweak the display of Impact anaysis: which tab to display first? list or graphics?
SVN:trunk[2500]
2012-12-04 14:50:59 +00:00
Romain Quetiez
46005c19ce Allow the deletion of a shortcut while preserving it from being edited through UI.php
SVN:trunk[2499]
2012-12-04 14:46:18 +00:00
Denis Flaven
442c0d6956 Prevent a server crash when using together APC cache and Mcrypt
SVN:trunk[2498]
2012-12-04 14:01:51 +00:00
Romain Quetiez
1e155ffc13 Fixed stopper issue (found with an audit) due to copies of DBObjectSearch not cloned (or not cloned well)
There is still one place where this should be fixed, but it reveals another bug so we've decided to leave it as is for the moment (see comment in DBObjectSearch::AddCondition_PointingTo)

SVN:trunk[2497]
2012-12-04 13:26:48 +00:00
Romain Quetiez
90bc24d5c0 Optimization of SQL queries: fixed two issues (SELECT to track object linked to... and SELECT ExternalUser)
SVN:trunk[2496]
2012-12-03 17:00:38 +00:00
Romain Quetiez
fe27ee4f22 Debugging: run_query now produces the debug output (log_kpi_duration)
SVN:trunk[2495]
2012-12-03 11:24:19 +00:00
Denis Flaven
84e498e744 Protect against empty email addresses
SVN:trunk[2494]
2012-12-03 09:13:39 +00:00
Erwan Taloc
2af564bc03 Update descriptions for each linkset
Add Application solution tab for Virtual machines


SVN:trunk[2493]
2012-12-01 16:54:06 +00:00
Erwan Taloc
b0c48ce2a7 Change Name into Last Name for a object person in English dictionary (Trac #530)
Fix icone issue for change mgmt
Allow selection of Location defined in each parent location for Person and Physical Devices (Trac #412)
Make sure all names are mandatory in the module Service Management , Service Management Provider (Trac #530)
Fix wrong impact rules for storage system

SVN:trunk[2492]
2012-12-01 12:46:23 +00:00
Erwan Taloc
14520dabc0 Prompt planned start and end date for change for status planned (Trac #563)
Change Name into Last Name for a object person in English dictionary (Trac #530)
Allow service manager to delete objects in the service catalog (Trac #506)

SVN:trunk[2491]
2012-12-01 12:41:41 +00:00
Erwan Taloc
8a3d922882 All Service Manager to delete objects from service catalog (Trac #506)
SVN:trunk[2490]
2012-11-30 17:31:00 +00:00
Erwan Taloc
faa1c37613 Add dependency between server and logical volume (Trac #617)
Add Pertual field for Licence (Trac #535)
Make Name mandatory for all CIS

SVN:trunk[2489]
2012-11-30 17:30:08 +00:00
Denis Flaven
a0d267ed2f Bug fix: "Configure this list" was not working on some ,lists (with a ID containing a colon (:) from a Menu)
SVN:trunk[2488]
2012-11-30 16:57:37 +00:00
Denis Flaven
09209533d0 Support multiple recipients in To: Cc: and Bcc:
SVN:trunk[2487]
2012-11-30 16:46:50 +00:00
Romain Quetiez
3784a41d9e Optimization of SQL queries: fixed!
SVN:trunk[2486]
2012-11-30 16:26:53 +00:00
Romain Quetiez
78cb9f793a Optimization of SQL queries: reduce the number of JOINS, assuming that data are consistent. Can be disabled with config setting query_optimization_enabled => 0.
Also fixed caching issue (reproduced when replaying a query log)

SVN:trunk[2485]
2012-11-30 13:34:46 +00:00
Romain Quetiez
941d056db4 Improved the query logging + replay mechanism
SVN:trunk[2484]
2012-11-30 13:27:07 +00:00
Denis Flaven
d69163199b Fix for Trac #569: Mandatory date (and time) fields are prefilled with the current date (and time).
SVN:trunk[2483]
2012-11-30 10:51:15 +00:00
Denis Flaven
b563a64eb6 Added PHP and MySQL versions and OS to the statistics
SVN:trunk[2482]
2012-11-30 10:08:26 +00:00
Denis Flaven
a975974fc0 Fix for Trac #608: install broken on PHP < 5.2.17
SVN:trunk[2481]
2012-11-30 09:23:17 +00:00
Denis Flaven
b87abb7603 Make sure that we don't call OnFormCancel during a true submit.
SVN:trunk[2480]
2012-11-28 17:51:46 +00:00
Denis Flaven
0313f54d3e Fix for "undefined property" as reported in Trac#629
SVN:trunk[2479]
2012-11-28 17:50:24 +00:00
Denis Flaven
63cb32b7a7 Fix for Trac #497: allow bulk modification of "duration" fields.
- Proper display of the modifications on the SynchroAttributes in the History of a SynchroDataSource
- Better display of the history of Boolean atrtibutes (false is no longer displayed as an empty string)

SVN:trunk[2478]
2012-11-28 17:45:00 +00:00
Denis Flaven
323147c7f4 Fixed Trac #619 : Added the option -- single-transaction to the mysqldump command to avoid locking issues with non-existing definer accounts.
SVN:trunk[2477]
2012-11-28 11:17:45 +00:00
Denis Flaven
a9d17903cf Fix for Trac#627: Don't log the parameters in the call stack in case of exception to protect sensitive data.
SVN:trunk[2476]
2012-11-28 10:53:43 +00:00
Denis Flaven
b3b19bcaf6 Prevent a undefined varialbe when logging directly to a details page (bookmarked page)
SVN:trunk[2475]
2012-11-28 09:04:28 +00:00
Denis Flaven
e0800944a8 Make sure that CSV files end with a proper carriage return
SVN:trunk[2474]
2012-11-28 09:03:30 +00:00
Denis Flaven
352a95decb Added a detailed log of the compiler (temporary ? for debugging purposes ?)
SVN:trunk[2473]
2012-11-28 09:01:43 +00:00
Romain Quetiez
85974da27b New developer tool: cosmetics
SVN:trunk[2472]
2012-11-27 17:24:35 +00:00
Denis Flaven
e1d2723283 Fix for Trac#589, do not use ExchangeException here ! Copy/paste killed us ?
SVN:trunk[2471]
2012-11-27 17:21:23 +00:00
Denis Flaven
0818a67e75 Fixed bug #624: corrupted display of the log when updating from the portal.
Also fixed a bit the portal's stylesheet and prevent calling OnFormCancel on a true submit !!

SVN:trunk[2470]
2012-11-27 17:11:47 +00:00
Romain Quetiez
9b982df4f0 New developer tool: set log_queries=1 to enable query logging into data/
The accumulative log data/queries.log can be replayed with test/replay_query_log.php which produces a result file (to check the stability of the results) and a benchmark file (to see the efficiency in CSV)

SVN:trunk[2469]
2012-11-27 16:53:24 +00:00
Denis Flaven
51af2e9662 Fix for Trac #625: CSV export of boolean attributes was broken (false => "")
SVN:trunk[2468]
2012-11-27 16:30:41 +00:00
Denis Flaven
f8f8c327af Typo: Sycnhro => Synchro
SVN:trunk[2467]
2012-11-27 16:28:22 +00:00
Denis Flaven
baf1e80cca Fix for Trac #584 (Documentation of needed piviledges)
SVN:trunk[2466]
2012-11-27 15:44:40 +00:00
Denis Flaven
5be8937518 Fix inconsistencies in the sample data.
SVN:trunk[2465]
2012-11-27 15:28:13 +00:00
Denis Flaven
2c9884cfa5 Fixed Trac #631: impossible to assign a routine or emergency change.
Cleanup: removed useless state definitions.

SVN:trunk[2464]
2012-11-27 14:52:53 +00:00
Denis Flaven
933bb62c6c Missing dict entries for "parent_incident_id".
SVN:trunk[2463]
2012-11-27 14:17:08 +00:00
Denis Flaven
b10b894b24 Protects the display of the history against renmaed/removed attributes.
SVN:trunk[2462]
2012-11-27 13:44:47 +00:00
Denis Flaven
35a3b145f8 Regression from previous fix...
SVN:trunk[2461]
2012-11-23 17:01:00 +00:00
Denis Flaven
c04ea6d220 Bug fix:
- Correct intial sort order of a table if the default sort column is not an "alphabetical" column (i.e. IP Address)
- Properly sort on the first column (name) when the name is made of a column with a different sort algorithm (i.e. IP Address).

SVN:trunk[2460]
2012-11-23 15:29:13 +00:00
Denis Flaven
ea48279a90 Bug fix:
- Correct intial sort order of a table if the default sort column is not an "alphabetical" column (i.e. IP Address)
- Properly sort on the first column (name) when the name is made of a column with a different sort algorithm (i.e. IP Address).

SVN:trunk[2459]
2012-11-23 15:25:55 +00:00
Romain Quetiez
9bc263b106 Fixed messed up dictionaries.
1) In english, we have the following:
- Delivery model class shown in japanese
- Server, Person and Subnet additional tabs shown in french
- Known errors menus shown in french
2) In ? we have the Attachments in german (but it is ok in english, for my installation...)


SVN:trunk[2458]
2012-11-22 09:08:41 +00:00
Denis Flaven
27619a9118 Changed Eugène to Eugene to work around an XML load problem.
SVN:trunk[2457]
2012-11-21 15:47:58 +00:00
Denis Flaven
ff2603a8fe Review of the readme. Ready for building Beta 2.
SVN:trunk[2456]
2012-11-21 15:22:21 +00:00
Romain Quetiez
4a0002058e Updated the readme for iTop 2.0 Beta 2
SVN:trunk[2455]
2012-11-21 14:58:08 +00:00
Romain Quetiez
656675206e #602 Description not shown in portal
SVN:trunk[2454]
2012-11-21 14:11:21 +00:00
Erwan Taloc
07fee4ac00 Fix tab translation for Subnet
SVN:trunk[2453]
2012-11-21 13:53:13 +00:00
Denis Flaven
084609bfad Increased memory_limit for the setup to 64 MB
SVN:trunk[2452]
2012-11-21 13:52:44 +00:00
Erwan Taloc
e1742fa24d Fix issue with Subnet usage computation
SVN:trunk[2451]
2012-11-21 13:48:20 +00:00
Romain Quetiez
241ac4c4d0 Fixed typo in spanish dictionary
SVN:trunk[2450]
2012-11-21 13:42:09 +00:00
Romain Quetiez
d75ad72057 Renamed classes/attributes and enums, for the latest dictionaries (based on names from 2.0 beta 1)
SVN:trunk[2449]
2012-11-21 13:31:23 +00:00
Denis Flaven
b2031c5e44 Changed mysqldump invocation to verbose mode (at least for the duration of the beta) in order to ease the troubleshooting of backup failures.
SVN:trunk[2448]
2012-11-21 13:26:10 +00:00
Denis Flaven
8fa41e2fd0 Localization update:
- German thanks to David Guembel
- Japanese thanks to Shoji Seki
- Spanish thanks to Miguel Turrubiates

SVN:trunk[2447]
2012-11-21 11:18:59 +00:00
Erwan Taloc
9016ce7149 add software list on PC devices
SVN:trunk[2446]
2012-11-21 11:18:52 +00:00
Erwan Taloc
cf38a3eec4 renumbering of dashlet id
SVN:trunk[2445]
2012-11-21 11:17:53 +00:00
Erwan Taloc
7bf1f9ca49 allow duplicate links for device / network connections
add PC software in Dashboard
All documentation of software on a PC device

SVN:trunk[2444]
2012-11-21 11:17:18 +00:00
Denis Flaven
1f9950507c Allow to automatically hide/show the menu pane as a parameter to the page (useful for automating the documentation)
SVN:trunk[2443]
2012-11-21 11:08:36 +00:00
Denis Flaven
a4ddc99446 Removed user-rights verification for generting the image... easier for generating the documentation
SVN:trunk[2442]
2012-11-21 11:06:31 +00:00
Denis Flaven
52c1830d42 GetTargetAttDef is made public (it's used for auto documenting)
SVN:trunk[2441]
2012-11-21 11:04:08 +00:00
Romain Quetiez
79e4a73408 Updated the russion translation, thanks to Shamil Khamit (note: this translation seems to be quite incomplete)
SVN:trunk[2440]
2012-11-21 11:03:27 +00:00
Denis Flaven
0f8f214367 Added more translators to the readme.
SVN:trunk[2439]
2012-11-21 11:01:15 +00:00
Romain Quetiez
914be40f02 Adapted the sample queries to the new datamodel.
SVN:trunk[2438]
2012-11-21 10:42:17 +00:00
Romain Quetiez
f196d03f6f error.log moved into the log directory
SVN:trunk[2437]
2012-11-21 10:19:28 +00:00
Romain Quetiez
f089d4282e Renamed priv_Userinternal into priv_userinternal: the upgrade must be idempotent!
SVN:trunk[2436]
2012-11-21 10:04:40 +00:00
Romain Quetiez
bedbc387eb Renamed priv_Userinternal into priv_userinternal, and added a check for table names (lowercase is the rule!)
SVN:trunk[2435]
2012-11-21 09:41:53 +00:00
Romain Quetiez
4d85ff60ab Fixed #618 and #621
+ renamed a few classes/enums/attributes to improve the classes naming consistency and ease the writing of OQLs
+ fixed errors in the profiles

SVN:trunk[2434]
2012-11-20 16:24:24 +00:00
Romain Quetiez
b38e818499 New feature: fixed bugs in shortcut edition (condition: list NOT paginated)
SVN:trunk[2433]
2012-11-19 10:25:38 +00:00
Erwan Taloc
b1fb7189de update profiles according to new data model
SVN:trunk[2432]
2012-11-19 09:07:00 +00:00
Romain Quetiez
7792b54d26 New feature: shortcuts to a search result. The feature is not automatically available with upgrade of custom versions -requires a ShortcutContainerMenuNode.
SVN:trunk[2431]
2012-11-16 11:21:00 +00:00
Erwan Taloc
8f398bd130 Change constraint on attribute agent_id for a workorder
SVN:trunk[2430]
2012-11-12 18:11:31 +00:00
Erwan Taloc
79db8a22e7 Make Request Mgmt module visible for all
Update translation for customer satisfaction

SVN:trunk[2429]
2012-11-12 18:11:12 +00:00
Erwan Taloc
058787a366 Make Request Mgmt module visible for all
Update translation for customer satisfaction

SVN:trunk[2428]
2012-11-12 18:09:35 +00:00
Erwan Taloc
4b99c584db Make Incident Mgmt module visible for all
Update translation for customer satisfaction

SVN:trunk[2427]
2012-11-12 18:09:07 +00:00
Erwan Taloc
b9d689baf1 update purchase_date type
SVN:trunk[2426]
2012-11-12 18:06:59 +00:00
Erwan Taloc
fe6c34030b update MakeIconeFrom name with good icone path
add transaltion for remated_problems_list

SVN:trunk[2425]
2012-11-12 18:05:02 +00:00
Erwan Taloc
b8f7fa975c update MakeIconeFrom name with good icone path
add transaltion for remated_problems_list

SVN:trunk[2424]
2012-11-12 18:03:37 +00:00
Denis Flaven
abdca9399d Bug fix: incorrect handling of "negative" selections in bulk delete
SVN:trunk[2423]
2012-11-12 15:05:17 +00:00
Romain Quetiez
3b93fcff3c #615 Fixed bug on multi column queries - wrong count resulting in strange effects in the display of results
SVN:trunk[2422]
2012-11-12 14:34:39 +00:00
Romain Quetiez
6987db54b5 #614 Fixed regression on multi column queries (could not display Null objects)
SVN:trunk[2421]
2012-11-12 14:32:29 +00:00
Denis Flaven
71d011b7f8 Prevent a crash when deleting objects accessed from a list of their abstract class (i.e. Select some Contacts, "delete...", select a Person, delete => crash).
SVN:trunk[2420]
2012-11-12 14:23:24 +00:00
Denis Flaven
b22c23dfee Bug fix: "save" in edit dashboard did nothing on Chrome on a *just reloaded* dashboard (actually on any page which URL contained a hash)
SVN:trunk[2419]
2012-11-12 10:36:34 +00:00
Romain Quetiez
59b7c0c025 Bug fix: display an empty string for the friendlyname of a NULL external key
SVN:trunk[2418]
2012-11-09 16:49:17 +00:00
Erwan Taloc
46e42f0ea2 Don't mind whether hidden fields are read-only or not.. they are hidden.
SVN:trunk[2417]
2012-11-09 15:12:16 +00:00
Romain Quetiez
bac286646b #611 Fixed regression in import.php
SVN:trunk[2416]
2012-11-09 08:44:00 +00:00
Denis Flaven
bd057018a0 Typo: Opened => Open
SVN:trunk[2415]
2012-11-08 14:22:29 +00:00
Denis Flaven
f2a63cbbce Bug fix: Trac#609 export/import was broken for dashboards with a non-alphanumeric identifier.
SVN:trunk[2414]
2012-11-08 13:02:38 +00:00
Romain Quetiez
247b1b4d78 Record the list of attachments (in EventNotificationEmail) + prerequisite to email-reply
SVN:trunk[2413]
2012-11-08 12:41:51 +00:00
Erwan Taloc
4ac9f0654c replace emergency by urgency for user portal variables
SVN:trunk[2412]
2012-11-02 08:56:04 +00:00
Denis Flaven
7cb5d60dd3 Rollback (temporarily) to fix the issue with linksets dependent on both sides.
SVN:trunk[2411]
2012-10-30 11:23:22 +00:00
Denis Flaven
2d04bfe2b9 Review of the readme for 2.0.0 beta
SVN:trunk[2410]
2012-10-30 09:28:16 +00:00
Romain Quetiez
954ae7cca0 Draft of the Readme for 2.0 beta
SVN:trunk[2409]
2012-10-30 08:53:08 +00:00
Romain Quetiez
0e6f2e2fb9 Workaround to an issue with reconciliation keys using "discarded" ext keys (target class implemented in an optional module)
SVN:trunk[2408]
2012-10-30 08:52:35 +00:00
Denis Flaven
73226092dc Change the versioning scheme: let's jump to 1.3.0 for this new branch.
SVN:trunk[2407]
2012-10-29 18:05:57 +00:00
Romain Quetiez
0abade970a MetaModel: when an ext key on a Link is discarded, then discard the corresponding linkset attributes
SVN:trunk[2406]
2012-10-29 17:55:51 +00:00
Erwan Taloc
78948c06fe Change Label of Friendly name from "Name" to "Friendy Name" to avoid misunderstanding when importing or synchronizing data
SVN:trunk[2405]
2012-10-29 17:47:37 +00:00
Denis Flaven
1df7fb44dd Make the two modules: Known Errors and Problem Mgmt independent from each other.
SVN:trunk[2403]
2012-10-29 13:54:21 +00:00
Denis Flaven
0048978cbd New option for MFNodes: define_if_not_exists !!
SVN:trunk[2402]
2012-10-29 13:51:39 +00:00
Romain Quetiez
cd745f1df1 Dashboards - make sure that dashlet ids are unique within a given dashboard (not a cell), which can become uneasy when the dashlets are spread amongst several modules
SVN:trunk[2401]
2012-10-29 12:56:40 +00:00
Denis Flaven
3a52e4cd83 Incorrect formatting visible only with IE !
SVN:trunk[2400]
2012-10-29 12:46:00 +00:00
Denis Flaven
a0d222d593 Correct detection of whether there are any changes or not compared to a std build.
SVN:trunk[2399]
2012-10-29 11:42:31 +00:00
Denis Flaven
b7ce575a5f Added the manifest of previous versions for safe upgrades.
SVN:trunk[2398]
2012-10-29 10:45:34 +00:00
Denis Flaven
0c35ef8085 Allow updating sample data while loading them !!
SVN:trunk[2397]
2012-10-26 17:01:53 +00:00
Denis Flaven
b59d5062c7 Invalid MACAddress value in sample data !!!
SVN:trunk[2396]
2012-10-26 16:08:30 +00:00
Denis Flaven
5105773996 Invalid MACAddress value in sample data !!!
SVN:trunk[2395]
2012-10-26 15:20:41 +00:00
Romain Quetiez
0c0a54db69 Internal: regression in the bulk install
SVN:trunk[2394]
2012-10-26 15:18:12 +00:00
Romain Quetiez
3a90af5fdc Internal: fixed reporting issue for bulk installer
SVN:trunk[2393]
2012-10-26 14:30:50 +00:00
Romain Quetiez
bbad591334 Internal: improved (a little) the API to detect datamodel inconsistencies
SVN:trunk[2392]
2012-10-26 14:29:17 +00:00
Denis Flaven
15edf33a56 Edit in-place for audit rules from their category.
SVN:trunk[2391]
2012-10-26 14:25:23 +00:00
Denis Flaven
e8341448b7 Cosmetics in the setup.
SVN:trunk[2390]
2012-10-26 14:12:51 +00:00
Denis Flaven
40cc93e5f5 Adapt the webservice to either 1.x or 2.x datamodels
SVN:trunk[2389]
2012-10-26 14:11:30 +00:00
Denis Flaven
5af0f5f320 Proper error reporting...
SVN:trunk[2388]
2012-10-26 13:57:40 +00:00
Erwan Taloc
050037acb2 set default order descending on ticket ref
SVN:trunk[2387]
2012-10-26 13:24:39 +00:00
Erwan Taloc
ba4c382fe8 add sample date related to virtualization
SVN:trunk[2386]
2012-10-26 13:17:34 +00:00
Erwan Taloc
2e7b991252 do not lot delivery model in this module
SVN:trunk[2385]
2012-10-26 13:15:57 +00:00
Erwan Taloc
1ada274c56 do not lot delivery model in this module
SVN:trunk[2384]
2012-10-26 13:15:34 +00:00
Erwan Taloc
5e3889a8a5 replace type Emergency by Urgency
SVN:trunk[2383]
2012-10-26 13:14:56 +00:00
Denis Flaven
39d8888890 Protect the webservices...
SVN:trunk[2382]
2012-10-26 13:11:02 +00:00
Erwan Taloc
d894ec0a9f replace type Emergency by Urgency
SVN:trunk[2381]
2012-10-26 13:09:47 +00:00
Erwan Taloc
9b8b95017d replace type Emergency by Urgency
SVN:trunk[2380]
2012-10-26 13:09:19 +00:00
Erwan Taloc
cbe7b7f3bb replace type Emergency by Urgency
SVN:trunk[2379]
2012-10-26 13:08:51 +00:00
Erwan Taloc
7103d524e0 update sample date to not load in CMDB core the data related to virtualization
SVN:trunk[2378]
2012-10-26 13:08:14 +00:00
Denis Flaven
bfa41966d9 Adapt the webservice to either 1.x or 2.x datamodels
SVN:trunk[2377]
2012-10-26 12:29:45 +00:00
Denis Flaven
85ee91a38c Fix: the configuration path changed in 2.0
SVN:trunk[2376]
2012-10-26 12:17:59 +00:00
Erwan Taloc
0bcbf5825a change translation for trigger on threshold reached
SVN:trunk[2375]
2012-10-26 11:54:26 +00:00
Denis Flaven
99b4719335 Log the response file as a standalone XML file to be able to easily replay each installation
SVN:trunk[2374]
2012-10-26 08:12:14 +00:00
Erwan Taloc
a1f5a330d4 add dictionary for change mgmt ITIL
Add external field for link SLA / SLT

SVN:trunk[2373]
2012-10-26 07:13:47 +00:00
Denis Flaven
0f4d2990f7 Bug fix: properly preserve user's choices in case of upgrade (for alternatives)
SVN:trunk[2372]
2012-10-25 16:20:14 +00:00
Denis Flaven
fa9237f04b Log the installation parameters in case an investigation is needed
SVN:trunk[2371]
2012-10-25 16:10:53 +00:00
Romain Quetiez
3c9082d978 Fixed datamodel consistency issue (acceptance_comment removed from emergency change)
SVN:trunk[2370]
2012-10-25 15:36:15 +00:00
Denis Flaven
f45d2520cf itop-tickets is a mandatory module, whatever happens, install it !
SVN:trunk[2369]
2012-10-25 15:19:03 +00:00
Romain Quetiez
89029d4410 Regression -a bug was hidden by the issue solved in revision [2356] !
SVN:trunk[2368]
2012-10-25 15:16:36 +00:00
Denis Flaven
c39f11193e Beware: the 'lifecycle' directories contain big images. Exclude them from the list of icons.
SVN:trunk[2367]
2012-10-25 14:57:01 +00:00
Denis Flaven
f14ebdb019 Allow non-integer ranks on dashlets/cells
SVN:trunk[2366]
2012-10-25 14:55:47 +00:00
Denis Flaven
e3698b07f6 Exclude Incidents from the Portal since this way of handling them would not work once opening the tickets in the normal UI.
SVN:trunk[2365]
2012-10-25 14:49:40 +00:00
Denis Flaven
a57e5e0af4 - Data model finalization... renamed ElectricalConnection to PowerConnection and Arrival to PowerSource
- Changes in the default choices for the setup

SVN:trunk[2364]
2012-10-25 14:47:54 +00:00
Romain Quetiez
d73405d1f4 Compiler: take into account the "is_null_allowed" flag for blobs
SVN:trunk[2363]
2012-10-25 14:36:06 +00:00
Romain Quetiez
cae32294a1 Integrated the multiple select in the portal (search closed tickets)
SVN:trunk[2362]
2012-10-25 14:24:38 +00:00
Romain Quetiez
ce63939855 Added/XMLized service overview dashboard, for every version + added an overview for change mgmt in ITIL version
SVN:trunk[2361]
2012-10-25 13:51:53 +00:00
Denis Flaven
13de0f5702 Redundant typo !
SVN:trunk[2360]
2012-10-25 13:40:26 +00:00
Romain Quetiez
cc331c7f72 Adjusted the text of the "Notifications" welcome page (added two types of triggers)
SVN:trunk[2359]
2012-10-25 13:25:23 +00:00
Denis Flaven
20103def45 Ignore silently unknown attributes when loading a XML file since we know have variations in the data model of the CMDB...
SVN:trunk[2358]
2012-10-25 13:24:22 +00:00
Denis Flaven
664adcb990 Fixed some interdependencies of the CMDB modules.
SVN:trunk[2357]
2012-10-25 13:17:13 +00:00
Romain Quetiez
db5d832207 Fixed error in JA dictionary, messing up the English and Japanese dictionaries for the class EventIssue
SVN:trunk[2356]
2012-10-25 13:16:11 +00:00
Denis Flaven
1210732852 Oops, missing file.
SVN:trunk[2355]
2012-10-25 10:54:49 +00:00
Denis Flaven
9f263ca603 Installation wizard icons for 2.x.
SVN:trunk[2354]
2012-10-25 10:47:41 +00:00
Denis Flaven
7597630d18 Moved the dashboards into the datamodel XML (thanks to Christophe)
SVN:trunk[2353]
2012-10-25 10:34:18 +00:00
Denis Flaven
66e3554308 Split of the datamodel into 5 modules:
- Core (as before, mandatory)
- Storage
- End-User devices
- Datacenter devices
- Virtualization

SVN:trunk[2352]
2012-10-25 10:22:41 +00:00
Romain Quetiez
467c4c6258 Added TriggerOnThresholdReached to the dictionary
SVN:trunk[2351]
2012-10-25 10:17:04 +00:00
Denis Flaven
4ccf908738 Prevent an error in case of exception !
SVN:trunk[2350]
2012-10-25 10:08:05 +00:00
Romain Quetiez
c1072bb744 Fixed regression in the licenses shown at setup (2 had disappeared)
SVN:trunk[2349]
2012-10-25 07:50:00 +00:00
Erwan Taloc
5eb4b557e0 Add specific module for Datacenter related CIs
SVN:trunk[2348]
2012-10-24 16:02:21 +00:00
Erwan Taloc
4d4c9674fa remove Datacenter related CIS
SVN:trunk[2347]
2012-10-24 16:01:15 +00:00
Romain Quetiez
217b7048c5 XML Datamodel: new format (fixed issue seen with some versions of PHP)
SVN:trunk[2346]
2012-10-24 14:40:13 +00:00
Denis Flaven
bbd581e9c5 Do not perform time consuming computations for building the menus if there are too many objects in a list (limit is configurable).
SVN:trunk[2345]
2012-10-24 14:17:27 +00:00
Romain Quetiez
d7e492b711 XML Datamodel: new format (version + zlists changed) - not compatible with 2.0 alpha!!!
SVN:trunk[2342]
2012-10-24 13:54:02 +00:00
Denis Flaven
80ec842042 Slight (incomptaible!) modification to the dashboards format to support incremental changes through the XML.
SVN:trunk[2336]
2012-10-24 08:04:17 +00:00
Romain Quetiez
b72151d968 Fixed typo in new XML datamodel
SVN:trunk[2335]
2012-10-24 07:51:20 +00:00
Denis Flaven
3c3c805298 Finishing touch on the setup program... ready for 2.0 beta ??
SVN:trunk[2334]
2012-10-24 07:30:43 +00:00
Romain Quetiez
721faa7e1e Updated copyright (2012) and license (LGPL changed to AGPL)
SVN:trunk[2333]
2012-10-23 21:41:36 +00:00
Denis Flaven
54a3c849ed Testing external fields pointing to external keys...
SVN:trunk[2332]
2012-10-23 09:34:51 +00:00
Romain Quetiez
5582607b76 CSV Import: when using cut&paste, the character set is de facto utf-8 (no user choice)
SVN:trunk[2331]
2012-10-23 09:33:31 +00:00
Romain Quetiez
3889bdf293 Fixed regression in 2.0: plugins ONDBInsert and ONDBUpdate where not called anymore
SVN:trunk[2330]
2012-10-23 09:26:28 +00:00
Denis Flaven
4981344c24 "Refresh" button replaced by an small icon
SVN:trunk[2329]
2012-10-23 09:11:10 +00:00
Denis Flaven
2ca4b02548 Bug fix: cloning a DBObject has a special meaning !!
SVN:trunk[2328]
2012-10-23 09:09:55 +00:00
Denis Flaven
180f215ab0 Small optimization: do not recompute external fields if the value of the external key did not change
SVN:trunk[2327]
2012-10-22 13:22:01 +00:00
Denis Flaven
9f47c09cdf Bug of month: make sure that GetFilter returns a usable filter (i.e. with the parameters)
SVN:trunk[2326]
2012-10-22 13:12:00 +00:00
Romain Quetiez
7b790cc84f Fixed two bugs revealed with specific constraints (query expression like 'SELECT b FROM a JOIN b', AND the organization context is set)
SVN:trunk[2325]
2012-10-22 13:02:15 +00:00
Denis Flaven
281a01fca5 Added more precomputed life cycle images
SVN:trunk[2324]
2012-10-22 09:14:57 +00:00
Erwan Taloc
b5af98b150 update on_target_delete rule to avoid automatic deletion in some cases
SVN:trunk[2321]
2012-10-21 09:01:02 +00:00
Erwan Taloc
216bbd0ce1 Add edit mode for Linkset
SVN:trunk[2320]
2012-10-21 08:40:50 +00:00
Erwan Taloc
a78b8a604c Add edit mode for Linkset
SVN:trunk[2319]
2012-10-21 08:39:49 +00:00
Erwan Taloc
6e7ee18e7f Add icone for this module
SVN:trunk[2318]
2012-10-21 08:17:54 +00:00
Erwan Taloc
aa49610e31 Rename Fiber Channel interface to correct typo
SVN:trunk[2317]
2012-10-21 08:10:55 +00:00
Erwan Taloc
e3a285e423 Remove obsolete attribute
SVN:trunk[2316]
2012-10-21 08:00:55 +00:00
Denis Flaven
37f75428d2 Typos
SVN:trunk[2315]
2012-10-20 20:26:29 +00:00
Denis Flaven
f9eacfa2d0 Typos ??
SVN:trunk[2314]
2012-10-20 20:19:00 +00:00
Denis Flaven
bc6d3df0c2 EMail, CSV export and Add To Dashbaord menu items are now in the "toolkit" menu.
SVN:trunk[2313]
2012-10-20 20:14:01 +00:00
Denis Flaven
79900e89a2 Cosmetic enhancements to ease the search for a class in the schema.
SVN:trunk[2312]
2012-10-20 19:22:57 +00:00
Denis Flaven
4efa2cb3c0 Added a refresh button (and creation /modification messages) on the details of an object
SVN:trunk[2311]
2012-10-20 17:16:46 +00:00
Denis Flaven
135abdb9e0 Fixed the "Reset(APC)Cache" at the end of the installation.
SVN:trunk[2310]
2012-10-20 15:42:39 +00:00
Denis Flaven
a48d2f97e8 Bug fix: do not overwrite the 'extensions' directory during the setup!
SVN:trunk[2309]
2012-10-20 14:55:29 +00:00
Denis Flaven
c9b1883905 Bug fix: preserve the previous settings in the configuration file in case of upgrade.
SVN:trunk[2308]
2012-10-20 14:39:14 +00:00
Denis Flaven
86b615a9a5 Added the proper mimetype for XML pages for the impact analysis graph.
SVN:trunk[2307]
2012-10-20 13:37:46 +00:00
Denis Flaven
08a320cf2b Ajax file upload is now part of the standard JS includes in the iTop pages.
SVN:trunk[2306]
2012-10-20 13:36:20 +00:00
Denis Flaven
c05c1062ce Implemented the "multiple choices" in search forms for Enums and External keys.
SVN:trunk[2305]
2012-10-20 13:32:59 +00:00
Denis Flaven
f61af1fe5c Added a new favicon
SVN:trunk[2304]
2012-10-20 13:06:31 +00:00
Denis Flaven
80f2f0f66f Cosmetics for the setup
SVN:trunk[2303]
2012-10-19 16:59:07 +00:00
Erwan Taloc
d3b6d468b0 Add edition in place for Physical Interfaces on Connectable CI
SVN:trunk[2302]
2012-10-19 15:35:42 +00:00
Romain Quetiez
27fec353dd #593 Losing attachments when performing massive change
SVN:trunk[2301]
2012-10-19 15:11:53 +00:00
Denis Flaven
ab6cfb56b4 Fixed a regression: don't put some JS script in every ajax_page (even though they claim to contain some HTML)
SVN:trunk[2300]
2012-10-19 14:11:57 +00:00
Romain Quetiez
a57aed9ffc Portal adapted to datamodels 1.x, 2.x (simple tickets, or ITIL tickets)
SVN:trunk[2299]
2012-10-19 13:07:35 +00:00
Denis Flaven
7a817ad1d8 Localization for in-place edition of 1:n linksets
SVN:trunk[2298]
2012-10-19 10:52:47 +00:00
Denis Flaven
b3caa1f002 Life cycle images enhancements:
- precomputed images are now stored in the "lifecycle" directory of the module in which the class is declared.
- graphviz.php makes a proper usage of the data directory for its data files
- life cycles images are now transparent

SVN:trunk[2297]
2012-10-19 10:17:47 +00:00
Denis Flaven
77606c32c5 Added pre-computed life-cycle images and a fixed typo.
SVN:trunk[2296]
2012-10-19 09:28:15 +00:00
Erwan Taloc
d89be97297 remove SLA computation herited from ticket
SVN:trunk[2295]
2012-10-19 09:16:08 +00:00
Erwan Taloc
da4419b848 remove SLA computation herited from ticket
SVN:trunk[2294]
2012-10-19 09:15:43 +00:00
Erwan Taloc
7809037963 Make requestype for Service sub category mandatory
SVN:trunk[2293]
2012-10-19 09:12:59 +00:00
Erwan Taloc
c28c4bd675 Make requestype for Service sub category mandatory
SVN:trunk[2292]
2012-10-19 09:12:42 +00:00
Romain Quetiez
fa8cbd08d4 Internal: you can add 'attachments' => array of ormDocument to the context of a trigger, the attachments will be added to the email sent
SVN:trunk[2291]
2012-10-18 17:15:06 +00:00
Denis Flaven
53aefa895b Implemented a new (optional) UI for managing 1:n linksets.
SVN:trunk[2290]
2012-10-18 12:03:33 +00:00
Romain Quetiez
c9d5743c4a Config: use app_icon_url to change the hyperlink used when clicking on the main icon
SVN:trunk[2289]
2012-10-18 10:17:49 +00:00
Erwan Taloc
7d5e2637c4 Rename class PCsoftware into PCSoftware
Add role attribute on link Person / Team

SVN:trunk[2288]
2012-10-18 09:51:13 +00:00
Romain Quetiez
e938dfb5c9 Internal: AttributeDateTime column changed from TIMESTAMP to DATETIME (issues with some bulk imports)
SVN:trunk[2287]
2012-10-18 09:50:39 +00:00
Romain Quetiez
ed15cde281 #583 Losing attachments when performing massive change
SVN:trunk[2284]
2012-10-18 09:33:49 +00:00
Erwan Taloc
96c62463d5 Initial load of data model 2.0
SVN:trunk[2283]
2012-10-18 09:26:30 +00:00
Romain Quetiez
ce77c65e6e #565 Fixed security issues (XSS)
SVN:trunk[2282]
2012-10-17 15:38:09 +00:00
Denis Flaven
0f9280399b Properly handle all types of fields when entering values via the state transition "wizard" screen
SVN:trunk[2280]
2012-10-17 14:11:26 +00:00
Romain Quetiez
4f9115ca02 Objects always recorded before the notifications are sent
SVN:trunk[2277]
2012-10-17 13:31:10 +00:00
Romain Quetiez
84a8310912 Portal: enable adding dependent attributes in the request creation form
SVN:trunk[2273]
2012-10-17 12:40:38 +00:00
Romain Quetiez
c45dbb2e07 Portal: enable adding dependent attributes in the request creation form
SVN:trunk[2270]
2012-10-17 12:03:29 +00:00
Romain Quetiez
b36ebc6e0f Fixed issue in the portal: the list of opened requests and closed request where messed up when pagination was activated on both lists
SVN:trunk[2267]
2012-10-17 09:02:24 +00:00
Romain Quetiez
09a1c17052 CSV import: show flag csv_import_history_display in the default config file
SVN:trunk[2264]
2012-10-16 14:40:20 +00:00
Romain Quetiez
bddda8e256 CSV import: added a flag to disable the history tab (too long to display, when the feature is heavily used)
SVN:trunk[2263]
2012-10-16 14:31:15 +00:00
Romain Quetiez
020089b1d3 Internal: MetaModel to ignore classes declared only with the purpose of implementing behaviors (missing function Init). Note: declaring such a class as abstract is recommended, though it seems enough to omit the Init method. Perfs: benchmarked as an additional 1ms out of 1s for the whole page.
SVN:trunk[2262]
2012-10-16 14:07:21 +00:00
Romain Quetiez
e454a12346 Dev productivity: SVN to ignore log/setup.log
SVN:trunk[2261]
2012-10-16 13:11:04 +00:00
Romain Quetiez
b304307ad7 Spurious chars corrupting CSV download:
- factorized in WebPage as TrashUnexpectedOutput()
- added early tracking and reporting into MetaModel::IncludeModule, use the new config flag 'debug_track_spurious_chars' to blame the harmful module/file.
- protected export.php
- removed a space at the beginning of page 'createfrommail.php'

SVN:trunk[2260]
2012-10-16 13:06:50 +00:00
Romain Quetiez
6039ea47fc Bug: download CSV result with search criteria
SVN:trunk[2259]
2012-10-15 16:00:25 +00:00
Denis Flaven
8d26d1dd34 Fixed the support of the toolkit
SVN:trunk[2258]
2012-10-15 15:28:48 +00:00
Romain Quetiez
1507259cfe Fix: removed a debug trace
SVN:trunk[2257]
2012-10-15 14:12:35 +00:00
Romain Quetiez
a79336116f Fixed regression - still, the API MetaModel::BulkDelete cannot be used in any case (e.g. hierarchical keys)
SVN:trunk[2256]
2012-10-15 13:57:19 +00:00
Romain Quetiez
f805e8b6c5 Fixed export.php usage description
SVN:trunk[2255]
2012-10-15 13:55:54 +00:00
Erwan Taloc
7015a44268 Allow utilization of place holder in from and reply_to fields for action emails
SVN:trunk[2254]
2012-10-15 12:27:09 +00:00
Romain Quetiez
e33523ddc8 CSV import/export reworked:
Trac #174 and #283: import.php localized by default, option no_localize to disable
Trac #554: export.php localized by default, option no_localize to disable
Trac #555: friendlyname abusively used as a reconciliation key
+ Default charset is ISO-8859-1 to be compatible with Excel (See config parameter csv_file_default_charset)
+ CSV export in UTF-8 with BOM to help Excel in getting it right (not all versions)
+ Fixed reporting issues (wrong class, exceptions, changed external key)
+ Fixed settings lost when navigating in the import wizard
+ Fixed issues when some html entities were found in the data (reporting + export)
+ Added a link to download the CSV export.php


SVN:trunk[2253]
2012-10-12 15:48:54 +00:00
Denis Flaven
ec3c42e87c - Changes to the setup program: Backup now works for real
- A few cosmetic changes...

SVN:trunk[2252]
2012-10-12 12:15:06 +00:00
Denis Flaven
8edfac5cff Smaller and nicer tar/zip icon
SVN:trunk[2251]
2012-10-12 11:10:46 +00:00
Romain Quetiez
1bd9e77a87 Brand new setup: fixed two issues
SVN:trunk[2250]
2012-10-10 14:22:22 +00:00
Denis Flaven
3e5581dd24 Not needed if there is no installation.xml file
SVN:trunk[2249]
2012-10-10 10:23:05 +00:00
Denis Flaven
ebc0114284 Installation.xml is useless for a 1.x datamodel
SVN:trunk[2248]
2012-10-10 10:21:48 +00:00
Denis Flaven
f788f589fa ResetCache requires the Dict class.
SVN:trunk[2247]
2012-10-10 10:16:29 +00:00
Denis Flaven
44aa1d34b7 Do not search for modules when its not needed
SVN:trunk[2246]
2012-10-10 10:02:05 +00:00
Denis Flaven
06aef10f25 Imported the "old" addon from the 1.2 branch
SVN:trunk[2245]
2012-10-10 09:49:58 +00:00
Denis Flaven
9c58240474 Start using the new setup 2.0 ! Be brave !!
SVN:trunk[2244]
2012-10-10 09:36:04 +00:00
Denis Flaven
4f29019351 Start using the new setup 2.0 ! Be brave !!
SVN:trunk[2243]
2012-10-10 09:35:34 +00:00
Denis Flaven
59df6b61d0 More information for the setup program
SVN:trunk[2242]
2012-10-10 09:33:48 +00:00
Denis Flaven
4cf90dee55 Rollback an unwanted - experimental - change.
SVN:trunk[2241]
2012-10-10 09:32:06 +00:00
Denis Flaven
01d4746b0c Moving the datamodel to its new place
SVN:trunk[2240]
2012-10-10 09:28:22 +00:00
Denis Flaven
011c08676e New way of storing the "source" data model(s)
SVN:trunk[2239]
2012-10-10 09:23:32 +00:00
Denis Flaven
ecaa870880 "extensions" is now the offical place for storing extension modules
SVN:trunk[2238]
2012-10-10 09:21:40 +00:00
Denis Flaven
847a538912 Some progress on the 2.0 setup...
SVN:trunk[2237]
2012-10-10 09:18:32 +00:00
Romain Quetiez
7dbbb1c299 #439 Record and display changes in the link sets (ex: Members of a team)
#439 Make sure that changes made by a plugin get recorded
+ simplified the change tracking for the plugins. Simply call DBObject::DBInsert (resp. Update and Delete) and the change will be recorded for the current page. This is compatible with the old (not mandatory anymore) way that was requiring DBInsertTracked APIs (resp. Update, Delete).

SVN:trunk[2236]
2012-10-08 12:17:56 +00:00
865 changed files with 111363 additions and 20130 deletions

View File

@@ -1,26 +1,26 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* UserRightsMatrix (User management Module)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,27 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* UserRightsNull
* User management Module - say Yeah! to everything
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class UserRightsNull extends UserRightsAddOnAPI

View File

@@ -1,27 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* UserRightsProfile
* User management Module, basing the right on profiles and a matrix (similar to UserRightsMatrix, but profiles and other decorations have been added)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
define('ADMIN_PROFILE_NAME', 'Administrator');
@@ -311,11 +311,9 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Installation: create the very first user
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
{
// Create a change to record the history of the User object
$oChange = MetaModel::NewObject("CMDBChange");
$oChange->Set("date", time());
$oChange->Set("userinfo", "Initialization");
$iChangeId = $oChange->DBInsert();
CMDBObject::SetTrackInfo('Initialization');
$oChange = CMDBObject::GetCurrentChange();
$iContactId = 0;
// Support drastic data model changes: no organization class (or not writable)!

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* UserRightsProjection
* User management Module, basing the right on profiles and a matrix (similar to UserRightsProfile, but enhanced with dimensions and projection of classes and profile over the dimensions)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
define('ADMIN_PROFILE_ID', 1);

View File

@@ -1,27 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Simple web page with no includes, header or fancy formatting, useful to
* generate HTML fragments when called by an AJAX method
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT."/application/webpage.class.inc.php");
@@ -36,6 +36,7 @@ class ajax_page extends WebPage
protected $m_sCurrentTab;
protected $m_sCurrentTabContainer;
protected $m_aTabs;
private $m_sMenu; // If set, then the menu will be updated
/**
* constructor for the web page
@@ -52,6 +53,7 @@ class ajax_page extends WebPage
$this->m_aTabs = array();
$this->sContentType = 'text/html';
$this->sContentDisposition = 'inline';
$this->m_sMenu = "";
}
public function AddTabContainer($sTabContainer, $sPrefix = '')
@@ -93,6 +95,11 @@ class ajax_page extends WebPage
return $this->m_sCurrentTab;
}
public function AddToMenu($sHtml)
{
$this->m_sMenu .= $sHtml;
}
/**
* Echoes the content of the whole page
* @return void
@@ -113,7 +120,7 @@ class ajax_page extends WebPage
}
if (count($this->m_aTabs) > 0)
{
$this->add_ready_script(
$this->add_ready_script(
<<<EOF
// The "tab widgets" to handle.
var tabs = $('div[id^=tabbedContent]');
@@ -183,7 +190,33 @@ EOF
$this->s_content = str_replace("\$Tabs:$sTabContainerName\$", $sTabs, $this->s_content);
$container_index++;
}
// Additional UI widgets to be activated inside the ajax fragment ??
if (($this->sContentType == 'text/html') && (preg_match('/class="date-pick"/', $this->s_content) || preg_match('/class="datetime-pick"/', $this->s_content)) )
{
$this->add_ready_script(
<<<EOF
$(".date-pick").datepicker({
showOn: 'button',
buttonImage: '../images/calendar.png',
buttonImageOnly: true,
dateFormat: 'yy-mm-dd',
constrainInput: false,
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
});
EOF
);
}
$s_captured_output = ob_get_contents();
ob_end_clean();
if (($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'))
@@ -195,6 +228,24 @@ EOF
{
echo $this->s_content;
}
if (!empty($this->m_sMenu))
{
$uid = time();
echo "<div id=\"accordion_temp_$uid\">\n";
echo "<div id=\"accordion\">\n";
echo "<!-- Beginning of the accordion menu -->\n";
echo self::FilterXSS($this->m_sMenu);
echo "<!-- End of the accordion menu-->\n";
echo "</div>\n";
echo "</div>\n";
echo "<script type=\"text/javascript\">\n";
echo "$('#inner_menu').html($('#accordion_temp_$uid').html());\n";
echo "$('#accordion_temp_$uid').remove();\n";
echo "$('#accordion').accordion({ header: 'h3', navigation: true, autoHeight: false, collapsible: false, icons: false });\n";
echo "\n</script>\n";
}
//echo $this->s_deferred_content;
if (count($this->a_scripts) > 0)
{
@@ -214,10 +265,16 @@ EOF
echo $this->m_sReadyScript; // Ready Scripts are output as simple scripts
echo "\n</script>\n";
}
if (trim($s_captured_output) != "")
{
echo self::FilterXSS($s_captured_output);
}
if (class_exists('MetaModel'))
{
MetaModel::RecordQueryTrace();
}
}
/**

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Includes all the classes to have the application up and running
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/application/applicationcontext.class.inc.php');

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 ApplicationContext
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT."/application/utils.inc.php");

View File

@@ -1,50 +1,264 @@
<?php
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 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)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @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,19 +463,501 @@ 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' => '');
}
}
/**
* 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
* width of the page
* * 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.
* 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 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 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 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

@@ -1,28 +1,29 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* This class manages the audit "categories". Each category defines a set of objects
* to check and is linked to a set of rules that determine the valid or invalid objects
* inside the set
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/application/cmdbabstract.class.inc.php');
@@ -46,7 +47,7 @@ class AuditCategory extends cmdbAbstractObject
MetaModel::Init_AddAttribute(new AttributeString("name", array("description"=>"Short name for this category", "allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeOQL("definition_set", array("allowed_values"=>null, "sql"=>"definition_set", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLinkedSet("rules_list", array("linked_class"=>"AuditRule", "ext_key_to_me"=>"category_id", "allowed_values"=>null, "count_min"=>0, "count_max"=>0, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeLinkedSet("rules_list", array("linked_class"=>"AuditRule", "ext_key_to_me"=>"category_id", "allowed_values"=>null, "count_min"=>0, "count_max"=>0, "depends_on"=>array(), "edit_mode" => LINKSET_EDITMODE_INPLACE)));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'description', 'definition_set', 'rules_list')); // Attributes to be displayed for the complete details

View File

@@ -1,18 +1,21 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* This class manages the audit "rule" linked to a given audit category.
@@ -20,10 +23,8 @@
* or the "bad" ones. The core audit engines computes the complement to the definition
* set when needed to obtain either the valid objects, or the ones with an error
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/application/audit.category.class.inc.php');

View File

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* CLI page
* The page adds the content-type text/XML and the encoding into the headers
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT."/application/webpage.class.inc.php");
@@ -34,6 +35,10 @@ class CLIPage implements Page
public function output()
{
if (class_exists('MetaModel'))
{
MetaModel::RecordQueryTrace();
}
}
public function add($sText)

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Simple web page with no includes or fancy formatting, useful to generateXML documents
* The page adds the content-type text/XML and the encoding into the headers
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT."/application/webpage.class.inc.php");
@@ -31,8 +32,9 @@ class CSVPage extends WebPage
function __construct($s_title)
{
parent::__construct($s_title);
$this->add_header("Content-type: text/html; charset=utf-8");
$this->add_header("Content-type: text/plain; charset=utf-8");
$this->add_header("Cache-control: no-cache");
//$this->add_header("Content-Transfer-Encoding: binary");
}
public function output()
@@ -43,6 +45,12 @@ class CSVPage extends WebPage
header($s_header);
}
echo trim($this->s_content);
echo "\n";
if (class_exists('MetaModel'))
{
MetaModel::RecordQueryTrace();
}
}
public function small_p($sText)

View File

@@ -1,18 +1,20 @@
<?php
// Copyright (C) 2012 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
require_once(APPROOT.'application/dashboardlayout.class.inc.php');
require_once(APPROOT.'application/dashlet.class.inc.php');
@@ -20,6 +22,8 @@ require_once(APPROOT.'application/dashlet.class.inc.php');
/**
* A user editable dashboard page
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
abstract class Dashboard
{
@@ -55,22 +59,54 @@ abstract class Dashboard
$oCellsNode = $this->oDOMNode->getElementsByTagName('cells')->item(0);
$oCellsList = $oCellsNode->getElementsByTagName('cell');
$aCellOrder = array();
$iCellRank = 0;
foreach($oCellsList as $oCellNode)
{
$aDashletList = array();
$oDashletList = $oCellNode->getElementsByTagName('dashlet');
$oCellRank = $oCellNode->getElementsByTagName('rank')->item(0);
if ($oCellRank)
{
$iCellRank = (float)$oCellRank->textContent;
}
$oDashletsNode = $oCellNode->getElementsByTagName('dashlets')->item(0);
$oDashletList = $oDashletsNode->getElementsByTagName('dashlet');
$iRank = 0;
$aDashletOrder = array();
foreach($oDashletList as $oDomNode)
{
$sDashletClass = $oDomNode->getAttribute('xsi:type');
$oRank = $oDomNode->getElementsByTagName('rank')->item(0);
if ($oRank)
{
$iRank = (float)$oRank->textContent;
}
$sId = $oDomNode->getAttribute('id');
$oNewDashlet = new $sDashletClass($sId);
$oNewDashlet->FromDOMNode($oDomNode);
$aDashletList[] = $oNewDashlet;
$aDashletOrder[] = array('rank' => $iRank, 'dashlet' => $oNewDashlet);
}
$this->aCells[] = $aDashletList;
usort($aDashletOrder, array(get_class($this), 'SortOnRank'));
$aDashletList = array();
foreach($aDashletOrder as $aItem)
{
$aDashletList[] = $aItem['dashlet'];
}
$aCellOrder[] = array('rank' => $iCellRank, 'dashlets' => $aDashletList);
}
usort($aCellOrder, array(get_class($this), 'SortOnRank'));
foreach($aCellOrder as $aItem)
{
$this->aCells[] = $aItem['dashlets'];
}
}
static function SortOnRank($aItem1, $aItem2)
{
return ($aItem1['rank'] > $aItem2['rank']) ? +1 : -1;
}
/**
* Error handler to turn XML loading warnings into exceptions
*/
@@ -104,17 +140,29 @@ abstract class Dashboard
$oCellsNode = $oDoc->createElement('cells');
$oMainNode->appendChild($oCellsNode);
$iCellRank = 0;
foreach ($this->aCells as $aCell)
{
$oCellNode = $oDoc->createElement('cell');
$oCellNode->setAttribute('id', $iCellRank);
$oCellsNode->appendChild($oCellNode);
$oCellRank = $oDoc->createElement('rank', $iCellRank);
$oCellNode->appendChild($oCellRank);
$iCellRank++;
$iDashletRank = 0;
$oDashletsNode = $oDoc->createElement('dashlets');
$oCellNode->appendChild($oDashletsNode);
foreach ($aCell as $oDashlet)
{
$oNode = $oDoc->createElement('dashlet');
$oCellNode->appendChild($oNode);
$oDashletsNode->appendChild($oNode);
$oNode->setAttribute('id', $oDashlet->GetID());
$oNode->setAttribute('xsi:type', get_class($oDashlet));
$oDashletRank = $oDoc->createElement('rank', $iDashletRank);
$oNode->appendChild($oDashletRank);
$iDashletRank++;
$oDashlet->ToDOMNode($oNode);
}
}

View File

@@ -1,4 +1,29 @@
<?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/>
/**
* Dashboard presentation
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
abstract class DashboardLayout
{
public function __construct()

View File

@@ -1,24 +1,28 @@
<?php
// Copyright (C) 2012 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
require_once(APPROOT.'application/forms.class.inc.php');
/**
* Base class for all 'dashlets' (i.e. widgets to be inserted into a dashboard)
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
abstract class Dashlet
{
@@ -454,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':
@@ -464,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:
@@ -804,7 +808,7 @@ class DashletHeaderStatic extends Dashlet
while (($sFile = readdir($hDir)) !== false)
{
$aMatches = array();
if (($sFile != '.') && ($sFile != '..') && is_dir($sBaseDir.'/'.$sDir.'/'.$sFile))
if (($sFile != '.') && ($sFile != '..') && ($sFile != 'lifecycle') && is_dir($sBaseDir.'/'.$sDir.'/'.$sFile))
{
$sDirSubPath = ($sDir == '') ? $sFile : $sDir.'/'.$sFile;
$aResult = array_merge($aResult, self::FindIcons($sBaseDir, $sDirSubPath));

View File

@@ -1,25 +1,25 @@
<?php
// Copyright (C) 2012 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Data Table to display a set of objects in a tabular manner in HTML
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html GPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class DataTable
@@ -40,7 +40,7 @@ class DataTable
*/
public function __construct($iListId, $oSet, $aClassAliases, $sTableId = null)
{
$this->iListId = $iListId;
$this->iListId = utils::GetSafeId($iListId); // Make a "safe" ID for jQuery
$this->oSet = $oSet;
$this->aClassAliases = $aClassAliases;
$this->sTableId = $sTableId;
@@ -60,6 +60,10 @@ class DataTable
{
// Custom settings overload the default ones
$this->bUseCustomSettings = true;
if ($this->oDefaultSettings->iDefaultPageSize == 0)
{
$oCustomSettings->iDefaultPageSize = 0;
}
}
else
{
@@ -73,6 +77,10 @@ class DataTable
$this->oSet->SetOrderBy($oCustomSettings->GetSortOrder());
$bToolkitMenu = true;
if (isset($aExtraParams['toolkit_menu']))
{
$bToolkitMenu = (bool) $aExtraParams['toolkit_menu'];
}
if (UserRights::IsPortalUser())
{
// Portal users have a limited access to data, for now they can only see what's configured for them
@@ -172,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
{
@@ -222,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>
@@ -235,6 +246,7 @@ class DataTable
</td>
</tr>
</table>
</div>
</td>
EOF;
return $sHtml;
@@ -341,6 +353,12 @@ EOF;
protected function GetHTMLTableValues($aColumns, $sSelectMode, $iPageSize, $bViewLink, $aExtraParams)
{
$bLocalize = true;
if (isset($aExtraParams['localize_values']))
{
$bLocalize = (bool) $aExtraParams['localize_values'];
}
$aValues = array();
$this->oSet->Seek(0);
$iMaxObjects = $iPageSize;
@@ -350,41 +368,61 @@ EOF;
$aRow = array();
foreach($this->aClassAliases as $sAlias => $sClassName)
{
$sHilightClass = $aObjects[$sAlias]->GetHilightClass();
if ($sHilightClass != '')
if (is_object($aObjects[$sAlias]))
{
$aRow['@class'] = $sHilightClass;
}
if ((($sSelectMode == 'single') || ($sSelectMode == 'multiple')) && $bFirstObject)
{
if (array_key_exists('selection_enabled', $aExtraParams) && isset($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()]))
$sHilightClass = $aObjects[$sAlias]->GetHilightClass();
if ($sHilightClass != '')
{
$sDisabled = ($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()]) ? '' : ' disabled="disabled"';
$aRow['@class'] = $sHilightClass;
}
else
if ((($sSelectMode == 'single') || ($sSelectMode == 'multiple')) && $bFirstObject)
{
$sDisabled = '';
}
if ($sSelectMode == 'single')
{
$aRow['form::select'] = "<input type=\"radio\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
}
else
{
$aRow['form::select'] = "<input type=\"checkBox\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject[]\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
}
}
foreach($aColumns[$sAlias] as $sAttCode => $aData)
{
if ($aData['checked'])
{
if ($sAttCode == '_key_')
if (array_key_exists('selection_enabled', $aExtraParams) && isset($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()]))
{
$aRow['key_'.$sAlias] = $aObjects[$sAlias]->GetHyperLink();
$sDisabled = ($aExtraParams['selection_enabled'][$aObjects[$sAlias]->GetKey()]) ? '' : ' disabled="disabled"';
}
else
{
$aRow[$sAttCode.'_'.$sAlias] = $aObjects[$sAlias]->GetAsHTML($sAttCode);
$sDisabled = '';
}
if ($sSelectMode == 'single')
{
$aRow['form::select'] = "<input type=\"radio\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
}
else
{
$aRow['form::select'] = "<input type=\"checkBox\" $sDisabled class=\"selectList{$this->iListId}\" name=\"selectObject[]\" value=\"".$aObjects[$sAlias]->GetKey()."\"></input>";
}
}
foreach($aColumns[$sAlias] as $sAttCode => $aData)
{
if ($aData['checked'])
{
if ($sAttCode == '_key_')
{
$aRow['key_'.$sAlias] = $aObjects[$sAlias]->GetHyperLink();
}
else
{
$aRow[$sAttCode.'_'.$sAlias] = $aObjects[$sAlias]->GetAsHTML($sAttCode, $bLocalize);
}
}
}
}
else
{
foreach($aColumns[$sAlias] as $sAttCode => $aData)
{
if ($aData['checked'])
{
if ($sAttCode == '_key_')
{
$aRow['key_'.$sAlias] = '';
}
else
{
$aRow[$sAttCode.'_'.$sAlias] = '';
}
}
}
}
@@ -476,18 +514,22 @@ EOF;
$aDefaultSort[] = "[".($iColOffset).",".($bAscending ? '0' : '1')."]";
}
}
$sSortList = '';
$sFakeSortList = '';
if (count($aDefaultSort) > 0)
{
$sSortList = ', sortList: ['.implode(',', $aDefaultSort).']';
$sFakeSortList = '['.implode(',', $aDefaultSort).']';
}
$sOQL = addslashes($this->oSet->GetFilter()->serialize());
$oPage->add_ready_script(
<<<EOF
var oTable = $('#{$this->iListId} table.listResults');
oTable.tablesorter( { $sHeaders widgets: ['myZebra', 'truncatedList'] $sSortList} ).tablesorterPager({container: $('#pager{$this->iListId}'), totalRows:$iCount, size: $iPageSize, filter: '$sOQL', extra_params: '$sExtraParams', select_mode: '$sSelectModeJS', displayKey: $sDisplayKey, columns: $sJSColumns, class_aliases: $sJSClassAliases $sCssCount});
oTable.tablesorter( { $sHeaders widgets: ['myZebra', 'truncatedList']} ).tablesorterPager({container: $('#pager{$this->iListId}'), totalRows:$iCount, size: $iPageSize, filter: '$sOQL', extra_params: '$sExtraParams', select_mode: '$sSelectModeJS', displayKey: $sDisplayKey, columns: $sJSColumns, class_aliases: $sJSClassAliases $sCssCount});
EOF
);
if ($sFakeSortList != '')
{
$oPage->add_ready_script("oTable.trigger(\"fakesorton\", [$sFakeSortList]);");
}
//if ($iNbPages == 1)
if (false)
{

View File

@@ -1,26 +1,26 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* DisplayBlock and derived class
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/application/webpage.class.inc.php');
@@ -52,13 +52,18 @@ class DisplayBlock
public function __construct(DBObjectSearch $oFilter, $sStyle = 'list', $bAsynchronous = false, $aParams = array(), $oSet = null)
{
$this->m_oFilter = clone $oFilter;
$this->m_oFilter = $oFilter->DeepClone();
$this->m_aConditions = array();
$this->m_sStyle = $sStyle;
$this->m_bAsynchronous = $bAsynchronous;
$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;
}
@@ -300,23 +312,40 @@ class DisplayBlock
}
foreach($aFilterCodes as $sFilterCode)
{
$sExternalFilterValue = utils::ReadParam($sFilterCode, '', false, 'raw_data');
$externalFilterValue = utils::ReadParam($sFilterCode, '', false, 'raw_data');
$condition = null;
if (isset($aExtraParams[$sFilterCode]))
{
$condition = $aExtraParams[$sFilterCode];
}
// else if ($bDoSearch && $sExternalFilterValue != "")
if ($bDoSearch && $sExternalFilterValue != "")
if ($bDoSearch && $externalFilterValue != "")
{
// Search takes precedence over context params...
unset($aExtraParams[$sFilterCode]);
$condition = trim($sExternalFilterValue);
if (!is_array($externalFilterValue))
{
$condition = trim($externalFilterValue);
}
else if (count($externalFilterValue) == 1)
{
$condition = trim($externalFilterValue[0]);
}
else
{
$condition = $externalFilterValue;
}
}
if (!is_null($condition))
{
$this->AddCondition($sFilterCode, $condition);
$sOpCode = null; // default operator
if (is_array($condition))
{
// Multiple values, add them as AND X IN (v1, v2, v3...)
$sOpCode = 'IN';
}
$this->AddCondition($sFilterCode, $condition, $sOpCode);
}
}
if ($bDoSearch)
@@ -373,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();
@@ -397,7 +426,7 @@ class DisplayBlock
foreach($aGroupBy as $iRow => $iCount)
{
// Build the search for this subset
$oSubsetSearch = clone $this->m_oFilter;
$oSubsetSearch = $this->m_oFilter->DeepClone();
$oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($aValues[$iRow]));
$oSubsetSearch->AddConditionExpression($oCondition);
$sFilter = urlencode($oSubsetSearch->serialize());
@@ -475,7 +504,7 @@ class DisplayBlock
$sHtml .= "<table>\n";
// Construct a new (parametric) query that will return the content of this block
$oBlockFilter = clone $this->m_oFilter;
$oBlockFilter = $this->m_oFilter->DeepClone();
$aExpressions = array();
$index = 0;
foreach($aGroupByFields as $aField)
@@ -568,11 +597,13 @@ class DisplayBlock
{
if ((UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES))
{
$sLinkTarget = '';
$oAppContext = new ApplicationContext();
$sParams = $oAppContext->GetForLink();
// 1:n links, populate the target object as a default value when creating a new linked object
if (isset($aExtraParams['target_attr']))
{
$sLinkTarget = ' target="_blank" ';
$aExtraParams['default'][$aExtraParams['target_attr']] = $aExtraParams['object_id'];
}
$sDefault = '';
@@ -584,7 +615,7 @@ class DisplayBlock
}
}
$sHtml .= $oPage->GetP("<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=new&class=$sClass&$sParams{$sDefault}\">".Dict::Format('UI:ClickToCreateNew', Metamodel::GetName($sClass))."</a>\n");
$sHtml .= $oPage->GetP("<a{$sLinkTarget} href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=new&class=$sClass&$sParams{$sDefault}\">".Dict::Format('UI:ClickToCreateNew', Metamodel::GetName($sClass))."</a>\n");
}
}
}
@@ -707,11 +738,11 @@ class DisplayBlock
$oAttDef = MetaModel::GetAttributeDef($sClass, $sStateAttrCode);
foreach($aStates as $sStateValue)
{
$oFilter = clone($this->m_oFilter);
$oFilter = $this->m_oFilter->DeepClone();
$oFilter->AddCondition($sStateAttrCode, $sStateValue, '=');
$oSet = new DBObjectSet($oFilter);
$aCounts[$sStateValue] = $oSet->Count();
$aStateLabels[$sStateValue] = $oAttDef->GetValueLabel($sStateValue);
$aStateLabels[$sStateValue] = htmlentities($oAttDef->GetValueLabel($sStateValue), ENT_QUOTES, 'UTF-8');
if ($aCounts[$sStateValue] == 0)
{
$aCounts[$sStateValue] = '-';
@@ -733,8 +764,67 @@ class DisplayBlock
break;
case 'csv':
$bAdvancedMode = utils::ReadParam('advanced', false);
$sCsvFile = strtolower($this->m_oFilter->GetClass()).'.csv';
$sDownloadLink = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?expression='.urlencode($this->m_oFilter->ToOQL(true)).'&format=csv&filename='.urlencode($sCsvFile);
$sLinkToToggle = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.urlencode($this->m_oFilter->serialize()).'&format=csv';
if ($bAdvancedMode)
{
$sDownloadLink .= '&fields_advanced=1';
$sChecked = 'CHECKED';
}
else
{
$sLinkToToggle = $sLinkToToggle.'&advanced=1';
$sChecked = '';
}
$sCSVData = cmdbAbstractObject::GetSetAsCSV($this->m_oSet, array('fields_advanced' => $bAdvancedMode));
$sCharset = MetaModel::GetConfig()->Get('csv_file_default_charset');
if ($sCharset == 'UTF-8')
{
$bLostChars = false;
}
else
{
$sConverted = @iconv('UTF-8', $sCharset, $sCSVData);
$sRestored = @iconv($sCharset, 'UTF-8', $sConverted);
$bLostChars = ($sRestored != $sCSVData);
}
if ($bLostChars)
{
$sCharsetNotice = "&nbsp;&nbsp;<span id=\"csv_charset_issue\">";
$sCharsetNotice .= '<img src="../images/error.png" style="vertical-align:middle"/>';
$sCharsetNotice .= "</span>";
$sTip = "<p>".htmlentities(Dict::S('UI:CSVExport:LostChars'), ENT_QUOTES, 'UTF-8')."</p>";
$sTip .= "<p>".htmlentities(Dict::Format('UI:CSVExport:LostChars+', $sCharset), ENT_QUOTES, 'UTF-8')."</p>";
$oPage->add_ready_script("$('#csv_charset_issue').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );");
}
else
{
$sCharsetNotice = '';
}
$sHtml .= "<div>";
$sHtml .= '<table style="width:100%" class="transparent">';
$sHtml .= '<tr>';
$sHtml .= '<td><a href="'.$sDownloadLink.'">'.Dict::Format('UI:Download-CSV', $sCsvFile).'</a>'.$sCharsetNotice.'</td>';
$sHtml .= '<td style="text-align:right"><input type="checkbox" '.$sChecked.' onClick="window.location.href=\''.$sLinkToToggle.'\'">&nbsp;'.Dict::S('UI:CSVExport:AdvancedMode').'</td>';
$sHtml .= '</tr>';
$sHtml .= '</table>';
if ($bAdvancedMode)
{
$sHtml .= "<p>";
$sHtml .= htmlentities(Dict::S('UI:CSVExport:AdvancedMode+'), ENT_QUOTES, 'UTF-8');
$sHtml .= "</p>";
}
$sHtml .= "</div>";
$sHtml .= "<textarea style=\"width:95%;height:98%\">\n";
$sHtml .= cmdbAbstractObject::GetSetAsCSV($this->m_oSet);
$sHtml .= htmlentities($sCSVData, ENT_QUOTES, 'UTF-8');
$sHtml .= "</textarea>\n";
break;
@@ -810,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();
@@ -833,7 +923,7 @@ EOF
foreach($aGroupBy as $iRow => $iCount)
{
// Build the search for this subset
$oSubsetSearch = clone $this->m_oFilter;
$oSubsetSearch = $this->m_oFilter->DeepClone();
$oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($aValues[$iRow]));
$oSubsetSearch->AddConditionExpression($oCondition);
$aURLs[$idx] = $oSubsetSearch->serialize();
@@ -885,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();
@@ -966,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();
@@ -1028,7 +1119,7 @@ EOF
* Add a condition (restriction) to the current DBObjectSearch on which the display block is based
* taking into account the hierarchical keys for which the condition is based on the 'below' operator
*/
protected function AddCondition($sFilterCode, $condition)
protected function AddCondition($sFilterCode, $condition, $sOpCode = null)
{
// Workaround to an issue revealed whenever a condition on org_id is applied twice (with a hierarchy of organizations)
// Moreover, it keeps the query as simple as possible
@@ -1054,12 +1145,29 @@ EOF
if ($sHierarchicalKeyCode !== false)
{
$oFilter = new DBObjectSearch($oAttDef->GetTargetClass());
$oFilter->AddCondition('id', $condition);
if (($sOpCode == 'IN') && is_array($condition))
{
$oFilter->AddConditionExpression(self::GetConditionIN($oFilter, 'id', $condition));
}
else
{
$oFilter->AddCondition('id', $condition);
}
$oHKFilter = new DBObjectSearch($oAttDef->GetTargetClass());
$oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW); // Use the 'below' operator by default
$this->m_oFilter->AddCondition_PointingTo($oHKFilter, $sFilterCode);
$bConditionAdded = true;
}
else if (($sOpCode == 'IN') && is_array($condition))
{
$this->m_oFilter->AddConditionExpression(self::GetConditionIN($this->m_oFilter, $sFilterCode, $condition));
$bConditionAdded = true;
}
}
else if (($sOpCode == 'IN') && is_array($condition))
{
$this->m_oFilter->AddConditionExpression(self::GetConditionIN($this->m_oFilter, $sFilterCode, $condition));
$bConditionAdded = true;
}
}
@@ -1069,6 +1177,15 @@ EOF
$this->m_oFilter->AddCondition($sFilterCode, $condition); // Use the default 'loose' operator
}
}
static protected function GetConditionIN($oFilter, $sFilterCode, $condition)
{
$oField = new FieldExpression($sFilterCode, $oFilter->GetClassAlias());
$sListExpr = '('.implode(', ', CMDBSource::Quote($condition)).')';
$sOQLCondition = $oField->Render()." IN $sListExpr";
$oNewCondition = Expression::FromOQL($sOQLCondition);
return $oNewCondition;
}
}
/**
@@ -1255,6 +1372,7 @@ class MenuBlock extends DisplayBlock
$aActions[$sRelationCode] = array ('label' => MetaModel::GetRelationVerbUp($sRelationCode), 'url' => "{$sRootUrl}pages/$sUIPage?operation=swf_navigator&relation=$sRelationCode&class=$sClass&id=$id{$sContext}");
}
}
/*
$this->AddMenuSeparator($aActions);
// Static menus: Email this page & CSV Export
$sUrl = ApplicationContext::MakeObjectUrl($sClass, $id);
@@ -1267,6 +1385,7 @@ class MenuBlock extends DisplayBlock
$sOQL = addslashes($sFilterDesc);
$aActions['UI:Menu:AddToDashboard'] = array ('label' => Dict::S('UI:Menu:AddToDashboard'), 'url' => "#", 'onclick' => "return DashletCreationDlg('$sOQL')");
}
*/
}
$this->AddMenuSeparator($aActions);
foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance)
@@ -1305,7 +1424,10 @@ class MenuBlock extends DisplayBlock
// Stimuli
$aStates = MetaModel::EnumStates($sClass);
if (count($aStates) > 0)
// Do not perform time consuming computations if there are too may objects in the list
$iLimit = MetaModel::GetConfig()->Get('complex_actions_limit');
if ((count($aStates) > 0) && (($iLimit == 0) || ($oSet->Count() < $iLimit)))
{
// Life cycle actions may be available... if all objects are in the same state
$oSet->Rewind();
@@ -1342,51 +1464,55 @@ class MenuBlock extends DisplayBlock
}
}
}
/*
$this->AddMenuSeparator($aActions);
$sUrl = utils::GetAbsoluteUrlAppRoot();
$aActions['UI:Menu:EMail'] = array ('label' => Dict::S('UI:Menu:EMail'), 'url' => "mailto:?subject=$sFilterDesc&body=".urlencode("{$sUrl}pages/$sUIPage?operation=search&filter=".urlencode($sFilter)."{$sContext}"));
$aActions['UI:Menu:CSVExport'] = array ('label' => Dict::S('UI:Menu:CSVExport'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=search&filter=".urlencode($sFilter)."&format=csv{$sContext}");
$sOQL = addslashes($sFilterDesc);
$aActions['UI:Menu:AddToDashboard'] = array ('label' => Dict::S('UI:Menu:AddToDashboard'), 'url' => "#", 'onclick' => "return DashletCreationDlg('$sOQL')");
*/
}
$this->AddMenuSeparator($aActions);
foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance)
}
$this->AddMenuSeparator($aActions);
foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance)
{
$oSet->Rewind();
foreach($oExtensionInstance->EnumAllowedActions($oSet) as $sLabel => $data)
{
$oSet->Rewind();
foreach($oExtensionInstance->EnumAllowedActions($oSet) as $sLabel => $data)
if (is_array($data))
{
if (is_array($data))
{
// New plugins can provide javascript handlers via the 'onclick' property
//TODO: enable extension of different menus by checking the 'target' property ??
$aActions[$sLabel] = array ('label' => $sLabel, 'url' => isset($data['url']) ? $data['url'] : '#', 'onclick' => isset($data['onclick']) ? $data['onclick'] : '');
}
else
{
// Backward compatibility with old plugins
$aActions[$sLabel] = array ('label' => $sLabel, 'url' => $data);
}
// New plugins can provide javascript handlers via the 'onclick' property
//TODO: enable extension of different menus by checking the 'target' property ??
$aActions[$sLabel] = array ('label' => $sLabel, 'url' => isset($data['url']) ? $data['url'] : '#', 'onclick' => isset($data['onclick']) ? $data['onclick'] : '');
}
else
{
// Backward compatibility with old plugins
$aActions[$sLabel] = array ('label' => $sLabel, 'url' => $data);
}
}
// New extensions based on iPopupMenuItem interface
switch($this->m_sStyle)
{
case 'list':
$oSet->Rewind();
$param = $oSet;
$iMenuId = iPopupMenuExtension::MENU_OBJLIST_ACTIONS;
break;
case 'details':
$oSet->Rewind();
$param = $oSet->Fetch();
$iMenuId = iPopupMenuExtension::MENU_OBJDETAILS_ACTIONS;
break;
}
utils::GetPopupMenuItems($oPage, $iMenuId, $param, $aActions);
}
// New extensions based on iPopupMenuItem interface
switch($this->m_sStyle)
{
case 'list':
$oSet->Rewind();
$param = $oSet;
$iMenuId = iPopupMenuExtension::MENU_OBJLIST_ACTIONS;
break;
case 'details':
$oSet->Rewind();
$param = $oSet->Fetch();
$iMenuId = iPopupMenuExtension::MENU_OBJDETAILS_ACTIONS;
break;
}
utils::GetPopupMenuItems($oPage, $iMenuId, $param, $aActions);
$aFavoriteActions = array();
$aCallSpec = array($sClass, 'GetShortcutActions');
if (is_callable($aCallSpec))
@@ -1478,23 +1604,51 @@ class ExtraMenus implements iPopupMenuExtension
new JSPopupMenuItem('Test::Item2', 'List Test 2', "alert('Test 2')"),
);
break;
$this->AddMenuSeparator($aActions);
$sUrl = utils::GetAbsoluteUrlAppRoot();
$aActions['UI:Menu:EMail'] = array ('label' => Dict::S('UI:Menu:EMail'), 'url' => "mailto:?subject=$sFilterDesc&body=".urlencode("{$sUrl}pages/$sUIPage?operation=search&filter=".urlencode($sFilter)."{$sContext}"));
$aActions['UI:Menu:CSVExport'] = array ('label' => Dict::S('UI:Menu:CSVExport'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=search&filter=".urlencode($sFilter)."&format=csv{$sContext}");
$sOQL = addslashes($sFilterDesc);
$aActions['UI:Menu:AddToDashboard'] = array ('label' => Dict::S('UI:Menu:AddToDashboard'), 'url' => "#", 'onclick' => "return DashletCreationDlg('$sOQL')");
*/
case iPopupMenuExtension::MENU_OBJLIST_TOOLKIT:
// $param is a DBObjectSet
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink();
$sUIPage = cmdbAbstractObject::ComputeStandardUIPage($param->GetFilter()->GetClass());
$sOQL = addslashes($param->GetFilter()->ToOQL(true));
$sFilter = urlencode($param->GetFilter()->serialize());
$sUrl = utils::GetAbsoluteUrlAppRoot()."pages/$sUIPage?operation=search&filter=".$sFilter."&{$sContext}";
$aResult = array(
new JSPopupMenuItem('Test::Item1', 'Toolkit Test 1', "alert('Test 1')"),
new JSPopupMenuItem('Test::Item2', 'Toolkit Test 2', "alert('Test 2')"),
new SeparatorPopupMenuItem(),
// Static menus: Email this page, CSV Export & Add to Dashboard
new URLPopupMenuItem('UI:Menu:EMail', Dict::S('UI:Menu:EMail'), "mailto:?body=".urlencode($sUrl)),
new URLPopupMenuItem('UI:Menu:CSVExport', Dict::S('UI:Menu:CSVExport'), $sUrl."&format=csv"),
new JSPopupMenuItem('UI:Menu:AddToDashboard', Dict::S('UI:Menu:AddToDashboard'), "DashletCreationDlg('$sOQL')"),
new JSPopupMenuItem('UI:Menu:ShortcutList', Dict::S('UI:Menu:ShortcutList'), "ShortcutListDlg('$sOQL', '$sContext')"),
);
break;
case iPopupMenuExtension::MENU_OBJDETAILS_ACTIONS:
// $param is a DBObject
$oObj = $param;
$oFilter = DBobjectSearch::FromOQL("SELECT ".get_class($oObj)." WHERE id=".$oObj->GetKey());
$sFilter = $oFilter->serialize();
$sUrl = ApplicationContext::MakeObjectUrl(get_class($oObj), $oObj->GetKey());
$sUIPage = cmdbAbstractObject::ComputeStandardUIPage(get_class($oObj));
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink();
$aResult = array(
new JSPopupMenuItem('Test::Item1', 'Object Test 1', "alert('Test 1')"),
new JSPopupMenuItem('Test::Item2', 'Object Test 2', "alert('Test 2')"),
new SeparatorPopupMenuItem(),
// Static menus: Email this page & CSV Export
new URLPopupMenuItem('UI:Menu:EMail', Dict::S('UI:Menu:EMail'), "mailto:?subject=".urlencode($oObj->GetRawName())."&body=".urlencode($sUrl)),
new URLPopupMenuItem('UI:Menu:CSVExport', Dict::S('UI:Menu:CSVExport'), utils::GetAbsoluteUrlAppRoot()."pages/$sUIPage?operation=search&filter=".urlencode($sFilter)."&format=csv&{$sContext}"),
);
break;
*/
case iPopupMenuExtension::MENU_DASHBOARD_ACTIONS:
// $param is a Dashboard
@@ -1507,8 +1661,7 @@ class ExtraMenus implements iPopupMenuExtension
$aResult = array(
new SeparatorPopupMenuItem(),
new URLPopupMenuItem('UI:ExportDashboard', Dict::S('UI:ExportDashBoard'), utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=export_dashboard&id='.$sMenuId),
new JSPopupMenuItem('UI:ImportDashboard', Dict::S('UI:ImportDashBoard'), "UploadDashboard({dashboard_id: '$sMenuId', title: '$sDlgTitle', text: '$sDlgText', close_btn: '$sCloseBtn' })",
array('../js/ajaxfileupload.js')),
new JSPopupMenuItem('UI:ImportDashboard', Dict::S('UI:ImportDashBoard'), "UploadDashboard({dashboard_id: '$sMenuId', title: '$sDlgTitle', text: '$sDlgText', close_btn: '$sCloseBtn' })"),
);
break;

View File

@@ -1,23 +1,27 @@
<?php
// Copyright (C) 2012 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Helper class to build interactive forms to be used either in stand-alone
* modal dialog or in "property-sheet" panes.
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class DesignerForm
{

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Persistent class InputOutputTask
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/application/cmdbabstract.class.inc.php');

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program 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 General Public License for more details.
// 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.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 iTopWebPage
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT."/application/nicewebpage.class.inc.php");
@@ -56,12 +57,11 @@ class iTopWebPage extends NiceWebPage
$this->add_linked_stylesheet("../css/jquery.treeview.css");
$this->add_linked_stylesheet("../css/jquery.autocomplete.css");
$this->add_linked_stylesheet("../css/fg.menu.css");
$this->add_linked_stylesheet("../css/jquery.multiselect.css");
$this->add_linked_script('../js/jquery.layout.min.js');
$this->add_linked_script('../js/jquery.ba-bbq.min.js');
$this->add_linked_script("../js/jquery.treeview.js");
$this->add_linked_script("../js/jquery.autocomplete.js");
$this->add_linked_script("../js/jquery.positionBy.js");
$this->add_linked_script("../js/jquery.popupmenu.js");
$this->add_linked_script("../js/date.js");
$this->add_linked_script("../js/jquery.blockUI.js");
$this->add_linked_script("../js/utils.js");
@@ -77,8 +77,19 @@ class iTopWebPage extends NiceWebPage
$this->add_linked_script('../js/g.pie.js');
$this->add_linked_script('../js/g.dot.js');
$this->add_linked_script('../js/charts.js');
$this->add_linked_script('../js/field_sorter.js');
$this->add_linked_script('../js/datatable.js');
$this->add_linked_script('../js/jquery.multiselect.min.js');
$this->add_linked_script('../js/ajaxfileupload.js');
$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 = '';
if (($bForceMenuPane !== null) && ($bForceMenuPane == 0))
{
$sInitClosed = 'initClosed: true,';
}
$this->m_sInitScript =
<<< EOF
@@ -90,7 +101,7 @@ class iTopWebPage extends NiceWebPage
paneSize = GetUserPreference('menu_size', 300)
myLayout = $('body').layout({
west : {
minSize: 200, size: paneSize, spacing_open: 16, spacing_close: 16, slideTrigger_open: "mouseover", hideTogglerOnSlide: true, enableCursorHotkey: false,
$sInitClosed minSize: 200, size: paneSize, spacing_open: 16, spacing_close: 16, slideTrigger_open: "mouseover", hideTogglerOnSlide: true, enableCursorHotkey: false,
onclose_end: function(name, elt, state, options, layout)
{
if (state.isSliding == false)
@@ -130,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'});
@@ -159,6 +171,8 @@ class iTopWebPage extends NiceWebPage
}
});
$('.multiselect').multiselect({header: false, noneSelectedText: '$sSearchAny', selectedList: 1, selectedText:'$sSearchNbSelected'});
$('.resizable').filter(':visible').resizable();
}
catch(err)
@@ -285,7 +299,7 @@ EOF
changeMonth: true,
changeYear: true
});
$(".datetime-pick").datepicker({
$(".datetime-pick").datepicker({
showOn: 'button',
buttonImage: '../images/calendar.png',
buttonImageOnly: true,
@@ -294,23 +308,6 @@ EOF
changeMonth: true,
changeYear: true
});
// Restore the persisted sortable order, for all sortable lists... if any
$('.sortable').each(function()
{
var sTemp = GetUserPreference(this.id+'_order', undefined);
if (sTemp != undefined)
{
var aSerialized = sTemp.split(',');
var sortable = $(this);
$.each(aSerialized, function(i,v) {
var item = $('#menu_'+v);
if (item.length > 0) // Check that the menu exists
{
sortable.append(item);
}
});
}
});
// Make sortable, everything that claims to be sortable
$('.sortable').sortable( {axis: 'y', cursor: 'move', handle: '.drag_handle', stop: function()
@@ -395,6 +392,11 @@ EOF
});
function FixPaneVis()
{
$('.ui-layout-center, .ui-layout-north, .ui-layout-south').css({display: 'block'});
}
EOF
);
}
@@ -450,7 +452,9 @@ EOF
$sFavoriteOrgs = '';
$oWidget = new UIExtKeyWidget('Organization', 'org_id', '', true /* search mode */);
$sHtml .= $oWidget->Display($this, 50, false, '', $oSet, $iCurrentOrganization, 'org_id', false, 'c[org_id]', '', array('iFieldSize' => 20, 'iMinChars' => MetaModel::GetConfig()->Get('min_autocomplete_chars'), 'sDefaultValue' => Dict::S('UI:AllOrganizations')));
$sHtml .= $oWidget->Display($this, 50, false, '', $oSet, $iCurrentOrganization, 'org_id', false, 'c[org_id]', '',
array('iFieldSize' => 20, 'iMinChars' => MetaModel::GetConfig()->Get('min_autocomplete_chars'), 'sDefaultValue' => Dict::S('UI:AllOrganizations')),
null, 'select', false /* bSearchMultiple */);
$this->add_ready_script('$("#org_id").bind("extkeychange", function() { $("#SiloSelection form").submit(); } )');
$this->add_ready_script("$('#label_org_id').click( function() { $(this).val(''); $('#org_id').val(''); return true; } );\n");
// Add other dimensions/context information to this form
@@ -483,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
@@ -530,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
@@ -544,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");
@@ -712,15 +736,29 @@ EOF
}
$sApplicationBanner .= '<div id="admin-banner"><span style="padding:5px;">'.Dict::Format('UI:ApplicationEnvironment', $sEnvLabel).$sBackButton.'<span></div>';
}
$sApplicationBanner .= $sBannerExtraHtml;
if (!empty($sNorthPane))
{
$sNorthPane = '<div id="bottom-pane" class="ui-layout-north">'.$sNorthPane.'</div>';
}
if (!empty($sSouthPane))
{
$sSouthPane = '<div id="bottom-pane" class="ui-layout-south">'.$sSouthPane.'</div>';
}
$sIconUrl = Utils::GetConfig()->Get('app_icon_url');
$sOnlineHelpUrl = MetaModel::GetConfig()->Get('online_help');
//$sLogOffMenu = "<span id=\"logOffBtn\" style=\"height:55px;padding:0;margin:0;\"><img src=\"../images/onOffBtn.png\"></span>";
$sHtml .= $sNorthPane;
$sHtml .= '<div id="left-pane" class="ui-layout-west">';
$sHtml .= '<!-- Beginning of the left pane -->';
$sHtml .= ' <div class="ui-layout-north">';
$sHtml .= ' <div id="header-logo">';
$sHtml .= ' <div id="top-left"></div><div id="logo"><a href="http://www.combodo.com/itop"><img src="../images/itop-logo.png" title="'.htmlentities($sVersionString, ENT_QUOTES, 'UTF-8').'" style="border:0; margin-top:16px; margin-right:40px;"/></a></div>';
$sHtml .= ' <div id="top-left"></div><div id="logo"><a href="'.htmlentities($sIconUrl, ENT_QUOTES, 'UTF-8').'"><img src="../images/itop-logo.png" title="'.htmlentities($sVersionString, ENT_QUOTES, 'UTF-8').'" style="border:0; margin-top:16px; margin-right:40px;"/></a></div>';
$sHtml .= ' </div>';
$sHtml .= ' <div class="header-menu">';
$sHtml .= ' <div class="icon ui-state-default ui-corner-all"><span id="tPinMenu" class="ui-icon ui-icon-pin-w">pin</span></div>';
@@ -736,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>';
@@ -755,7 +793,8 @@ EOF
$sHtml .= ' <!-- End of page content -->';
$sHtml .= ' </div>';
$sHtml .= '</div>';
$sHtml .= $sSouthPane;
// Add the captured output
if (trim($s_captured_output) != "")
{
@@ -801,6 +840,7 @@ EOF
}
$oMPDF->Output($sOutputName, 'I');
}
MetaModel::RecordQueryTrace();
}
public function AddTabContainer($sTabContainer)

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 iTopWizardWebPage
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once('itopwebpage.class.inc.php');

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 LoginWebPage
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT."/application/nicewebpage.class.inc.php");
@@ -121,7 +122,8 @@ EOF
$sAuthPwd = utils::ReadParam('suggest_pwd', '', true, 'raw_data');
$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_VERSION);
$this->add("<div id=\"login-logo\"><a href=\"http://www.combodo.com/itop\"><img title=\"$sVersionShort\" src=\"../images/itop-logo-external.png\"></a></div>\n");
$sIconUrl = Utils::GetConfig()->Get('app_icon_url');
$this->add("<div id=\"login-logo\"><a href=\"".htmlentities($sIconUrl, ENT_QUOTES, 'UTF-8')."\"><img title=\"$sVersionShort\" src=\"../images/itop-logo-external.png\"></a></div>\n");
$this->add("<div id=\"login\">\n");
$this->add("<h1>".Dict::S('UI:Login:Welcome')."</h1>\n");
if ($bFailedLogin)
@@ -146,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");
@@ -176,7 +198,8 @@ function DoCheckPwd()
}
EOF
);
$this->add("<div id=\"login-logo\"><a href=\"http://www.combodo.com/itop\"><img title=\"$sVersionShort\" src=\"../images/itop-logo.png\"></a></div>\n");
$sIconUrl = Utils::GetConfig()->Get('app_icon_url');
$this->add("<div id=\"login-logo\"><a href=\"".htmlentities($sIconUrl, ENT_QUOTES, 'UTF-8')."\"><img title=\"$sVersionShort\" src=\"../images/itop-logo.png\"></a></div>\n");
$this->add("<div id=\"login\">\n");
$this->add("<h1>".Dict::S('UI:Login:ChangeYourPassword')."</h1>\n");
if ($bFailedLogin)
@@ -217,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!');
@@ -424,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

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Construction and display of the application's main menu
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/application/utils.inc.php');
@@ -79,6 +80,15 @@ class ApplicationMenu
call_user_func($aCallSpec);
}
}
// Build menus from the menus themselves (e.g. the ShortcutContainerMenuNode will do that)
//
foreach(self::$aRootMenus as $aMenu)
{
$oMenuNode = self::GetMenuNode($aMenu['index']);
$oMenuNode->PopulateChildMenus();
}
self::$bAdditionalMenusLoaded = true;
}
}
@@ -130,7 +140,7 @@ class ApplicationMenu
// they were not used to display the menus (redundant or unused)
//
$aBacktrace = debug_backtrace();
$sFile = $aBacktrace[2]["file"];
$sFile = isset($aBacktrace[2]["file"]) ? $aBacktrace[2]["file"] : $aBacktrace[1]["file"];
self::$aMenusIndex[$index] = array('node' => $oMenuNode, 'children' => array(), 'parent' => $sParentId, 'rank' => $fRank, 'source_file' => $sFile);
}
else
@@ -153,7 +163,7 @@ class ApplicationMenu
/**
* Entry point to display the whole menu into the web page, used by iTopWebPage
*/
static public function DisplayMenu(iTopWebPage $oPage, $aExtraParams)
static public function DisplayMenu($oPage, $aExtraParams)
{
self::LoadAdditionalMenus();
// Sort the root menu based on the rank
@@ -252,11 +262,11 @@ class ApplicationMenu
/**
* Helper function to get the list of child(ren) of a menu
*/
static protected function GetChildren($index)
static public function GetChildren($index)
{
return self::$aMenusIndex[$index]['children'];
}
/**
* Helper function to get the ID of a menu based on its name
* @param string $sTitle Title of the menu (as passed when creating the menu)
@@ -406,6 +416,16 @@ abstract class MenuNode
return $this->index;
}
public function PopulateChildMenus()
{
foreach (ApplicationMenu::GetChildren($this->GetIndex()) as $aMenu)
{
$index = $aMenu['index'];
$oMenu = ApplicationMenu::GetMenuNode($index);
$oMenu->PopulateChildMenus();
}
}
public function GetHyperlink($aExtraParams)
{
$aExtraParams['c[menu]'] = $this->GetMenuId();
@@ -616,31 +636,39 @@ class OQLMenuNode extends MenuNode
public function RenderContent(WebPage $oPage, $aExtraParams = array())
{
$aExtraParams = array_merge($aExtraParams, $this->m_aParams);
try
{
$oSearch = DBObjectSearch::FromOQL($this->sOQL);
$sIcon = MetaModel::GetClassIcon($oSearch->GetClass());
}
catch(Exception $e)
{
$sIcon = '';
}
OQLMenuNode::RenderOQLSearch
(
$this->sOQL,
Dict::S($this->sPageTitle),
'Menu_'.$this->GetMenuId(),
$this->bSearch, // Search pane
true, // Search open
$oPage,
array_merge($this->m_aParams, $aExtraParams)
);
}
if ($this->bSearch)
public static function RenderOQLSearch($sOql, $sTitle, $sUsageId, $bSearchPane, $bSearchOpen, WebPage $oPage, $aExtraParams = array())
{
$sUsageId = utils::GetSafeId($sUsageId);
$oSearch = DBObjectSearch::FromOQL($sOql);
$sIcon = MetaModel::GetClassIcon($oSearch->GetClass());
if ($bSearchPane)
{
$aParams = array_merge(array('open' => true, 'table_id' => 'Menu_'.$this->GetMenuId()), $aExtraParams);
$aParams = array_merge(array('open' => $bSearchOpen, 'table_id' => $sUsageId), $aExtraParams);
$oBlock = new DisplayBlock($oSearch, 'search', false /* Asynchronous */, $aParams);
$oBlock->Display($oPage, 0);
}
$oPage->add("<p class=\"page-header\">$sIcon ".Dict::S($this->sPageTitle)."</p>");
$oPage->add("<p class=\"page-header\">$sIcon ".Dict::S($sTitle)."</p>");
$aParams = array_merge(array('table_id' => 'Menu_'.$this->GetMenuId()), $aExtraParams);
$aParams = array_merge(array('table_id' => $sUsageId), $aExtraParams);
$oBlock = new DisplayBlock($oSearch, 'list', false /* Asynchronous */, $aParams);
$oBlock->Display($oPage, 1);
$oBlock->Display($oPage, $sUsageId);
}
}
/**
* This class defines a menu item that displays a search form for the given class of objects
*/
@@ -672,7 +700,7 @@ class SearchMenuNode extends MenuNode
public function RenderContent(WebPage $oPage, $aExtraParams = array())
{
$oSearch = new DBObjectSearch($this->sClass);
$aParams = array_merge(array('open' => true, 'table_id' => 'Menu_'.$this->GetMenuId()), $aExtraParams);
$aParams = array_merge(array('open' => true, 'table_id' => 'Menu_'.utils::GetSafeId($this->GetMenuId())), $aExtraParams);
$oBlock = new DisplayBlock($oSearch, 'search', false /* Asynchronous */, $aParams);
$oBlock->Display($oPage, 0);
}
@@ -892,3 +920,95 @@ class DashboardMenuNode extends MenuNode
}
/**
* A shortcut container is the preferred destination of newly created shortcuts
*/
class ShortcutContainerMenuNode extends MenuNode
{
public function GetHyperlink($aExtraParams)
{
return '';
}
public function RenderContent(WebPage $oPage, $aExtraParams = array())
{
}
public function PopulateChildMenus()
{
// Load user shortcuts in DB
//
$oBMSearch = new DBObjectSearch('Shortcut');
$oBMSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oBMSet = new DBObjectSet($oBMSearch, array('friendlyname' => true)); // ascending on friendlyname
$fRank = 1;
while ($oShortcut = $oBMSet->Fetch())
{
$sName = $this->GetMenuId().'_'.$oShortcut->GetKey();
$oShortcutMenu = new ShortcutMenuNode($sName, $oShortcut, $this->GetIndex(), $fRank++);
}
// Complete the tree
//
parent::PopulateChildMenus();
}
}
require_once(APPROOT.'application/shortcut.class.inc.php');
/**
* This class defines a menu item which content is a shortcut.
*/
class ShortcutMenuNode extends MenuNode
{
protected $oShortcut;
/**
* Create a menu item based on a custom template and inserts it into the application's main menu
* @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
* @param object $oShortcut Shortcut object
* @param integer $iParentIndex ID of the parent menu
* @param float $fRank Number used to order the list, any number will do, but for a given level (i.e same parent) all menus are sorted based on this value
* @param string $sEnableClass Name of class of object
* @param integer $iActionCode Either UR_ACTION_READ, UR_ACTION_MODIFY, UR_ACTION_DELETE, UR_ACTION_BULKREAD, UR_ACTION_BULKMODIFY or UR_ACTION_BULKDELETE
* @param integer $iAllowedResults Expected "rights" for the action: either UR_ALLOWED_YES, UR_ALLOWED_NO, UR_ALLOWED_DEPENDS or a mix of them...
* @return MenuNode
*/
public function __construct($sMenuId, $oShortcut, $iParentIndex, $fRank = 0, $sEnableClass = null, $iActionCode = null, $iAllowedResults = UR_ALLOWED_YES, $sEnableStimulus = null)
{
parent::__construct($sMenuId, $iParentIndex, $fRank, $sEnableClass, $iActionCode, $iAllowedResults, $sEnableStimulus);
$this->oShortcut = $oShortcut;
$this->aReflectionProperties['shortcut'] = $oShortcut->GetKey();
}
public function GetHyperlink($aExtraParams)
{
$sContext = $this->oShortcut->Get('context');
$aContext = unserialize($sContext);
if (isset($aContext['menu']))
{
unset($aContext['menu']);
}
foreach ($aContext as $sArgName => $sArgValue)
{
$aExtraParams[$sArgName] = $sArgValue;
}
return parent::GetHyperlink($aExtraParams);
}
public function RenderContent(WebPage $oPage, $aExtraParams = array())
{
$this->oShortcut->RenderContent($oPage, $aExtraParams);
}
public function GetTitle()
{
return $this->oShortcut->Get('name');
}
public function GetLabel()
{
return $this->oShortcut->Get('name');
}
}

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 NiceWebPage
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT."/application/webpage.class.inc.php");
@@ -41,9 +42,13 @@ class NiceWebPage extends WebPage
$this->add_linked_script('../js/jquery-ui-1.8.17.custom.min.js');
$this->add_linked_script("../js/hovertip.js");
// table sorting
$this->add_linked_script("../js/jquery.tablesorter.min.js");
$this->add_linked_script("../js/jquery.tablesorter.js");
$this->add_linked_script("../js/jquery.tablesorter.pager.js");
$this->add_linked_script("../js/jquery.tablehover.js");
$this->add_linked_script('../js/field_sorter.js');
$this->add_linked_script('../js/datatable.js');
$this->add_linked_script("../js/jquery.positionBy.js");
$this->add_linked_script("../js/jquery.popupmenu.js");
$this->add_ready_script(
<<< EOF
//add new widget called TruncatedList to properly display truncated lists when they are sorted

View File

@@ -1,26 +1,26 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 PortalWebPage
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT."/application/nicewebpage.class.inc.php");
@@ -59,6 +59,7 @@ class PortalWebPage extends NiceWebPage
$this->add_header("Cache-control: no-cache");
$this->add_linked_stylesheet("../css/jquery.treeview.css");
$this->add_linked_stylesheet("../css/jquery.autocomplete.css");
$this->add_linked_stylesheet("../css/jquery.multiselect.css");
$sAbsURLAppRoot = addslashes(utils::GetAbsoluteUrlAppRoot()); // Pass it to Javascript scripts
$sAbsURLModulesRoot = addslashes(utils::GetAbsoluteUrlModulesRoot()); // Pass it to Javascript scripts
$oAppContext = new ApplicationContext();
@@ -86,6 +87,8 @@ class PortalWebPage extends NiceWebPage
$this->add_linked_script("../js/forms-json-utils.js");
$this->add_linked_script("../js/swfobject.js");
$this->add_linked_script("../js/jquery.qtip-1.0.min.js");
$this->add_linked_script('../js/jquery.multiselect.min.js');
$this->add_linked_script("../js/ajaxfileupload.js");
$this->add_ready_script(
<<<EOF
try
@@ -135,6 +138,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(); });
}
@@ -218,8 +232,10 @@ EOF
}
EOF
);
}
// For Wizard helper to process the ajax replies
$this->add('<div id="ajax_content"></div>');
}
public function SetCurrentTab($sTabLabel = '')
{
@@ -250,6 +266,21 @@ EOF
public function output()
{
$sApplicationBanner = '';
if (!MetaModel::DBHasAccess(ACCESS_USER_WRITE))
{
$sReadOnly = Dict::S('UI:AccessRO-Users');
$sAdminMessage = trim(MetaModel::GetConfig()->Get('access_message'));
$sApplicationBanner .= '<div id="admin-banner">';
$sApplicationBanner .= '<img src="../images/locked.png" style="vertical-align:middle;">';
$sApplicationBanner .= '&nbsp;<b>'.$sReadOnly.'</b>';
if (strlen($sAdminMessage) > 0)
{
$sApplicationBanner .= '&nbsp;: '.$sAdminMessage.'';
}
$sApplicationBanner .= '</div>';
}
$sMenu = '';
if ($this->m_bEnableDisconnectButton)
{
@@ -259,7 +290,7 @@ EOF
{
$sMenu .= "<a class=\"button\" id=\"{$aMenuItem['id']}\" href=\"{$aMenuItem['hyperlink']}\"><span>".Dict::S($aMenuItem['label'])."</span></a>";
}
$this->s_content = '<div id="portal"><div id="welcome">'.$this->m_sWelcomeMsg.'</div><div id="banner"><div id="logo"></div><div id="menu">'.$sMenu.'</div></div><div id="content">'.$this->s_content.'</div></div>';
$this->s_content = '<div id="portal"><div id="welcome">'.$this->m_sWelcomeMsg.'</div><div id="banner"><div id="logo"></div><div id="menu">'.$sMenu.'</div></div>'.$sApplicationBanner.'<div id="content">'.$this->s_content.'</div></div>';
parent::output();
}
@@ -279,13 +310,9 @@ EOF
{
// Home-made and very limited display of an object set
//
//$oSet->Seek(0);// juste pour que le warning soit moins crado
//$oSet->Fetch();// juste pour que le warning soit moins crado
//
$this->add("<div id=\"listOf$sClass\">\n");
cmdbAbstractObject::DisplaySet($this, $oSet, array('currentId' => $this->GetUniqueId()."$sClass", 'menu' => false, 'zlist' => false, 'extra_fields' => implode(',', $aZList)));
$sUniqueId = $sClass.$this->GetUniqueId();
$this->add("<div id=\"$sUniqueId\">\n"); // The id here MUST be the same as currentId, otherwise the pagination will be broken
cmdbAbstractObject::DisplaySet($this, $oSet, array('currentId' => $sUniqueId, 'menu' => false, 'zlist' => false, 'extra_fields' => implode(',', $aZList)));
$this->add("</div>\n");
}
else
@@ -598,7 +625,7 @@ EOF
{
$sFieldName = str_replace('->', PARAM_ARROW_SEP, $sAttSpec);
$value = utils::ReadPostedParam($sPrefix.$sFieldName, null, 'raw_data');
if (!is_null($value) && strlen($value) > 0)
if (!is_null($value) && (is_array($value) ? count($value)>0 : strlen($value)>0))
{
$oFilter->AddConditionAdvanced($sAttSpec, $value);
$iCountParams++;
@@ -656,26 +683,24 @@ EOF
}
}
// Record the change
//
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$sUserString = CMDBChange::GetCurrentUserName();
$oMyChange->Set("userinfo", $sUserString);
$iChangeId = $oMyChange->DBInsert();
$oObj->DBUpdateTracked($oMyChange);
// Trigger ?
//
$aClasses = MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL);
$sClassList = implode(", ", CMDBSource::Quote($aClasses));
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnPortalUpdate AS t WHERE t.target_class IN ($sClassList)"));
while ($oTrigger = $oSet->Fetch())
if ($oObj->IsModified())
{
$oTrigger->DoActivate($oObj->ToArgs('this'));
// Record the change
//
$oObj->DBUpdate();
// Trigger ?
//
$aClasses = MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL);
$sClassList = implode(", ", CMDBSource::Quote($aClasses));
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnPortalUpdate AS t WHERE t.target_class IN ($sClassList)"));
while ($oTrigger = $oSet->Fetch())
{
$oTrigger->DoActivate($oObj->ToArgs('this'));
}
$this->p("<h1>".Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName())."</h1>\n");
}
$this->p("<h1>".Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName())."</h1>\n");
}
/**
@@ -732,7 +757,7 @@ EOF
$this->m_sWizardId = $sId;
// multipart... needed for file upload
$this->add("<form id=\"{$this->m_sWizardId}\" method=\"$sMethod\" enctype=\"multipart/form-data\">\n");
$this->add("<form id=\"{$this->m_sWizardId}\" method=\"$sMethod\" enctype=\"multipart/form-data\" onsubmit=\"window.bInSubmit = true;\">\n");
$aPreviousSteps = $this->GetWizardStepHistory();
if (utils::ReadParam('step_back', 0) == 1)

View File

@@ -1,28 +1,29 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Persistent class Event and derived
* Application internal events
* There is also a file log
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
abstract class Query extends cmdbAbstractObject
@@ -46,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
@@ -87,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)
{
@@ -101,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

@@ -0,0 +1,284 @@
<?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/>
/**
* Persistent class Shortcut and derived
* Shortcuts of any kind
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
abstract class Shortcut extends DBObject implements iDisplay
{
public static function Init()
{
$aParams = array
(
"category" => "gui,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_shortcut",
"db_key_field" => "id",
"db_finalclass_field" => "realclass",
"display_template" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("targetclass"=>"User", "allowed_values"=>null, "sql"=>"user_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
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("context", array("allowed_values"=>null, "sql"=>"context", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'context')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name')); // Attributes to be displayed for a list
// Search criteria
// 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
}
abstract public function RenderContent(WebPage $oPage, $aExtraParams = array());
protected function OnInsert()
{
$this->Set('user_id', UserRights::GetUserId());
}
public function StartRenameDialog($oPage)
{
$oPage->add('<div id="shortcut_rename_dlg">');
$oForm = new DesignerForm();
$sDefault = $this->Get('name');
$oField = new DesignerTextField('name', Dict::S('Class:Shortcut/Attribute:name'), $sDefault);
$oField->SetMandatory(true);
$oForm->AddField($oField);
$oForm->Render($oPage);
$oPage->add('</div>');
$sDialogTitle = Dict::S('UI:ShortcutRenameDlg:Title');
$sOkButtonLabel = Dict::S('UI:Button:Ok');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$iShortcut = $this->GetKey();
$oPage->add_ready_script(
<<<EOF
function ShortcutRenameOK()
{
var oForm = $(this).find('form');
var sFormId = oForm.attr('id');
var oParams = null;
var aErrors = ValidateForm(sFormId, false);
if (aErrors.length == 0)
{
oParams = ReadFormParams(sFormId);
}
oParams.operation = 'shortcut_rename_go';
oParams.id = $iShortcut;
var me = $(this);
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function(data) {
me.dialog( "close" );
me.remove();
$('body').append(data);
});
}
$('#shortcut_rename_dlg form').bind('submit', function() { return false; });
$('#shortcut_rename_dlg').dialog({
width: 400,
modal: true,
title: '$sDialogTitle',
buttons: [
{ text: "$sOkButtonLabel", click: ShortcutRenameOK},
{ text: "$sCancelButtonLabel", click: function() {
$(this).dialog( "close" ); $(this).remove();
} },
],
close: function() { $(this).remove(); }
});
EOF
);
}
// Minimual implementation of iDisplay: to make the shortcut be listable
//
public static function MapContextParam($sContextParam)
{
return (($sContextParam == 'menu') ? null : $sContextParam);
}
public function GetHilightClass()
{
return HILIGHT_CLASS_NONE;
}
public static function GetUIPage()
{
return '';
}
function DisplayDetails(WebPage $oPage, $bEditMode = false)
{
}
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
{
return array();
}
// End of the minimal implementation of iDisplay
}
class ShortcutOQL extends Shortcut
{
public static function Init()
{
$aParams = array
(
"category" => "gui,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "name",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_shortcut_oql",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeOQL("oql", array("allowed_values"=>null, "sql"=>"oql", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'context', 'oql')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name')); // Attributes to be displayed for a list
// Search criteria
// 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
}
public function RenderContent(WebPage $oPage, $aExtraParams = array())
{
$oPage->set_title($this->Get('name'));
$bSearchPane = true;
$bSearchOpen = false;
try
{
OQLMenuNode::RenderOQLSearch($this->Get('oql'), $this->Get('name'), 'shortcut_'.$this->GetKey(), $bSearchPane, $bSearchOpen, $oPage, $aExtraParams);
}
catch (Exception $e)
{
throw new Exception("The OQL shortcut '".$this->Get('name')."' (id: ".$this->GetKey().") could not be displayed: ".$e->getMessage());
}
}
public static function GetCreationForm($sOQL = null)
{
$oForm = new DesignerForm();
// Find a unique default name
// -> The class of the query + an index if necessary
if ($sOQL == null)
{
$sDefault = '';
}
else
{
$oBMSearch = new DBObjectSearch('Shortcut');
$oBMSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
$oBMSet = new DBObjectSet($oBMSearch);
$aNames = $oBMSet->GetColumnAsArray('name');
$oSearch = DBObjectSearch::FromOQL($sOQL);
$sDefault = utils::MakeUniqueName($oSearch->GetClass(), $aNames);
}
$oField = new DesignerTextField('name', Dict::S('Class:Shortcut/Attribute:name'), $sDefault);
$oField->SetMandatory(true);
$oForm->AddField($oField);
//$oField = new DesignerLongTextField('oql', Dict::S('Class:Shortcut/Attribute:oql'), $sOQL);
//$oField->SetMandatory();
$oField = new DesignerHiddenField('oql', '', $sOQL);
$oForm->AddField($oField);
return $oForm;
}
public static function GetCreationDlgFromOQL($oPage, $sOQL)
{
$oPage->add('<div id="shortcut_creation_dlg">');
$oForm = self::GetCreationForm($sOQL);
$oForm->Render($oPage);
$oPage->add('</div>');
$sDialogTitle = Dict::S('UI:ShortcutListDlg:Title');
$sOkButtonLabel = Dict::S('UI:Button:Ok');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$oAppContext = new ApplicationContext();
$sContext = $oAppContext->GetForLink();
$oPage->add_ready_script(
<<<EOF
function ShortcutCreationOK()
{
var oForm = $('#shortcut_creation_dlg form');
var sFormId = oForm.attr('id');
var oParams = null;
var aErrors = ValidateForm(sFormId, false);
if (aErrors.length == 0)
{
oParams = ReadFormParams(sFormId);
}
oParams.operation = 'shortcut_list_create';
var me = $('#shortcut_creation_dlg');
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?$sContext', oParams, function(data) {
me.dialog( "close" );
me.remove();
$('body').append(data);
});
}
$('#shortcut_creation_dlg form').bind('submit', function() { ShortcutCreationOK(); return false; });
$('#shortcut_creation_dlg').dialog({
width: 400,
modal: true,
title: '$sDialogTitle',
buttons: [
{ text: "$sOkButtonLabel", click: ShortcutCreationOK },
{ text: "$sCancelButtonLabel", click: function() {
$(this).dialog( "close" ); $(this).remove();
} },
],
close: function() { $(this).remove(); }
});
EOF
);
}
}
?>

View File

@@ -1,27 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* SqlBlock - display tables or charts, given an SQL query - use cautiously!
*
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* File to include to initialize the datamodel in memory
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/core/cmdbobject.class.inc.php');

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 DisplayTemplate
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/application/displayblock.class.inc.php');
@@ -282,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

@@ -1,24 +1,29 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* This class records the pending "transactions" corresponding to forms that have not been
* submitted yet, in order to prevent double submissions. When created a transaction remains valid
* until the user's session expires
*
* @package iTop
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,18 +1,20 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 UIExtKeyWidget
* UI wdiget for displaying and editing external keys when
@@ -52,10 +54,8 @@
* | | +--------+ +-----+ | |
* | +--------------------------------------------+ |
* +------------------------------------------------+
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/application/webpage.class.inc.php');
@@ -96,12 +96,12 @@ 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
*/
public function Display(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), $bSearchMode = null, $sDisplayStyle = 'select')
public function Display(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), $bSearchMode = null, $sDisplayStyle = 'select', $bSearchMultiple = true)
{
if (!is_null($bSearchMode))
{
@@ -169,14 +169,22 @@ class UIExtKeyWidget
$sHelpText = ''; //$this->oAttDef->GetHelpOnEdition();
$sHTMLValue = "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\">\n";
if ($this->bSearchMode)
{
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : Dict::S('UI:SearchValue:Any');
$sHTMLValue .= "<option value=\"\">$sDisplayValue</option>\n";
if ($bSearchMultiple)
{
$sHTMLValue = "<select class=\"multiselect\" multiple title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}[]\" id=\"$this->iId\">\n";
}
else
{
$sHTMLValue = "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\">\n";
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : Dict::S('UI:SearchValue:Any');
$sHTMLValue .= "<option value=\"\">$sDisplayValue</option>\n";
}
}
else
{
$sHTMLValue = "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\">\n";
$sHTMLValue .= "<option value=\"\">".Dict::S('UI:SelectOne')."</option>\n";
}
$oAllowedValues->Rewind();
@@ -192,11 +200,15 @@ class UIExtKeyWidget
}
else
{
$sSelected = ($value == $key) ? ' selected' : '';
$sSelected = (is_array($value) && in_array($key, $value)) || ($value == $key) ? ' selected' : '';
}
$sHTMLValue .= "<option value=\"$key\"$sSelected>$display_value</option>\n";
}
$sHTMLValue .= "</select>\n";
if (($this->bSearchMode) && $bSearchMultiple)
{
$oPage->add_ready_script("$('.multiselect').multiselect({header: false, noneSelectedText: '".addslashes(Dict::S('UI:SearchValue:Any'))."', selectedList: 1, selectedText:'".addslashes(Dict::S('UI:SearchValue:NbSelected'))."'});");
}
$oPage->add_ready_script(
<<<EOF
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', true, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode);
@@ -213,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'] : '';
@@ -332,23 +353,15 @@ EOF
{
throw new Exception('Implementation: null value for allowed values definition');
}
try
$oFilter = DBObjectSearch::FromOQL($sFilter);
if (strlen($sRemoteClass) > 0)
{
$oFilter = DBObjectSearch::FromOQL($sFilter);
$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
}
catch(MissingQueryArgument $e)
{
// When used in a search form the $this parameter may be missing, in this case return all possible values...
// TODO check if we can improve this behavior...
$sOQL = 'SELECT '.$sRemoteClass;
$oFilter = DBObjectSearch::FromOQL($sOQL);
$oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
//$oBlock = new DisplayBlock($oFilter, 'list', false);
//$oBlock->Display($oP, $this->iId.'_results', array('cssCount'=> '#count_'.$this->iId, 'menu' => false, 'selection_mode' => true, 'selection_type' => 'single')); // Don't display the 'Actions' menu on the results
$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
}
/**
@@ -424,7 +437,7 @@ EOF
// 3rd - set values from the page argument 'default'
$oNewObj->UpdateObjectFromArg('default');
$sDialogTitle = addslashes($this->sTitle);
$sDialogTitle = '';
$oPage->add('<div id="ac_create_'.$this->iId.'"><div class="wizContainer" style="vertical-align:top;"><div id="dcr_'.$this->iId.'">');
$oPage->add("<h1>".MetaModel::GetClassIcon($this->sTargetClass)."&nbsp;".Dict::Format('UI:CreationTitle_Class', MetaModel::GetName($this->sTargetClass))."</h1>\n");
cmdbAbstractObject::DisplayCreationForm($oPage, $this->sTargetClass, $oNewObj, array(), array('formPrefix' => $this->iId, 'noRelations' => true));
@@ -485,12 +498,7 @@ EOF
$aErrors = $oObj->UpdateObjectFromPostedForm($this->iId);
if (count($aErrors) == 0)
{
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$sUserString = CMDBChange::GetCurrentUserName();
$oMyChange->Set("userinfo", $sUserString);
$iChangeId = $oMyChange->DBInsert();
$oObj->DBInsertTracked($oMyChange);
$oObj->DBInsert();
return array('name' => $oObj->GetName(), 'id' => $oObj->GetKey());
}
else

View File

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 UIHTMLEditorWidget
* UI wdiget for displaying and editing one-way encrypted passwords
*
* @author Phil Eddies
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class UIHTMLEditorWidget

View File

@@ -0,0 +1,255 @@
<?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/>
/**
* Class UILinksWidgetDirect
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class UILinksWidgetDirect
{
protected $sClass;
protected $sAttCode;
protected $sInputid;
protected $sNameSuffix;
protected $sLinkedClass;
public function __construct($sClass, $sAttCode, $sInputId, $sNameSuffix = '')
{
$this->sClass = $sClass;
$this->sAttCode = $sAttCode;
$this->sInputid = $sInputId;
$this->sNameSuffix = $sNameSuffix;
$this->aZlist = array();
$this->sLinkedClass = '';
// Compute the list of attributes visible from the given objet:
// All the attributes from the "list" Zlist of the Link class except
// the ExternalKey that points to the current object and its related external fields
$oLinksetDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
$this->sLinkedClass = $oLinksetDef->GetLinkedClass();
$sExtKeyToMe = $oLinksetDef->GetExtKeyToMe();
$aZList = MetaModel::FlattenZList(MetaModel::GetZListItems($this->sLinkedClass, 'list'));
foreach($aZList as $sLinkedAttCode)
{
if ($sLinkedAttCode != $sExtKeyToMe)
{
$oAttDef = MetaModel::GetAttributeDef($this->sLinkedClass, $sLinkedAttCode);
if (!$oAttDef->IsExternalField() || ($oAttDef->GetKeyAttCode() != $sExtKeyToMe) )
{
$this->aZlist[] = $sLinkedAttCode;
}
}
}
}
public function Display(WebPage $oPage, DBObjectSet $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj)
{
$oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
switch($oLinksetDef->GetEditMode())
{
case LINKSET_EDITMODE_NONE: // The linkset is read-only
$this->DisplayAsBlock($oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, false /* bDisplayMenu*/);
break;
case LINKSET_EDITMODE_ADDONLY: // The only possible action is to open (in a new window) the form to create a new object
if ($oCurrentObj && !$oCurrentObj->IsNew())
{
$sTargetClass = $oLinksetDef->GetLinkedClass();
$sExtKeyToMe = $oLinksetDef->GetExtKeyToMe();
$sDefault = "default[$sExtKeyToMe]=".$oCurrentObj->GetKey();
$oAppContext = new ApplicationContext();
$sParams = $oAppContext->GetForLink();
$oPage->p("<a target=\"_blank\" href=\"".utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=new&class=$sTargetClass&$sParams{$sDefault}\">".Dict::Format('UI:ClickToCreateNew', Metamodel::GetName($sTargetClass))."</a>\n");
}
$this->DisplayAsBlock($oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, false /* bDisplayMenu*/);
break;
case LINKSET_EDITMODE_INPLACE: // The whole linkset can be edited 'in-place'
$this->DisplayEditInPlace($oPage, $oValue, $aArgs, $sFormPrefix, $oCurrentObj);
break;
case LINKSET_EDITMODE_ACTIONS:
default:
$this->DisplayAsBlock($oPage, $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, true /* bDisplayMenu*/);
}
}
protected function DisplayAsBlock(WebPage $oPage, DBObjectSet $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, $bDisplayMenu)
{
$oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
$sTargetClass = $oLinksetDef->GetLinkedClass();
if ($oCurrentObj && $oCurrentObj->IsNew() && $bDisplayMenu)
{
$oPage->p(Dict::Format('UI:BeforeAdding_Class_ObjectsSaveThisObject', MetaModel::GetName($sTargetClass)));
}
else
{
$oFilter = new DBObjectSearch($sTargetClass);
$oFilter->AddCondition($oLinksetDef->GetExtKeyToMe(), $oCurrentObj->GetKey(),'=');
$aDefaults = array($oLinksetDef->GetExtKeyToMe() => $oCurrentObj->GetKey());
$oAppContext = new ApplicationContext();
foreach($oAppContext->GetNames() as $sKey)
{
// The linked object inherits the parent's value for the context
if (MetaModel::IsValidAttCode($this->sClass, $sKey) && $oCurrentObj)
{
$aDefaults[$sKey] = $oCurrentObj->Get($sKey);
}
}
$aParams = array(
'target_attr' => $oLinksetDef->GetExtKeyToMe(),
'object_id' => $oCurrentObj ? $oCurrentObj->GetKey() : null,
'menu' => $bDisplayMenu,
'default' => $aDefaults,
'table_id' => $this->sClass.'_'.$this->sAttCode,
);
$oBlock = new DisplayBlock($oFilter, 'list', false);
$oBlock->Display($oPage, $this->sInputid, $aParams);
}
}
protected function DisplayEditInPlace(WebPage $oPage, DBObjectSet $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj)
{
$aAttribs = $this->GetTableConfig();
$oValue->Rewind();
$oPage->add('<table class="listContainer" id="'.$this->sInputid.'"><tr><td>');
$aData = array();
while($oLinkObj = $oValue->Fetch())
{
$aRow = array();
$aRow['form::select'] = '<input type="checkbox" class="selectList'.$this->sInputid.'" value="'.$oLinkObj->GetKey().'"/>';
foreach($this->aZlist as $sLinkedAttCode)
{
$aRow[$sLinkedAttCode] = $oLinkObj->GetAsHTML($sLinkedAttCode);
}
$aData[] = $aRow;
}
$oPage->table($aAttribs, $aData);
$oPage->add('</td></tr></table>'); //listcontainer
$sInputName = $sFormPrefix.'attr_'.$this->sAttCode;
$aLabels = array(
'delete' => Dict::S('UI:Button:Delete'),
// 'modify' => 'Modify...' ,
'creation_title' => Dict::Format('UI:CreationTitle_Class', MetaModel::GetName($this->sLinkedClass)),
'create' => Dict::Format('UI:ClickToCreateNew', MetaModel::GetName($this->sLinkedClass)),
);
$sSubmitUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
$sJSONLabels = json_encode($aLabels);
$oPage->add_ready_script("$('#{$this->sInputid}').directlinks({class_name: '$this->sClass', att_code: '$this->sAttCode', input_name:'$sInputName', labels: $sJSONLabels, sumit_to: '$sSubmitUrl' });");
}
public function GetObjectCreationDlg(WebPage $oPage, $sProposedRealClass = '')
{
// For security reasons: check that the "proposed" class is actually a subclass of the linked class
// and that the current user is allowed to create objects of this class
$sRealClass = '';
$oPage->add('<div class="wizContainer" style="vertical-align:top;"><div>');
$aSubClasses = MetaModel::EnumChildClasses($this->sLinkedClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself
$aPossibleClasses = array();
foreach($aSubClasses as $sCandidateClass)
{
if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES))
{
if ($sCandidateClass == $sProposedRealClass)
{
$sRealClass = $sProposedRealClass;
}
$aPossibleClasses[$sCandidateClass] = MetaModel::GetName($sCandidateClass);
}
}
// Only one of the subclasses can be instantiated...
if (count($aPossibleClasses) == 1)
{
$aKeys = array_keys($aPossibleClasses);
$sRealClass = $aKeys[0];
}
if ($sRealClass != '')
{
$oPage->add("<h1>".MetaModel::GetClassIcon($sRealClass)."&nbsp;".Dict::Format('UI:CreationTitle_Class', MetaModel::GetName($sRealClass))."</h1>\n");
$oLinksetDef = MetaModel::GetAttributeDef($this->sClass, $this->sAttCode);
$sExtKeyToMe = $oLinksetDef->GetExtKeyToMe();
$aFieldFlags = array( $sExtKeyToMe => OPT_ATT_HIDDEN);
cmdbAbstractObject::DisplayCreationForm($oPage, $sRealClass, null, array(), array('formPrefix' => $this->sInputid, 'noRelations' => true, 'fieldsFlags' => $aFieldFlags));
}
else
{
$sClassLabel = MetaModel::GetName($this->sLinkedClass);
$oPage->add('<p>'.Dict::Format('UI:SelectTheTypeOf_Class_ToCreate', $sClassLabel));
$oPage->add('<nobr><select name="class">');
asort($aPossibleClasses);
foreach($aPossibleClasses as $sClassName => $sClassLabel)
{
$oPage->add("<option value=\"$sClassName\">$sClassLabel</option>");
}
$oPage->add('</select>');
$oPage->add('&nbsp; <button type="button" onclick="$(\'#'.$this->sInputid.'\').directlinks(\'subclassSelected\');">'.Dict::S('UI:Button:Apply').'</button><span class="indicator" style="display:inline-block;width:16px"></span></nobr></p>');
}
$oPage->add('</div></div>');
}
public function GetObjectModificationDlg()
{
}
protected function GetTableConfig()
{
$aAttribs = array();
$aAttribs['form::select'] = array('label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$this->sInputid}:not(:disabled)', this.checked);\" class=\"checkAll\"></input>", 'description' => Dict::S('UI:SelectAllToggle+'));
foreach($this->aZlist as $sLinkedAttCode)
{
$oAttDef = MetaModel::GetAttributeDef($this->sLinkedClass, $sLinkedAttCode);
$aAttribs[$sLinkedAttCode] = array('label' => MetaModel::GetLabel($this->sLinkedClass, $sLinkedAttCode), 'description' => $oAttDef->GetOrderByHint());
}
return $aAttribs;
}
public function GetRow($oPage, $sRealClass, $aValues, $iTempId)
{
$aAttribs = $this->GetTableConfig();
if ($sRealClass == '')
{
$sRealClass = $this->sLinkedClass;
}
$oLinkObj = new $sRealClass();
$oLinkObj->UpdateObjectFromPostedForm($this->sInputid);
$aRow = array();
$aRow['form::select'] = '<input type="checkbox" class="selectList'.$this->sInputid.'" value="'.(-$iTempId).'"/>';
foreach($this->aZlist as $sLinkedAttCode)
{
$aRow[$sLinkedAttCode] = $oLinkObj->GetAsHTML($sLinkedAttCode);
}
return $oPage->GetTableRow($aRow, $aAttribs);
}
public function UpdateFromArray($oObj, $aData)
{
}
}

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 UILinksWidget
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/application/webpage.class.inc.php');
@@ -105,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);
@@ -119,7 +120,7 @@ class UILinksWidget
foreach($this->m_aEditableFields as $sFieldCode)
{
$sFieldId = $this->m_iInputId.'_'.$sFieldCode.'['.$linkObjOrId->GetKey().']';
$sSafeId = self::MakeID($sFieldId);
$sSafeId = utils::GetSafeId($sFieldId);
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
$aRow[$sFieldCode] = cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $linkObjOrId->Get($sFieldCode), '' /* DisplayValue */, $sSafeId, $sNameSuffix, 0, $aArgs);
$aFieldsMap[$sFieldCode] = $sSafeId;
@@ -129,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);
@@ -144,7 +157,7 @@ class UILinksWidget
foreach($this->m_aEditableFields as $sFieldCode)
{
$sFieldId = $this->m_iInputId.'_'.$sFieldCode.'['.$linkObjOrId.']';
$sSafeId = self::MakeID($sFieldId);
$sSafeId = utils::GetSafeId($sFieldId);
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
$aRow[$sFieldCode] = cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $oNewLinkObj->Get($sFieldCode) /* TO DO/ call GetDefaultValue($oObject->ToArgs()) */, '' /* DisplayValue */, $sSafeId /* id */, $sNameSuffix, 0, $aArgs);
$aFieldsMap[$sFieldCode] = $sSafeId;
@@ -174,11 +187,11 @@ EOF
);
}
$sExtKeyToMeId = self::MakeID($sPrefix.$this->m_sExtKeyToMe);
$sExtKeyToMeId = utils::GetSafeId($sPrefix.$this->m_sExtKeyToMe);
$aFieldsMap[$this->m_sExtKeyToMe] = $sExtKeyToMeId;
$aRow['form::checkbox'] .= "<input type=\"hidden\" id=\"$sExtKeyToMeId\" value=\"".$oCurrentObj->GetKey()."\">";
$sExtKeyToRemoteId = self::MakeID($sPrefix.$this->m_sExtKeyToRemote);
$sExtKeyToRemoteId = utils::GetSafeId($sPrefix.$this->m_sExtKeyToRemote);
$aFieldsMap[$this->m_sExtKeyToRemote] = $sExtKeyToRemoteId;
$aRow['form::checkbox'] .= "<input type=\"hidden\" id=\"$sExtKeyToRemoteId\" value=\"$iRemoteObjKey\">";
@@ -199,11 +212,6 @@ EOF
}
return $aRow;
}
protected function MakeID($sName)
{
return str_replace(array('[', ']', '-'), '_', $sName);
}
/**
* Display one row of the whole form
@@ -279,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())
@@ -288,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
{
@@ -301,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

@@ -1,27 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 UIPasswordWidget
* UI wdiget for displaying and editing one-way encrypted passwords
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/application/webpage.class.inc.php');

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 UILinksWizard
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class UILinksWizard

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 UIWizard
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class UIWizard

View File

@@ -1,26 +1,26 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Store and retrieve user custom dashboards
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/core/dbobject.class.php');

View File

@@ -1,26 +1,26 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Store and retrieve user's preferences (i.e persistent per user settings)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/core/dbobject.class.php');
require_once(APPROOT.'/core/userrights.class.inc.php');
@@ -103,7 +103,7 @@ class appUserPreferences extends DBObject
}
else
{
unset($aPrefs[$sCode]);
unset($aPrefs[$sCodeOrPattern]);
self::$oUserPrefs->Set('preferences', $aPrefs);
}
// Save only if needed

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Static class utils
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/core/config.class.inc.php');
@@ -507,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')
{
@@ -570,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:
@@ -612,7 +632,7 @@ class utils
$bCASDebug = self::GetConfig()->Get('cas_debug');
if ($bCASDebug)
{
phpCAS::setDebug(APPROOT.'/error.log');
phpCAS::setDebug(APPROOT.'log/error.log');
}
if (!self::$m_bCASClient)
@@ -775,7 +795,15 @@ class utils
{
foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance)
{
foreach($oExtensionInstance->EnumItems($iMenuId, $param) as $oMenuItem)
if (is_object($param) && !($param instanceof DBObject))
{
$tmpParam = clone $param; // In case the parameter is an DBObjectSet, clone it to prevent alterations
}
else
{
$tmpParam = $param;
}
foreach($oExtensionInstance->EnumItems($iMenuId, $tmpParam) as $oMenuItem)
{
if (is_object($oMenuItem))
{
@@ -810,5 +838,37 @@ class utils
$sUrl = self::GetAbsoluteUrlAppRoot().'env-'.self::GetCurrentEnvironment().'/';
return $sUrl;
}
/**
* Returns a name unique amongst the given list
* @param string $sProposed The default value
* @param array $aExisting An array of existing values (strings)
*/
static public function MakeUniqueName($sProposed, $aExisting)
{
if (in_array($sProposed, $aExisting))
{
$i = 1;
while (in_array($sProposed.$i, $aExisting) && ($i < 50))
{
$i++;
}
return $sProposed.$i;
}
else
{
return $sProposed;
}
}
/**
* Some characters cause troubles with jQuery when used inside DOM IDs, so let's replace them by the safe _ (underscore)
* @param string $sId The ID to sanitize
* @return string The sanitized ID
*/
static public function GetSafeId($sId)
{
return str_replace(array(':', '[', ']', '+', '-'), '_', $sId);
}
}
?>

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 WebPage
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -56,6 +57,7 @@ class WebPage implements Page
protected $s_content;
protected $s_deferred_content;
protected $a_scripts;
protected $a_dict_entries;
protected $a_styles;
protected $a_include_scripts;
protected $a_include_stylesheets;
@@ -75,6 +77,7 @@ class WebPage implements Page
$this->s_content = "";
$this->s_deferred_content = '';
$this->a_scripts = array();
$this->a_dict_entries = array();
$this->a_styles = array();
$this->a_linked_scripts = array();
$this->a_linked_stylesheets = array();
@@ -230,6 +233,16 @@ class WebPage implements Page
{
// Do nothing silently... this is not supported by this type of page...
}
/**
* Add a dictionary entry for the Javascript side
*/
public function add_dict_entry($s_entryId)
{
$this->a_dict_entries[$s_entryId] = Dict::S($s_entryId);
}
/**
* Add some CSS definitions to the header of the page
*/
@@ -378,6 +391,25 @@ class WebPage implements Page
return $sHTMLValue;
}
/**
* Discard unexpected output data
* This is a MUST when the Page output is DATA (download of a document, download CSV export, download ...)
*/
public function TrashUnexpectedOutput()
{
// This protection is redundant with a protection implemented in MetaModel::IncludeModule
// which detects such issues while loading module files
// Here, the purpose is to detect and discard characters produced by the code execution (echo)
$sPreviousContent = ob_get_clean();
if (trim($sPreviousContent) != '')
{
if (Utils::GetConfig() && Utils::GetConfig()->Get('debug_report_spurious_chars'))
{
IssueLog::Error("Output already started before downloading file:\nContent was:'$sPreviousContent'\n");
}
}
}
/**
* Outputs (via some echo) the complete HTML page by assembling all its elements
*/
@@ -418,6 +450,7 @@ class WebPage implements Page
}
echo "</script>\n";
}
$this->output_dict_entries();
foreach($this->a_linked_stylesheets as $a_stylesheet)
{
if ($a_stylesheet['condition'] != "")
@@ -454,6 +487,11 @@ class WebPage implements Page
echo '<div id="at_the_end">'.self::FilterXSS($this->s_deferred_content).'</div>';
echo "</body>\n";
echo "</html>\n";
if (class_exists('MetaModel'))
{
MetaModel::RecordQueryTrace();
}
}
/**
@@ -613,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...
@@ -623,17 +662,53 @@ 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($bReturnOutput = false)
{
$sHtml = '';
if (count($this->a_dict_entries)>0)
{
$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)
{
$sHtml .= "Dict._entries['$s_entry'] = '".addslashes($s_value)."';\n";
}
$sHtml .= "</script>\n";
}
if ($bReturnOutput)
{
return $sHtml;
}
else
{
echo $sHtml;
}
}
}
?>

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 WizardHelper
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/application/uiwizard.class.inc.php');

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2013 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 XMLPage
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT."/application/webpage.class.inc.php");
@@ -36,65 +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);
}
}
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

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Various dev/debug helpers
* TODO: cleanup or at least re-organize
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Persistent classes (internal): user defined actions
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -212,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);
}
@@ -288,8 +293,8 @@ class ActionEmail extends ActionNotification
$sCC = $this->FindRecipients('cc', $aContextArgs);
$sBCC = $this->FindRecipients('bcc', $aContextArgs);
$sFrom = $this->Get('from');
$sReplyTo = $this->Get('reply_to');
$sFrom = MetaModel::ApplyParams($this->Get('from'), $aContextArgs);
$sReplyTo = MetaModel::ApplyParams($this->Get('reply_to'), $aContextArgs);
$sSubject = MetaModel::ApplyParams($this->Get('subject'), $aContextArgs);
$sBody = MetaModel::ApplyParams($this->Get('body'), $aContextArgs);
@@ -356,6 +361,17 @@ class ActionEmail extends ActionNotification
$oEmail->SetMessageId($sMessageId);
}
if (isset($aContextArgs['attachments']))
{
$aAttachmentReport = array();
foreach($aContextArgs['attachments'] as $oDocument)
{
$oEmail->AddAttachment($oDocument->GetData(), $oDocument->GetFileName(), $oDocument->GetMimeType());
$aAttachmentReport[] = array($oDocument->GetFileName(), $oDocument->GetMimeType(), strlen($oDocument->GetData()));
}
$oLog->Set('attachments', $aAttachmentReport);
}
if (empty($this->m_aMailErrors))
{
if ($this->m_iRecipients == 0)
@@ -392,4 +408,4 @@ class ActionEmail extends ActionNotification
}
}
}
?>
?>

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Utility to import/export the DB from/to a ZIP file
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Persistent classes (internal): user defined actions
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -138,6 +139,7 @@ class AsyncSendEmail extends AsyncTask
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
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"=>false, "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())));
@@ -160,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();
}
@@ -168,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)
{

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 BackgroundProcess
* interface iBackgroundProcess
* Any extension that must be called regularly to be executed in the background
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
interface iBackgroundProcess

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

@@ -1,29 +1,34 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Bulk change facility (common to interactive and batch usages)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
// The BOM is added at the head of exported UTF-8 CSV data, and removed (if present) from input UTF-8 data.
// This helps MS-Excel (Version > 2007, Windows only) in changing its interpretation of a CSV file (by default Excel reads data as ISO-8859-1 -not 100% sure!)
define('UTF8_BOM', chr(239).chr(187).chr(191)); // 0xEF, 0xBB, 0xBF
/**
* BulkChange
* Interpret a given data set and update the DB accordingly (fake mode avail.)
@@ -84,15 +89,16 @@ class CellStatus_Modify extends CellChangeSpec
{
protected $m_previousValue;
public function __construct($proposedValue, $previousValue)
public function __construct($proposedValue, $previousValue = null)
{
$this->m_previousValue = $previousValue;
// Unused (could be costly to know -see the case of reconciliation on ext keys)
//$this->m_previousValue = $previousValue;
parent::__construct($proposedValue);
}
public function GetDescription()
{
return 'Modified';
return Dict::S('UI:CSVReport-Value-Modified');
}
//public function GetPreviousValue()
@@ -115,9 +121,9 @@ class CellStatus_Issue extends CellStatus_Modify
{
if (is_null($this->m_proposedValue))
{
return 'Could not be changed - reason: '.$this->m_sReason;
return Dict::Format('UI:CSVReport-Value-SetIssue', $this->m_sReason);
}
return 'Could not be changed to '.$this->m_proposedValue.' - reason: '.$this->m_sReason;
return Dict::Format('UI:CSVReport-Value-ChangeIssue', $this->m_proposedValue, $this->m_sReason);
}
}
@@ -130,7 +136,7 @@ class CellStatus_SearchIssue extends CellStatus_Issue
public function GetDescription()
{
return 'No match';
return Dict::S('UI:CSVReport-Value-NoMatch');
}
}
@@ -143,7 +149,7 @@ class CellStatus_NullIssue extends CellStatus_Issue
public function GetDescription()
{
return 'Missing mandatory value';
return Dict::S('UI:CSVReport-Value-Missing');
}
}
@@ -162,7 +168,7 @@ class CellStatus_Ambiguous extends CellStatus_Issue
public function GetDescription()
{
$sCount = $this->m_iCount;
return "Ambiguous: found $sCount objects";
return Dict::Format('UI:CSVReport-Value-Ambiguous', $sCount);
}
}
@@ -186,7 +192,7 @@ class RowStatus_NoChange extends RowStatus
{
public function GetDescription()
{
return "unchanged";
return Dict::S('UI:CSVReport-Row-Unchanged');
}
}
@@ -194,7 +200,7 @@ class RowStatus_NewObj extends RowStatus
{
public function GetDescription()
{
return "created";
return Dict::S('UI:CSVReport-Row-Created');
}
}
@@ -209,7 +215,7 @@ class RowStatus_Modify extends RowStatus
public function GetDescription()
{
return "updated ".$this->m_iChanged." cols";
return Dict::Format('UI:CSVReport-Row-Updated', $this->m_iChanged);
}
}
@@ -217,7 +223,7 @@ class RowStatus_Disappeared extends RowStatus_Modify
{
public function GetDescription()
{
return "disappeared, changed ".$this->m_iChanged." cols";
return Dict::Format('UI:CSVReport-Row-Disappeared', $this->m_iChanged);
}
}
@@ -232,7 +238,7 @@ class RowStatus_Issue extends RowStatus
public function GetDescription()
{
return 'Issue: '.$this->m_sReason;
return Dict::Format('UI:CSVReport-Row-Issue', $this->m_sReason);
}
}
@@ -253,8 +259,9 @@ class BulkChange
protected $m_sSynchroScope; // OQL - if specified, then the missing items will be reported
protected $m_aOnDisappear; // array of attcode => value, values to be set when an object gets out of scope (ignored if no scope has been defined)
protected $m_sDateFormat; // Date format specification, see utils::StringToTime()
protected $m_bLocalizedValues; // Values in the data set are localized (see AttributeEnum)
public function __construct($sClass, $aData, $aAttList, $aExtKeys, $aReconcilKeys, $sSynchroScope = null, $aOnDisappear = null, $sDateFormat = null)
public function __construct($sClass, $aData, $aAttList, $aExtKeys, $aReconcilKeys, $sSynchroScope = null, $aOnDisappear = null, $sDateFormat = null, $bLocalize = false)
{
$this->m_sClass = $sClass;
$this->m_aData = $aData;
@@ -264,6 +271,7 @@ class BulkChange
$this->m_sSynchroScope = $sSynchroScope;
$this->m_aOnDisappear = $aOnDisappear;
$this->m_sDateFormat = $sDateFormat;
$this->m_bLocalizedValues = $bLocalize;
}
protected $m_bReportHtml = false;
@@ -289,7 +297,9 @@ class BulkChange
foreach ($this->m_aExtKeys[$sAttCode] as $sForeignAttCode => $iCol)
{
// The foreign attribute is one of our reconciliation key
$oReconFilter->AddCondition($sForeignAttCode, $aRowData[$iCol], '=');
$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]);
}
@@ -331,6 +341,7 @@ class BulkChange
{
foreach ($aKeyConfig as $sForeignAttCode => $iCol)
{
// Default reporting
$aResults[$iCol] = new CellStatus_Void($aRowData[$iCol]);
}
if ($oExtKey->IsNullAllowed())
@@ -340,8 +351,8 @@ class BulkChange
}
else
{
$aErrors[$sAttCode] = "Null not allowed";
$aResults[$sAttCode]= new CellStatus_Issue(null, $oTargetObj->Get($sAttCode), 'Null not allowed');
$aErrors[$sAttCode] = Dict::S('UI:CSVReport-Value-Issue-Null');
$aResults[$sAttCode]= new CellStatus_Issue(null, $oTargetObj->Get($sAttCode), Dict::S('UI:CSVReport-Value-Issue-Null'));
}
}
else
@@ -350,14 +361,23 @@ 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);
switch($oExtObjects->Count())
{
case 0:
$aErrors[$sAttCode] = "Object not found";
$aErrors[$sAttCode] = Dict::S('UI:CSVReport-Value-Issue-NotFound');
$aResults[$sAttCode]= new CellStatus_SearchIssue();
break;
case 1:
@@ -366,7 +386,7 @@ class BulkChange
$oTargetObj->Set($sAttCode, $oForeignObj->GetKey());
break;
default:
$aErrors[$sAttCode] = "Found ".$oExtObjects->Count()." matches";
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-FoundMany', $oExtObjects->Count());
$aResults[$sAttCode]= new CellStatus_Ambiguous($oTargetObj->Get($sAttCode), $oExtObjects->Count(), $oReconFilter->ToOql());
}
}
@@ -384,6 +404,11 @@ class BulkChange
else
{
$aResults[$sAttCode]= new CellStatus_Modify($iForeignObj, $oTargetObj->GetOriginal($sAttCode));
foreach ($aKeyConfig as $sForeignAttCode => $iCol)
{
// Report the change on reconciliation values as well
$aResults[$iCol] = new CellStatus_Modify($aRowData[$iCol]);
}
}
}
else
@@ -405,31 +430,39 @@ class BulkChange
$iFlags = $oTargetObj->GetAttributeFlags($sAttCode, $aReasons);
if ( (($iFlags & OPT_ATT_READONLY) == OPT_ATT_READONLY) && ( $oTargetObj->Get($sAttCode) != $aRowData[$iCol]) )
{
$aErrors[$sAttCode] = "the attribute '$sAttCode' is read-only and cannot be modified (current value: ".$oTargetObj->Get($sAttCode).", proposed value: {$aRowData[$iCol]}).";
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-Readonly', $sAttCode, $oTargetObj->Get($sAttCode), $aRowData[$iCol]);
}
else if ($oAttDef->IsLinkSet() && $oAttDef->IsIndirect())
{
try
{
$oSet = $oAttDef->MakeValueFromString($aRowData[$iCol]);
$oSet = $oAttDef->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
$oTargetObj->Set($sAttCode, $oSet);
}
catch(CoreException $e)
{
$aErrors[$sAttCode] = "Failed to process input: ".$e->getMessage();
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-Format', $e->getMessage());
}
}
else
{
$res = $oTargetObj->CheckValue($sAttCode, $aRowData[$iCol]);
if ($res === true)
$value = $oAttDef->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
if (is_null($value) && (strlen($aRowData[$iCol]) > 0))
{
$oTargetObj->Set($sAttCode, $aRowData[$iCol]);
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-NoMatch', $sAttCode);
}
else
{
// $res is a string with the error description
$aErrors[$sAttCode] = "Unexpected value for attribute '$sAttCode': $res";
$res = $oTargetObj->CheckValue($sAttCode, $value);
if ($res === true)
{
$oTargetObj->Set($sAttCode, $value);
}
else
{
// $res is a string with the error description
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-Unknown', $sAttCode, $res);
}
}
}
}
@@ -447,17 +480,19 @@ class BulkChange
{
if ($this->m_bReportHtml)
{
$sCurValue = $oTargetObj->GetAsHTML($sAttCode);
$sOrigValue = $oTargetObj->GetOriginalAsHTML($sAttCode);
$sCurValue = $oTargetObj->GetAsHTML($sAttCode, $this->m_bLocalizedValues);
$sOrigValue = $oTargetObj->GetOriginalAsHTML($sAttCode, $this->m_bLocalizedValues);
$sInput = htmlentities($aRowData[$iCol], ENT_QUOTES, 'UTF-8');
}
else
{
$sCurValue = $oTargetObj->GetAsCSV($sAttCode, $this->m_sReportCsvSep, $this->m_sReportCsvDelimiter);
$sOrigValue = $oTargetObj->GetOriginalAsCSV($sAttCode, $this->m_sReportCsvSep, $this->m_sReportCsvDelimiter);
$sCurValue = $oTargetObj->GetAsCSV($sAttCode, $this->m_sReportCsvSep, $this->m_sReportCsvDelimiter, $this->m_bLocalizedValues);
$sOrigValue = $oTargetObj->GetOriginalAsCSV($sAttCode, $this->m_sReportCsvSep, $this->m_sReportCsvDelimiter, $this->m_bLocalizedValues);
$sInput = $aRowData[$iCol];
}
if (isset($aErrors[$sAttCode]))
{
$aResults[$iCol]= new CellStatus_Issue($sCurValue, $sOrigValue, $aErrors[$sAttCode]);
$aResults[$iCol]= new CellStatus_Issue($aRowData[$iCol], $sOrigValue, $aErrors[$sAttCode]);
}
elseif (array_key_exists($sAttCode, $aChangedFields))
{
@@ -484,7 +519,7 @@ class BulkChange
if ($res !== true)
{
// $res contains the error description
$aErrors["GLOBAL"] = "Attributes not consistent with each others: $res";
$aErrors["GLOBAL"] = Dict::Format('UI:CSVReport-Row-Issue-Inconsistent', $res);
}
return $aResults;
}
@@ -548,7 +583,7 @@ class BulkChange
if ($res !== true)
{
// $res contains the error description
$aErrors["GLOBAL"] = "Attributes not consistent with each others: $res";
$aErrors["GLOBAL"] = Dict::Format('UI:CSVReport-Row-Issue-Inconsistent', $res);
}
return $aResults;
}
@@ -562,7 +597,7 @@ class BulkChange
if (count($aErrors) > 0)
{
$sErrors = implode(', ', $aErrors);
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue("Unexpected attribute value(s)");
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Attribute'));
return $oTargetObj;
}
@@ -581,7 +616,7 @@ class BulkChange
if (count($aMissingKeys) > 0)
{
$sMissingKeys = implode(', ', $aMissingKeys);
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue("Could not be created, due to missing external key(s): $sMissingKeys");
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::Format('UI:CSVReport-Row-Issue-MissingExtKey', $sMissingKeys));
return $oTargetObj;
}
@@ -615,7 +650,7 @@ class BulkChange
if (count($aErrors) > 0)
{
$sErrors = implode(', ', $aErrors);
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue("Unexpected attribute value(s)");
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Attribute'));
return;
}
@@ -656,7 +691,7 @@ class BulkChange
if (count($aErrors) > 0)
{
$sErrors = implode(', ', $aErrors);
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue("Unexpected attribute value(s)");
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Attribute'));
return;
}
@@ -732,8 +767,8 @@ class BulkChange
else
{
// Leave the cell unchanged
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue("wrong date format");
$aResult[$iRow][$sAttCode] = new CellStatus_Issue(null, $this->m_aData[$iRow][$iCol], 'Wrong date format');
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
$aResult[$iRow][$sAttCode] = new CellStatus_Issue(null, $this->m_aData[$iRow][$iCol], Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
}
}
}
@@ -753,91 +788,106 @@ class BulkChange
// An issue at the earlier steps - skip the rest
continue;
}
$oReconciliationFilter = new CMDBSearchFilter($this->m_sClass);
$bSkipQuery = false;
foreach($this->m_aReconcilKeys as $sAttCode)
try
{
$valuecondition = null;
if (array_key_exists($sAttCode, $this->m_aExtKeys))
$oReconciliationFilter = new CMDBSearchFilter($this->m_sClass);
$bSkipQuery = false;
foreach($this->m_aReconcilKeys as $sAttCode)
{
if ($this->IsNullExternalKeySpec($aRowData, $sAttCode))
$valuecondition = null;
if (array_key_exists($sAttCode, $this->m_aExtKeys))
{
$oExtKey = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
if ($oExtKey->IsNullAllowed())
if ($this->IsNullExternalKeySpec($aRowData, $sAttCode))
{
$valuecondition = $oExtKey->GetNullValue();
$aResult[$iRow][$sAttCode] = new CellStatus_Void($oExtKey->GetNullValue());
$oExtKey = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
if ($oExtKey->IsNullAllowed())
{
$valuecondition = $oExtKey->GetNullValue();
$aResult[$iRow][$sAttCode] = new CellStatus_Void($oExtKey->GetNullValue());
}
else
{
$aResult[$iRow][$sAttCode] = new CellStatus_NullIssue();
}
}
else
{
$aResult[$iRow][$sAttCode] = new CellStatus_NullIssue();
}
// The value has to be found or verified
list($sQuery, $aMatches) = $this->ResolveExternalKey($aRowData, $sAttCode, $aResult[$iRow]);
if (count($aMatches) == 1)
{
$oRemoteObj = reset($aMatches); // first item
$valuecondition = $oRemoteObj->GetKey();
$aResult[$iRow][$sAttCode] = new CellStatus_Void($oRemoteObj->GetKey());
}
elseif (count($aMatches) == 0)
{
$aResult[$iRow][$sAttCode] = new CellStatus_SearchIssue();
}
else
{
$aResult[$iRow][$sAttCode] = new CellStatus_Ambiguous(null, count($aMatches), $sQuery);
}
}
}
else
{
// The value has to be found or verified
list($sQuery, $aMatches) = $this->ResolveExternalKey($aRowData, $sAttCode, $aResult[$iRow]);
if (count($aMatches) == 1)
// The value is given in the data row
$iCol = $this->m_aAttList[$sAttCode];
if ($sAttCode == 'id')
{
$oRemoteObj = reset($aMatches); // first item
$valuecondition = $oRemoteObj->GetKey();
$aResult[$iRow][$sAttCode] = new CellStatus_Void($oRemoteObj->GetKey());
}
elseif (count($aMatches) == 0)
{
$aResult[$iRow][$sAttCode] = new CellStatus_SearchIssue();
}
$valuecondition = $aRowData[$iCol];
}
else
{
$aResult[$iRow][$sAttCode] = new CellStatus_Ambiguous(null, count($aMatches), $sQuery);
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
$valuecondition = $oAttDef->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
}
}
}
else
{
// The value is given in the data row
$iCol = $this->m_aAttList[$sAttCode];
$valuecondition = $aRowData[$iCol];
}
if (is_null($valuecondition))
{
$bSkipQuery = true;
}
else
{
$oReconciliationFilter->AddCondition($sAttCode, $valuecondition, '=');
}
}
if ($bSkipQuery)
{
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue("failed to reconcile");
}
else
{
$oReconciliationSet = new CMDBObjectSet($oReconciliationFilter);
switch($oReconciliationSet->Count())
{
case 0:
$oTargetObj = $this->CreateObject($aResult, $iRow, $aRowData, $oChange);
// $aResult[$iRow]["__STATUS__"]=> set in CreateObject
$aVisited[] = $oTargetObj->GetKey();
break;
case 1:
$oTargetObj = $oReconciliationSet->Fetch();
$this->UpdateObject($aResult, $iRow, $oTargetObj, $aRowData, $oChange);
// $aResult[$iRow]["__STATUS__"]=> set in UpdateObject
if (!is_null($this->m_sSynchroScope))
{
$aVisited[] = $oTargetObj->GetKey();
}
break;
default:
// Found several matches, ambiguous
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue("ambiguous reconciliation");
$aResult[$iRow]["id"]= new CellStatus_Ambiguous(0, $oReconciliationSet->Count(), $oReconciliationFilter->ToOql());
$aResult[$iRow]["finalclass"]= 'n/a';
if (is_null($valuecondition))
{
$bSkipQuery = true;
}
else
{
$oReconciliationFilter->AddCondition($sAttCode, $valuecondition, '=');
}
}
if ($bSkipQuery)
{
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Reconciliation'));
}
else
{
$oReconciliationSet = new CMDBObjectSet($oReconciliationFilter);
switch($oReconciliationSet->Count())
{
case 0:
$oTargetObj = $this->CreateObject($aResult, $iRow, $aRowData, $oChange);
// $aResult[$iRow]["__STATUS__"]=> set in CreateObject
$aVisited[] = $oTargetObj->GetKey();
break;
case 1:
$oTargetObj = $oReconciliationSet->Fetch();
$this->UpdateObject($aResult, $iRow, $oTargetObj, $aRowData, $oChange);
// $aResult[$iRow]["__STATUS__"]=> set in UpdateObject
if (!is_null($this->m_sSynchroScope))
{
$aVisited[] = $oTargetObj->GetKey();
}
break;
default:
// Found several matches, ambiguous
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Ambiguous'));
$aResult[$iRow]["id"]= new CellStatus_Ambiguous(0, $oReconciliationSet->Count(), $oReconciliationFilter->ToOql());
$aResult[$iRow]["finalclass"]= 'n/a';
}
}
}
catch (Exception $e)
{
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::Format('UI:CSVReport-Row-Issue-Internal', get_class($e), $e->getMessage()));
}
}
@@ -1166,49 +1216,6 @@ EOF
}
$oPage->table($aConfig, $aDetails);
}
/**
* Get the user friendly name for an 'extended' attribute code i.e 'name', becomes 'Name' and 'org_id->name' becomes 'Organization->Name'
* @param string $sClassName The name of the class
* @param string $sAttCodeEx Either an attribute code or ext_key_name->att_code
* @return string A user friendly format of the string: AttributeName or AttributeName->ExtAttributeName
*/
public static function GetFriendlyAttCodeName($sClassName, $sAttCodeEx)
{
$sFriendlyName = '';
if (preg_match('/(.+)->(.+)/', $sAttCodeEx, $aMatches) > 0)
{
$sAttribute = $aMatches[1];
$sField = $aMatches[2];
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttribute);
if ($oAttDef->IsExternalKey())
{
$sTargetClass = $oAttDef->GetTargetClass();
$oTargetAttDef = MetaModel::GetAttributeDef($sTargetClass, $sField);
$sFriendlyName = $oAttDef->GetLabel().'->'.$oTargetAttDef->GetLabel();
}
else
{
// hum, hum... should never happen, we'd better raise an exception
throw(new Exception(Dict::Format('UI:CSVImport:ErrorExtendedAttCode', $sAttCodeEx, $sAttribute, $sClassName)));
}
}
else
{
if ($sAttCodeEx == 'id')
{
$sFriendlyName = Dict::S('UI:CSVImport:idField');
}
else
{
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCodeEx);
$sFriendlyName = $oAttDef->GetLabel();
}
}
return $sFriendlyName;
}
}

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Persistent class (internal) cmdbChange
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Persistent classes (internal) : cmdbChangeOp and derived
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -64,6 +65,19 @@ class CMDBChangeOp extends DBObject
{
return '';
}
/**
* Safety net: in case the change is not given, let's guarantee that it will
* be set to the current ongoing change (or create a new one)
*/
protected function OnInsert()
{
if ($this->Get('change') <= 0)
{
$this->Set('change', CMDBObject::GetCurrentChange());
}
parent::OnInsert();
}
}
@@ -124,6 +138,11 @@ class CMDBChangeOpDelete extends CMDBChangeOp
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
// Final class of the object (objclass must be set to the root class for efficiency purposes)
MetaModel::Init_AddAttribute(new AttributeString("fclass", array("allowed_values"=>null, "sql"=>"fclass", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
// Last friendly name of the object
MetaModel::Init_AddAttribute(new AttributeString("fname", array("allowed_values"=>null, "sql"=>"fname", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
}
/**
* Describe (as a text string) the modifications corresponding to this change
@@ -267,8 +286,16 @@ class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode')))
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
}
else
{
// The attribute was renamed or removed from the object ?
$sAttName = $this->Get('attcode');
}
$oPrevDoc = $this->Get('prevdata');
$sDocView = $oPrevDoc->GetAsHtml();
$sDocView .= "<br/>".Dict::Format('UI:OpenDocumentInNewWindow_',$oPrevDoc->GetDisplayLink(get_class($this), $this->GetKey(), 'prevdata')).", \n";
@@ -323,8 +350,16 @@ class CMDBChangeOpSetAttributeOneWayPassword extends CMDBChangeOpSetAttribute
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode')))
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
}
else
{
// The attribute was renamed or removed from the object ?
$sAttName = $this->Get('attcode');
}
$sResult = Dict::Format('Change:AttName_Changed', $sAttName);
}
return $sResult;
@@ -375,8 +410,16 @@ class CMDBChangeOpSetAttributeEncrypted extends CMDBChangeOpSetAttribute
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode')))
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
}
else
{
// The attribute was renamed or removed from the object ?
$sAttName = $this->Get('attcode');
}
$sPrevString = $this->Get('prevstring');
$sResult = Dict::Format('Change:AttName_Changed_PreviousValue_OldValue', $sAttName, $sPrevString);
}
@@ -430,8 +473,81 @@ class CMDBChangeOpSetAttributeText extends CMDBChangeOpSetAttribute
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode')))
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
}
else
{
// The attribute was renamed or removed from the object ?
$sAttName = $this->Get('attcode');
}
$sTextView = '<div>'.$this->GetAsHtml('prevdata').'</div>';
//$sDocView = $oPrevDoc->GetDisplayInline(get_class($this), $this->GetKey(), 'prevdata');
$sResult = Dict::Format('Change:AttName_Changed_PreviousValue_OldValue', $sAttName, $sTextView);
}
return $sResult;
}
}
/**
* Record the modification of a multiline string (text)
*
* @package iTopORM
*/
class CMDBChangeOpSetAttributeLongText extends CMDBChangeOpSetAttribute
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"key_type" => "",
"name_attcode" => "change",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_changeop_setatt_longtext",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeLongText("prevdata", array("allowed_values"=>null, "sql"=>"prevdata", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
}
/**
* Describe (as a text string) the modifications corresponding to this change
*/
public function GetDescription()
{
// Temporary, until we change the options of GetDescription() -needs a more global revision
$bIsHtml = true;
$sResult = '';
$oTargetObjectClass = $this->Get('objclass');
$oTargetObjectKey = $this->Get('objkey');
$oTargetSearch = new DBObjectSearch($oTargetObjectClass);
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
{
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode')))
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
}
else
{
// The attribute was renamed or removed from the object ?
$sAttName = $this->Get('attcode');
}
$sTextView = '<div>'.$this->GetAsHtml('prevdata').'</div>';
//$sDocView = $oPrevDoc->GetDisplayInline(get_class($this), $this->GetKey(), 'prevdata');
@@ -490,8 +606,16 @@ class CMDBChangeOpSetAttributeCaseLog extends CMDBChangeOpSetAttribute
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
if (MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode')))
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
}
else
{
// The attribute was renamed or removed from the object ?
$sAttName = $this->Get('attcode');
}
$sResult = Dict::Format('Change:AttName_EntryAdded', $sAttName);
}
return $sResult;
@@ -535,4 +659,185 @@ class CMDBChangeOpPlugin extends CMDBChangeOp
return $this->Get('description');
}
}
/**
* Record added/removed objects from within a link set
*
* @package iTopORM
*/
abstract class CMDBChangeOpSetAttributeLinks extends CMDBChangeOpSetAttribute
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"key_type" => "",
"name_attcode" => "change",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_changeop_links",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
// Note: item class/id points to the link class itself in case of a direct link set (e.g. Server::interface_list => Interface)
// item class/id points to the remote class in case of a indirect link set (e.g. Server::contract_list => Contract)
MetaModel::Init_AddAttribute(new AttributeString("item_class", array("allowed_values"=>null, "sql"=>"item_class", "default_value"=>'', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeInteger("item_id", array("allowed_values"=>null, "sql"=>"item_id", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
}
}
/**
* Record added/removed objects from within a link set
*
* @package iTopORM
*/
class CMDBChangeOpSetAttributeLinksAddRemove extends CMDBChangeOpSetAttributeLinks
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"key_type" => "",
"name_attcode" => "change",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_changeop_links_addremove",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeEnum("type", array("allowed_values"=>new ValueSetEnum('added,removed'), "sql"=>"type", "default_value"=>"added", "is_null_allowed"=>false, "depends_on"=>array())));
}
/**
* Describe (as a text string) the modifications corresponding to this change
*/
public function GetDescription()
{
$sResult = '';
$oTargetObjectClass = $this->Get('objclass');
$oTargetObjectKey = $this->Get('objkey');
$oTargetSearch = new DBObjectSearch($oTargetObjectClass);
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
{
if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) return ''; // Protects against renamed attributes...
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
$sItemDesc = MetaModel::GetHyperLink($this->Get('item_class'), $this->Get('item_id'));
$sResult = $sAttName.' - ';
switch ($this->Get('type'))
{
case 'added':
$sResult .= Dict::Format('Change:LinkSet:Added', $sItemDesc);
break;
case 'removed':
$sResult .= Dict::Format('Change:LinkSet:Removed', $sItemDesc);
break;
}
}
return $sResult;
}
}
/**
* Record attribute changes from within a link set
* A single record redirects to the modifications made within the same change
*
* @package iTopORM
*/
class CMDBChangeOpSetAttributeLinksTune extends CMDBChangeOpSetAttributeLinks
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"key_type" => "",
"name_attcode" => "change",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_changeop_links_tune",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeInteger("link_id", array("allowed_values"=>null, "sql"=>"link_id", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
}
/**
* Describe (as a text string) the modifications corresponding to this change
*/
public function GetDescription()
{
$sResult = '';
$oTargetObjectClass = $this->Get('objclass');
$oTargetObjectKey = $this->Get('objkey');
$oTargetSearch = new DBObjectSearch($oTargetObjectClass);
$oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
{
if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) return ''; // Protects against renamed attributes...
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
$sLinkClass = $oAttDef->GetLinkedClass();
$aLinkClasses = MetaModel::EnumChildClasses($sLinkClass, ENUM_CHILD_CLASSES_ALL);
// Search for changes on the corresponding link
//
$oSearch = new DBObjectSearch('CMDBChangeOpSetAttribute');
$oSearch->AddCondition('change', $this->Get('change'), '=');
$oSearch->AddCondition('objkey', $this->Get('link_id'), '=');
if (count($aLinkClasses) == 1)
{
// Faster than the whole building of the expression below for just one value ??
$oSearch->AddCondition('objclass', $sLinkClass, '=');
}
else
{
$oField = new FieldExpression('objclass', $oSearch->GetClassAlias());
$sListExpr = '('.implode(', ', CMDBSource::Quote($aLinkClasses)).')';
$sOQLCondition = $oField->Render()." IN $sListExpr";
$oNewCondition = Expression::FromOQL($sOQLCondition);
$oSearch->AddConditionExpression($oNewCondition);
}
$oSet = new DBObjectSet($oSearch);
$aChanges = array();
while ($oChangeOp = $oSet->Fetch())
{
$aChanges[] = $oChangeOp->GetDescription();
}
if (count($aChanges) == 0)
{
return '';
}
$sItemDesc = MetaModel::GetHyperLink($this->Get('item_class'), $this->Get('item_id'));
$sResult = $sAttName.' - ';
$sResult .= Dict::Format('Change:LinkSet:Modified', $sItemDesc);
$sResult .= ' : '.implode(', ', $aChanges);
}
return $sResult;
}
}
?>

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 cmdbObject
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -91,8 +92,11 @@ abstract class CMDBObject extends DBObject
protected $m_datUpdated;
// Note: this value is static, but that could be changed because it is sometimes a real issue (see update of interfaces / connected_to
protected static $m_oCurrChange = null;
protected static $m_sInfo = null; // null => the information is built in a standard way
/**
* Specify another change (this is mainly for backward compatibility)
*/
public static function SetCurrentChange(CMDBChange $oChange)
{
self::$m_oCurrChange = $oChange;
@@ -100,34 +104,86 @@ abstract class CMDBObject extends DBObject
//
// Todo: simplify the APIs and do not pass the current change as an argument anymore
// SetCurrentChange to be invoked in very few cases (UI.php, CSV import, Data synchro)
// SetTrackInfo to be invoked in very few cases (UI.php, CSV import, Data synchro)
// SetCurrentChange is an alternative to SetTrackInfo (csv ?)
// GetCurrentChange to be called ONCE (!) by CMDBChangeOp::OnInsert ($this->Set('change', ..GetCurrentChange())
// GetCurrentChange to create a default change if not already done in the current context
//
public static function GetCurrentChange()
/**
* Get a change record (create it if not existing)
*/
public static function GetCurrentChange($bAutoCreate = true)
{
if ($bAutoCreate && is_null(self::$m_oCurrChange))
{
self::CreateChange();
}
return self::$m_oCurrChange;
}
private function RecordObjCreation(CMDBChange $oChange)
/**
* Override the additional information (defaulting to user name)
* A call to this verb should replace every occurence of
* $oMyChange = MetaModel::NewObject("CMDBChange");
* $oMyChange->Set("date", time());
* $oMyChange->Set("userinfo", 'this is done by ... for ...');
* $iChangeId = $oMyChange->DBInsert();
*/
public static function SetTrackInfo($sInfo)
{
self::$m_sInfo = $sInfo;
}
/**
* Get the additional information (defaulting to user name)
*/
protected static function GetTrackInfo()
{
if (is_null(self::$m_sInfo))
{
return CMDBChange::GetCurrentUserName();
}
else
{
return self::$m_sInfo;
}
}
/**
* Create a standard change record (done here 99% of the time, and nearly once per page)
*/
protected static function CreateChange()
{
self::$m_oCurrChange = MetaModel::NewObject("CMDBChange");
self::$m_oCurrChange->Set("date", time());
self::$m_oCurrChange->Set("userinfo", self::GetTrackInfo());
self::$m_oCurrChange->DBInsert();
}
protected function RecordObjCreation()
{
parent::RecordObjCreation();
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpCreate");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$iId = $oMyChangeOp->DBInsertNoReload();
}
private function RecordObjDeletion(CMDBChange $oChange, $objkey)
protected function RecordObjDeletion($objkey)
{
parent::RecordObjDeletion($objkey);
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpDelete");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objclass", MetaModel::GetRootClass(get_class($this)));
$oMyChangeOp->Set("objkey", $objkey);
$oMyChangeOp->Set("fclass", get_class($this));
$oMyChangeOp->Set("fname", $this->GetRawName());
$iId = $oMyChangeOp->DBInsertNoReload();
}
private function RecordAttChanges(CMDBChange $oChange, array $aValues, array $aOrigValues)
protected function RecordAttChanges(array $aValues, array $aOrigValues)
{
parent::RecordAttChanges($aValues, $aOrigValues);
// $aValues is an array of $sAttCode => $value
//
foreach ($aValues as $sAttCode=> $value)
@@ -149,7 +205,6 @@ abstract class CMDBObject extends DBObject
{
// One Way encrypted passwords' history is stored -one way- encrypted
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeOneWayPassword");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
@@ -165,7 +220,6 @@ abstract class CMDBObject extends DBObject
{
// Encrypted string history is stored encrypted
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeEncrypted");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
@@ -181,7 +235,6 @@ abstract class CMDBObject extends DBObject
{
// Data blobs
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeBlob");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
@@ -209,7 +262,6 @@ abstract class CMDBObject extends DBObject
if ($item_value != $item_original)
{
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeScalar");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sSubItemAttCode);
@@ -223,7 +275,6 @@ abstract class CMDBObject extends DBObject
elseif ($oAttDef instanceOf AttributeCaseLog)
{
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeCaseLog");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
@@ -231,11 +282,10 @@ abstract class CMDBObject extends DBObject
$oMyChangeOp->Set("lastentry", $value->GetLatestEntryIndex());
$iId = $oMyChangeOp->DBInsertNoReload();
}
elseif ($oAttDef instanceOf AttributeText)
elseif ($oAttDef instanceOf AttributeLongText)
{
// Data blobs
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeText");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeLongText");
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
@@ -247,12 +297,48 @@ abstract class CMDBObject extends DBObject
$oMyChangeOp->Set("prevdata", $original);
$iId = $oMyChangeOp->DBInsertNoReload();
}
elseif ($oAttDef instanceOf AttributeText)
{
// Data blobs
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeText");
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
if (!is_null($original) && ($original instanceof ormCaseLog))
{
$original = $original->GetText();
}
$oMyChangeOp->Set("prevdata", $original);
$iId = $oMyChangeOp->DBInsertNoReload();
}
elseif ($oAttDef instanceOf AttributeBoolean)
{
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeScalar");
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
$oMyChangeOp->Set("oldvalue", $original ? 1 : 0);
$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
//
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeScalar");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
@@ -294,32 +380,24 @@ abstract class CMDBObject extends DBObject
public function DBInsert()
{
if(!is_object(self::$m_oCurrChange))
{
throw new CoreException("DBInsert() could not be used here, please use DBInsertTracked() instead");
}
return $this->DBInsertTracked_Internal();
}
public function DBInsertTracked(CMDBChange $oChange, $bSkipStrongSecurity = null)
{
self::SetCurrentChange($oChange);
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
$oPreviousChange = self::$m_oCurrChange;
self::$m_oCurrChange = $oChange;
$ret = $this->DBInsertTracked_Internal();
self::$m_oCurrChange = $oPreviousChange;
return $ret;
}
public function DBInsertTrackedNoReload(CMDBChange $oChange, $bSkipStrongSecurity = null)
{
self::SetCurrentChange($oChange);
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
$oPreviousChange = self::$m_oCurrChange;
self::$m_oCurrChange = $oChange;
$ret = $this->DBInsertTracked_Internal(true);
self::$m_oCurrChange = $oPreviousChange;
return $ret;
}
@@ -333,25 +411,18 @@ abstract class CMDBObject extends DBObject
{
$ret = parent::DBInsert();
}
$this->RecordObjCreation(self::$m_oCurrChange);
return $ret;
}
public function DBClone($newKey = null)
{
if(!self::$m_oCurrChange)
{
throw new CoreException("DBClone() could not be used here, please use DBCloneTracked() instead");
}
return $this->DBCloneTracked_Internal();
}
public function DBCloneTracked(CMDBChange $oChange, $newKey = null)
{
$oPreviousChange = self::$m_oCurrChange;
self::$m_oCurrChange = $oChange;
self::SetCurrentChange($oChange);
$this->DBCloneTracked_Internal($newKey);
self::$m_oCurrChange = $oPreviousChange;
}
protected function DBCloneTracked_Internal($newKey = null)
@@ -359,128 +430,57 @@ abstract class CMDBObject extends DBObject
$newKey = parent::DBClone($newKey);
$oClone = MetaModel::GetObject(get_class($this), $newKey);
$oClone->RecordObjCreation(self::$m_oCurrChange);
return $newKey;
}
public function DBUpdate()
{
if(!self::$m_oCurrChange)
{
throw new CoreException("DBUpdate() could not be used here, please use DBUpdateTracked() instead");
}
return $this->DBUpdateTracked_internal();
}
public function DBUpdateTracked(CMDBChange $oChange, $bSkipStrongSecurity = null)
{
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
$oPreviousChange = self::$m_oCurrChange;
self::$m_oCurrChange = $oChange;
$this->DBUpdateTracked_Internal();
self::$m_oCurrChange = $oPreviousChange;
}
protected function DBUpdateTracked_Internal()
{
// Copy the changes list before the update (the list should be reset afterwards)
$aChanges = $this->ListChanges();
if (count($aChanges) == 0)
{
//throw new CoreWarning("Attempting to update an unchanged object");
return;
}
// Save the original values (will be reset to the new values when the object get written to the DB)
$aOriginalValues = $this->m_aOrigValues;
$ret = parent::DBUpdate();
$this->RecordAttChanges(self::$m_oCurrChange, $aChanges, $aOriginalValues);
return $ret;
}
public function DBUpdateTracked(CMDBChange $oChange, $bSkipStrongSecurity = null)
{
self::SetCurrentChange($oChange);
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
$this->DBUpdate();
}
public function DBDelete(&$oDeletionPlan = null)
{
if(!self::$m_oCurrChange)
{
throw new CoreException("DBDelete() could not be used here, please use DBDeleteTracked() instead");
}
return $this->DBDeleteTracked_Internal($oDeletionPlan);
}
public function DBDeleteTracked(CMDBChange $oChange, $bSkipStrongSecurity = null, &$oDeletionPlan = null)
{
self::SetCurrentChange($oChange);
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_DELETE);
$oPreviousChange = self::$m_oCurrChange;
self::$m_oCurrChange = $oChange;
$this->DBDeleteTracked_Internal($oDeletionPlan);
self::$m_oCurrChange = $oPreviousChange;
}
protected function DBDeleteTracked_Internal(&$oDeletionPlan = null)
{
$prevkey = $this->GetKey();
$ret = parent::DBDelete($oDeletionPlan);
$this->RecordObjDeletion(self::$m_oCurrChange, $prevkey);
return $ret;
}
public static function BulkDelete(DBObjectSearch $oFilter)
{
if(!self::$m_oCurrChange)
{
throw new CoreException("BulkDelete() could not be used here, please use BulkDeleteTracked() instead");
}
return $this->BulkDeleteTracked_Internal($oFilter);
}
public static function BulkDeleteTracked(CMDBChange $oChange, DBObjectSearch $oFilter)
{
$oPreviousChange = self::$m_oCurrChange;
self::$m_oCurrChange = $oChange;
$this->BulkDeleteTracked_Internal($oFilter);
self::$m_oCurrChange = $oPreviousChange;
}
protected static function BulkDeleteTracked_Internal(DBObjectSearch $oFilter)
{
throw new CoreWarning("Change tracking not tested for bulk operations");
// Get the list of objects to delete (and record data before deleting the DB records)
$oObjSet = new CMDBObjectSet($oFilter);
$aObjAndKeys = array(); // array of id=>object
while ($oItem = $oObjSet->Fetch())
{
$aObjAndKeys[$oItem->GetKey()] = $oItem;
}
$oObjSet->FreeResult();
// Delete in one single efficient query
$ret = parent::BulkDelete($oFilter);
// Record... in many queries !!!
foreach($aObjAndKeys as $prevkey=>$oItem)
{
$oItem->RecordObjDeletion(self::$m_oCurrChange, $prevkey);
}
return $ret;
}
public static function BulkUpdate(DBObjectSearch $oFilter, array $aValues)
{
if(!self::$m_oCurrChange)
{
throw new CoreException("BulkUpdate() could not be used here, please use BulkUpdateTracked() instead");
}
return $this->BulkUpdateTracked_Internal($oFilter, $aValues);
}
public static function BulkUpdateTracked(CMDBChange $oChange, DBObjectSearch $oFilter, array $aValues)
{
$oPreviousChange = self::$m_oCurrChange;
self::$m_oCurrChange = $oChange;
self::SetCurrentChange($oChange);
$this->BulkUpdateTracked_Internal($oFilter, $aValues);
self::$m_oCurrChange = $oPreviousChange;
}
protected static function BulkUpdateTracked_Internal(DBObjectSearch $oFilter, array $aValues)
@@ -507,7 +507,7 @@ abstract class CMDBObject extends DBObject
while ($oItem = $oObjSet->Fetch())
{
$aChangedValues = $oItem->ListChangedValues($aValues);
$oItem->RecordAttChanges(self::$m_oCurrChange, $aChangedValues, $aOriginalValues[$oItem->GetKey()]);
$oItem->RecordAttChanges($aChangedValues, $aOriginalValues[$oItem->GetKey()]);
}
return $ret;
}

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* DB Server abstraction
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once('MyHelpers.class.inc.php');
@@ -57,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));
}
}
}
@@ -119,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`"));
}
}
@@ -132,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));
}
@@ -374,6 +389,11 @@ class CMDBSource
return mysqli_num_rows($result);
}
public static function AffectedRows()
{
return mysqli_affected_rows(self::$m_resDBLink);
}
public static function FetchArray($result)
{
return mysqli_fetch_array($result, MYSQLI_ASSOC);

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Any extension to compute things like a stop watch deadline or working hours
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**

View File

@@ -1,18 +1,21 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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('ITOP_APPLICATION', 'iTop');
define('ITOP_VERSION', '$ITOP_VERSION$');
@@ -27,10 +30,8 @@ define('ACCESS_READONLY', 0);
/**
* Configuration read/write
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once('coreexception.class.inc.php');
@@ -48,7 +49,7 @@ define ('DEFAULT_LOG_ISSUE', true);
define ('DEFAULT_LOG_WEB_SERVICE', true);
define ('DEFAULT_LOG_KPI_DURATION', false);
define ('DEFAULT_LOG_KPI_MEMORY', false);
define ('DEFAULT_DEBUG_QUERIES', false);
define ('DEFAULT_LOG_QUERIES', false);
define ('DEFAULT_QUERY_CACHE_ENABLED', true);
@@ -90,7 +91,7 @@ class Config
'default' => '',
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'app_root_url' => array(
'type' => 'string',
@@ -100,6 +101,14 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'app_icon_url' => array(
'type' => 'string',
'description' => 'Hyperlink to redirect the user when clicking on the application icon (in the main window, or login/logoff pages)',
'default' => 'http://www.combodo.com/itop',
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'skip_check_to_write' => array(
'type' => 'bool',
'description' => 'Disable data format and integrity checks to boost up data load (insert or update)',
@@ -124,6 +133,22 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'query_optimization_enabled' => array(
'type' => 'bool',
'description' => 'The queries are optimized based on the assumption that the DB integrity has been preserved. By disabling the optimization one can ensure that the fetched data is clean... but this can be really slower or not usable at all (some queries will exceed the allowed number of joins in MySQL: 61!)',
'default' => true,
'value' => true,
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'query_indentation_enabled' => array(
'type' => 'bool',
'description' => 'For developpers: format the SQL queries for human analysis',
'default' => false,
'value' => false,
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'graphviz_path' => array(
'type' => 'string',
'description' => 'Path to the Graphviz "dot" executable for graphing objects lifecycle',
@@ -205,6 +230,14 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'csv_import_history_display' => array(
'type' => 'bool',
'description' => 'Display the history tab in the import wizard',
'default' => false,
'value' => false,
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'access_mode' => array(
'type' => 'integer',
'description' => 'Combination of flags (ACCESS_USER_WRITE | ACCESS_ADMIN_WRITE, or ACCESS_FULL)',
@@ -391,7 +424,7 @@ class Config
'default' => '2.0',
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'cas_host' => array(
'type' => 'string',
@@ -400,7 +433,7 @@ class Config
'default' => '',
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'cas_port' => array(
'type' => 'integer',
@@ -409,7 +442,7 @@ class Config
'default' => 443,
'value' => 443,
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'cas_context' => array(
'type' => 'string',
@@ -418,7 +451,7 @@ class Config
'default' => '',
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'cas_server_ca_cert_path' => array(
'type' => 'string',
@@ -427,7 +460,7 @@ class Config
'default' => '',
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'cas_logout_redirect_service' => array(
'type' => 'string',
@@ -436,7 +469,7 @@ class Config
'default' => '',
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'cas_memberof' => array(
'type' => 'string',
@@ -445,7 +478,7 @@ class Config
'default' => '',
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'cas_user_synchro' => array(
'type' => 'bool',
@@ -454,7 +487,7 @@ class Config
'default' => 0,
'value' => 0,
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'cas_update_profiles' => array(
'type' => 'bool',
@@ -463,7 +496,7 @@ class Config
'default' => 0,
'value' => 0,
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'cas_profile_pattern' => array(
'type' => 'string',
@@ -472,7 +505,7 @@ class Config
'default' => '/^cn=([^,]+),/',
'value' => '/^cn=([^,]+),/',
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'cas_default_profiles' => array(
'type' => 'string',
@@ -481,7 +514,7 @@ class Config
'default' => 'Portal user',
'value' => 'Portal user',
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'cas_debug' => array(
'type' => 'bool',
@@ -490,7 +523,7 @@ class Config
'default' => false,
'value' => false,
'source_of_value' => '',
'show_in_conf_sample' => true,
'show_in_conf_sample' => false,
),
'deadline_format' => array(
'type' => 'string',
@@ -519,6 +552,15 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'complex_actions_limit' => array(
'type' => 'integer',
'description' => 'Display the "actions" menu items that require long computation only if the list of objects is contains less objects than this number (0 means no limit)',
// examples... not used
'default' => 50,
'value' => 50,
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'synchro_prevent_delete_all' => array(
'type' => 'bool',
'description' => 'Stop the synchro if all the replicas of a data source become obsolete at the same time.',
@@ -532,7 +574,45 @@ class Config
'type' => 'string',
'description' => 'Source directory for the datamodel files. (which gets compiled to env-production).',
// examples... not used
'default' => 'datamodels/latest',
'default' => '',
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'csv_file_default_charset' => array(
'type' => 'string',
'description' => 'Character set used by default for downloading and uploading data as a CSV file. Warning: it is case sensitive (uppercase is preferable).',
// examples... not used
'default' => 'ISO-8859-1',
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'debug_report_spurious_chars' => array(
'type' => 'bool',
'description' => 'Report, in the error log, the characters found in the output buffer, echoed by mistake in the loaded modules, and potentially corrupting the output',
// examples... not used
'default' => false,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'impact_analysis_first_tab' => array(
'type' => 'string',
'description' => 'Which tab to display first in the impact analysis view: list or graphics. Graphics are nicer but slower to display when there are many objects',
// examples... not used
'default' => 'graphics',
'value' => '',
'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,
@@ -597,7 +677,7 @@ class Config
protected $m_bLogWebService;
protected $m_bLogKPIDuration; // private setting
protected $m_bLogKPIMemory; // private setting
protected $m_bDebugQueries; // private setting
protected $m_bLogQueries; // private setting
protected $m_bQueryCacheEnabled; // private setting
/**
@@ -678,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(
@@ -844,7 +925,7 @@ class Config
$this->m_bLogWebService = isset($MySettings['log_web_service']) ? (bool) trim($MySettings['log_web_service']) : DEFAULT_LOG_WEB_SERVICE;
$this->m_bLogKPIDuration = isset($MySettings['log_kpi_duration']) ? (bool) trim($MySettings['log_kpi_duration']) : DEFAULT_LOG_KPI_DURATION;
$this->m_bLogKPIMemory = isset($MySettings['log_kpi_memory']) ? (bool) trim($MySettings['log_kpi_memory']) : DEFAULT_LOG_KPI_MEMORY;
$this->m_bDebugQueries = isset($MySettings['debug_queries']) ? (bool) trim($MySettings['debug_queries']) : DEFAULT_DEBUG_QUERIES;
$this->m_bLogQueries = isset($MySettings['log_queries']) ? (bool) trim($MySettings['log_queries']) : DEFAULT_LOG_QUERIES;
$this->m_bQueryCacheEnabled = isset($MySettings['query_cache_enabled']) ? (bool) trim($MySettings['query_cache_enabled']) : DEFAULT_QUERY_CACHE_ENABLED;
$this->m_iMinDisplayLimit = isset($MySettings['min_display_limit']) ? trim($MySettings['min_display_limit']) : DEFAULT_MIN_DISPLAY_LIMIT;
@@ -992,9 +1073,9 @@ class Config
return $this->m_bLogKPIMemory;
}
public function GetDebugQueries()
public function GetLogQueries()
{
return $this->m_bDebugQueries;
return $this->m_bLogQueries;
}
public function GetQueryCacheEnabled()
@@ -1278,8 +1359,24 @@ class Config
'value' => $bValue,
);
}
// Old fashioned non boolean values
// Old fashioned integer settings
$aIntValues = array(
'fast_reload_interval' => $this->m_iFastReloadInterval,
'max_display_limit' => $this->m_iMaxDisplayLimit,
'min_display_limit' => $this->m_iMinDisplayLimit,
'standard_reload_interval' => $this->m_iStandardReloadInterval,
);
foreach($aIntValues as $sKey => $iValue)
{
$aConfigSettings[$sKey] = array(
'show_in_conf_sample' => true,
'type' => 'integer',
'value' => $iValue,
);
}
// Old fashioned remaining values
$aOtherValues = array(
'db_host' => $this->m_sDBHost,
'db_user' => $this->m_sDBUser,
@@ -1306,7 +1403,8 @@ class Config
fwrite($hFile, "\$MySettings = array(\n");
foreach($aConfigSettings as $sPropCode => $aSettingInfo)
{
if ($aSettingInfo['show_in_conf_sample'])
// Write all values that are either always visible or present in the cloned config file
if ($aSettingInfo['show_in_conf_sample'] || (!empty($aSettingInfo['source_of_value']) && ($aSettingInfo['source_of_value'] != 'unknown')) )
{
$sType = $aSettingInfo['type'];
switch($sType)
@@ -1420,7 +1518,7 @@ class Config
/**
* Helper function to initialize a configuration from the page arguments
*/
public function UpdateFromParams($aParamValues, $sModulesDir = null)
public function UpdateFromParams($aParamValues, $sModulesDir = null, $bPreserveModuleSettings = false)
{
if (isset($aParamValues['application_path']))
{
@@ -1469,7 +1567,7 @@ class Config
// Merge the values with the ones provided by the modules
// Make sure when don't load the same file twice...
$aModules = ModuleDiscovery::GetAvailableModules(APPROOT, $sModulesDir);
$aModules = ModuleDiscovery::GetAvailableModules(array(APPROOT.$sModulesDir));
foreach($aModules as $sModuleId => $aModuleInfo)
{
list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId);
@@ -1483,16 +1581,19 @@ 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);
foreach($aModuleInfo['settings'] as $sProperty => $value)
{
list($sName, $sVersion) = ModuleDiscovery::GetModuleName($sModuleId);
$this->SetModuleSetting($sName, $sProperty, $value);
if ($bPreserveModuleSettings && isset($this->m_aModuleSettings[$sName][$sProperty]))
{
// Do nothing keep the original value
}
else
{
$this->SetModuleSetting($sName, $sProperty, $value);
}
}
}
if (isset($aModuleInfo['installer']))
@@ -1515,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

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Exception management
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* CSV parser
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* data generator
* helps the consultants in creating dummy data sets, for various test purposes (validation, usability, scalability)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 dbObject: the root of persistent classes
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once('metamodel.class.php');
@@ -331,7 +332,7 @@ abstract class DBObject
}
}
}
else
else if ($this->m_aCurrValues[$sAttCode] != $value)
{
// Setting an external key, but no any other information is available...
// Invalidate the corresponding fields so that they get reloaded in case they are needed (See Get())
@@ -454,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
{
@@ -508,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
*/
@@ -518,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());
@@ -548,7 +558,7 @@ abstract class DBObject
$this->ComputeValues();
}
public function GetAsHTML($sAttCode)
public function GetAsHTML($sAttCode, $bLocalize = true)
{
$sClass = get_class($this);
$oAtt = MetaModel::GetAttributeDef($sClass, $sAttCode);
@@ -571,7 +581,7 @@ abstract class DBObject
}
// That's a standard attribute (might be an ext field or a direct field, etc.)
return $oAtt->GetAsHTML($this->Get($sAttCode), $this);
return $oAtt->GetAsHTML($this->Get($sAttCode), $this, $bLocalize);
}
public function GetEditValue($sAttCode)
@@ -609,34 +619,34 @@ abstract class DBObject
return $sEditValue;
}
public function GetAsXML($sAttCode)
public function GetAsXML($sAttCode, $bLocalize = true)
{
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
return $oAtt->GetAsXML($this->Get($sAttCode), $this);
return $oAtt->GetAsXML($this->Get($sAttCode), $this, $bLocalize);
}
public function GetAsCSV($sAttCode, $sSeparator = ',', $sTextQualifier = '"')
public function GetAsCSV($sAttCode, $sSeparator = ',', $sTextQualifier = '"', $bLocalize = true)
{
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
return $oAtt->GetAsCSV($this->Get($sAttCode), $sSeparator, $sTextQualifier, $this);
return $oAtt->GetAsCSV($this->Get($sAttCode), $sSeparator, $sTextQualifier, $this, $bLocalize);
}
public function GetOriginalAsHTML($sAttCode)
public function GetOriginalAsHTML($sAttCode, $bLocalize = true)
{
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
return $oAtt->GetAsHTML($this->GetOriginal($sAttCode), $this);
return $oAtt->GetAsHTML($this->GetOriginal($sAttCode), $this, $bLocalize);
}
public function GetOriginalAsXML($sAttCode)
public function GetOriginalAsXML($sAttCode, $bLocalize = true)
{
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
return $oAtt->GetAsXML($this->GetOriginal($sAttCode), $this);
return $oAtt->GetAsXML($this->GetOriginal($sAttCode), $this, $bLocalize);
}
public function GetOriginalAsCSV($sAttCode, $sSeparator = ',', $sTextQualifier = '"')
public function GetOriginalAsCSV($sAttCode, $sSeparator = ',', $sTextQualifier = '"', $bLocalize = true)
{
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
return $oAtt->GetAsCSV($this->GetOriginal($sAttCode), $sSeparator, $sTextQualifier, $this);
return $oAtt->GetAsCSV($this->GetOriginal($sAttCode), $sSeparator, $sTextQualifier, $this, $bLocalize);
}
public static function MakeHyperLink($sObjClass, $sObjKey, $sLabel = '', $sUrlMakerClass = null, $bWithNavigationContext = true)
@@ -1424,6 +1434,8 @@ abstract class DBObject
$oTrigger->DoActivate($this->ToArgs('this'));
}
$this->RecordObjCreation();
return $this->m_iKey;
}
@@ -1434,13 +1446,15 @@ abstract class DBObject
return $this->m_iKey;
}
public function DBInsertTracked(CMDBChange $oVoid)
public function DBInsertTracked(CMDBChange $oChange)
{
CMDBObject::SetCurrentChange($oChange);
return $this->DBInsert();
}
public function DBInsertTrackedNoReload(CMDBChange $oVoid)
public function DBInsertTrackedNoReload(CMDBChange $oChange)
{
CMDBObject::SetCurrentChange($oChange);
return $this->DBInsertNoReload();
}
@@ -1450,7 +1464,9 @@ abstract class DBObject
{
$this->m_bIsInDB = false;
$this->m_iKey = $iNewKey;
return $this->DBInsert();
$ret = $this->DBInsert();
$this->RecordObjCreation();
return $ret;
}
/**
@@ -1498,7 +1514,7 @@ abstract class DBObject
$aChanges = $this->ListChanges();
if (count($aChanges) == 0)
{
//throw new CoreWarning("Attempting to update an unchanged object");
// Attempting to update an unchanged object
return;
}
@@ -1510,6 +1526,9 @@ abstract class DBObject
throw new CoreException("Object not following integrity rules", array('issues' => $sIssues, 'class' => get_class($this), 'id' => $this->GetKey()));
}
// Save the original values (will be reset to the new values when the object get written to the DB)
$aOriginalValues = $this->m_aOrigValues;
$bHasANewExternalKeyValue = false;
$aHierarchicalKeys = array();
foreach($aChanges as $sAttCode => $valuecurr)
@@ -1587,12 +1606,31 @@ abstract class DBObject
{
$this->Reload();
}
else
{
// Reset original values although the object has not been reloaded
foreach ($this->m_aLoadedAtt as $sAttCode => $bLoaded)
{
if ($bLoaded)
{
$value = $this->m_aCurrValues[$sAttCode];
$this->m_aOrigValues[$sAttCode] = is_object($value) ? clone $value : $value;
}
}
}
if (count($aChanges) != 0)
{
$this->RecordAttChanges($aChanges, $aOriginalValues);
}
return $this->m_iKey;
}
public function DBUpdateTracked(CMDBChange $oVoid)
public function DBUpdateTracked(CMDBChange $oChange)
{
CMDBObject::SetCurrentChange($oChange);
return $this->DBUpdate();
}
@@ -1624,10 +1662,11 @@ abstract class DBObject
protected function DBDeleteSingleObject()
{
$this->OnDelete();
if (!MetaModel::DBIsReadOnly())
{
$this->OnDelete();
$this->RecordObjDeletion($this->m_iKey); // May cause a reload for storing history information
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode => $oAttDef)
{
if ($oAttDef->IsHierarchicalKey())
@@ -1660,12 +1699,12 @@ abstract class DBObject
{
$this->DBDeleteSingleTable($sParentClass);
}
$this->AfterDelete();
$this->m_bIsInDB = false;
$this->m_iKey = null;
}
$this->AfterDelete();
$this->m_bIsInDB = false;
$this->m_iKey = null;
}
// Delete an object... and guarantee data integrity
@@ -1719,8 +1758,9 @@ abstract class DBObject
return $oDeletionPlan;
}
public function DBDeleteTracked(CMDBChange $oVoid, $bSkipStrongSecurity = null, &$oDeletionPlan = null)
public function DBDeleteTracked(CMDBChange $oChange, $bSkipStrongSecurity = null, &$oDeletionPlan = null)
{
CMDBObject::SetCurrentChange($oChange);
$this->DBDelete($oDeletionPlan);
}
@@ -1737,7 +1777,7 @@ abstract class DBObject
* Designed as an action to be called when a stop watch threshold times out
* or from within the framework
*/
public function ApplyStimulus($sStimulusCode)
public function ApplyStimulus($sStimulusCode, $bDoNotWrite = false)
{
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
if (empty($sStateAttCode)) return false;
@@ -1745,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
@@ -1773,20 +1818,7 @@ abstract class DBObject
}
if ($bSuccess)
{
// Change state triggers...
$sClass = get_class($this);
$sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateLeave AS t WHERE t.target_class IN ('$sClassList') AND t.state='$sPreviousState'"));
while ($oTrigger = $oSet->Fetch())
{
$oTrigger->DoActivate($this->ToArgs('this'));
}
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateEnter AS t WHERE t.target_class IN ('$sClassList') AND t.state='$sNewState'"));
while ($oTrigger = $oSet->Fetch())
{
$oTrigger->DoActivate($this->ToArgs('this'));
}
// Stop watches
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
@@ -1805,6 +1837,25 @@ abstract class DBObject
$this->Set($sAttCode, $oSW);
}
}
if (!$bDoNotWrite)
{
$this->DBWrite();
}
// Change state triggers...
$sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateLeave AS t WHERE t.target_class IN ('$sClassList') AND t.state='$sPreviousState'"));
while ($oTrigger = $oSet->Fetch())
{
$oTrigger->DoActivate($this->ToArgs('this'));
}
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateEnter AS t WHERE t.target_class IN ('$sClassList') AND t.state='$sNewState'"));
while ($oTrigger = $oSet->Fetch())
{
$oTrigger->DoActivate($this->ToArgs('this'));
}
}
return $bSuccess;
@@ -1899,6 +1950,152 @@ abstract class DBObject
{
}
/**
* Common to the recording of link set changes (add/remove/modify)
*/
private function PrepareChangeOpLinkSet($iLinkSetOwnerId, $oLinkSet, $sChangeOpClass, $aOriginalValues = null)
{
if ($iLinkSetOwnerId <= 0)
{
return null;
}
if (!is_subclass_of($oLinkSet->GetHostClass(), 'CMDBObject'))
{
// The link set owner class does not keep track of its history
return null;
}
// Determine the linked item class and id
//
if ($oLinkSet->IsIndirect())
{
// The "item" is on the other end (N-N links)
$sExtKeyToRemote = $oLinkSet->GetExtKeyToRemote();
$oExtKeyToRemote = MetaModel::GetAttributeDef(get_class($this), $sExtKeyToRemote);
$sItemClass = $oExtKeyToRemote->GetTargetClass();
if ($aOriginalValues)
{
// Get the value from the original values
$iItemId = $aOriginalValues[$sExtKeyToRemote];
}
else
{
$iItemId = $this->Get($sExtKeyToRemote);
}
}
else
{
// I am the "item" (1-N links)
$sItemClass = get_class($this);
$iItemId = $this->GetKey();
}
// Get the remote object, to determine its exact class
// Possible optimization: implement a tool in MetaModel, to get the final class of an object (not always querying + query reduced to a select on the root table!
$oOwner = MetaModel::GetObject($oLinkSet->GetHostClass(), $iLinkSetOwnerId, false);
if ($oOwner)
{
$sLinkSetOwnerClass = get_class($oOwner);
$oMyChangeOp = MetaModel::NewObject($sChangeOpClass);
$oMyChangeOp->Set("objclass", $sLinkSetOwnerClass);
$oMyChangeOp->Set("objkey", $iLinkSetOwnerId);
$oMyChangeOp->Set("attcode", $oLinkSet->GetCode());
$oMyChangeOp->Set("item_class", $sItemClass);
$oMyChangeOp->Set("item_id", $iItemId);
return $oMyChangeOp;
}
else
{
// Depending on the deletion order, it may happen that the id is already invalid... ignore
return null;
}
}
/**
* This object has been created/deleted, record that as a change in link sets pointing to this (if any)
*/
private function RecordLinkSetListChange($bAdd = true)
{
$aForwardChangeTracking = MetaModel::GetTrackForwardExternalKeys(get_class($this));
foreach(MetaModel::GetTrackForwardExternalKeys(get_class($this)) as $sExtKeyAttCode => $oLinkSet)
{
if (($oLinkSet->GetTrackingLevel() & LINKSET_TRACKING_LIST) == 0) continue;
$iLinkSetOwnerId = $this->Get($sExtKeyAttCode);
$oMyChangeOp = $this->PrepareChangeOpLinkSet($iLinkSetOwnerId, $oLinkSet, 'CMDBChangeOpSetAttributeLinksAddRemove');
if ($oMyChangeOp)
{
if ($bAdd)
{
$oMyChangeOp->Set("type", "added");
}
else
{
$oMyChangeOp->Set("type", "removed");
}
$iId = $oMyChangeOp->DBInsertNoReload();
}
}
}
protected function RecordObjCreation()
{
$this->RecordLinkSetListChange(true);
}
protected function RecordObjDeletion($objkey)
{
$this->RecordLinkSetListChange(false);
}
protected function RecordAttChanges(array $aValues, array $aOrigValues)
{
$aForwardChangeTracking = MetaModel::GetTrackForwardExternalKeys(get_class($this));
foreach(MetaModel::GetTrackForwardExternalKeys(get_class($this)) as $sExtKeyAttCode => $oLinkSet)
{
if (array_key_exists($sExtKeyAttCode, $aValues))
{
if (($oLinkSet->GetTrackingLevel() & LINKSET_TRACKING_LIST) == 0) continue;
// Keep track of link added/removed
//
$iLinkSetOwnerNext = $aValues[$sExtKeyAttCode];
$oMyChangeOp = $this->PrepareChangeOpLinkSet($iLinkSetOwnerNext, $oLinkSet, 'CMDBChangeOpSetAttributeLinksAddRemove');
if ($oMyChangeOp)
{
$oMyChangeOp->Set("type", "added");
$oMyChangeOp->DBInsertNoReload();
}
$iLinkSetOwnerPrevious = $aOrigValues[$sExtKeyAttCode];
$oMyChangeOp = $this->PrepareChangeOpLinkSet($iLinkSetOwnerPrevious, $oLinkSet, 'CMDBChangeOpSetAttributeLinksAddRemove', $aOrigValues);
if ($oMyChangeOp)
{
$oMyChangeOp->Set("type", "removed");
$oMyChangeOp->DBInsertNoReload();
}
}
else
{
// Keep track of link changes
//
if (($oLinkSet->GetTrackingLevel() & LINKSET_TRACKING_DETAILS) == 0) continue;
$iLinkSetOwnerId = $this->Get($sExtKeyAttCode);
$oMyChangeOp = $this->PrepareChangeOpLinkSet($iLinkSetOwnerId, $oLinkSet, 'CMDBChangeOpSetAttributeLinksTune');
if ($oMyChangeOp)
{
$oMyChangeOp->Set("link_id", $this->GetKey());
$iId = $oMyChangeOp->DBInsertNoReload();
}
}
}
}
// Return an empty set for the parent of all
public static function GetRelationQueries($sRelCode)
{
@@ -2103,7 +2300,7 @@ abstract class DBObject
}
// to be continued...
}
}
?>

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Define filters for a given class of objects (formerly named "filter")
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
define('TREE_OPERATOR_EQUALS', 0);
@@ -70,6 +71,14 @@ class DBObjectSearch
$this->m_aModifierProperties = array();
}
/**
* Perform a deep clone (as opposed to "clone" which does copy a reference to the underlying objects
**/
public function DeepClone()
{
return unserialize(serialize($this));
}
public function AllowAllData() {$this->m_bAllowAllData = true;}
public function IsAllDataAllowed() {return $this->m_bAllowAllData;}
public function IsDataFiltered() {return $this->m_bDataFiltered; }
@@ -109,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();
@@ -339,7 +402,7 @@ class DBObjectSearch
{
foreach($aPointingTo as $iOperatorCode => $aFilter)
{
foreach($aFilter as $sAlias => $oExtFilter)
foreach($aFilter as $oExtFilter)
{
$oExtFilter->RenameParam($sOldName, $sNewName);
}
@@ -474,7 +537,7 @@ class DBObjectSearch
* Specify a condition on external keys or link sets
* @param sAttSpec Can be either an attribute code or extkey->[sAttSpec] or linkset->[sAttSpec] and so on, recursively
* Example: infra_list->ci_id->location_id->country
* @param value The value to match
* @param value The value to match (can be an array => IN(val1, val2...)
* @return void
*/
public function AddConditionAdvanced($sAttSpec, $value)
@@ -521,7 +584,18 @@ class DBObjectSearch
{
// $sAttSpec is an attribute code
//
$this->AddCondition($sAttSpec, $value);
if (is_array($value))
{
$oField = new FieldExpression($sAttSpec, $this->GetClass());
$oListExpr = ListExpression::FromScalars($value);
$oInValues = new BinaryExpression($oField, 'IN', $oListExpr);
$this->AddConditionExpression($oInValues);
}
else
{
$this->AddCondition($sAttSpec, $value);
}
}
}
@@ -586,7 +660,7 @@ class DBObjectSearch
{
foreach($aPointingTo as $iOperatorCode => $aFilter)
{
foreach($aFilter as $sAlias => $oFilter)
foreach($aFilter as $oFilter)
{
$oFilter->AddToNameSpace($aClassAliases, $aAliasTranslation);
}
@@ -602,8 +676,56 @@ class DBObjectSearch
}
}
// Browse the tree nodes recursively
//
protected function GetNode($sAlias)
{
if ($this->GetFirstJoinedClassAlias() == $sAlias)
{
return $this;
}
else
{
foreach($this->m_aPointingTo as $sExtKeyAttCode=>$aPointingTo)
{
foreach($aPointingTo as $iOperatorCode => $aFilter)
{
foreach($aFilter as $oFilter)
{
$ret = $oFilter->GetNode($sAlias);
if (is_object($ret))
{
return $ret;
}
}
}
}
foreach($this->m_aReferencedBy as $sForeignClass=>$aReferences)
{
foreach($aReferences as $sForeignExtKeyAttCode=>$oForeignFilter)
{
$ret = $oForeignFilter->GetNode($sAlias);
if (is_object($ret))
{
return $ret;
}
}
}
}
// Not found
return null;
}
public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS)
{
// Note: though it seems to be a good practice to clone the given source filter
// (as it was done and fixed an issue in MergeWith())
// this was not implemented here because it was causing a regression (login as admin, select an org, click on any badge)
// root cause: FromOQL relies on the fact that the passed filter can be modified later
// NO: $oFilter = $oFilter->DeepClone();
// See also: Trac #639, and self::AddCondition_ReferencedBy()
$aAliasTranslation = array();
$res = $this->AddCondition_PointingTo_InNameSpace($oFilter, $sExtKeyAttCode, $this->m_aClasses, $aAliasTranslation, $iOperatorCode);
$this->TransferConditionExpression($oFilter, $aAliasTranslation);
@@ -626,33 +748,21 @@ class DBObjectSearch
throw new CoreException("The specified tree operator $iOperatorCode is not applicable to the key '{$this->GetClass()}::$sExtKeyAttCode', which is not a HierarchicalKey");
}
$bSamePointingTo = false;
if (array_key_exists($sExtKeyAttCode, $this->m_aPointingTo))
{
if (array_key_exists($iOperatorCode, $this->m_aPointingTo[$sExtKeyAttCode]))
{
if (array_key_exists($oFilter->GetClassAlias(), $this->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode]))
{
$bSamePointingTo = true;
}
}
}
// Find the node on which the new tree must be attached (most of the time it is "this")
$oReceivingFilter = $this->GetNode($this->GetClassAlias());
if ($bSamePointingTo)
{
// Same ext key, alias and same operator, merge the filters together
$oFilter->AddToNamespace($aClassAliases, $aAliasTranslation, true /* Don't translate the main alias */);
$this->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode][$oFilter->GetClassAlias()] = $oFilter;
}
else
{
$oFilter->AddToNamespace($aClassAliases, $aAliasTranslation);
$this->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode][$oFilter->GetClassAlias()] = $oFilter;
}
$oFilter->AddToNamespace($aClassAliases, $aAliasTranslation);
$oReceivingFilter->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode][] = $oFilter;
}
public function AddCondition_ReferencedBy(DBObjectSearch $oFilter, $sForeignExtKeyAttCode)
{
// Note: though it seems to be a good practice to clone the given source filter
// (as it was done and fixed an issue in MergeWith())
// this was not implemented here because it was causing a regression (login as admin, select an org, click on any badge)
// root cause: FromOQL relies on the fact that the passed filter can be modified later
// NO: $oFilter = $oFilter->DeepClone();
// See also: Trac #639, and self::AddCondition_PointingTo()
$aAliasTranslation = array();
$res = $this->AddCondition_ReferencedBy_InNameSpace($oFilter, $sForeignExtKeyAttCode, $this->m_aClasses, $aAliasTranslation);
$this->TransferConditionExpression($oFilter, $aAliasTranslation);
@@ -672,31 +782,26 @@ class DBObjectSearch
{
throw new CoreException("The specified filter (objects referencing an object of class {$this->GetClass()}) is not compatible with the key '{$sForeignClass}::$sForeignExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}");
}
// Find the node on which the new tree must be attached (most of the time it is "this")
$oReceivingFilter = $this->GetNode($this->GetClassAlias());
if (array_key_exists($sForeignClass, $this->m_aReferencedBy) && array_key_exists($sForeignExtKeyAttCode, $this->m_aReferencedBy[$sForeignClass]))
{
$this->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode]->MergeWith_InNamespace($oFilter, $aClassAliases, $aAliasTranslation);
$oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode]->MergeWith_InNamespace($oFilter, $aClassAliases, $aAliasTranslation);
}
else
{
$oFilter->AddToNamespace($aClassAliases, $aAliasTranslation);
// #@# The condition expression found in that filter should not be used - could be another kind of structure like a join spec tree !!!!
//$oNewFilter = clone $oFilter;
//$oNewFilter = $oFilter->DeepClone();
//$oNewFilter->ResetCondition();
$this->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode]= $oFilter;
$oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode]= $oFilter;
}
}
public function AddCondition_LinkedTo(DBObjectSearch $oLinkFilter, $sExtKeyAttCodeToMe, $sExtKeyAttCodeTarget, DBObjectSearch $oFilterTarget)
{
$oLinkFilterFinal = clone $oLinkFilter;
// todo : new function prototype
$oLinkFilterFinal->AddCondition_PointingTo($sExtKeyAttCodeToMe);
$this->AddCondition_ReferencedBy($oLinkFilterFinal, $sExtKeyAttCodeToMe);
}
public function AddCondition_RelatedTo(DBObjectSearch $oFilter, $sRelCode, $iMaxDepth)
{
MyHelpers::CheckValueInArray('relation code', $sRelCode, MetaModel::EnumRelations());
@@ -705,6 +810,7 @@ class DBObjectSearch
public function MergeWith($oFilter)
{
$oFilter = $oFilter->DeepClone();
$aAliasTranslation = array();
$res = $this->MergeWith_InNamespace($oFilter, $this->m_aClasses, $aAliasTranslation);
$this->TransferConditionExpression($oFilter, $aAliasTranslation);
@@ -728,7 +834,7 @@ class DBObjectSearch
{
foreach($aPointingTo as $iOperatorCode => $aFilter)
{
foreach($aFilter as $sAlias => $oExtFilter)
foreach($aFilter as $oExtFilter)
{
$this->AddCondition_PointingTo_InNamespace($oExtFilter, $sExtKeyAttCode, $aClassAliases, $aAliasTranslation, $iOperatorCode);
}
@@ -951,7 +1057,7 @@ class DBObjectSearch
{
foreach($aPointingTo as $iOperatorCode => $aFilter)
{
foreach($aFilter as $sAlias => $oFilter)
foreach($aFilter as $oFilter)
{
switch($iOperatorCode)
{
@@ -1126,7 +1232,12 @@ class DBObjectSearch
if ($bOQLCacheEnabled && array_key_exists($sQuery, self::$m_aOQLQueries))
{
// hit!
return clone self::$m_aOQLQueries[$sQuery];
$oClone = self::$m_aOQLQueries[$sQuery]->DeepClone();
if (!is_null($aParams))
{
$oClone->m_aParams = $aParams;
}
return $oClone;
}
$oOql = new OqlInterpreter($sQuery);
@@ -1271,7 +1382,7 @@ class DBObjectSearch
if ($bOQLCacheEnabled)
{
self::$m_aOQLQueries[$sQuery] = clone $oResultFilter;
self::$m_aOQLQueries[$sQuery] = $oResultFilter->DeepClone();
}
return $oResultFilter;
@@ -1288,4 +1399,4 @@ class DBObjectSearch
}
?>
?>

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Object set management
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -41,7 +42,7 @@ class DBObjectSet
public function __construct(DBObjectSearch $oFilter, $aOrderBy = array(), $aArgs = array(), $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0)
{
$this->m_oFilter = $oFilter;
$this->m_oFilter = $oFilter->DeepClone();
$this->m_aAddedIds = array();
$this->m_aOrderBy = $aOrderBy;
$this->m_aArgs = $aArgs;
@@ -269,14 +270,18 @@ class DBObjectSet
public function GetFilter()
{
// Make sure that we carry on the parameters of the set with the filter
$oFilter = $this->m_oFilter->DeepClone();
// 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)
{
return $this->m_oFilter;
return $oFilter;
}
else
{
$oFilter = clone $this->m_oFilter;
$oIdListExpr = ListExpression::FromScalars(array_keys($this->m_aAddedIds));
$oIdExpr = new FieldExpression('id', $oFilter->GetClassAlias());
$oIdInList = new BinaryExpression($oIdExpr, 'IN', $oIdListExpr);

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Database properties - manage database instances in a complex installation
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 dbObject: the root of persistent classes
* Algorithm to delete object(s) and maintain data integrity
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class DeleteException extends CoreException
@@ -81,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

@@ -1,27 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 Dict
* Management of localizable strings
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class DictException extends CoreException
@@ -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

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Send an email (abstraction for synchronous/asynchronous modes)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'/lib/swiftmailer/lib/swift_required.php');
@@ -32,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)
{
@@ -45,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
@@ -101,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
@@ -135,27 +219,17 @@ 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();
switch(strtolower($sKey))
{
case 'from':
case 'cc':
case 'bcc':
$aMatches = array();
// Header may be in the form: John Doe <jd@company.com>
if (preg_match('/^([^<]+) <([^>]+)>$/', $sValue, $aMatches))
{
$aHeader = array($aMatches[2] => $aMatches[1]);
}
else
{
$aHeader = array($sValue);
}
$oHeaders->addMailboxHeader($sKey, $aHeader);
break;
default:
$oHeaders->addTextHeader($sKey, $sValue);
}
@@ -164,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);
@@ -179,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()
@@ -202,9 +290,32 @@ 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_oMessage->setTo($sAddress);
$this->m_aData['to'] = $sAddress;
if (!empty($sAddress))
{
$aAddresses = $this->AddressStringToArray($sAddress);
$this->m_oMessage->setTo($aAddresses);
}
}
public function GetRecipientTO($bAsString = false)
@@ -235,21 +346,32 @@ class EMail
public function SetRecipientCC($sAddress)
{
$this->AddToHeader('Cc', $sAddress);
$this->m_aData['cc'] = $sAddress;
if (!empty($sAddress))
{
$aAddresses = $this->AddressStringToArray($sAddress);
$this->m_oMessage->setCc($aAddresses);
}
}
public function SetRecipientBCC($sAddress)
{
$this->AddToHeader('Bcc', $sAddress);
$this->m_aData['bcc'] = $sAddress;
if (!empty($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));
}
else
else if (!empty($sAddress))
{
$this->m_oMessage->setFrom($sAddress);
}
@@ -257,7 +379,11 @@ class EMail
public function SetRecipientReplyTo($sAddress)
{
$this->AddToHeader('Reply-To', $sAddress);
$this->m_aData['reply_to'] = $sAddress;
if (!empty($sAddress))
{
$this->m_oMessage->setReplyTo($sAddress);
}
}
}

View File

@@ -1,28 +1,29 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Persistent class Event and derived
* Application internal events
* There is also a file log
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class Event extends DBObject implements iDisplay
@@ -40,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();
@@ -105,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);
@@ -116,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();
}
}
@@ -134,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();
@@ -166,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();
@@ -175,10 +180,11 @@ class EventNotificationEmail extends EventNotification
MetaModel::Init_AddAttribute(new AttributeText("from", array("allowed_values"=>null, "sql"=>"from", "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"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeHTML("body", array("allowed_values"=>null, "sql"=>"body", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeTable("attachments", array("allowed_values"=>null, "sql"=>"attachments", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'message', 'trigger_id', 'action_id', 'object_id', 'to', 'cc', 'bcc', 'from', 'subject', 'body')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'message', 'to', 'subject')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'message', 'trigger_id', 'action_id', 'object_id', 'to', 'cc', 'bcc', 'from', 'subject', 'body', 'attachments')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'message', 'to', 'subject', 'attachments')); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
@@ -202,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();
@@ -301,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();
@@ -335,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

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* General definition of an expression tree (could be OQL, SQL or whatever)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class MissingQueryArgument extends CoreException
@@ -41,6 +42,9 @@ abstract class Expression
// recursively builds an array of class => fieldname
abstract public function ListRequiredFields();
// recursively list field parents ($aTable = array of sParent => dummy)
abstract public function CollectUsedParents(&$aTable);
abstract public function IsTrue();
// recursively builds an array of [classAlias][fieldName] => value
@@ -143,6 +147,10 @@ class SQLExpression extends Expression
{
return array();
}
public function CollectUsedParents(&$aTable)
{
}
public function ListConstantFields()
{
@@ -259,7 +267,12 @@ class BinaryExpression extends Expression
$aRight = $this->GetRightExpr()->ListRequiredFields();
return array_merge($aLeft, $aRight);
}
public function CollectUsedParents(&$aTable)
{
$this->GetLeftExpr()->CollectUsedParents($aTable);
$this->GetRightExpr()->CollectUsedParents($aTable);
}
/**
* List all constant expression of the form <field> = <scalar> or <field> = :<variable>
@@ -350,6 +363,10 @@ class UnaryExpression extends Expression
return array();
}
public function CollectUsedParents(&$aTable)
{
}
public function ListConstantFields()
{
return array();
@@ -366,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)));
}
@@ -451,6 +468,11 @@ class FieldExpression extends UnaryExpression
return array($this->m_sParent.'.'.$this->m_sName);
}
public function CollectUsedParents(&$aTable)
{
$aTable[$this->m_sParent] = true;
}
public function GetUnresolvedFields($sAlias, &$aUnresolved)
{
if ($this->m_sParent == $sAlias)
@@ -596,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)));
}
}
@@ -710,6 +732,14 @@ class ListExpression extends Expression
return $aRes;
}
public function CollectUsedParents(&$aTable)
{
foreach ($this->m_aExpressions as $oExpr)
{
$oExpr->CollectUsedParents($aTable);
}
}
public function ListConstantFields()
{
$aRes = array();
@@ -813,6 +843,14 @@ class FunctionExpression extends Expression
return $aRes;
}
public function CollectUsedParents(&$aTable)
{
foreach ($this->m_aArgs as $oExpr)
{
$oExpr->CollectUsedParents($aTable);
}
}
public function ListConstantFields()
{
$aRes = array();
@@ -841,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;
}
@@ -931,6 +1001,10 @@ class IntervalExpression extends Expression
return array();
}
public function CollectUsedParents(&$aTable)
{
}
public function ListConstantFields()
{
return array();
@@ -1019,6 +1093,14 @@ class CharConcatExpression extends Expression
return $aRes;
}
public function CollectUsedParents(&$aTable)
{
foreach ($this->m_aExpressions as $oExpr)
{
$oExpr->CollectUsedParents($aTable);
}
}
public function ListConstantFields()
{
$aRes = array();
@@ -1071,13 +1153,20 @@ class QueryBuilderExpressions
protected $m_aSelectExpr;
protected $m_aGroupByExpr;
protected $m_aJoinFields;
protected $m_aClassIds;
public function __construct($oCondition, $aGroupByExpr = null)
public function __construct($oSearch, $aGroupByExpr = null)
{
$this->m_oConditionExpr = $oCondition;
$this->m_oConditionExpr = $oSearch->GetCriteria();
$this->m_aSelectExpr = array();
$this->m_aGroupByExpr = $aGroupByExpr;
$this->m_aJoinFields = array();
$this->m_aClassIds = array();
foreach($oSearch->GetJoinedClasses() as $sClassAlias => $sClass)
{
$this->m_aClassIds[$sClassAlias] = new FieldExpression('id', $sClassAlias);
}
}
public function GetSelect()
@@ -1116,6 +1205,20 @@ class QueryBuilderExpressions
array_push($this->m_aJoinFields, $oExpression);
}
/**
* Get tables representing the queried objects
* Could be further optimized: when the first join is an outer join, then the rest can be omitted
*/
public function GetMandatoryTables(&$aTables = null)
{
if (is_null($aTables)) $aTables = array();
foreach($this->m_aClassIds as $sClass => $oExpression)
{
$oExpression->CollectUsedParents($aTables);
}
}
public function GetUnresolvedFields($sAlias, &$aUnresolved)
{
$this->m_oConditionExpr->GetUnresolvedFields($sAlias, $aUnresolved);
@@ -1154,6 +1257,11 @@ class QueryBuilderExpressions
{
$this->m_aJoinFields[$index] = $oExpression->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
}
foreach($this->m_aClassIds as $sClass => $oExpression)
{
$this->m_aClassIds[$sClass] = $oExpression->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
}
}
public function RenameParam($sOldName, $sNewName)

View File

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Definition of a filter
* Most of the time, a filter corresponds to an attribute, but we could imagine other search criteria
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Measures operations duration, memory usage, etc. (and some other KPIs)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class ExecutionKPI

View File

@@ -1,26 +1,26 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* File logging
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class FileLog

View File

@@ -1,18 +1,20 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
require_once(APPROOT.'core/modulehandler.class.inc.php');
require_once(APPROOT.'core/querybuildercontext.class.inc.php');
@@ -23,10 +25,8 @@ require_once(APPROOT.'core/computing.inc.php');
/**
* Metamodel
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
// #@# todo: change into class const (see Doctrine)
@@ -240,6 +240,8 @@ abstract class MetaModel
private static $m_bQueryCacheEnabled = false;
private static $m_bTraceQueries = false;
private static $m_bIndentQueries = false;
private static $m_bOptimizeQueries = false;
private static $m_aQueriesLog = array();
private static $m_bLogIssue = false;
@@ -879,11 +881,73 @@ abstract class MetaModel
}
}
public static function GetLabel($sClass, $sAttCode)
protected static $m_aTrackForwardCache = array();
/**
* List external keys for which there is a LinkSet (direct or indirect) on the other end
* For those external keys, a change will have a special meaning on the other end
* in term of change tracking
*/
final static public function GetTrackForwardExternalKeys($sClass)
{
$oAttDef = self::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef) return $oAttDef->GetLabel();
return "";
if (!isset(self::$m_aTrackForwardCache[$sClass]))
{
$aRes = array();
foreach (MetaModel::GetExternalKeys($sClass) as $sAttCode => $oAttDef)
{
$sRemoteClass = $oAttDef->GetTargetClass();
foreach (MetaModel::ListAttributeDefs($sRemoteClass) as $sRemoteAttCode => $oRemoteAttDef)
{
if (!$oRemoteAttDef->IsLinkSet()) continue;
if (!is_subclass_of($sClass, $oRemoteAttDef->GetLinkedClass()) && $oRemoteAttDef->GetLinkedClass() != $sClass) continue;
if ($oRemoteAttDef->GetExtKeyToMe() != $sAttCode) continue;
$aRes[$sAttCode] = $oRemoteAttDef;
}
}
self::$m_aTrackForwardCache[$sClass] = $aRes;
}
return self::$m_aTrackForwardCache[$sClass];
}
/**
* Get the attribute label
* @param string sClass Persistent class
* @param string sAttCodeEx Extended attribute code: attcode[->attcode]
* @return string A user friendly format of the string: AttributeName or AttributeName->ExtAttributeName
*/
public static function GetLabel($sClass, $sAttCodeEx)
{
$sLabel = '';
if (preg_match('/(.+)->(.+)/', $sAttCodeEx, $aMatches) > 0)
{
$sAttribute = $aMatches[1];
$sField = $aMatches[2];
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttribute);
if ($oAttDef->IsExternalKey())
{
$sTargetClass = $oAttDef->GetTargetClass();
$oTargetAttDef = MetaModel::GetAttributeDef($sTargetClass, $sField);
$sLabel = $oAttDef->GetLabel().'->'.$oTargetAttDef->GetLabel();
}
else
{
// Let's return something displayable... but this should never happen!
$sLabel = $oAttDef->GetLabel().'->'.$aMatches[2];
}
}
else
{
if ($sAttCodeEx == 'id')
{
$sLabel = Dict::S('UI:CSVImport:idField');
}
else
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCodeEx);
$sLabel = $oAttDef->GetLabel();
}
}
return $sLabel;
}
public static function GetDescription($sClass, $sAttCode)
@@ -1176,7 +1240,10 @@ abstract class MetaModel
foreach($aStates[$sState] as $sPrevState)
{
$iPrevFlags = self::GetAttributeFlags($sClass, $sPrevState, $sAttCode);
$bReadOnly = $bReadOnly && (($iPrevFlags & OPT_ATT_READONLY) == OPT_ATT_READONLY); // if it is/was not readonly => then it's not
if (($iPrevFlags & OPT_ATT_HIDDEN) != OPT_ATT_HIDDEN)
{
$bReadOnly = $bReadOnly && (($iPrevFlags & OPT_ATT_READONLY) == OPT_ATT_READONLY); // if it is/was not readonly => then it's not
}
$bHidden = $bHidden && (($iPrevFlags & OPT_ATT_HIDDEN) == OPT_ATT_HIDDEN); // if it is/was not hidden => then it's not
}
if ($bReadOnly)
@@ -1261,7 +1328,7 @@ abstract class MetaModel
// Build the list of available extensions
//
$aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension');
$aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension');
foreach($aInterfaces as $sInterface)
{
self::$m_aExtensionClasses[$sInterface] = array();
@@ -1286,7 +1353,8 @@ abstract class MetaModel
// Initialize the classes (declared attributes, etc.)
//
foreach(get_declared_classes() as $sPHPClass) {
foreach(get_declared_classes() as $sPHPClass)
{
if (is_subclass_of($sPHPClass, 'DBObject'))
{
$sParent = get_parent_class($sPHPClass);
@@ -1295,14 +1363,22 @@ abstract class MetaModel
// Inherit info about attributes to ignore
self::$m_aIgnoredAttributes[$sPHPClass] = self::$m_aIgnoredAttributes[$sParent];
}
if (method_exists($sPHPClass, 'Init'))
try
{
call_user_func(array($sPHPClass, 'Init'));
foreach (MetaModel::EnumPlugins('iOnClassInitialization') as $sPluginClass => $oClassInit)
$oMethod = new ReflectionMethod($sPHPClass, 'Init');
if ($oMethod->getDeclaringClass()->name == $sPHPClass)
{
$oClassInit->OnAfterClassInitialization($sPHPClass);
call_user_func(array($sPHPClass, 'Init'));
foreach (MetaModel::EnumPlugins('iOnClassInitialization') as $sPluginClass => $oClassInit)
{
$oClassInit->OnAfterClassInitialization($sPHPClass);
}
}
}
catch (ReflectionException $e)
{
// This class is only implementing methods, ignore it from the MetaModel perspective
}
}
}
@@ -1891,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)
@@ -1929,7 +2020,8 @@ abstract class MetaModel
{
self::_check_subclass($sClass);
$aSubClasses = array();
foreach(get_declared_classes() as $sSubClass) {
foreach(self::$m_aClassParams as $sSubClass => $foo)
{
if (is_subclass_of($sSubClass, $sClass))
{
$aSubClasses[] = $sSubClass;
@@ -1999,15 +2091,33 @@ 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
{
$sRes = $oSelect->RenderGroupBy($aScalarArgs);
$bBeautifulSQL = self::$m_bTraceQueries || self::$m_bDebugQuery || self::$m_bIndentQueries;
$sRes = $oSelect->RenderGroupBy($aScalarArgs, $bBeautifulSQL);
}
catch (MissingQueryArgument $e)
{
@@ -2015,6 +2125,7 @@ abstract class MetaModel
$e->addInfo('OQL', $oFilter->ToOQL());
throw $e;
}
self::AddQueryTraceGroupBy($oFilter, $aArgs, $aGroupByExpr, $sRes);
return $sRes;
}
@@ -2024,36 +2135,37 @@ abstract class MetaModel
// Check the order by specification, and prefix with the class alias
// and make sure that the ordering columns are going to be selected
//
$sClass = $oFilter->GetClass();
$sClassAlias = $oFilter->GetClassAlias();
$aOrderSpec = array();
foreach ($aOrderBy as $sFieldAlias => $bAscending)
{
if ($sFieldAlias != 'id')
{
MyHelpers::CheckValueInArray('field name in ORDER BY spec', $sFieldAlias, self::GetAttributesList($oFilter->GetFirstJoinedClass()));
MyHelpers::CheckValueInArray('field name in ORDER BY spec', $sFieldAlias, self::GetAttributesList($sClass));
}
if (!is_bool($bAscending))
{
throw new CoreException("Wrong direction in ORDER BY spec, found '$bAscending' and expecting a boolean value");
}
$sFirstClassAlias = $oFilter->GetClassAlias();
if (self::IsValidAttCode($oFilter->GetClass(), $sFieldAlias))
if (self::IsValidAttCode($sClass, $sFieldAlias))
{
$oAttDef = self::GetAttributeDef($oFilter->GetClass(), $sFieldAlias);
foreach($oAttDef->GetOrderBySQLExpressions($sFirstClassAlias) as $sSQLExpression)
$oAttDef = self::GetAttributeDef($sClass, $sFieldAlias);
foreach($oAttDef->GetOrderBySQLExpressions($sClassAlias) as $sSQLExpression)
{
$aOrderSpec[$sSQLExpression] = $bAscending;
}
}
else
{
$aOrderSpec['`'.$sFirstClassAlias.$sFieldAlias.'`'] = $bAscending;
$aOrderSpec['`'.$sClassAlias.$sFieldAlias.'`'] = $bAscending;
}
// Make sure that the columns used for sorting are present in the loaded columns
if (!is_null($aAttToLoad) && !isset($aAttToLoad[$sFirstClassAlias][$sFieldAlias]))
if (!is_null($aAttToLoad) && !isset($aAttToLoad[$sClassAlias][$sFieldAlias]))
{
$aAttToLoad[$sFirstClassAlias][$sFieldAlias] = MetaModel::GetAttributeDef($oFilter->GetFirstJoinedClass(), $sFieldAlias);
$aAttToLoad[$sClassAlias][$sFieldAlias] = MetaModel::GetAttributeDef($sClass, $sFieldAlias);
}
}
@@ -2062,8 +2174,9 @@ abstract class MetaModel
$aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams());
try
{
$sRes = $oSelect->RenderSelect($aOrderSpec, $aScalarArgs, $iLimitCount, $iLimitStart, $bGetCount);
if ($oFilter->GetClassAlias() == 'itop')
$bBeautifulSQL = self::$m_bTraceQueries || self::$m_bDebugQuery || self::$m_bIndentQueries;
$sRes = $oSelect->RenderSelect($aOrderSpec, $aScalarArgs, $iLimitCount, $iLimitStart, $bGetCount, $bBeautifulSQL);
if ($sClassAlias == '_itop_')
{
echo $sRes."<br/>\n";
}
@@ -2071,9 +2184,10 @@ abstract class MetaModel
catch (MissingQueryArgument $e)
{
// Add some information...
$e->addInfo('OQL', $sOqlQuery);
$e->addInfo('OQL', $oFilter->ToOQL());
throw $e;
}
self::AddQueryTraceSelect($oFilter, $aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $sRes);
return $sRes;
}
@@ -2106,6 +2220,8 @@ abstract class MetaModel
//
$aModifierProperties = self::MakeModifierProperties($oFilter);
// Create a unique cache id
//
if (self::$m_bQueryCacheEnabled || self::$m_bTraceQueries)
{
// Need to identify the query
@@ -2124,18 +2240,16 @@ abstract class MetaModel
$sRawId = $sOqlQuery.$sModifierProperties;
if (!is_null($aAttToLoad))
{
foreach($aAttToLoad as $sAlias => $aAttributes)
{
$sRawId = $sOqlQuery.'|'.implode(',', array_keys($aAttributes));
}
$sRawId .= json_encode($aAttToLoad);
}
if (!is_null($aGroupByExpr))
{
foreach($aGroupByExpr as $sAlias => $oExpr)
{
$sRawId = 'g:'.$sAlias.'!'.$oExpr->Render();
$sRawId .= 'g:'.$sAlias.'!'.$oExpr->Render();
}
}
$sRawId .= $bGetCount;
$sOqlId = md5($sRawId);
}
else
@@ -2162,7 +2276,8 @@ abstract class MetaModel
if (array_key_exists($sOqlId, self::$m_aQueryStructCache))
{
// hit!
$oSelect = clone self::$m_aQueryStructCache[$sOqlId];
$oSelect = unserialize(serialize(self::$m_aQueryStructCache[$sOqlId]));
// Note: cloning is not enough because the subtree is made of objects
}
elseif (self::$m_bUseAPCCache)
{
@@ -2200,6 +2315,17 @@ abstract class MetaModel
$oSelect->SetSelect($oBuild->m_oQBExpressions->GetSelect());
}
if (self::$m_bOptimizeQueries)
{
if ($bGetCount)
{
// Simplify the query if just getting the count
$oSelect->SetSelect(array());
}
$oBuild->m_oQBExpressions->GetMandatoryTables($aMandatoryTables);
$oSelect->OptimizeJoins($aMandatoryTables);
}
$oKPI->ComputeStats('MakeQuery (select)', $sOqlQuery);
if (self::$m_bQueryCacheEnabled)
@@ -2211,7 +2337,7 @@ abstract class MetaModel
$oKPI->ComputeStats('Query APC (store)', $sOqlQuery);
}
self::$m_aQueryStructCache[$sOqlId] = clone $oSelect;
self::$m_aQueryStructCache[$sOqlId] = $oSelect->DeepClone();
}
}
@@ -2230,65 +2356,128 @@ abstract class MetaModel
$oSelect->AddInnerJoin($oSelectExt, 'id', $aExtendedDataSpec['join_key'] /*, $sTableAlias*/);
}
if (self::$m_bTraceQueries)
{
$sQueryId = md5($sRes);
if(!isset(self::$m_aQueriesLog[$sOqlId]))
{
self::$m_aQueriesLog[$sOqlId]['oql'] = $sOqlQuery;
self::$m_aQueriesLog[$sOqlId]['hits'] = 1;
}
else
{
self::$m_aQueriesLog[$sOqlId]['hits']++;
}
if(!isset(self::$m_aQueriesLog[$sOqlId]['queries'][$sQueryId]))
{
self::$m_aQueriesLog[$sOqlId]['queries'][$sQueryId]['sql'] = $sRes;
self::$m_aQueriesLog[$sOqlId]['queries'][$sQueryId]['count'] = 1;
}
else
{
self::$m_aQueriesLog[$sOqlId]['queries'][$sQueryId]['count']++;
}
}
return $oSelect;
}
public static function ShowQueryTrace()
protected static function AddQueryTraceSelect($oFilter, $aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $sSql)
{
if (self::$m_bTraceQueries)
{
$aQueryData = array(
'type' => 'select',
'filter' => $oFilter,
'order_by' => $aOrderBy,
'args' => $aArgs,
'att_to_load' => $aAttToLoad,
'extended_data_spec' => $aExtendedDataSpec,
'limit_count' => $iLimitCount,
'limit_start' => $iLimitStart,
'is_count' => $bGetCount
);
$sOql = $oFilter->ToOQL(true, $aArgs);
self::AddQueryTrace($aQueryData, $sOql, $sSql);
}
}
protected static function AddQueryTraceGroupBy($oFilter, $aArgs, $aGroupByExpr, $sSql)
{
if (self::$m_bTraceQueries)
{
$aQueryData = array(
'type' => 'group_by',
'filter' => $oFilter,
'args' => $aArgs,
'group_by_expr' => $aGroupByExpr
);
$sOql = $oFilter->ToOQL(true, $aArgs);
self::AddQueryTrace($aQueryData, $sOql, $sSql);
}
}
protected static function AddQueryTrace($aQueryData, $sOql, $sSql)
{
if (self::$m_bTraceQueries)
{
$sQueryId = md5(serialize($aQueryData));
$sMySQLQueryId = md5($sSql);
if(!isset(self::$m_aQueriesLog[$sQueryId]))
{
self::$m_aQueriesLog[$sQueryId]['data'] = serialize($aQueryData);
self::$m_aQueriesLog[$sQueryId]['oql'] = $sOql;
self::$m_aQueriesLog[$sQueryId]['hits'] = 1;
}
else
{
self::$m_aQueriesLog[$sQueryId]['hits']++;
}
if(!isset(self::$m_aQueriesLog[$sQueryId]['queries'][$sMySQLQueryId]))
{
self::$m_aQueriesLog[$sQueryId]['queries'][$sMySQLQueryId]['sql'] = $sSql;
self::$m_aQueriesLog[$sQueryId]['queries'][$sMySQLQueryId]['count'] = 1;
$iTableCount = count(CMDBSource::ExplainQuery($sSql));
self::$m_aQueriesLog[$sQueryId]['queries'][$sMySQLQueryId]['table_count'] = $iTableCount;
}
else
{
self::$m_aQueriesLog[$sQueryId]['queries'][$sMySQLQueryId]['count']++;
}
}
}
public static function RecordQueryTrace()
{
if (!self::$m_bTraceQueries) return;
$iOqlCount = count(self::$m_aQueriesLog);
if ($iOqlCount == 0)
{
echo "<p>Trace activated, but no query found</p>\n";
return;
}
$iSqlCount = 0;
foreach (self::$m_aQueriesLog as $aOqlData)
foreach (self::$m_aQueriesLog as $sQueryId => $aOqlData)
{
$iSqlCount += $aOqlData['hits'];
}
echo "<h2>Stats on SELECT queries: OQL=$iOqlCount, SQL=$iSqlCount</h2>\n";
foreach (self::$m_aQueriesLog as $aOqlData)
$sHtml = "<h2>Stats on SELECT queries: OQL=$iOqlCount, SQL=$iSqlCount</h2>\n";
foreach (self::$m_aQueriesLog as $sQueryId => $aOqlData)
{
$sOql = $aOqlData['oql'];
$sHits = $aOqlData['hits'];
echo "<p><b>$sHits</b> hits for OQL query: $sOql</p>\n";
echo "<ul id=\"ClassesRelationships\" class=\"treeview\">\n";
$sHtml .= "<p><b>$sHits</b> hits for OQL query: $sOql</p>\n";
$sHtml .= "<ul id=\"ClassesRelationships\" class=\"treeview\">\n";
foreach($aOqlData['queries'] as $aSqlData)
{
$sQuery = $aSqlData['sql'];
$sSqlHits = $aSqlData['count'];
echo "<li><b>$sSqlHits</b> hits for SQL: <span style=\"font-size:60%\">$sQuery</span><li>\n";
$iTableCount = $aSqlData['table_count'];
$sHtml .= "<li><b>$sSqlHits</b> hits for SQL ($iTableCount tables): <pre style=\"font-size:60%\">$sQuery</pre></li>\n";
}
echo "</ul>\n";
$sHtml .= "</ul>\n";
}
$sLogFile = 'queries.latest';
file_put_contents(APPROOT.'data/'.$sLogFile.'.html', $sHtml);
$sLog = "<?php\n\$aQueriesLog = ".var_export(self::$m_aQueriesLog, true).";";
file_put_contents(APPROOT.'data/'.$sLogFile.'.log', $sLog);
// Cumulate the queries
$sAllQueries = APPROOT.'data/queries.log';
if (file_exists($sAllQueries))
{
// Merge the new queries into the existing log
include($sAllQueries);
foreach (self::$m_aQueriesLog as $sQueryId => $aOqlData)
{
if (!array_key_exists($sQueryId, $aQueriesLog))
{
$aQueriesLog[$sQueryId] = $aOqlData;
}
}
}
else
{
$aQueriesLog = self::$m_aQueriesLog;
}
$sLog = "<?php\n\$aQueriesLog = ".var_export($aQueriesLog, true).";";
file_put_contents($sAllQueries, $sLog);
}
protected static function MakeModifierProperties($oFilter)
@@ -2354,7 +2543,6 @@ abstract class MetaModel
{
// default to the whole list of attributes + the very std id/finalclass
$oBuild->m_oQBExpressions->AddSelect($sClassAlias.'id', new FieldExpression('id', $sClassAlias));
if (is_null($aAttToLoad) || !array_key_exists($sClassAlias, $aAttToLoad))
{
$aAttList = self::ListAttributeDefs($sClass);
@@ -2532,7 +2720,7 @@ abstract class MetaModel
foreach(self::EnumParentClasses($sClass) as $sParentClass)
{
if (!self::HasTable($sParentClass)) continue;
//echo "<p>Parent class: $sParentClass... let's call MakeQuerySingleTable()</p>";
self::DbgTrace("Parent class: $sParentClass... let's call MakeQuerySingleTable()");
$oSelectParentTable = self::MakeQuerySingleTable($oBuild, $oFilter, $sParentClass, $aExtKeys, $aValues);
if (is_null($oSelectBase))
@@ -2648,20 +2836,15 @@ abstract class MetaModel
// 1/a - Get the key and friendly name
//
// We need one pkey to be the key, let's take the one corresponding to the root class
// (used to be based on the leaf, but it may happen that this one has no table defined)
$sRootClass = self::GetRootClass($sTargetClass);
// We need one pkey to be the key, let's take the first one available
$oSelectedIdField = null;
if ($sTableClass == $sRootClass)
{
$oIdField = new FieldExpressionResolved(self::DBGetKey($sTableClass), $sTableAlias);
$aTranslation[$sTargetAlias]['id'] = $oIdField;
$oIdField = new FieldExpressionResolved(self::DBGetKey($sTableClass), $sTableAlias);
$aTranslation[$sTargetAlias]['id'] = $oIdField;
if ($bIsOnQueriedClass)
{
// Add this field to the list of queried fields (required for the COUNT to work fine)
$oSelectedIdField = $oIdField;
}
if ($bIsOnQueriedClass)
{
// Add this field to the list of queried fields (required for the COUNT to work fine)
$oSelectedIdField = $oIdField;
}
// 1/b - Get the other attributes
@@ -2755,7 +2938,7 @@ abstract class MetaModel
{
foreach($aPointingTo as $iOperatorCode => $aFilter)
{
foreach($aFilter as $sAlias => $oExtFilter)
foreach($aFilter as $oExtFilter)
{
if (!MetaModel::IsValidAttCode($sTableClass, $sKeyAttCode)) continue; // Not defined in the class, skip it
// The aliases should not conflict because normalization occured while building the filter
@@ -3088,7 +3271,7 @@ abstract class MetaModel
throw new CoreException('Failed to create an alias', array('aliases' => $aAliases, 'new'=>$sNewName));
}
public static function CheckDefinitions()
public static function CheckDefinitions($bExitOnError = true)
{
if (count(self::GetClasses()) == 0)
{
@@ -3099,6 +3282,14 @@ abstract class MetaModel
$aSugFix = array();
foreach (self::GetClasses() as $sClass)
{
$sTable = self::DBGetTable($sClass);
$sTableLowercase = strtolower($sTable);
if ($sTableLowercase != $sTable)
{
$aErrors[$sClass][] = "Table name '".$sTable."' has upper case characters. You might encounter issues when moving your installation between Linux and Windows.";
$aSugFix[$sClass][] = "Use '$sTableLowercase' instead. Step 1: If already installed, then rename manually in the DB: RENAME TABLE `$sTable` TO `{$sTableLowercase}_tempname`, `{$sTableLowercase}_tempname` TO `$sTableLowercase`; Step 2: Rename the table in the datamodel and compile the application. Note: the MySQL statement provided in step 1 has been designed to be compatible with Windows or Linux.";
}
$aNameSpec = self::GetNameSpec($sClass);
foreach($aNameSpec[1] as $i => $sAttCode)
{
@@ -3338,9 +3529,9 @@ abstract class MetaModel
}
echo "</ul>\n";
}
echo "<p>Aborting...</p>\n";
if ($bExitOnError) echo "<p>Aborting...</p>\n";
echo "</div>\n";
exit;
if ($bExitOnError) exit;
}
}
@@ -4323,12 +4514,12 @@ abstract class MetaModel
if (self::$m_oConfig->GetLogIssue())
{
self::$m_bLogIssue = true;
IssueLog::Enable(APPROOT.'/error.log');
IssueLog::Enable(APPROOT.'log/error.log');
}
self::$m_bLogNotification = self::$m_oConfig->GetLogNotification();
self::$m_bLogWebService = self::$m_oConfig->GetLogWebService();
ToolsLog::Enable(APPROOT.'/tools.log');
ToolsLog::Enable(APPROOT.'log/tools.log');
}
else
{
@@ -4346,9 +4537,11 @@ abstract class MetaModel
ExecutionKPI::EnableMemory();
}
self::$m_bTraceQueries = self::$m_oConfig->GetDebugQueries();
self::$m_bTraceQueries = self::$m_oConfig->GetLogQueries();
self::$m_bIndentQueries = self::$m_oConfig->Get('query_indentation_enabled');
self::$m_bQueryCacheEnabled = self::$m_oConfig->GetQueryCacheEnabled();
self::$m_bOptimizeQueries = self::$m_oConfig->Get('query_optimization_enabled');
self::$m_bSkipCheckToWrite = self::$m_oConfig->Get('skip_check_to_write');
self::$m_bSkipCheckExtKeys = self::$m_oConfig->Get('skip_check_ext_keys');
@@ -4543,7 +4736,22 @@ abstract class MetaModel
$sConfigFile = self::$m_oConfig->GetLoadedFile();
throw new CoreException('Wrong filename in configuration file', array('file' => $sConfigFile, 'module' => $sModuleType, 'filename' => $sFile));
}
// Note: We do not expect the modules to output characters while loading them.
// Therefore, and because unexpected characters can corrupt the output,
// they must be trashed here.
// Additionnaly, pages aiming at delivering data in their output can call WebPage::TrashUnexpectedOutput()
// to get rid of chars that could be generated during the execution of the code
ob_start();
require_once($sFile);
$sPreviousContent = ob_get_clean();
if (self::$m_oConfig->Get('debug_report_spurious_chars'))
{
if ($sPreviousContent != '')
{
IssueLog::Error("Spurious characters injected by $sModuleType/$sToInclude");
}
}
}
// Building an object
@@ -4730,7 +4938,23 @@ abstract class MetaModel
$oObj = self::GetObject($sTargetClass, $iKey, false);
if (is_null($oObj))
{
return "$sTargetClass: $iKey (not found)";
// Whatever we are looking for, the root class is the key to search for
$sRootClass = self::GetRootClass($sTargetClass);
$oSearch = DBObjectSearch::FromOQL('SELECT CMDBChangeOpDelete WHERE objclass = :objclass AND objkey = :objkey', array('objclass' => $sRootClass, 'objkey' => $iKey));
$oSet = new DBObjectSet($oSearch);
$oRecord = $oSet->Fetch();
// An empty fname is obtained with iTop < 2.0
if (is_null($oRecord) || (strlen(trim($oRecord->Get('fname'))) == 0))
{
$sName = Dict::Format('Core:UnknownObjectLabel', $sTargetClass, $iKey);
$sTitle = Dict::S('Core:UnknownObjectTip');
}
else
{
$sName = $oRecord->Get('fname');
$sTitle = Dict::Format('Core:DeletedObjectTip', $oRecord->Get('date'), $oRecord->Get('userinfo'));
}
return '<span class="itop-deleted-object" title="'.htmlentities($sTitle, ENT_QUOTES, 'UTF-8').'">'.htmlentities($sName, ENT_QUOTES, 'UTF-8').'</span>';
}
return $oObj->GetHyperLink();
}
@@ -4749,6 +4973,15 @@ abstract class MetaModel
return $iNextKey;
}
/**
* Deletion of records, bypassing DBObject::DBDelete !!!
* It is NOT recommended to use this shortcut
* In particular, it will not work
* - if the class is not a final class
* - if the class has a hierarchical key (need to rebuild the indexes)
* - if the class overload DBDelete !
* Todo: protect it against forbidden usages (in such a case, delete objects one by one)
*/
public static function BulkDelete(DBObjectSearch $oFilter)
{
$sSQL = self::MakeDeleteQuery($oFilter);
@@ -4947,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.'-';
@@ -4964,18 +5197,18 @@ abstract class MetaModel
return $aEntries;
}
public static function ResetCache($sEnvironment = null)
public static function ResetCache($sEnvironmentId = null)
{
if (!function_exists('apc_delete')) return;
if (is_null($sEnvironment))
if (is_null($sEnvironmentId))
{
$sEnvironment = MetaModel::GetEnvironmentId();
$sEnvironmentId = MetaModel::GetEnvironmentId();
}
$sAppIdentity = 'itop-'.$sEnvironment;
$sAppIdentity = 'itop-'.$sEnvironmentId;
Dict::ResetCache($sAppIdentity);
foreach(self::GetCacheEntries($sEnvironment) as $sKey => $aAPCInfo)
foreach(self::GetCacheEntries($sEnvironmentId) as $sKey => $aAPCInfo)
{
$sAPCKey = $aAPCInfo['info'];
apc_delete($sAPCKey);

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Any extension to hook the initialization of the metamodel
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
interface iOnClassInitialization

View File

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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 ModuleHandler
* Defines the API to implement module specific actions during page execution
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
abstract class ModuleHandlerAPI

View File

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
// Notes (from the source file: oql-lexer.plex) - Romain
@@ -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

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
// Notes (from the source file: oql-lexer.plex) - Romain
@@ -94,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 = "!="
@@ -155,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]*)/
@@ -203,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;
}
@@ -350,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

@@ -1,26 +1,26 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Special handling for OQL syntax errors
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Wrapper to execute the parser, lexical analyzer and normalization of an OQL query
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Classes defined for lexical analyze (see oql-parser.y)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
// Position a string within an OQL query
@@ -53,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,27 +1,30 @@
<?php
// Copyright (C) 2011-2012 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 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('CASELOG_VISIBLE_ITEMS', 2);
define('CASELOG_SEPARATOR', "\n".'========== %1$s : %2$s (%3$d) ============'."\n\n");
//require_once(APPROOT.'/core/userrights.class.inc.php');
//require_once(APPROOT.'/application/webpage.class.inc.php');
/**
* Class to store a "case log" in a structured way, keeping track of its successive entries
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class ormCaseLog {
protected $m_sLog;

View File

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* ormDocument
* encapsulate the behavior of a binary data set that will be stored an attribute of class AttributeBlob
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,18 +1,21 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
require_once(APPROOT.'/core/simplecrypt.class.inc.php');
@@ -23,10 +26,8 @@ require_once(APPROOT.'/core/simplecrypt.class.inc.php');
* If a cryptographic random number generator is available (on Linux or Windows)
* it will be used for generating the salt.
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
* @package itopORM
*/

View File

@@ -1,18 +1,20 @@
<?php
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
require_once('backgroundprocess.inc.php');
@@ -20,10 +22,8 @@ require_once('backgroundprocess.inc.php');
* ormStopWatch
* encapsulate the behavior of a stop watch that will be stored as an attribute of class AttributeStopWatch
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -389,6 +389,7 @@ class CheckStopWatchThresholds implements iBackgroundProcess
{
foreach (MetaModel::GetClasses() as $sClass)
{
$aList = array();
foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
if ($oAttDef instanceof AttributeStopWatch)
@@ -400,7 +401,6 @@ class CheckStopWatchThresholds implements iBackgroundProcess
$sExpression = "SELECT $sClass WHERE {$sAttCode}_laststart AND {$sAttCode}_{$iThreshold}_triggered = 0 AND {$sAttCode}_{$iThreshold}_deadline < NOW()";
//echo $sExpression."<br/>\n";
$oFilter = DBObjectSearch::FromOQL($sExpression);
$aList = array();
$oSet = new DBObjectSet($oFilter);
while ((time() < $iTimeLimit) && ($oObj = $oSet->Fetch()))
{
@@ -429,12 +429,9 @@ class CheckStopWatchThresholds implements iBackgroundProcess
if($oObj->IsModified())
{
// Todo - factorize so that only one single change will be instantiated
$oMyChange = new CMDBChange();
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Automatic - threshold triggered");
$iChangeId = $oMyChange->DBInsertNoReload();
CMDBObject::SetTrackInfo("Automatic - threshold triggered");
$oMyChange = CMDBObject::GetCurrentChange();
$oObj->DBUpdateTracked($oMyChange, true /*skip security*/);
}

View File

@@ -1,26 +1,26 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Associated with the metamodel -> MakeQuery/MakeQuerySingleTable
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class QueryBuilderContext
@@ -35,7 +35,7 @@ class QueryBuilderContext
public function __construct($oFilter, $aModifierProperties, $aGroupByExpr = null)
{
$this->m_oRootFilter = $oFilter;
$this->m_oQBExpressions = new QueryBuilderExpressions($oFilter->GetCriteria(), $aGroupByExpr);
$this->m_oQBExpressions = new QueryBuilderExpressions($oFilter, $aGroupByExpr);
$this->m_aClassAliases = $oFilter->GetJoinedClasses();
$this->m_aTableAliases = array();

View File

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Interface iQueryModifier
* Defines the API to tweak queries (e.g. translate data on the fly)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
interface iQueryModifier

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

@@ -1,18 +1,20 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* SimpleCrypt Class - crypto helpers
@@ -34,12 +36,9 @@
* A string encrypted with one engine can't be decrypted with
* a different one even if the key is the same.
*
* @author Miguel Ros <rossoft@gmail.com>
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @version 0.3
* @license GPL
* @author Miguel Ros <rossoft@gmail.com>
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class SimpleCrypt
@@ -221,9 +220,16 @@ class SimpleCryptMcryptEngine implements CryptEngine
{
$iv = substr($encrypted_data, 0, mcrypt_enc_get_iv_size($this->td));
$string = substr($encrypted_data, mcrypt_enc_get_iv_size($this->td));
mcrypt_generic_init($this->td, $key, $iv);
$decrypted_data = rtrim(mdecrypt_generic($this->td, $string), "\0");
mcrypt_generic_deinit($this->td);
$r = mcrypt_generic_init($this->td, $key, $iv);
if (($r < 0) || ($r === false))
{
$decrypted_data = '** decryption error **';
}
else
{
$decrypted_data = rtrim(mdecrypt_generic($this->td, $string), "\0");
mcrypt_generic_deinit($this->td);
}
return $decrypted_data;
}

View File

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* SQLQuery
* build an mySQL compatible SQL query
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -47,6 +48,7 @@ class SQLQuery
private $m_aValues = array(); // Values to set in case of an update query
private $m_oSelectedIdField = null;
private $m_aJoinSelects = array();
private $m_bBeautifulQuery = false;
public function __construct($sTable, $sTableAlias, $aFields, $bToDelete = true, $aValues = array(), $oSelectedIdField = null)
{
@@ -70,6 +72,14 @@ class SQLQuery
$this->m_oSelectedIdField = $oSelectedIdField;
}
/**
* Perform a deep clone (as opposed to "clone" which does copy a reference to the underlying objects
**/
public function DeepClone()
{
return unserialize(serialize($this));
}
public function GetTableAlias()
{
return $this->m_sTableAlias;
@@ -292,8 +302,12 @@ class SQLQuery
}
// Interface, build the SQL query
public function RenderSelect($aOrderBy = array(), $aArgs = array(), $iLimitCount = 0, $iLimitStart = 0, $bGetCount = false)
public function RenderSelect($aOrderBy = array(), $aArgs = array(), $iLimitCount = 0, $iLimitStart = 0, $bGetCount = false, $bBeautifulQuery = false)
{
$this->m_bBeautifulQuery = $bBeautifulQuery;
$sLineSep = $this->m_bBeautifulQuery ? "\n" : '';
$sIndent = $this->m_bBeautifulQuery ? " " : null;
// The goal will be to complete the lists as we build the Joins
$aFrom = array();
$aFields = array();
@@ -304,18 +318,23 @@ class SQLQuery
$aSelectedIdFields = array();
$this->privRender($aFrom, $aFields, $aGroupBy, $oCondition, $aDelTables, $aSetValues, $aSelectedIdFields);
$sFrom = self::ClauseFrom($aFrom);
$sFrom = self::ClauseFrom($aFrom, $sIndent);
$sWhere = self::ClauseWhere($oCondition, $aArgs);
if ($bGetCount)
{
if (count($aSelectedIdFields) > 0)
{
$sIDFields = implode(', ', $aSelectedIdFields);
$sSQL = "SELECT COUNT(DISTINCT $sIDFields) AS COUNT FROM $sFrom WHERE $sWhere";
$aCountFields = array();
foreach ($aSelectedIdFields as $sFieldExpr)
{
$aCountFields[] = "COALESCE($sFieldExpr, 0)"; // Null values are excluded from the count
}
$sCountFields = implode(', ', $aCountFields);
$sSQL = "SELECT$sLineSep COUNT(DISTINCT $sCountFields) AS COUNT$sLineSep FROM $sFrom$sLineSep WHERE $sWhere";
}
else
{
$sSQL = "SELECT COUNT(*) AS COUNT FROM $sFrom WHERE $sWhere";
$sSQL = "SELECT$sLineSep COUNT(*) AS COUNT$sLineSep FROM $sFrom$sLineSep WHERE $sWhere";
}
}
else
@@ -334,14 +353,18 @@ class SQLQuery
{
$sLimit = '';
}
$sSQL = "SELECT DISTINCT $sSelect FROM $sFrom WHERE $sWhere $sOrderBy $sLimit";
$sSQL = "SELECT$sLineSep DISTINCT $sSelect$sLineSep FROM $sFrom$sLineSep WHERE $sWhere$sLineSep $sOrderBy$sLineSep $sLimit";
}
return $sSQL;
}
// Interface, build the SQL query
public function RenderGroupBy($aArgs = array())
public function RenderGroupBy($aArgs = array(), $bBeautifulQuery = false)
{
$this->m_bBeautifulQuery = $bBeautifulQuery;
$sLineSep = $this->m_bBeautifulQuery ? "\n" : '';
$sIndent = $this->m_bBeautifulQuery ? " " : null;
// The goal will be to complete the lists as we build the Joins
$aFrom = array();
$aFields = array();
@@ -353,10 +376,10 @@ class SQLQuery
$this->privRender($aFrom, $aFields, $aGroupBy, $oCondition, $aDelTables, $aSetValues, $aSelectedIdFields);
$sSelect = self::ClauseSelect($aFields);
$sFrom = self::ClauseFrom($aFrom);
$sFrom = self::ClauseFrom($aFrom, $sIndent);
$sWhere = self::ClauseWhere($oCondition, $aArgs);
$sGroupBy = self::ClauseGroupBy($aGroupBy);
$sSQL = "SELECT $sSelect, COUNT(*) AS _itop_count_ FROM $sFrom WHERE $sWhere GROUP BY $sGroupBy";
$sSQL = "SELECT $sSelect,$sLineSep COUNT(*) AS _itop_count_$sLineSep FROM $sFrom$sLineSep WHERE $sWhere$sLineSep GROUP BY $sGroupBy";
return $sSQL;
}
@@ -388,27 +411,30 @@ class SQLQuery
return $sDelTables;
}
private static function ClauseFrom($aFrom)
private static function ClauseFrom($aFrom, $sIndent = null, $iIndentLevel = 0)
{
$sLineBreakLong = $sIndent ? "\n".str_repeat($sIndent, $iIndentLevel + 1) : '';
$sLineBreak = $sIndent ? "\n".str_repeat($sIndent, $iIndentLevel) : '';
$sFrom = "";
foreach ($aFrom as $sTableAlias => $aJoinInfo)
{
switch ($aJoinInfo["jointype"])
{
case "first":
$sFrom .= "`".$aJoinInfo["tablename"]."` AS `$sTableAlias`";
$sFrom .= " ".self::ClauseFrom($aJoinInfo["subfrom"]);
$sFrom .= $sLineBreakLong."`".$aJoinInfo["tablename"]."` AS `$sTableAlias`";
$sFrom .= self::ClauseFrom($aJoinInfo["subfrom"], $sIndent, $iIndentLevel + 1);
break;
case "inner":
case "inner_tree":
$sFrom .= " INNER JOIN (`".$aJoinInfo["tablename"]."` AS `$sTableAlias`";
$sFrom .= " ".self::ClauseFrom($aJoinInfo["subfrom"]);
$sFrom .= ") ON ".$aJoinInfo["joincondition"];
$sFrom .= $sLineBreak."INNER JOIN ($sLineBreakLong`".$aJoinInfo["tablename"]."` AS `$sTableAlias`";
$sFrom .= " ".self::ClauseFrom($aJoinInfo["subfrom"], $sIndent, $iIndentLevel + 1);
$sFrom .= $sLineBreak.") ON ".$aJoinInfo["joincondition"];
break;
case "left":
$sFrom .= " LEFT JOIN (`".$aJoinInfo["tablename"]."` AS `$sTableAlias`";
$sFrom .= " ".self::ClauseFrom($aJoinInfo["subfrom"]);
$sFrom .= ") ON ".$aJoinInfo["joincondition"];
$sFrom .= $sLineBreak."LEFT JOIN ($sLineBreakLong`".$aJoinInfo["tablename"]."` AS `$sTableAlias`";
$sFrom .= " ".self::ClauseFrom($aJoinInfo["subfrom"], $sIndent, $iIndentLevel + 1);
$sFrom .= $sLineBreak.") ON ".$aJoinInfo["joincondition"];
break;
default:
throw new CoreException("Unknown jointype: '".$aJoinInfo["jointype"]."'");
@@ -555,7 +581,6 @@ class SQLQuery
{
$aDelTables[] = "`{$this->m_sTableAlias}`";
}
//echo "<p>in privRenderSingleTable this->m_aValues<pre>".print_r($this->m_aValues, true)."</pre></p>\n";
foreach($this->m_aValues as $sFieldName=>$value)
{
$aSetValues["`{$this->m_sTableAlias}`.`$sFieldName`"] = $value; // quoted further!
@@ -580,6 +605,98 @@ class SQLQuery
return $this->m_sTableAlias;
}
}
public function OptimizeJoins($aUsedTables, $bTopCall = true)
{
if ($bTopCall)
{
// Top call: complete the list of tables absolutely required to perform the right query
$this->CollectUsedTables($aUsedTables);
}
?>
$aToDiscard = array();
foreach ($this->m_aJoinSelects as $i => $aJoinInfo)
{
$oSQLQuery = $aJoinInfo["select"];
$sTableAlias = $oSQLQuery->GetTableAlias();
if ($oSQLQuery->OptimizeJoins($aUsedTables, false) && !array_key_exists($sTableAlias, $aUsedTables))
{
$aToDiscard[] = $i;
}
}
foreach ($aToDiscard as $i)
{
unset($this->m_aJoinSelects[$i]);
}
return (count($this->m_aJoinSelects) == 0);
}
protected function CollectUsedTables(&$aTables)
{
$this->m_oConditionExpr->CollectUsedParents($aTables);
foreach($this->m_aFields as $sFieldAlias => $oField)
{
$oField->CollectUsedParents($aTables);
}
if ($this->m_aGroupBy)
{
foreach($this->m_aGroupBy as $sAlias => $oExpression)
{
$oExpression->CollectUsedParents($aTables);
}
}
if (!is_null($this->m_oSelectedIdField))
{
$this->m_oSelectedIdField->CollectUsedParents($aTables);
}
foreach ($this->m_aJoinSelects as $i => $aJoinInfo)
{
$oSQLQuery = $aJoinInfo["select"];
if ($oSQLQuery->HasRequiredTables($aTables))
{
// There is something required in the branch, then this node is a MUST
if (isset($aJoinInfo['righttablealias']))
{
$aTables[$aJoinInfo['righttablealias']] = true;
}
if (isset($aJoinInfo["on_expression"]))
{
$sJoinCond = $aJoinInfo["on_expression"]->CollectUsedParents($aTables);
}
}
}
return $aTables;
}
// Is required in the JOIN, and therefore we must ensure that the join expression will be valid
protected function HasRequiredTables(&$aTables)
{
$bResult = false;
if (array_key_exists($this->m_sTableAlias, $aTables))
{
$bResult = true;
}
foreach ($this->m_aJoinSelects as $i => $aJoinInfo)
{
$oSQLQuery = $aJoinInfo["select"];
if ($oSQLQuery->HasRequiredTables($aTables))
{
// There is something required in the branch, then this node is a MUST
if (isset($aJoinInfo['righttablealias']))
{
$aTables[$aJoinInfo['righttablealias']] = true;
}
if (isset($aJoinInfo["on_expression"]))
{
$sJoinCond = $aJoinInfo["on_expression"]->CollectUsedParents($aTables);
}
$bResult = true;
}
}
// None of the tables is in the list of required tables
return $bResult;
}
}
?>

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Object lifecycle management: stimulus
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/

View File

@@ -1,18 +1,21 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Simple helper class to interpret and transform a template string
@@ -21,10 +24,8 @@
* $oString = new TemplateString("Blah $this->friendlyname$ is in location $this->location_id->name$ ('$this->location_id->org_id->name$)");
* echo $oString->Render(array('this' => $oContact));
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**

View File

@@ -1,27 +1,28 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Persistent class Trigger and derived
* User defined triggers, that may be used in conjunction with user defined actions
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -75,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
@@ -104,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

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* User rights management API
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -281,7 +282,7 @@ abstract class UserInternal extends User
"name_attcode" => "login",
"state_attcode" => "",
"reconc_keys" => array('login'),
"db_table" => "priv_internalUser",
"db_table" => "priv_internaluser",
"db_key_field" => "id",
"db_finalclass_field" => "",
);

View File

@@ -1,26 +1,27 @@
<?php
// Copyright (C) 2010 Combodo SARL
// Copyright (C) 2010-2012 Combodo SARL
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This file is part of iTop.
//
// This program is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Value set definitions (from a fixed list or from a query, etc.)
*
* @author Erwan Taloc <erwan.taloc@combodo.com>
* @author Romain Quetiez <romain.quetiez@combodo.com>
* @author Denis Flaven <denis.flaven@combodo.com>
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once('MyHelpers.class.inc.php');

View File

@@ -0,0 +1,23 @@
.ui-multiselect { padding:2px 0 2px 4px; text-align:left }
.ui-multiselect span.ui-icon { float:right }
.ui-multiselect-single .ui-multiselect-checkboxes input { position:absolute !important; top: auto !important; left:-9999px; }
.ui-multiselect-single .ui-multiselect-checkboxes label { padding:5px !important }
.ui-multiselect-header { margin-bottom:3px; padding:3px 0 3px 4px }
.ui-multiselect-header ul { font-size:0.9em }
.ui-multiselect-header ul li { float:left; padding:0 10px 0 0 }
.ui-multiselect-header a { text-decoration:none }
.ui-multiselect-header a:hover { text-decoration:underline }
.ui-multiselect-header span.ui-icon { float:left }
.ui-multiselect-header li.ui-multiselect-close { float:right; text-align:right; padding-right:0 }
.ui-multiselect-menu { display:none; padding:3px; position:absolute; z-index:10000; text-align: left }
.ui-multiselect-checkboxes { position:relative /* fixes bug in IE6/7 */; overflow-y:scroll }
.ui-multiselect-checkboxes label { cursor:default; display:block; border:1px solid transparent; padding:3px 1px }
.ui-multiselect-checkboxes label input { position:relative; top:1px }
.ui-multiselect-checkboxes li { clear:both; font-size:0.9em; padding-right:3px }
.ui-multiselect-checkboxes li.ui-multiselect-optgroup-label { text-align:center; font-weight:bold; border-bottom:1px solid }
.ui-multiselect-checkboxes li.ui-multiselect-optgroup-label a { display:block; padding:3px; margin:1px 0; text-decoration:none }
/* remove label borders in IE6 because IE6 does not support transparency */
* html .ui-multiselect-checkboxes label { border:none }

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