Merge remote-tracking branch 'origin/QA_4_7' into QA_4_7
[phpmyadmin.git] / js / error_report.js
blob98f068c092bb60a3c1ec658c12b86b14b3757d61
1 /* vim: set expandtab sw=4 ts=4 sts=4: */
2 /**
3  * general function, usually for data manipulation pages
4  *
5  */
7 var ErrorReport = {
8     /**
9      * @var object stores the last exception info
10      */
11     _last_exception: null,
12     /**
13      * handles thrown error exceptions based on user preferences
14      *
15      * @return void
16      */
17     error_handler: function (exception) {
18         if (exception.name === null || typeof(exception.name) == "undefined") {
19             exception.name = ErrorReport._extractExceptionName(exception);
20         }
21         ErrorReport._last_exception = exception;
22         $.get("error_report.php", {
23             ajax_request: true,
24             server: PMA_commonParams.get('server'),
25             token: PMA_commonParams.get('token'),
26             get_settings: true,
27             exception_type: 'js'
28         }, function (data) {
29             if (data.success !== true) {
30                 PMA_ajaxShowMessage(data.error, false);
31                 return;
32             }
33             if (data.report_setting == "ask") {
34                 ErrorReport._showErrorNotification();
35             } else if (data.report_setting == "always") {
36                 report_data = ErrorReport._get_report_data(exception);
37                 post_data = $.extend(report_data, {
38                     send_error_report: true,
39                     automatic: true
40                 });
41                 $.post("error_report.php", post_data, function (data) {
42                     if (data.success === false) {
43                         //in the case of an error, show the error message returned.
44                         PMA_ajaxShowMessage(data.error, false);
45                     } else {
46                         PMA_ajaxShowMessage(data.message, false);
47                     }
48                 });
49             }
50         });
51     },
52     /**
53      * Shows the modal dialog previewing the report
54      *
55      * @param exception object error report info
56      *
57      * @return void
58      */
59     _showReportDialog: function (exception) {
60         var report_data = ErrorReport._get_report_data(exception);
62         /*Remove the hidden dialogs if there are*/
63         if ($('#error_report_dialog').length !== 0) {
64             $('#error_report_dialog').remove();
65         }
66         var $div = $('<div id="error_report_dialog"></div>');
67         $div.css('z-index', '1000');
69         var button_options = {};
71         button_options[PMA_messages.strSendErrorReport] = function () {
72             var $dialog = $(this);
73             var post_data = $.extend(report_data, {
74                 send_error_report: true,
75                 description: $("#report_description").val(),
76                 always_send: $("#always_send_checkbox")[0].checked
77             });
78             $.post("error_report.php", post_data, function (data) {
79                 $dialog.dialog('close');
80                 if (data.success === false) {
81                     //in the case of an error, show the error message returned.
82                     PMA_ajaxShowMessage(data.error, false);
83                 } else {
84                     PMA_ajaxShowMessage(data.message, 3000);
85                 }
86             });
87         };
89         button_options[PMA_messages.strCancel] = function () {
90             $(this).dialog('close');
91         };
93         $.post("error_report.php", report_data, function (data) {
94             if (data.success === false) {
95                 //in the case of an error, show the error message returned.
96                 PMA_ajaxShowMessage(data.error, false);
97             } else {
98                 // Show dialog if the request was successful
99                 $div
100                 .append(data.message)
101                 .dialog({
102                     title: PMA_messages.strSubmitErrorReport,
103                     width: 650,
104                     modal: true,
105                     buttons: button_options,
106                     close: function () {
107                         $(this).remove();
108                     }
109                 });
110             }
111         }); // end $.get()
112     },
113     /**
114      * Shows the small notification that asks for user permission
115      *
116      * @return void
117      */
118     _showErrorNotification: function () {
119         ErrorReport._removeErrorNotification();
121         var $div = $(
122             '<div style="position:fixed;bottom:0;left:0;right:0;margin:0;' +
123             'z-index:1000" class="error" id="error_notification"></div>'
124         ).append(
125             PMA_getImage("s_error.png") + PMA_messages.strErrorOccurred
126         );
128         var $buttons = $('<div class="floatright"></div>');
130         var button_html  = '<button id="show_error_report">';
131         button_html += PMA_messages.strShowReportDetails;
132         button_html += '</button>';
134         button_html += '<a id="change_error_settings">';
135         button_html += PMA_getImage('s_cog.png', PMA_messages.strChangeReportSettings);
136         button_html += '</a>';
138         button_html += '<a href="#" id="ignore_error">';
139         button_html += PMA_getImage('b_close.png', PMA_messages.strIgnore);
140         button_html += '</a>';
142         $buttons.html(button_html);
144         $div.append($buttons);
145         $div.appendTo(document.body);
146         $("#change_error_settings").on("click", ErrorReport._redirect_to_settings);
147         $("#show_error_report").on("click", ErrorReport._createReportDialog);
148         $("#ignore_error").on("click", ErrorReport._removeErrorNotification);
149     },
150     /**
151      * Removes the notification if it was displayed before
152      *
153      * @return void
154      */
155     _removeErrorNotification: function (e) {
156         if (e) {
157             // don't remove the hash fragment by navigating to #
158             e.preventDefault();
159         }
160         $("#error_notification").fadeOut(function () {
161             $(this).remove();
162         });
163     },
164     /**
165      * Extracts Exception name from message if it exists
166      *
167      * @return String
168      */
169     _extractExceptionName: function (exception) {
170         if (exception.message === null || typeof(exception.message) == "undefined") {
171             return "";
172         }
174         var reg = /([a-zA-Z]+):/;
175         var regex_result = reg.exec(exception.message);
176         if (regex_result && regex_result.length == 2) {
177             return regex_result[1];
178         }
180         return "";
181     },
182     /**
183      * Shows the modal dialog previewing the report
184      *
185      * @return void
186      */
187     _createReportDialog: function () {
188         ErrorReport._removeErrorNotification();
189         ErrorReport._showReportDialog(ErrorReport._last_exception);
190     },
191     /**
192      * Redirects to the settings page containing error report
193      * preferences
194      *
195      * @return void
196      */
197     _redirect_to_settings: function () {
198         window.location.href = "prefs_forms.php?token=" + PMA_commonParams.get('token');
199     },
200     /**
201      * Returns the report data to send to the server
202      *
203      * @param exception object exception info
204      *
205      * @return object
206      */
207     _get_report_data: function (exception) {
208         var report_data = {
209             "ajax_request": true,
210             "token": PMA_commonParams.get('token'),
211             "exception": exception,
212             "current_url": window.location.href,
213             "exception_type": 'js'
214         };
215         if (AJAX.scriptHandler._scripts.length > 0) {
216             report_data.scripts = AJAX.scriptHandler._scripts.map(
217                 function (script) {
218                     return script.name;
219                 }
220             );
221         }
222         return report_data;
223     },
224     /**
225      * Wraps all global functions that start with PMA_
226      *
227      * @return void
228      */
229     wrap_global_functions: function () {
230         for (var key in window) {
231             if (key.indexOf("PMA_") === 0) {
232                 var global = window[key];
233                 if (typeof(global) === "function") {
234                     window[key] = ErrorReport.wrap_function(global);
235                 }
236             }
237         }
238     },
239     /**
240      * Wraps given function in error reporting code and returns wrapped function
241      *
242      * @param func function to be wrapped
243      *
244      * @return function
245      */
246     wrap_function: function (func) {
247         if (!func.wrapped) {
248             var new_func = function () {
249                 try {
250                     return func.apply(this, arguments);
251                 } catch (x) {
252                     TraceKit.report(x);
253                 }
254             };
255             new_func.wrapped = true;
256             //Set guid of wrapped function same as original function, so it can be removed
257             //See bug#4146 (problem with jquery draggable and sortable)
258             new_func.guid = func.guid = func.guid || new_func.guid || jQuery.guid++;
259             return new_func;
260         } else {
261             return func;
262         }
263     },
264     /**
265      * Automatically wraps the callback in AJAX.registerOnload
266      *
267      * @return void
268      */
269     _wrap_ajax_onload_callback: function () {
270         var oldOnload = AJAX.registerOnload;
271         AJAX.registerOnload = function (file, func) {
272             func = ErrorReport.wrap_function(func);
273             oldOnload.call(this, file, func);
274         };
275     },
276     /**
277      * Automatically wraps the callback in $.fn.on
278      *
279      * @return void
280      */
281     _wrap_$_on_callback: function () {
282         var oldOn = $.fn.on;
283         $.fn.on = function () {
284             for (var i = 1; i <= 3; i++) {
285                 if (typeof(arguments[i]) === "function") {
286                     arguments[i] = ErrorReport.wrap_function(arguments[i]);
287                     break;
288                 }
289             }
290             return oldOn.apply(this, arguments);
291         };
292     },
293     /**
294      * Wraps all global functions that start with PMA_
295      * also automatically wraps the callback in AJAX.registerOnload
296      *
297      * @return void
298      */
299     set_up_error_reporting: function () {
300         ErrorReport.wrap_global_functions();
301         ErrorReport._wrap_ajax_onload_callback();
302         ErrorReport._wrap_$_on_callback();
303     }
307 AJAX.registerOnload('error_report.js', function(){
308     TraceKit.report.subscribe(ErrorReport.error_handler);
309     ErrorReport.set_up_error_reporting();
310     ErrorReport.wrap_global_functions();