|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/* Copyright (C) 2000-2007 Rodolphe Quiedeville <[email protected]> |
|
4
|
|
|
* Copyright (C) 2003 Jean-Louis Bergamo <[email protected]> |
|
5
|
|
|
* Copyright (C) 2004-2022 Laurent Destailleur <[email protected]> |
|
6
|
|
|
* Copyright (C) 2004 Sebastien Di Cintio <[email protected]> |
|
7
|
|
|
* Copyright (C) 2004 Benoit Mortier <[email protected]> |
|
8
|
|
|
* Copyright (C) 2004 Christophe Combelles <[email protected]> |
|
9
|
|
|
* Copyright (C) 2005-2019 Regis Houssin <[email protected]> |
|
10
|
|
|
* Copyright (C) 2008 Raphael Bertrand (Resultic) <[email protected]> |
|
11
|
|
|
* Copyright (C) 2010-2018 Juanjo Menent <[email protected]> |
|
12
|
|
|
* Copyright (C) 2013 Cédric Salvador <[email protected]> |
|
13
|
|
|
* Copyright (C) 2013-2021 Alexandre Spangaro <[email protected]> |
|
14
|
|
|
* Copyright (C) 2014 Cédric GROSS <[email protected]> |
|
15
|
|
|
* Copyright (C) 2014-2015 Marcos García <[email protected]> |
|
16
|
|
|
* Copyright (C) 2015 Jean-François Ferry <[email protected]> |
|
17
|
|
|
* Copyright (C) 2018-2024 Frédéric France <[email protected]> |
|
18
|
|
|
* Copyright (C) 2019-2023 Thibault Foucart <[email protected]> |
|
19
|
|
|
* Copyright (C) 2020 Open-Dsi <[email protected]> |
|
20
|
|
|
* Copyright (C) 2021 Gauthier VERDOL <[email protected]> |
|
21
|
|
|
* Copyright (C) 2022 Anthony Berton <[email protected]> |
|
22
|
|
|
* Copyright (C) 2022 Ferran Marcet <[email protected]> |
|
23
|
|
|
* Copyright (C) 2022 Charlene Benke <[email protected]> |
|
24
|
|
|
* Copyright (C) 2023 Joachim Kueter <[email protected]> |
|
25
|
|
|
* Copyright (C) 2024 MDW <[email protected]> |
|
26
|
|
|
* Copyright (C) 2024 Lenin Rivas <[email protected]> |
|
27
|
|
|
* Copyright (C) 2024 Rafael San José <[email protected]> |
|
28
|
|
|
* |
|
29
|
|
|
* This program is free software; you can redistribute it and/or modify |
|
30
|
|
|
* it under the terms of the GNU General Public License as published by |
|
31
|
|
|
* the Free Software Foundation; either version 3 of the License, or |
|
32
|
|
|
* (at your option) any later version. |
|
33
|
|
|
* |
|
34
|
|
|
* This program is distributed in the hope that it will be useful, |
|
35
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
36
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
37
|
|
|
* GNU General Public License for more details. |
|
38
|
|
|
* |
|
39
|
|
|
* You should have received a copy of the GNU General Public License |
|
40
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. |
|
41
|
|
|
* or see https://www.gnu.org/ |
|
42
|
|
|
*/ |
|
43
|
|
|
|
|
44
|
|
|
/** |
|
45
|
|
|
* TODO: Convert to abstract class with static methods |
|
46
|
|
|
*/ |
|
47
|
|
|
|
|
48
|
|
|
use Dolibarr\Code\Bom\Classes\BOM; |
|
49
|
|
|
use Dolibarr\Code\Categories\Classes\Categorie; |
|
50
|
|
|
use Dolibarr\Code\Comm\Classes\ActionComm; |
|
51
|
|
|
use Dolibarr\Code\Comm\Classes\CActionComm; |
|
52
|
|
|
use Dolibarr\Code\Contact\Classes\Contact; |
|
53
|
|
|
use Dolibarr\Code\Core\Classes\Conf; |
|
54
|
|
|
use Dolibarr\Code\Core\Classes\Form; |
|
55
|
|
|
use Dolibarr\Code\Core\Classes\FormActions; |
|
56
|
|
|
use Dolibarr\Code\Core\Classes\HookManager; |
|
57
|
|
|
use Dolibarr\Code\Core\Classes\Translate; |
|
58
|
|
|
use Dolibarr\Code\Product\Classes\Product; |
|
59
|
|
|
use Dolibarr\Code\Societe\Classes\Societe; |
|
60
|
|
|
use Dolibarr\Code\Ticket\Classes\Ticket; |
|
61
|
|
|
use Dolibarr\Code\User\Classes\User; |
|
62
|
|
|
use Dolibarr\Code\Website\Classes\Website; |
|
63
|
|
|
use Dolibarr\Core\Base\CommonObject; |
|
64
|
|
|
use Dolibarr\Lib\Filters; |
|
65
|
|
|
|
|
66
|
|
|
/** |
|
67
|
|
|
* Create a dialog with two buttons for export and overwrite of a website |
|
68
|
|
|
* |
|
69
|
|
|
* @param string $name Unique identifier for the dialog |
|
70
|
|
|
* @param string $label Title of the dialog |
|
71
|
|
|
* @param string $buttonstring Text for the button that opens the dialog |
|
72
|
|
|
* @param string $exportSiteName Name of the "submit" input for site export |
|
73
|
|
|
* @param string $overwriteGitUrl URL for the link that triggers the overwrite action in GIT |
|
74
|
|
|
* @param Website $website Website object |
|
75
|
|
|
* @return string HTML and JavaScript code for the button and the dialog |
|
76
|
|
|
*/ |
|
77
|
|
|
function dolButtonToOpenExportDialog($name, $label, $buttonstring, $exportSiteName, $overwriteGitUrl, $website) |
|
78
|
|
|
{ |
|
79
|
|
|
global $langs, $db; |
|
80
|
|
|
|
|
81
|
|
|
$form = new Form($db); |
|
82
|
|
|
|
|
83
|
|
|
$templatenameforexport = $website->name_template; // Example 'website_template-corporate' |
|
84
|
|
|
if (empty($templatenameforexport)) { |
|
85
|
|
|
$templatenameforexport = 'website_' . $website->ref; |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
$out = ''; |
|
89
|
|
|
$out .= '<input type="button" class="cursorpointer button bordertransp" id="open-dialog-' . $name . '" value="' . dol_escape_htmltag($buttonstring) . '"/>'; |
|
90
|
|
|
|
|
91
|
|
|
// for generate popup |
|
92
|
|
|
$out .= '<script nonce="' . getNonce() . '" type="text/javascript">'; |
|
93
|
|
|
$out .= 'jQuery(document).ready(function () {'; |
|
94
|
|
|
$out .= ' jQuery("#open-dialog-' . $name . '").click(function () {'; |
|
95
|
|
|
$out .= ' var dialogHtml = \''; |
|
96
|
|
|
|
|
97
|
|
|
$dialogcontent = ' <div id="custom-dialog-' . $name . '">'; |
|
98
|
|
|
$dialogcontent .= ' <div style="margin-top: 20px;">'; |
|
99
|
|
|
$dialogcontent .= ' <label for="export-site-' . $name . '"><strong>' . $langs->trans("ExportSiteLabel") . '...</label><br>'; |
|
100
|
|
|
$dialogcontent .= ' <button class="button smallpaddingimp" id="export-site-' . $name . '">' . dol_escape_htmltag($langs->trans("DownloadZip")) . '</button>'; |
|
101
|
|
|
$dialogcontent .= ' </div>'; |
|
102
|
|
|
$dialogcontent .= ' <br>'; |
|
103
|
|
|
$dialogcontent .= ' <div style="margin-top: 20px;">'; |
|
104
|
|
|
$dialogcontent .= ' <strong>' . $langs->trans("ExportSiteGitLabel") . ' ' . $form->textwithpicto('', $langs->trans("SourceFiles"), 1, 'help', '', 0, 3, '') . '</strong><br>'; |
|
105
|
|
|
$dialogcontent .= ' <form action="' . dol_escape_htmltag($overwriteGitUrl) . '" method="POST">'; |
|
106
|
|
|
$dialogcontent .= ' <input type="hidden" name="action" value="overwritesite">'; |
|
107
|
|
|
$dialogcontent .= ' <input type="hidden" name="token" value="' . newToken() . '">'; |
|
108
|
|
|
$dialogcontent .= ' <input type="text" autofocus name="export_path" id="export-path-' . $name . '" placeholder="' . $langs->trans('ExportPath') . '" style="width:400px " value="' . dol_escape_htmltag($templatenameforexport) . '"/><br>'; |
|
109
|
|
|
$dialogcontent .= ' <button type="submit" class="button smallpaddingimp" id="overwrite-git-' . $name . '">' . dol_escape_htmltag($langs->trans("ExportIntoGIT")) . '</button>'; |
|
110
|
|
|
$dialogcontent .= ' </form>'; |
|
111
|
|
|
$dialogcontent .= ' </div>'; |
|
112
|
|
|
$dialogcontent .= ' </div>'; |
|
113
|
|
|
|
|
114
|
|
|
$out .= dol_escape_js($dialogcontent); |
|
115
|
|
|
|
|
116
|
|
|
$out .= '\';'; |
|
117
|
|
|
|
|
118
|
|
|
|
|
119
|
|
|
// Add the content of the dialog to the body of the page |
|
120
|
|
|
$out .= ' var $dialog = jQuery("#custom-dialog-' . $name . '");'; |
|
121
|
|
|
$out .= ' if ($dialog.length > 0) { |
|
122
|
|
|
$dialog.remove(); |
|
123
|
|
|
} |
|
124
|
|
|
jQuery("body").append(dialogHtml);'; |
|
125
|
|
|
|
|
126
|
|
|
// Configuration of popup |
|
127
|
|
|
$out .= ' jQuery("#custom-dialog-' . $name . '").dialog({'; |
|
128
|
|
|
$out .= ' autoOpen: false,'; |
|
129
|
|
|
$out .= ' modal: true,'; |
|
130
|
|
|
$out .= ' height: 290,'; |
|
131
|
|
|
$out .= ' width: "40%",'; |
|
132
|
|
|
$out .= ' title: "' . dol_escape_js($label) . '",'; |
|
133
|
|
|
$out .= ' });'; |
|
134
|
|
|
|
|
135
|
|
|
// Simulate a click on the original "submit" input to export the site. |
|
136
|
|
|
$out .= ' jQuery("#export-site-' . $name . '").click(function () {'; |
|
137
|
|
|
$out .= ' console.log("Clic on exportsite.");'; |
|
138
|
|
|
$out .= ' var target = jQuery("input[name=\'' . dol_escape_js($exportSiteName) . '\']");'; |
|
139
|
|
|
$out .= ' console.log("element founded:", target.length > 0);'; |
|
140
|
|
|
$out .= ' if (target.length > 0) { target.click(); }'; |
|
141
|
|
|
$out .= ' jQuery("#custom-dialog-' . $name . '").dialog("close");'; |
|
142
|
|
|
$out .= ' });'; |
|
143
|
|
|
|
|
144
|
|
|
// open popup |
|
145
|
|
|
$out .= ' jQuery("#custom-dialog-' . $name . '").dialog("open");'; |
|
146
|
|
|
$out .= ' return false;'; |
|
147
|
|
|
$out .= ' });'; |
|
148
|
|
|
$out .= '});'; |
|
149
|
|
|
$out .= '</script>'; |
|
150
|
|
|
|
|
151
|
|
|
return $out; |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
/** |
|
155
|
|
|
* Return HTML code to output a button to open a dialog popup box. |
|
156
|
|
|
* Such buttons must be included inside a HTML form. |
|
157
|
|
|
* |
|
158
|
|
|
* @param string $name A name for the html component |
|
159
|
|
|
* @param string $label Label shown in Popup title top bar |
|
160
|
|
|
* @param string $buttonstring button string (HTML text we can click on) |
|
161
|
|
|
* @param string $url Relative Url to open. For example '/project/card.php' |
|
162
|
|
|
* @param string $disabled Disabled text |
|
163
|
|
|
* @param string $morecss More CSS |
|
164
|
|
|
* @param string $jsonopen Some JS code to execute on click/open of popup |
|
165
|
|
|
* @param string $backtopagejsfields The back to page must be managed using javascript instead of a redirect. |
|
166
|
|
|
* Value is 'keyforpopupid:Name_of_html_component_to_set_with id,Name_of_html_component_to_set_with_label' |
|
167
|
|
|
* @param string $accesskey A key to use shortcut |
|
168
|
|
|
* @return string HTML component with button |
|
169
|
|
|
*/ |
|
170
|
|
|
function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled = '', $morecss = 'classlink button bordertransp', $jsonopen = '', $backtopagejsfields = '', $accesskey = '') |
|
171
|
|
|
{ |
|
172
|
|
|
global $conf; |
|
173
|
|
|
|
|
174
|
|
|
if (strpos($url, '?') > 0) { |
|
175
|
|
|
$url .= '&dol_hide_topmenu=1&dol_hide_leftmenu=1&dol_openinpopup=' . urlencode($name); |
|
176
|
|
|
} else { |
|
177
|
|
|
$url .= '?dol_hide_topmenu=1&dol_hide_leftmenu=1&dol_openinpopup=' . urlencode($name); |
|
178
|
|
|
} |
|
179
|
|
|
|
|
180
|
|
|
$out = ''; |
|
181
|
|
|
|
|
182
|
|
|
$backtopagejsfieldsid = ''; |
|
183
|
|
|
$backtopagejsfieldslabel = ''; |
|
184
|
|
|
if ($backtopagejsfields) { |
|
185
|
|
|
$tmpbacktopagejsfields = explode(':', $backtopagejsfields); |
|
186
|
|
|
if (empty($tmpbacktopagejsfields[1])) { // If the part 'keyforpopupid:' is missing, we add $name for it. |
|
187
|
|
|
$backtopagejsfields = $name . ":" . $backtopagejsfields; |
|
188
|
|
|
$tmp2backtopagejsfields = explode(',', $tmpbacktopagejsfields[0]); |
|
189
|
|
|
} else { |
|
190
|
|
|
$tmp2backtopagejsfields = explode(',', $tmpbacktopagejsfields[1]); |
|
191
|
|
|
} |
|
192
|
|
|
$backtopagejsfieldsid = empty($tmp2backtopagejsfields[0]) ? '' : $tmp2backtopagejsfields[0]; |
|
193
|
|
|
$backtopagejsfieldslabel = empty($tmp2backtopagejsfields[1]) ? '' : $tmp2backtopagejsfields[1]; |
|
194
|
|
|
$url .= '&backtopagejsfields=' . urlencode($backtopagejsfields); |
|
195
|
|
|
} |
|
196
|
|
|
|
|
197
|
|
|
//print '<input type="submit" class="button bordertransp"'.$disabled.' value="'.dol_escape_htmltag($langs->trans("MediaFiles")).'" name="file_manager">'; |
|
198
|
|
|
$out .= '<!-- a link for button to open url into a dialog popup with backtopagejsfields = ' . $backtopagejsfields . ' -->'; |
|
199
|
|
|
$out .= '<a ' . ($accesskey ? ' accesskey="' . $accesskey . '"' : '') . ' class="cursorpointer reposition button_' . $name . ($morecss ? ' ' . $morecss : '') . '"' . $disabled . ' title="' . dol_escape_htmltag($label) . '"'; |
|
200
|
|
|
if (empty($conf->use_javascript_ajax)) { |
|
201
|
|
|
$out .= ' href="' . constant('DOL_URL_ROOT') . $url . '" target="_blank"'; |
|
202
|
|
|
} elseif ($jsonopen) { |
|
203
|
|
|
$out .= ' href="#" onclick="' . $jsonopen . '"'; |
|
204
|
|
|
} else { |
|
205
|
|
|
$out .= ' href="#"'; |
|
206
|
|
|
} |
|
207
|
|
|
$out .= '>' . $buttonstring . '</a>'; |
|
208
|
|
|
|
|
209
|
|
|
if (!empty($conf->use_javascript_ajax)) { |
|
210
|
|
|
// Add code to open url using the popup. Add also hidden field to retrieve the returned variables |
|
211
|
|
|
$out .= '<!-- code to open popup and variables to retrieve returned variables -->'; |
|
212
|
|
|
$out .= '<div id="idfordialog' . $name . '" class="hidden">' . (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2 ? 'div for dialog' : '') . '</div>'; |
|
213
|
|
|
$out .= '<div id="varforreturndialogid' . $name . '" class="hidden">' . (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2 ? 'div for returned id' : '') . '</div>'; |
|
214
|
|
|
$out .= '<div id="varforreturndialoglabel' . $name . '" class="hidden">' . (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2 ? 'div for returned label' : '') . '</div>'; |
|
215
|
|
|
|
|
216
|
|
|
$out .= '<!-- Add js code to open dialog popup on dialog -->'; |
|
217
|
|
|
$out .= '<script nonce="' . getNonce() . '" type="text/javascript"> |
|
218
|
|
|
jQuery(document).ready(function () { |
|
219
|
|
|
jQuery(".button_' . $name . '").click(function () { |
|
220
|
|
|
console.log(\'Open popup with jQuery(...).dialog() on URL ' . dol_escape_js(DOL_URL_ROOT . $url) . '\'); |
|
221
|
|
|
var $tmpdialog = $(\'#idfordialog' . $name . '\'); |
|
222
|
|
|
$tmpdialog.html(\'<iframe class="iframedialog" id="iframedialog' . $name . '" style="border: 0px;" src="' . constant('DOL_URL_ROOT') . $url . '" width="100%" height="98%"></iframe>\'); |
|
223
|
|
|
$tmpdialog.dialog({ |
|
224
|
|
|
autoOpen: false, |
|
225
|
|
|
modal: true, |
|
226
|
|
|
height: (window.innerHeight - 150), |
|
227
|
|
|
width: \'80%\', |
|
228
|
|
|
title: \'' . dol_escape_js($label) . '\', |
|
229
|
|
|
open: function (event, ui) { |
|
230
|
|
|
console.log("open popup name=' . $name . ', backtopagejsfields=' . $backtopagejsfields . '"); |
|
231
|
|
|
}, |
|
232
|
|
|
close: function (event, ui) { |
|
233
|
|
|
var returnedid = jQuery("#varforreturndialogid' . $name . '").text(); |
|
234
|
|
|
var returnedlabel = jQuery("#varforreturndialoglabel' . $name . '").text(); |
|
235
|
|
|
console.log("popup has been closed. returnedid (js var defined into parent page)="+returnedid+" returnedlabel="+returnedlabel); |
|
236
|
|
|
if (returnedid != "" && returnedid != "div for returned id") { |
|
237
|
|
|
jQuery("#' . (empty($backtopagejsfieldsid) ? "none" : $backtopagejsfieldsid) . '").val(returnedid); |
|
238
|
|
|
} |
|
239
|
|
|
if (returnedlabel != "" && returnedlabel != "div for returned label") { |
|
240
|
|
|
jQuery("#' . (empty($backtopagejsfieldslabel) ? "none" : $backtopagejsfieldslabel) . '").val(returnedlabel); |
|
241
|
|
|
} |
|
242
|
|
|
} |
|
243
|
|
|
}); |
|
244
|
|
|
|
|
245
|
|
|
$tmpdialog.dialog(\'open\'); |
|
246
|
|
|
return false; |
|
247
|
|
|
}); |
|
248
|
|
|
}); |
|
249
|
|
|
</script>'; |
|
250
|
|
|
} |
|
251
|
|
|
return $out; |
|
252
|
|
|
} |
|
253
|
|
|
|
|
254
|
|
|
/** |
|
255
|
|
|
* Show tabs of a record |
|
256
|
|
|
* |
|
257
|
|
|
* @param array<int,array<int<0,5>,string>> $links Array of tabs (0=>url, 1=>label, 2=>code, 3=>not used, 4=>text after link, 5=>morecssonlink). Currently initialized by calling a function xxx_admin_prepare_head. Note that label into $links[$i][1] must be already HTML escaped. |
|
|
|
|
|
|
258
|
|
|
* @param string $active Active tab name |
|
259
|
|
|
* @param string $title Title |
|
260
|
|
|
* @param int $notab -1 or 0=Add tab header, 1=no tab header (if you set this to 1, using print dol_get_fiche_end() to close tab is not required), -2=Add tab header with no separation under tab (to start a tab just after), -3=-2+'noborderbottom' |
|
261
|
|
|
* @param string $picto Add a picto on tab title |
|
262
|
|
|
* @param int $pictoisfullpath If 1, image path is a full path. If you set this to 1, you can use url returned by dol_buildpath('/mymodyle/img/myimg.png',1) for $picto. |
|
263
|
|
|
* @param string $morehtmlright Add more html content on right of tabs title |
|
264
|
|
|
* @param string $morecss More CSS on the link <a> |
|
265
|
|
|
* @param int $limittoshow Limit number of tabs to show. Use 0 to use automatic default value. |
|
266
|
|
|
* @param string $moretabssuffix A suffix to use when you have several dol_get_fiche_head() in same page |
|
267
|
|
|
* @param int $dragdropfile 0 (default) or 1. 1 enable a drop zone for file to be upload, 0 disable it |
|
268
|
|
|
* @return string |
|
269
|
|
|
*/ |
|
270
|
|
|
function dol_get_fiche_head($links = array(), $active = '', $title = '', $notab = 0, $picto = '', $pictoisfullpath = 0, $morehtmlright = '', $morecss = '', $limittoshow = 0, $moretabssuffix = '', $dragdropfile = 0) |
|
271
|
|
|
{ |
|
272
|
|
|
global $conf, $langs, $hookmanager; |
|
273
|
|
|
|
|
274
|
|
|
// Show title |
|
275
|
|
|
$showtitle = 1; |
|
276
|
|
|
if (!empty($conf->dol_optimize_smallscreen)) { |
|
277
|
|
|
$showtitle = 0; |
|
278
|
|
|
} |
|
279
|
|
|
|
|
280
|
|
|
$out = "\n" . '<!-- dol_fiche_head - dol_get_fiche_head -->'; |
|
281
|
|
|
|
|
282
|
|
|
if ((!empty($title) && $showtitle) || $morehtmlright || !empty($links)) { |
|
283
|
|
|
$out .= '<div class="tabs' . ($picto ? '' : ' nopaddingleft') . '" data-role="controlgroup" data-type="horizontal">' . "\n"; |
|
284
|
|
|
} |
|
285
|
|
|
|
|
286
|
|
|
// Show right part |
|
287
|
|
|
if ($morehtmlright) { |
|
288
|
|
|
$out .= '<div class="inline-block floatright tabsElem">' . $morehtmlright . '</div>'; // Output right area first so when space is missing, text is in front of tabs and not under. |
|
289
|
|
|
} |
|
290
|
|
|
|
|
291
|
|
|
// Show title |
|
292
|
|
|
if (!empty($title) && $showtitle && !getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
|
293
|
|
|
$limittitle = 30; |
|
294
|
|
|
$out .= '<a class="tabTitle">'; |
|
295
|
|
|
if ($picto) { |
|
296
|
|
|
$noprefix = $pictoisfullpath; |
|
297
|
|
|
if (strpos($picto, 'fontawesome_') !== false) { |
|
298
|
|
|
$noprefix = 1; |
|
299
|
|
|
} |
|
300
|
|
|
$out .= img_picto($title, ($noprefix ? '' : 'object_') . $picto, '', $pictoisfullpath, 0, 0, '', 'imgTabTitle') . ' '; |
|
301
|
|
|
} |
|
302
|
|
|
$out .= '<span class="tabTitleText">' . dol_escape_htmltag(dol_trunc($title, $limittitle)) . '</span>'; |
|
303
|
|
|
$out .= '</a>'; |
|
304
|
|
|
} |
|
305
|
|
|
|
|
306
|
|
|
// Show tabs |
|
307
|
|
|
|
|
308
|
|
|
// Define max of key (max may be higher than sizeof because of hole due to module disabling some tabs). |
|
309
|
|
|
$maxkey = -1; |
|
310
|
|
|
if (is_array($links) && !empty($links)) { |
|
311
|
|
|
$keys = array_keys($links); |
|
312
|
|
|
if (count($keys)) { |
|
313
|
|
|
$maxkey = max($keys); |
|
314
|
|
|
} |
|
315
|
|
|
} |
|
316
|
|
|
|
|
317
|
|
|
// Show tabs |
|
318
|
|
|
// if =0 we don't use the feature |
|
319
|
|
|
if (empty($limittoshow)) { |
|
320
|
|
|
$limittoshow = (!getDolGlobalString('MAIN_MAXTABS_IN_CARD') ? 99 : $conf->global->MAIN_MAXTABS_IN_CARD); |
|
321
|
|
|
} |
|
322
|
|
|
if (!empty($conf->dol_optimize_smallscreen)) { |
|
323
|
|
|
$limittoshow = 2; |
|
324
|
|
|
} |
|
325
|
|
|
|
|
326
|
|
|
$displaytab = 0; |
|
327
|
|
|
$nbintab = 0; |
|
328
|
|
|
$popuptab = 0; |
|
329
|
|
|
$outmore = ''; |
|
330
|
|
|
for ($i = 0; $i <= $maxkey; $i++) { |
|
331
|
|
|
if ((is_numeric($active) && $i == $active) || (!empty($links[$i][2]) && !is_numeric($active) && $active == $links[$i][2])) { |
|
332
|
|
|
// If active tab is already present |
|
333
|
|
|
if ($i >= $limittoshow) { |
|
334
|
|
|
$limittoshow--; |
|
335
|
|
|
} |
|
336
|
|
|
} |
|
337
|
|
|
} |
|
338
|
|
|
|
|
339
|
|
|
for ($i = 0; $i <= $maxkey; $i++) { |
|
340
|
|
|
if ((is_numeric($active) && $i == $active) || (!empty($links[$i][2]) && !is_numeric($active) && $active == $links[$i][2])) { |
|
341
|
|
|
$isactive = true; |
|
342
|
|
|
} else { |
|
343
|
|
|
$isactive = false; |
|
344
|
|
|
} |
|
345
|
|
|
|
|
346
|
|
|
if ($i < $limittoshow || $isactive) { |
|
347
|
|
|
// Output entry with a visible tab |
|
348
|
|
|
$out .= '<div class="inline-block tabsElem' . ($isactive ? ' tabsElemActive' : '') . ((!$isactive && getDolGlobalString('MAIN_HIDE_INACTIVETAB_ON_PRINT')) ? ' hideonprint' : '') . '"><!-- id tab = ' . (empty($links[$i][2]) ? '' : dol_escape_htmltag($links[$i][2])) . ' -->'; |
|
349
|
|
|
|
|
350
|
|
|
if (isset($links[$i][2]) && $links[$i][2] == 'image') { |
|
351
|
|
|
if (!empty($links[$i][0])) { |
|
352
|
|
|
$out .= '<a class="tabimage' . ($morecss ? ' ' . $morecss : '') . '" href="' . $links[$i][0] . '">' . $links[$i][1] . '</a>' . "\n"; |
|
353
|
|
|
} else { |
|
354
|
|
|
$out .= '<span class="tabspan">' . $links[$i][1] . '</span>' . "\n"; |
|
355
|
|
|
} |
|
356
|
|
|
} elseif (!empty($links[$i][1])) { |
|
357
|
|
|
//print "x $i $active ".$links[$i][2]." z"; |
|
358
|
|
|
$out .= '<div class="tab tab' . ($isactive ? 'active' : 'unactive') . '" style="margin: 0 !important">'; |
|
359
|
|
|
if (!empty($links[$i][0])) { |
|
360
|
|
|
$titletoshow = preg_replace('/<.*$/', '', $links[$i][1]); |
|
361
|
|
|
$out .= '<a' . (!empty($links[$i][2]) ? ' id="' . $links[$i][2] . '"' : '') . ' class="tab inline-block valignmiddle' . ($morecss ? ' ' . $morecss : '') . (!empty($links[$i][5]) ? ' ' . $links[$i][5] : '') . '" href="' . $links[$i][0] . '" title="' . dol_escape_htmltag($titletoshow) . '">'; |
|
362
|
|
|
} |
|
363
|
|
|
$out .= $links[$i][1]; |
|
364
|
|
|
if (!empty($links[$i][0])) { |
|
365
|
|
|
$out .= '</a>' . "\n"; |
|
366
|
|
|
} |
|
367
|
|
|
$out .= empty($links[$i][4]) ? '' : $links[$i][4]; |
|
368
|
|
|
$out .= '</div>'; |
|
369
|
|
|
} |
|
370
|
|
|
|
|
371
|
|
|
$out .= '</div>'; |
|
372
|
|
|
} else { |
|
373
|
|
|
// Add entry into the combo popup with the other tabs |
|
374
|
|
|
if (!$popuptab) { |
|
375
|
|
|
$popuptab = 1; |
|
376
|
|
|
$outmore .= '<div class="popuptabset wordwrap">'; // The css used to hide/show popup |
|
377
|
|
|
} |
|
378
|
|
|
$outmore .= '<div class="popuptab wordwrap" style="display:inherit;">'; |
|
379
|
|
|
if (isset($links[$i][2]) && $links[$i][2] == 'image') { |
|
380
|
|
|
if (!empty($links[$i][0])) { |
|
381
|
|
|
$outmore .= '<a class="tabimage' . ($morecss ? ' ' . $morecss : '') . '" href="' . $links[$i][0] . '">' . $links[$i][1] . '</a>' . "\n"; |
|
382
|
|
|
} else { |
|
383
|
|
|
$outmore .= '<span class="tabspan">' . $links[$i][1] . '</span>' . "\n"; |
|
384
|
|
|
} |
|
385
|
|
|
} elseif (!empty($links[$i][1])) { |
|
386
|
|
|
$outmore .= '<a' . (!empty($links[$i][2]) ? ' id="' . $links[$i][2] . '"' : '') . ' class="wordwrap inline-block' . ($morecss ? ' ' . $morecss : '') . '" href="' . $links[$i][0] . '">'; |
|
387
|
|
|
$outmore .= preg_replace('/([a-z])\|([a-z])/i', '\\1 | \\2', $links[$i][1]); // Replace x|y with x | y to allow wrap on long composed texts. |
|
388
|
|
|
$outmore .= '</a>' . "\n"; |
|
389
|
|
|
} |
|
390
|
|
|
$outmore .= '</div>'; |
|
391
|
|
|
|
|
392
|
|
|
$nbintab++; |
|
393
|
|
|
} |
|
394
|
|
|
$displaytab = $i; |
|
395
|
|
|
} |
|
396
|
|
|
if ($popuptab) { |
|
397
|
|
|
$outmore .= '</div>'; |
|
398
|
|
|
} |
|
399
|
|
|
|
|
400
|
|
|
if ($popuptab) { // If there is some tabs not shown |
|
401
|
|
|
$left = ($langs->trans("DIRECTION") == 'rtl' ? 'right' : 'left'); |
|
402
|
|
|
$right = ($langs->trans("DIRECTION") == 'rtl' ? 'left' : 'right'); |
|
403
|
|
|
$widthofpopup = 200; |
|
404
|
|
|
|
|
405
|
|
|
$tabsname = $moretabssuffix; |
|
406
|
|
|
if (empty($tabsname)) { |
|
407
|
|
|
$tabsname = str_replace("@", "", $picto); |
|
408
|
|
|
} |
|
409
|
|
|
$out .= '<div id="moretabs' . $tabsname . '" class="inline-block tabsElem valignmiddle">'; |
|
410
|
|
|
if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2) { |
|
411
|
|
|
$out .= '<div class="tab valignmiddle"><a href="#" class="tab moretab inline-block tabunactive valignmiddle"><span class="hideonsmartphone">' . $langs->trans("More") . '</span>... (' . $nbintab . ')</a></div>'; // Do not use "reposition" class in the "More". |
|
412
|
|
|
} |
|
413
|
|
|
$out .= '<div id="moretabsList' . $tabsname . '" style="width: ' . $widthofpopup . 'px; position: absolute; ' . $left . ': -999em; text-align: ' . $left . '; margin:0px; padding:2px; z-index:10;">'; |
|
414
|
|
|
$out .= $outmore; |
|
415
|
|
|
$out .= '</div>'; |
|
416
|
|
|
$out .= '<div></div>'; |
|
417
|
|
|
$out .= "</div>\n"; |
|
418
|
|
|
|
|
419
|
|
|
$out .= '<script nonce="' . getNonce() . '">'; |
|
420
|
|
|
$out .= "$('#moretabs" . $tabsname . "').mouseenter( function() { |
|
421
|
|
|
var x = this.offsetLeft, y = this.offsetTop; |
|
422
|
|
|
console.log('mouseenter " . $left . " x='+x+' y='+y+' window.innerWidth='+window.innerWidth); |
|
423
|
|
|
if ((window.innerWidth - x) < " . ($widthofpopup + 10) . ") { |
|
424
|
|
|
$('#moretabsList" . $tabsname . "').css('" . $right . "','8px'); |
|
425
|
|
|
} |
|
426
|
|
|
$('#moretabsList" . $tabsname . "').css('" . $left . "','auto'); |
|
427
|
|
|
}); |
|
428
|
|
|
"; |
|
429
|
|
|
$out .= "$('#moretabs" . $tabsname . "').mouseleave( function() { console.log('mouseleave " . $left . "'); $('#moretabsList" . $tabsname . "').css('" . $left . "','-999em');});"; |
|
430
|
|
|
$out .= "</script>"; |
|
431
|
|
|
} |
|
432
|
|
|
|
|
433
|
|
|
if ((!empty($title) && $showtitle) || $morehtmlright || !empty($links)) { |
|
434
|
|
|
$out .= "</div>\n"; |
|
435
|
|
|
} |
|
436
|
|
|
|
|
437
|
|
|
if (!$notab || $notab == -1 || $notab == -2 || $notab == -3) { |
|
438
|
|
|
$out .= "\n" . '<div id="dragDropAreaTabBar" class="tabBar' . ($notab == -1 ? '' : ($notab == -2 ? ' tabBarNoTop' : (($notab == -3 ? ' noborderbottom' : '') . ' tabBarWithBottom'))); |
|
439
|
|
|
$out .= '">' . "\n"; |
|
440
|
|
|
} |
|
441
|
|
|
if (!empty($dragdropfile)) { |
|
442
|
|
|
include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; |
|
443
|
|
|
$out .= dragAndDropFileUpload("dragDropAreaTabBar"); |
|
444
|
|
|
} |
|
445
|
|
|
$parameters = array('tabname' => $active, 'out' => $out); |
|
446
|
|
|
$reshook = $hookmanager->executeHooks('printTabsHead', $parameters); // This hook usage is called just before output the head of tabs. Take also a look at "completeTabsHead" |
|
447
|
|
|
if ($reshook > 0) { |
|
448
|
|
|
$out = $hookmanager->resPrint; |
|
449
|
|
|
} |
|
450
|
|
|
|
|
451
|
|
|
return $out; |
|
452
|
|
|
} |
|
453
|
|
|
|
|
454
|
|
|
/** |
|
455
|
|
|
* Show tab footer of a card. |
|
456
|
|
|
* Note: $object->next_prev_filter can be set to restrict select to find next or previous record by $form->showrefnav. |
|
457
|
|
|
* |
|
458
|
|
|
* @param CommonObject $object Object to show |
|
459
|
|
|
* @param string $paramid Name of parameter to use to name the id into the URL next/previous link |
|
460
|
|
|
* @param string $morehtml More html content to output just before the nav bar |
|
461
|
|
|
* @param int $shownav Show Condition (navigation is shown if value is 1) |
|
462
|
|
|
* @param string $fieldid Name of the field in DB to use to select next et previous (we make the select max and min on this field). Use 'none' for no prev/next search. |
|
463
|
|
|
* @param string $fieldref Name of the field (object->ref) to use to select next et previous |
|
464
|
|
|
* @param string $morehtmlref More html to show after the ref (see $morehtmlleft for before) |
|
465
|
|
|
* @param string $moreparam More param to add in nav link url. |
|
466
|
|
|
* @param int $nodbprefix Do not include DB prefix to forge table name |
|
467
|
|
|
* @param string $morehtmlleft More html code to show before the ref (see $morehtmlref for after) |
|
468
|
|
|
* @param string $morehtmlstatus More html code to show under navigation arrows |
|
469
|
|
|
* @param int $onlybanner Put this to 1, if the card will contains only a banner (this add css 'arearefnobottom' on div) |
|
470
|
|
|
* @param string $morehtmlright More html code to show before navigation arrows |
|
471
|
|
|
* @return void |
|
472
|
|
|
*/ |
|
473
|
|
|
function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldid = 'rowid', $fieldref = 'ref', $morehtmlref = '', $moreparam = '', $nodbprefix = 0, $morehtmlleft = '', $morehtmlstatus = '', $onlybanner = 0, $morehtmlright = '') |
|
474
|
|
|
{ |
|
475
|
|
|
global $conf, $form, $user, $langs, $hookmanager, $action; |
|
476
|
|
|
|
|
477
|
|
|
$error = 0; |
|
478
|
|
|
|
|
479
|
|
|
$maxvisiblephotos = 1; |
|
480
|
|
|
$showimage = 1; |
|
481
|
|
|
$entity = (empty($object->entity) ? $conf->entity : $object->entity); |
|
482
|
|
|
// @phan-suppress-next-line PhanUndeclaredMethod |
|
483
|
|
|
$showbarcode = !isModEnabled('barcode') ? 0 : (empty($object->barcode) ? 0 : 1); |
|
|
|
|
|
|
484
|
|
|
if (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !$user->hasRight('barcode', 'lire_advance')) { |
|
485
|
|
|
$showbarcode = 0; |
|
486
|
|
|
} |
|
487
|
|
|
$modulepart = 'unknown'; |
|
488
|
|
|
|
|
489
|
|
|
if (in_array($object->element, ['societe', 'contact', 'product', 'ticket', 'bom'])) { |
|
490
|
|
|
$modulepart = $object->element; |
|
491
|
|
|
} elseif ($object->element == 'member') { |
|
492
|
|
|
$modulepart = 'memberphoto'; |
|
493
|
|
|
} elseif ($object->element == 'user') { |
|
494
|
|
|
$modulepart = 'userphoto'; |
|
495
|
|
|
} |
|
496
|
|
|
|
|
497
|
|
|
if (class_exists("Imagick")) { |
|
498
|
|
|
if ($object->element == 'expensereport' || $object->element == 'propal' || $object->element == 'commande' || $object->element == 'facture' || $object->element == 'supplier_proposal') { |
|
499
|
|
|
$modulepart = $object->element; |
|
500
|
|
|
} elseif ($object->element == 'fichinter' || $object->element == 'intervention') { |
|
501
|
|
|
$modulepart = 'ficheinter'; |
|
502
|
|
|
} elseif ($object->element == 'contrat' || $object->element == 'contract') { |
|
503
|
|
|
$modulepart = 'contract'; |
|
504
|
|
|
} elseif ($object->element == 'order_supplier') { |
|
505
|
|
|
$modulepart = 'supplier_order'; |
|
506
|
|
|
} elseif ($object->element == 'invoice_supplier') { |
|
507
|
|
|
$modulepart = 'supplier_invoice'; |
|
508
|
|
|
} |
|
509
|
|
|
} |
|
510
|
|
|
|
|
511
|
|
|
if ($object->element == 'product') { |
|
512
|
|
|
/** @var Product $object */ |
|
513
|
|
|
'@phan-var-force Product $object'; |
|
514
|
|
|
$width = 80; |
|
515
|
|
|
$cssclass = 'photowithmargin photoref'; |
|
516
|
|
|
$showimage = $object->is_photo_available($conf->product->multidir_output[$entity]); |
|
517
|
|
|
$maxvisiblephotos = getDolGlobalInt('PRODUCT_MAX_VISIBLE_PHOTO', 5); |
|
518
|
|
|
if ($conf->browser->layout == 'phone') { |
|
519
|
|
|
$maxvisiblephotos = 1; |
|
520
|
|
|
} |
|
521
|
|
|
if ($showimage) { |
|
522
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">' . $object->show_photos('product', $conf->product->multidir_output[$entity], 1, $maxvisiblephotos, 0, 0, 0, 0, $width, 0, '') . '</div>'; |
|
523
|
|
|
} else { |
|
524
|
|
|
if (getDolGlobalString('PRODUCT_NODISPLAYIFNOPHOTO')) { |
|
525
|
|
|
$nophoto = ''; |
|
526
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"></div>'; |
|
527
|
|
|
} else { // Show no photo link |
|
528
|
|
|
$nophoto = '/public/theme/common/nophoto.png'; |
|
529
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" title="' . dol_escape_htmltag($langs->trans("UploadAnImageToSeeAPhotoHere", $langs->transnoentitiesnoconv("Documents"))) . '" alt="No photo"' . ($width ? ' style="width: ' . $width . 'px"' : '') . ' src="' . constant('DOL_URL_ROOT') . $nophoto . '"></div>'; |
|
530
|
|
|
} |
|
531
|
|
|
} |
|
532
|
|
|
} elseif ($object->element == 'category') { |
|
533
|
|
|
/** @var Categorie $object */ |
|
534
|
|
|
'@phan-var-force Categorie $object'; |
|
535
|
|
|
$width = 80; |
|
536
|
|
|
$cssclass = 'photowithmargin photoref'; |
|
537
|
|
|
$showimage = $object->isAnyPhotoAvailable($conf->categorie->multidir_output[$entity]); |
|
538
|
|
|
$maxvisiblephotos = getDolGlobalInt('CATEGORY_MAX_VISIBLE_PHOTO', 5); |
|
539
|
|
|
if ($conf->browser->layout == 'phone') { |
|
540
|
|
|
$maxvisiblephotos = 1; |
|
541
|
|
|
} |
|
542
|
|
|
if ($showimage) { |
|
543
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">' . $object->show_photos('category', $conf->categorie->multidir_output[$entity], 'small', $maxvisiblephotos, 0, 0, 0, 0, $width, 0, '') . '</div>'; |
|
544
|
|
|
} else { |
|
545
|
|
|
if (getDolGlobalString('CATEGORY_NODISPLAYIFNOPHOTO')) { |
|
546
|
|
|
$nophoto = ''; |
|
547
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"></div>'; |
|
548
|
|
|
} else { // Show no photo link |
|
549
|
|
|
$nophoto = '/public/theme/common/nophoto.png'; |
|
550
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" title="' . dol_escape_htmltag($langs->trans("UploadAnImageToSeeAPhotoHere", $langs->transnoentitiesnoconv("Documents"))) . '" alt="No photo"' . ($width ? ' style="width: ' . $width . 'px"' : '') . ' src="' . constant('DOL_URL_ROOT') . $nophoto . '"></div>'; |
|
551
|
|
|
} |
|
552
|
|
|
} |
|
553
|
|
|
} elseif ($object->element == 'bom') { |
|
554
|
|
|
/** @var BOM $object */ |
|
555
|
|
|
'@phan-var-force Bom $object'; |
|
556
|
|
|
$width = 80; |
|
557
|
|
|
$cssclass = 'photowithmargin photoref'; |
|
558
|
|
|
$showimage = $object->is_photo_available($conf->bom->multidir_output[$entity]); |
|
559
|
|
|
$maxvisiblephotos = getDolGlobalInt('BOM_MAX_VISIBLE_PHOTO', 5); |
|
560
|
|
|
if ($conf->browser->layout == 'phone') { |
|
561
|
|
|
$maxvisiblephotos = 1; |
|
562
|
|
|
} |
|
563
|
|
|
if ($showimage) { |
|
564
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">' . $object->show_photos('bom', $conf->bom->multidir_output[$entity], 'small', $maxvisiblephotos, 0, 0, 0, 0, $width, 0, '') . '</div>'; |
|
565
|
|
|
} else { |
|
566
|
|
|
if (getDolGlobalString('BOM_NODISPLAYIFNOPHOTO')) { |
|
567
|
|
|
$nophoto = ''; |
|
568
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"></div>'; |
|
569
|
|
|
} else { // Show no photo link |
|
570
|
|
|
$nophoto = '/public/theme/common/nophoto.png'; |
|
571
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" title="' . dol_escape_htmltag($langs->trans("UploadAnImageToSeeAPhotoHere", $langs->transnoentitiesnoconv("Documents"))) . '" alt="No photo"' . ($width ? ' style="width: ' . $width . 'px"' : '') . ' src="' . constant('DOL_URL_ROOT') . $nophoto . '"></div>'; |
|
572
|
|
|
} |
|
573
|
|
|
} |
|
574
|
|
|
} elseif ($object->element == 'ticket') { |
|
575
|
|
|
$width = 80; |
|
576
|
|
|
$cssclass = 'photoref'; |
|
577
|
|
|
/** @var Ticket $object */ |
|
578
|
|
|
'@phan-var-force Ticket $object'; |
|
579
|
|
|
$showimage = $object->is_photo_available($conf->ticket->multidir_output[$entity] . '/' . $object->ref); |
|
580
|
|
|
$maxvisiblephotos = getDolGlobalInt('TICKET_MAX_VISIBLE_PHOTO', 2); |
|
581
|
|
|
if ($conf->browser->layout == 'phone') { |
|
582
|
|
|
$maxvisiblephotos = 1; |
|
583
|
|
|
} |
|
584
|
|
|
|
|
585
|
|
|
if ($showimage) { |
|
586
|
|
|
$showphoto = $object->show_photos('ticket', $conf->ticket->multidir_output[$entity], 'small', $maxvisiblephotos, 0, 0, 0, $width, 0); |
|
587
|
|
|
if ($object->nbphoto > 0) { |
|
588
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">' . $showphoto . '</div>'; |
|
589
|
|
|
} else { |
|
590
|
|
|
$showimage = 0; |
|
591
|
|
|
} |
|
592
|
|
|
} |
|
593
|
|
|
if (!$showimage) { |
|
594
|
|
|
if (getDolGlobalString('TICKET_NODISPLAYIFNOPHOTO')) { |
|
595
|
|
|
$nophoto = ''; |
|
596
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"></div>'; |
|
597
|
|
|
} else { // Show no photo link |
|
598
|
|
|
$nophoto = img_picto('No photo', 'object_ticket'); |
|
599
|
|
|
$morehtmlleft .= '<!-- No photo to show -->'; |
|
600
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref">'; |
|
601
|
|
|
$morehtmlleft .= $nophoto; |
|
602
|
|
|
$morehtmlleft .= '</div></div>'; |
|
603
|
|
|
} |
|
604
|
|
|
} |
|
605
|
|
|
} else { |
|
606
|
|
|
if ($showimage) { |
|
607
|
|
|
if ($modulepart != 'unknown' || method_exists($object, 'getDataToShowPhoto')) { |
|
608
|
|
|
$phototoshow = ''; |
|
609
|
|
|
// Check if a preview file is available |
|
610
|
|
|
if (in_array($modulepart, array('propal', 'commande', 'facture', 'ficheinter', 'contract', 'supplier_order', 'supplier_proposal', 'supplier_invoice', 'expensereport')) && class_exists("Imagick")) { |
|
611
|
|
|
$objectref = dol_sanitizeFileName($object->ref); |
|
612
|
|
|
$dir_output = (empty($conf->$modulepart->multidir_output[$entity]) ? $conf->$modulepart->dir_output : $conf->$modulepart->multidir_output[$entity]) . "/"; |
|
613
|
|
|
if (in_array($modulepart, array('invoice_supplier', 'supplier_invoice'))) { |
|
614
|
|
|
$subdir = get_exdir($object->id, 2, 0, 1, $object, $modulepart); |
|
615
|
|
|
$subdir .= ((!empty($subdir) && !preg_match('/\/$/', $subdir)) ? '/' : '') . $objectref; // the objectref dir is not included into get_exdir when used with level=2, so we add it at end |
|
616
|
|
|
} else { |
|
617
|
|
|
$subdir = get_exdir($object->id, 0, 0, 1, $object, $modulepart); |
|
618
|
|
|
} |
|
619
|
|
|
if (empty($subdir)) { |
|
620
|
|
|
$subdir = 'errorgettingsubdirofobject'; // Protection to avoid to return empty path |
|
621
|
|
|
} |
|
622
|
|
|
|
|
623
|
|
|
$filepath = $dir_output . $subdir . "/"; |
|
624
|
|
|
|
|
625
|
|
|
$filepdf = $filepath . $objectref . ".pdf"; |
|
626
|
|
|
$relativepath = $subdir . '/' . $objectref . '.pdf'; |
|
627
|
|
|
|
|
628
|
|
|
// Define path to preview pdf file (preview precompiled "file.ext" are "file.ext_preview.png") |
|
629
|
|
|
$fileimage = $filepdf . '_preview.png'; |
|
630
|
|
|
$relativepathimage = $relativepath . '_preview.png'; |
|
631
|
|
|
|
|
632
|
|
|
$pdfexists = file_exists($filepdf); |
|
633
|
|
|
|
|
634
|
|
|
// If PDF file exists |
|
635
|
|
|
if ($pdfexists) { |
|
636
|
|
|
// Conversion du PDF en image png si fichier png non existent |
|
637
|
|
|
if (!file_exists($fileimage) || (filemtime($fileimage) < filemtime($filepdf))) { |
|
638
|
|
|
if (!getDolGlobalString('MAIN_DISABLE_PDF_THUMBS')) { // If you experience trouble with pdf thumb generation and imagick, you can disable here. |
|
639
|
|
|
include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; |
|
640
|
|
|
$ret = dol_convert_file($filepdf, 'png', $fileimage, '0'); // Convert first page of PDF into a file _preview.png |
|
641
|
|
|
if ($ret < 0) { |
|
642
|
|
|
$error++; |
|
643
|
|
|
} |
|
644
|
|
|
} |
|
645
|
|
|
} |
|
646
|
|
|
} |
|
647
|
|
|
|
|
648
|
|
|
if ($pdfexists && !$error) { |
|
649
|
|
|
$heightforphotref = 80; |
|
650
|
|
|
if (!empty($conf->dol_optimize_smallscreen)) { |
|
651
|
|
|
$heightforphotref = 60; |
|
652
|
|
|
} |
|
653
|
|
|
// If the preview file is found |
|
654
|
|
|
if (file_exists($fileimage)) { |
|
655
|
|
|
$phototoshow = '<div class="photoref">'; |
|
656
|
|
|
$phototoshow .= '<img height="' . $heightforphotref . '" class="photo photowithborder" src="' . constant('BASE_URL') . '/viewimage.php?modulepart=apercu' . $modulepart . '&file=' . urlencode($relativepathimage) . '">'; |
|
657
|
|
|
$phototoshow .= '</div>'; |
|
658
|
|
|
} |
|
659
|
|
|
} |
|
660
|
|
|
} elseif (!$phototoshow) { // example if modulepart = 'societe' or 'photo' or 'memberphoto' |
|
661
|
|
|
$phototoshow .= $form->showphoto($modulepart, $object, 0, 0, 0, 'photowithmargin photoref', 'small', 1, 0, $maxvisiblephotos); |
|
662
|
|
|
} |
|
663
|
|
|
|
|
664
|
|
|
if ($phototoshow) { |
|
665
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">'; |
|
666
|
|
|
$morehtmlleft .= $phototoshow; |
|
667
|
|
|
$morehtmlleft .= '</div>'; |
|
668
|
|
|
} |
|
669
|
|
|
} |
|
670
|
|
|
|
|
671
|
|
|
if (empty($phototoshow)) { // Show No photo link (picto of object) |
|
672
|
|
|
if ($object->element == 'action') { |
|
673
|
|
|
$width = 80; |
|
674
|
|
|
$cssclass = 'photorefcenter'; |
|
675
|
|
|
$nophoto = img_picto('No photo', 'title_agenda'); |
|
676
|
|
|
} else { |
|
677
|
|
|
$width = 14; |
|
678
|
|
|
$cssclass = 'photorefcenter'; |
|
679
|
|
|
$picto = $object->picto; // @phan-suppress-current-line PhanUndeclaredProperty |
|
|
|
|
|
|
680
|
|
|
$prefix = 'object_'; |
|
681
|
|
|
if ($object->element == 'project' && !$object->public) { // @phan-suppress-current-line PhanUndeclaredProperty |
|
|
|
|
|
|
682
|
|
|
$picto = 'project'; // instead of projectpub |
|
683
|
|
|
} |
|
684
|
|
|
if (strpos($picto, 'fontawesome_') !== false) { |
|
685
|
|
|
$prefix = ''; |
|
686
|
|
|
} |
|
687
|
|
|
$nophoto = img_picto('No photo', $prefix . $picto); |
|
688
|
|
|
} |
|
689
|
|
|
$morehtmlleft .= '<!-- No photo to show -->'; |
|
690
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref">'; |
|
691
|
|
|
$morehtmlleft .= $nophoto; |
|
692
|
|
|
$morehtmlleft .= '</div></div>'; |
|
693
|
|
|
} |
|
694
|
|
|
} |
|
695
|
|
|
} |
|
696
|
|
|
|
|
697
|
|
|
// Show barcode |
|
698
|
|
|
if ($showbarcode) { |
|
699
|
|
|
$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">' . $form->showbarcode($object, 100, 'photoref valignmiddle') . '</div>'; |
|
700
|
|
|
} |
|
701
|
|
|
|
|
702
|
|
|
if ($object->element == 'societe') { |
|
703
|
|
|
if (!empty($conf->use_javascript_ajax) && $user->hasRight('societe', 'creer') && getDolGlobalString('MAIN_DIRECT_STATUS_UPDATE')) { |
|
704
|
|
|
$morehtmlstatus .= ajax_object_onoff($object, 'status', 'status', 'InActivity', 'ActivityCeased'); |
|
705
|
|
|
} else { |
|
706
|
|
|
$morehtmlstatus .= $object->getLibStatut(6); |
|
|
|
|
|
|
707
|
|
|
} |
|
708
|
|
|
} elseif ($object->element == 'product') { |
|
709
|
|
|
//$morehtmlstatus.=$langs->trans("Status").' ('.$langs->trans("Sell").') '; |
|
710
|
|
|
if (!empty($conf->use_javascript_ajax) && $user->hasRight('produit', 'creer') && getDolGlobalString('MAIN_DIRECT_STATUS_UPDATE')) { |
|
711
|
|
|
$morehtmlstatus .= ajax_object_onoff($object, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell'); |
|
712
|
|
|
} else { |
|
713
|
|
|
$morehtmlstatus .= '<span class="statusrefsell">' . $object->getLibStatut(6, 0) . '</span>'; |
|
714
|
|
|
} |
|
715
|
|
|
$morehtmlstatus .= ' '; |
|
716
|
|
|
//$morehtmlstatus.=$langs->trans("Status").' ('.$langs->trans("Buy").') '; |
|
717
|
|
|
if (!empty($conf->use_javascript_ajax) && $user->hasRight('produit', 'creer') && getDolGlobalString('MAIN_DIRECT_STATUS_UPDATE')) { |
|
718
|
|
|
$morehtmlstatus .= ajax_object_onoff($object, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy'); |
|
719
|
|
|
} else { |
|
720
|
|
|
$morehtmlstatus .= '<span class="statusrefbuy">' . $object->getLibStatut(6, 1) . '</span>'; |
|
721
|
|
|
} |
|
722
|
|
|
} elseif (in_array($object->element, array('salary'))) { |
|
723
|
|
|
$tmptxt = $object->getLibStatut(6, $object->alreadypaid); |
|
|
|
|
|
|
724
|
|
|
if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3)) { |
|
725
|
|
|
$tmptxt = $object->getLibStatut(5, $object->alreadypaid); |
|
726
|
|
|
} |
|
727
|
|
|
$morehtmlstatus .= $tmptxt; |
|
728
|
|
|
} elseif (in_array($object->element, array('facture', 'invoice', 'invoice_supplier', 'chargesociales', 'loan', 'tva'))) { // TODO Move this to use ->alreadypaid |
|
729
|
|
|
$tmptxt = $object->getLibStatut(6, $object->totalpaid); |
|
730
|
|
|
if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3)) { |
|
731
|
|
|
$tmptxt = $object->getLibStatut(5, $object->totalpaid); |
|
732
|
|
|
} |
|
733
|
|
|
$morehtmlstatus .= $tmptxt; |
|
734
|
|
|
} elseif ($object->element == 'contrat' || $object->element == 'contract') { |
|
735
|
|
|
if ($object->statut == 0) { |
|
736
|
|
|
$morehtmlstatus .= $object->getLibStatut(5); |
|
737
|
|
|
} else { |
|
738
|
|
|
$morehtmlstatus .= $object->getLibStatut(4); |
|
739
|
|
|
} |
|
740
|
|
|
} elseif ($object->element == 'facturerec') { |
|
741
|
|
|
'@phan-var-force FactureRec $object'; |
|
742
|
|
|
if ($object->frequency == 0) { |
|
|
|
|
|
|
743
|
|
|
$morehtmlstatus .= $object->getLibStatut(2); |
|
744
|
|
|
} else { |
|
745
|
|
|
$morehtmlstatus .= $object->getLibStatut(5); |
|
746
|
|
|
} |
|
747
|
|
|
} elseif ($object->element == 'project_task') { |
|
748
|
|
|
$object->fk_statut = 1; |
|
|
|
|
|
|
749
|
|
|
if ($object->progress > 0) { |
|
|
|
|
|
|
750
|
|
|
$object->fk_statut = 2; |
|
751
|
|
|
} |
|
752
|
|
|
if ($object->progress >= 100) { |
|
753
|
|
|
$object->fk_statut = 3; |
|
754
|
|
|
} |
|
755
|
|
|
$tmptxt = $object->getLibStatut(5); |
|
756
|
|
|
$morehtmlstatus .= $tmptxt; // No status on task |
|
757
|
|
|
} elseif (method_exists($object, 'getLibStatut')) { // Generic case for status |
|
758
|
|
|
$tmptxt = $object->getLibStatut(6); |
|
759
|
|
|
if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3)) { |
|
760
|
|
|
$tmptxt = $object->getLibStatut(5); |
|
761
|
|
|
} |
|
762
|
|
|
$morehtmlstatus .= $tmptxt; |
|
763
|
|
|
} |
|
764
|
|
|
|
|
765
|
|
|
// Add if object was dispatched "into accountancy" |
|
766
|
|
|
if (isModEnabled('accounting') && in_array($object->element, array('bank', 'paiementcharge', 'facture', 'invoice', 'invoice_supplier', 'expensereport', 'payment_various'))) { |
|
767
|
|
|
// Note: For 'chargesociales', 'salaries'... this is the payments that are dispatched (so element = 'bank') |
|
768
|
|
|
if (method_exists($object, 'getVentilExportCompta')) { |
|
769
|
|
|
$accounted = $object->getVentilExportCompta(); |
|
|
|
|
|
|
770
|
|
|
$langs->load("accountancy"); |
|
771
|
|
|
$morehtmlstatus .= '</div><div class="statusref statusrefbis"><span class="opacitymedium">' . ($accounted > 0 ? $langs->trans("Accounted") : $langs->trans("NotYetAccounted")) . '</span>'; |
|
772
|
|
|
} |
|
773
|
|
|
} |
|
774
|
|
|
|
|
775
|
|
|
// Add alias for thirdparty |
|
776
|
|
|
if (!empty($object->name_alias)) { |
|
|
|
|
|
|
777
|
|
|
'@phan-var-force Societe $object'; |
|
778
|
|
|
$morehtmlref .= '<div class="refidno opacitymedium">' . dol_escape_htmltag($object->name_alias) . '</div>'; |
|
779
|
|
|
} |
|
780
|
|
|
|
|
781
|
|
|
// Add label |
|
782
|
|
|
if (in_array($object->element, array('product', 'bank_account', 'project_task'))) { |
|
783
|
|
|
if (!empty($object->label)) { |
|
784
|
|
|
$morehtmlref .= '<div class="refidno opacitymedium">' . $object->label . '</div>'; |
|
785
|
|
|
} |
|
786
|
|
|
} |
|
787
|
|
|
// Show address and email |
|
788
|
|
|
if (method_exists($object, 'getBannerAddress') && !in_array($object->element, array('product', 'bookmark', 'ecm_directories', 'ecm_files'))) { |
|
789
|
|
|
$moreaddress = $object->getBannerAddress('refaddress', $object); // address, email, url, social networks |
|
|
|
|
|
|
790
|
|
|
if ($moreaddress) { |
|
791
|
|
|
$morehtmlref .= '<div class="refidno refaddress">'; |
|
792
|
|
|
$morehtmlref .= $moreaddress; |
|
793
|
|
|
$morehtmlref .= '</div>'; |
|
794
|
|
|
} |
|
795
|
|
|
} |
|
796
|
|
|
if (getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && (getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') == '1' || preg_match('/' . preg_quote($object->element, '/') . '/i', $conf->global->MAIN_SHOW_TECHNICAL_ID)) && !empty($object->id)) { |
|
797
|
|
|
$morehtmlref .= '<div style="clear: both;"></div>'; |
|
798
|
|
|
$morehtmlref .= '<div class="refidno opacitymedium">'; |
|
799
|
|
|
$morehtmlref .= $langs->trans("TechnicalID") . ': ' . ((int)$object->id); |
|
800
|
|
|
$morehtmlref .= '</div>'; |
|
801
|
|
|
} |
|
802
|
|
|
|
|
803
|
|
|
$parameters = array('morehtmlref' => &$morehtmlref, 'moreparam' => &$moreparam, 'morehtmlleft' => &$morehtmlleft, 'morehtmlstatus' => &$morehtmlstatus, 'morehtmlright' => &$morehtmlright); |
|
804
|
|
|
$reshook = $hookmanager->executeHooks('formDolBanner', $parameters, $object, $action); |
|
805
|
|
|
if ($reshook < 0) { |
|
806
|
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); |
|
807
|
|
|
} elseif (empty($reshook)) { |
|
808
|
|
|
$morehtmlref .= $hookmanager->resPrint; |
|
809
|
|
|
} elseif ($reshook > 0) { |
|
810
|
|
|
$morehtmlref = $hookmanager->resPrint; |
|
811
|
|
|
} |
|
812
|
|
|
|
|
813
|
|
|
|
|
814
|
|
|
print '<div class="' . ($onlybanner ? 'arearefnobottom ' : 'arearef ') . 'heightref valignmiddle centpercent">'; |
|
815
|
|
|
print $form->showrefnav($object, $paramid, $morehtml, $shownav, $fieldid, $fieldref, $morehtmlref, $moreparam, $nodbprefix, $morehtmlleft, $morehtmlstatus, $morehtmlright); |
|
816
|
|
|
print '</div>'; |
|
817
|
|
|
print '<div class="underrefbanner clearboth"></div>'; |
|
818
|
|
|
} |
|
819
|
|
|
|
|
820
|
|
|
/** |
|
821
|
|
|
* Show a string with the label tag dedicated to the HTML edit field. |
|
822
|
|
|
* |
|
823
|
|
|
* @param string $langkey Translation key |
|
824
|
|
|
* @param string $fieldkey Key of the html select field the text refers to |
|
825
|
|
|
* @param int $fieldrequired 1=Field is mandatory |
|
826
|
|
|
* @return string |
|
827
|
|
|
* @deprecated Form::editfieldkey |
|
828
|
|
|
*/ |
|
829
|
|
|
function fieldLabel($langkey, $fieldkey, $fieldrequired = 0) |
|
830
|
|
|
{ |
|
831
|
|
|
global $langs; |
|
832
|
|
|
$ret = ''; |
|
833
|
|
|
if ($fieldrequired) { |
|
834
|
|
|
$ret .= '<span class="fieldrequired">'; |
|
835
|
|
|
} |
|
836
|
|
|
$ret .= '<label for="' . $fieldkey . '">'; |
|
837
|
|
|
$ret .= $langs->trans($langkey); |
|
838
|
|
|
$ret .= '</label>'; |
|
839
|
|
|
if ($fieldrequired) { |
|
840
|
|
|
$ret .= '</span>'; |
|
841
|
|
|
} |
|
842
|
|
|
return $ret; |
|
843
|
|
|
} |
|
844
|
|
|
|
|
845
|
|
|
/** |
|
846
|
|
|
* Return string to add class property on html element with pair/impair. |
|
847
|
|
|
* |
|
848
|
|
|
* @param boolean $var false or true |
|
849
|
|
|
* @param string $moreclass More class to add |
|
850
|
|
|
* @return string String to add class onto HTML element |
|
851
|
|
|
*/ |
|
852
|
|
|
function dol_bc($var, $moreclass = '') |
|
853
|
|
|
{ |
|
854
|
|
|
global $bc; |
|
855
|
|
|
$ret = ' ' . $bc[$var]; |
|
856
|
|
|
if ($moreclass) { |
|
857
|
|
|
$ret = preg_replace('/class=\"/', 'class="' . $moreclass . ' ', $ret); |
|
858
|
|
|
} |
|
859
|
|
|
return $ret; |
|
860
|
|
|
} |
|
861
|
|
|
|
|
862
|
|
|
/** |
|
863
|
|
|
* Show Url link |
|
864
|
|
|
* |
|
865
|
|
|
* @param string $url Url to show |
|
866
|
|
|
* @param string $target Target for link |
|
867
|
|
|
* @param int $max Max number of characters to show |
|
868
|
|
|
* @param int $withpicto With picto |
|
869
|
|
|
* @param string $morecss More CSS |
|
870
|
|
|
* @return string HTML Link |
|
871
|
|
|
*/ |
|
872
|
|
|
function dol_print_url($url, $target = '_blank', $max = 32, $withpicto = 0, $morecss = '') |
|
873
|
|
|
{ |
|
874
|
|
|
global $langs; |
|
875
|
|
|
|
|
876
|
|
|
if (empty($url)) { |
|
877
|
|
|
return ''; |
|
878
|
|
|
} |
|
879
|
|
|
|
|
880
|
|
|
$linkstart = '<a href="'; |
|
881
|
|
|
if (!preg_match('/^http/i', $url)) { |
|
882
|
|
|
$linkstart .= 'http://'; |
|
883
|
|
|
} |
|
884
|
|
|
$linkstart .= $url; |
|
885
|
|
|
$linkstart .= '"'; |
|
886
|
|
|
if ($target) { |
|
887
|
|
|
$linkstart .= ' target="' . $target . '"'; |
|
888
|
|
|
} |
|
889
|
|
|
$linkstart .= ' title="' . $langs->trans("URL") . ': ' . $url . '"'; |
|
890
|
|
|
$linkstart .= '>'; |
|
891
|
|
|
|
|
892
|
|
|
$link = ''; |
|
893
|
|
|
if (!preg_match('/^http/i', $url)) { |
|
894
|
|
|
$link .= 'http://'; |
|
895
|
|
|
} |
|
896
|
|
|
$link .= dol_trunc($url, $max); |
|
897
|
|
|
|
|
898
|
|
|
$linkend = '</a>'; |
|
899
|
|
|
|
|
900
|
|
|
if ($morecss == 'float') { // deprecated |
|
901
|
|
|
return '<div class="nospan' . ($morecss ? ' ' . $morecss : '') . '" style="margin-right: 10px">' . ($withpicto ? img_picto($langs->trans("Url"), 'globe', 'class="paddingrightonly"') : '') . $link . '</div>'; |
|
902
|
|
|
} else { |
|
903
|
|
|
return $linkstart . '<span class="nospan' . ($morecss ? ' ' . $morecss : '') . '" style="margin-right: 10px">' . ($withpicto ? img_picto('', 'globe', 'class="paddingrightonly"') : '') . $link . '</span>' . $linkend; |
|
904
|
|
|
} |
|
905
|
|
|
} |
|
906
|
|
|
|
|
907
|
|
|
/** |
|
908
|
|
|
* Show EMail link formatted for HTML output. |
|
909
|
|
|
* |
|
910
|
|
|
* @param string $email EMail to show (only email, without 'Name of recipient' before) |
|
911
|
|
|
* @param int $cid Id of contact if known |
|
912
|
|
|
* @param int $socid Id of third party if known |
|
913
|
|
|
* @param int $addlink 0=no link, 1=email has a html email link (+ link to create action if constant AGENDA_ADDACTIONFOREMAIL is on) |
|
914
|
|
|
* @param int $max Max number of characters to show |
|
915
|
|
|
* @param int $showinvalid 1=Show warning if syntax email is wrong |
|
916
|
|
|
* @param int|string $withpicto Show picto |
|
917
|
|
|
* @return string HTML Link |
|
918
|
|
|
*/ |
|
919
|
|
|
function dol_print_email($email, $cid = 0, $socid = 0, $addlink = 0, $max = 64, $showinvalid = 1, $withpicto = 0) |
|
920
|
|
|
{ |
|
921
|
|
|
global $user, $langs, $hookmanager; |
|
922
|
|
|
|
|
923
|
|
|
//global $conf; $conf->global->AGENDA_ADDACTIONFOREMAIL = 1; |
|
924
|
|
|
//$showinvalid = 1; $email = 'rrrrr'; |
|
925
|
|
|
|
|
926
|
|
|
$newemail = dol_escape_htmltag($email); |
|
927
|
|
|
|
|
928
|
|
|
if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER') && $withpicto) { |
|
929
|
|
|
$withpicto = 0; |
|
930
|
|
|
} |
|
931
|
|
|
|
|
932
|
|
|
if (empty($email)) { |
|
933
|
|
|
return ' '; |
|
934
|
|
|
} |
|
935
|
|
|
|
|
936
|
|
|
if (!empty($addlink)) { |
|
937
|
|
|
$newemail = '<a class="paddingrightonly" style="text-overflow: ellipsis;" href="'; |
|
938
|
|
|
if (!preg_match('/^mailto:/i', $email)) { |
|
939
|
|
|
$newemail .= 'mailto:'; |
|
940
|
|
|
} |
|
941
|
|
|
$newemail .= $email; |
|
942
|
|
|
$newemail .= '">'; |
|
943
|
|
|
|
|
944
|
|
|
$newemail .= ($withpicto ? img_picto($langs->trans("EMail") . ' : ' . $email, (is_numeric($withpicto) ? 'email' : $withpicto), 'class="paddingrightonly"') : ''); |
|
945
|
|
|
|
|
946
|
|
|
$newemail .= dol_trunc($email, $max); |
|
947
|
|
|
$newemail .= '</a>'; |
|
948
|
|
|
if ($showinvalid && !isValidEmail($email)) { |
|
949
|
|
|
$langs->load("errors"); |
|
950
|
|
|
$newemail .= img_warning($langs->trans("ErrorBadEMail", $email), '', 'paddingrightonly'); |
|
951
|
|
|
} |
|
952
|
|
|
|
|
953
|
|
|
if (($cid || $socid) && isModEnabled('agenda') && $user->hasRight("agenda", "myactions", "create")) { |
|
954
|
|
|
$type = 'AC_EMAIL'; |
|
955
|
|
|
$linktoaddaction = ''; |
|
956
|
|
|
if (getDolGlobalString('AGENDA_ADDACTIONFOREMAIL')) { |
|
957
|
|
|
$linktoaddaction = '<a href="' . constant('BASE_URL') . '/comm/action/card.php?action=create&backtopage=1&actioncode=' . urlencode($type) . '&contactid=' . ((int)$cid) . '&socid=' . ((int)$socid) . '">' . img_object($langs->trans("AddAction"), "calendar") . '</a>'; |
|
958
|
|
|
} |
|
959
|
|
|
if ($linktoaddaction) { |
|
960
|
|
|
$newemail = '<div>' . $newemail . ' ' . $linktoaddaction . '</div>'; |
|
961
|
|
|
} |
|
962
|
|
|
} |
|
963
|
|
|
} else { |
|
964
|
|
|
$newemail = ($withpicto ? img_picto($langs->trans("EMail") . ' : ' . $email, (is_numeric($withpicto) ? 'email' : $withpicto), 'class="paddingrightonly"') : '') . $newemail; |
|
965
|
|
|
|
|
966
|
|
|
if ($showinvalid && !isValidEmail($email)) { |
|
967
|
|
|
$langs->load("errors"); |
|
968
|
|
|
$newemail .= img_warning($langs->trans("ErrorBadEMail", $email)); |
|
969
|
|
|
} |
|
970
|
|
|
} |
|
971
|
|
|
|
|
972
|
|
|
//$rep = '<div class="nospan" style="margin-right: 10px">'; |
|
973
|
|
|
//$rep = ($withpicto ? img_picto($langs->trans("EMail").' : '.$email, (is_numeric($withpicto) ? 'email' : $withpicto), 'class="paddingrightonly"') : '').$newemail; |
|
974
|
|
|
//$rep .= '</div>'; |
|
975
|
|
|
$rep = $newemail; |
|
976
|
|
|
|
|
977
|
|
|
if ($hookmanager) { |
|
978
|
|
|
$parameters = array('cid' => $cid, 'socid' => $socid, 'addlink' => $addlink, 'picto' => $withpicto); |
|
979
|
|
|
|
|
980
|
|
|
$reshook = $hookmanager->executeHooks('printEmail', $parameters, $email); |
|
981
|
|
|
if ($reshook > 0) { |
|
982
|
|
|
$rep = ''; |
|
983
|
|
|
} |
|
984
|
|
|
$rep .= $hookmanager->resPrint; |
|
985
|
|
|
} |
|
986
|
|
|
|
|
987
|
|
|
return $rep; |
|
988
|
|
|
} |
|
989
|
|
|
|
|
990
|
|
|
/** |
|
991
|
|
|
* Show social network link |
|
992
|
|
|
* |
|
993
|
|
|
* @param string $value Social network ID to show (only skype, without 'Name of recipient' before) |
|
994
|
|
|
* @param int $cid Id of contact if known |
|
995
|
|
|
* @param int $socid Id of third party if known |
|
996
|
|
|
* @param string $type 'skype','facebook',... |
|
997
|
|
|
* @param array<string,array{rowid:int,label:string,url:string,icon:string,active:int}> $dictsocialnetworks List of socialnetworks available |
|
998
|
|
|
* @return string HTML Link |
|
999
|
|
|
*/ |
|
1000
|
|
|
function dol_print_socialnetworks($value, $cid, $socid, $type, $dictsocialnetworks = array()) |
|
1001
|
|
|
{ |
|
1002
|
|
|
global $user, $langs; |
|
1003
|
|
|
|
|
1004
|
|
|
$htmllink = $value; |
|
1005
|
|
|
|
|
1006
|
|
|
if (empty($value)) { |
|
1007
|
|
|
return ' '; |
|
1008
|
|
|
} |
|
1009
|
|
|
|
|
1010
|
|
|
if (!empty($type)) { |
|
1011
|
|
|
$htmllink = '<div class="divsocialnetwork inline-block valignmiddle">'; |
|
1012
|
|
|
// Use dictionary definition for picto $dictsocialnetworks[$type]['icon'] |
|
1013
|
|
|
$htmllink .= '<span class="fab pictofixedwidth ' . ($dictsocialnetworks[$type]['icon'] ? $dictsocialnetworks[$type]['icon'] : 'fa-link') . '"></span>'; |
|
1014
|
|
|
if ($type == 'skype') { |
|
1015
|
|
|
$htmllink .= dol_escape_htmltag($value); |
|
1016
|
|
|
$htmllink .= ' <a href="skype:'; |
|
1017
|
|
|
$htmllink .= dol_string_nospecial($value, '_', '', array('@')); |
|
1018
|
|
|
$htmllink .= '?call" alt="' . $langs->trans("Call") . ' ' . $value . '" title="' . dol_escape_htmltag($langs->trans("Call") . ' ' . $value) . '">'; |
|
1019
|
|
|
$htmllink .= '<img src="' . constant('DOL_URL_ROOT') . '/theme/common/skype_callbutton.png" border="0">'; |
|
1020
|
|
|
$htmllink .= '</a><a href="skype:'; |
|
1021
|
|
|
$htmllink .= dol_string_nospecial($value, '_', '', array('@')); |
|
1022
|
|
|
$htmllink .= '?chat" alt="' . $langs->trans("Chat") . ' ' . $value . '" title="' . dol_escape_htmltag($langs->trans("Chat") . ' ' . $value) . '">'; |
|
1023
|
|
|
$htmllink .= '<img class="paddingleft" src="' . constant('DOL_URL_ROOT') . '/theme/common/skype_chatbutton.png" border="0">'; |
|
1024
|
|
|
$htmllink .= '</a>'; |
|
1025
|
|
|
if (($cid || $socid) && isModEnabled('agenda') && $user->hasRight('agenda', 'myactions', 'create')) { |
|
1026
|
|
|
$addlink = 'AC_SKYPE'; |
|
1027
|
|
|
$link = ''; |
|
1028
|
|
|
if (getDolGlobalString('AGENDA_ADDACTIONFORSKYPE')) { |
|
1029
|
|
|
$link = '<a href="' . constant('BASE_URL') . '/comm/action/card.php?action=create&backtopage=1&actioncode=' . $addlink . '&contactid=' . $cid . '&socid=' . $socid . '">' . img_object($langs->trans("AddAction"), "calendar") . '</a>'; |
|
1030
|
|
|
} |
|
1031
|
|
|
$htmllink .= ($link ? ' ' . $link : ''); |
|
1032
|
|
|
} |
|
1033
|
|
|
} else { |
|
1034
|
|
|
$networkconstname = 'MAIN_INFO_SOCIETE_' . strtoupper($type) . '_URL'; |
|
1035
|
|
|
if (getDolGlobalString($networkconstname)) { |
|
1036
|
|
|
$link = str_replace('{socialid}', $value, getDolGlobalString($networkconstname)); |
|
1037
|
|
|
if (preg_match('/^https?:\/\//i', $link)) { |
|
1038
|
|
|
$htmllink .= '<a href="' . dol_sanitizeUrl($link, 0) . '" target="_blank" rel="noopener noreferrer">' . dol_escape_htmltag($value) . '</a>'; |
|
1039
|
|
|
} else { |
|
1040
|
|
|
$htmllink .= '<a href="' . dol_sanitizeUrl($link, 1) . '" target="_blank" rel="noopener noreferrer">' . dol_escape_htmltag($value) . '</a>'; |
|
1041
|
|
|
} |
|
1042
|
|
|
} elseif (!empty($dictsocialnetworks[$type]['url'])) { |
|
1043
|
|
|
$tmpvirginurl = preg_replace('/\/?{socialid}/', '', $dictsocialnetworks[$type]['url']); |
|
1044
|
|
|
if ($tmpvirginurl) { |
|
1045
|
|
|
$value = preg_replace('/^www\.' . preg_quote($tmpvirginurl, '/') . '\/?/', '', $value); |
|
1046
|
|
|
$value = preg_replace('/^' . preg_quote($tmpvirginurl, '/') . '\/?/', '', $value); |
|
1047
|
|
|
|
|
1048
|
|
|
$tmpvirginurl3 = preg_replace('/^https:\/\//i', 'https://www.', $tmpvirginurl); |
|
1049
|
|
|
if ($tmpvirginurl3) { |
|
1050
|
|
|
$value = preg_replace('/^www\.' . preg_quote($tmpvirginurl3, '/') . '\/?/', '', $value); |
|
1051
|
|
|
$value = preg_replace('/^' . preg_quote($tmpvirginurl3, '/') . '\/?/', '', $value); |
|
1052
|
|
|
} |
|
1053
|
|
|
|
|
1054
|
|
|
$tmpvirginurl2 = preg_replace('/^https?:\/\//i', '', $tmpvirginurl); |
|
1055
|
|
|
if ($tmpvirginurl2) { |
|
1056
|
|
|
$value = preg_replace('/^www\.' . preg_quote($tmpvirginurl2, '/') . '\/?/', '', $value); |
|
1057
|
|
|
$value = preg_replace('/^' . preg_quote($tmpvirginurl2, '/') . '\/?/', '', $value); |
|
1058
|
|
|
} |
|
1059
|
|
|
} |
|
1060
|
|
|
$link = str_replace('{socialid}', $value, $dictsocialnetworks[$type]['url']); |
|
1061
|
|
|
if (preg_match('/^https?:\/\//i', $link)) { |
|
1062
|
|
|
$htmllink .= '<a href="' . dol_sanitizeUrl($link, 0) . '" target="_blank" rel="noopener noreferrer">' . dol_escape_htmltag($value) . '</a>'; |
|
1063
|
|
|
} else { |
|
1064
|
|
|
$htmllink .= '<a href="' . dol_sanitizeUrl($link, 1) . '" target="_blank" rel="noopener noreferrer">' . dol_escape_htmltag($value) . '</a>'; |
|
1065
|
|
|
} |
|
1066
|
|
|
} else { |
|
1067
|
|
|
$htmllink .= dol_escape_htmltag($value); |
|
1068
|
|
|
} |
|
1069
|
|
|
} |
|
1070
|
|
|
$htmllink .= '</div>'; |
|
1071
|
|
|
} else { |
|
1072
|
|
|
$langs->load("errors"); |
|
1073
|
|
|
$htmllink .= img_warning($langs->trans("ErrorBadSocialNetworkValue", $value)); |
|
1074
|
|
|
} |
|
1075
|
|
|
return $htmllink; |
|
1076
|
|
|
} |
|
1077
|
|
|
|
|
1078
|
|
|
/** |
|
1079
|
|
|
* Format phone numbers according to country |
|
1080
|
|
|
* |
|
1081
|
|
|
* @param string $phone Phone number to format |
|
1082
|
|
|
* @param string $countrycode Country code to use for formatting |
|
1083
|
|
|
* @param int $cid Id of contact if known |
|
1084
|
|
|
* @param int $socid Id of third party if known |
|
1085
|
|
|
* @param string $addlink ''=no link to create action, 'AC_TEL'=add link to clicktodial (if module enabled) and add link to create event (if conf->global->AGENDA_ADDACTIONFORPHONE set), 'tel'=Force "tel:..." link |
|
1086
|
|
|
* @param string $separ Separation between numbers for a better visibility example : xx.xx.xx.xx.xx. You can also use 'hidenum' to hide the number, keep only the picto. |
|
1087
|
|
|
* @param string $withpicto Show picto ('fax', 'phone', 'mobile') |
|
1088
|
|
|
* @param string $titlealt Text to show on alt |
|
1089
|
|
|
* @param int $adddivfloat Add div float around phone. |
|
1090
|
|
|
* @param string $morecss Add more css |
|
1091
|
|
|
* @return string Formatted phone number |
|
1092
|
|
|
*/ |
|
1093
|
|
|
function dol_print_phone($phone, $countrycode = '', $cid = 0, $socid = 0, $addlink = '', $separ = " ", $withpicto = '', $titlealt = '', $adddivfloat = 0, $morecss = '') |
|
1094
|
|
|
{ |
|
1095
|
|
|
global $conf, $user, $langs, $mysoc, $hookmanager; |
|
1096
|
|
|
|
|
1097
|
|
|
// Clean phone parameter |
|
1098
|
|
|
$phone = is_null($phone) ? '' : preg_replace("/[\s.-]/", "", trim($phone)); |
|
1099
|
|
|
if (empty($phone)) { |
|
1100
|
|
|
return ''; |
|
1101
|
|
|
} |
|
1102
|
|
|
if (getDolGlobalString('MAIN_PHONE_SEPAR')) { |
|
1103
|
|
|
$separ = getDolGlobalString('MAIN_PHONE_SEPAR'); |
|
1104
|
|
|
} |
|
1105
|
|
|
if (empty($countrycode) && is_object($mysoc)) { |
|
1106
|
|
|
$countrycode = $mysoc->country_code; |
|
1107
|
|
|
} |
|
1108
|
|
|
|
|
1109
|
|
|
// Short format for small screens |
|
1110
|
|
|
if (!empty($conf->dol_optimize_smallscreen) && $separ != 'hidenum') { |
|
1111
|
|
|
$separ = ''; |
|
1112
|
|
|
} |
|
1113
|
|
|
|
|
1114
|
|
|
$newphone = $phone; |
|
1115
|
|
|
$newphonewa = $phone; |
|
1116
|
|
|
if (strtoupper($countrycode) == "FR") { |
|
1117
|
|
|
// France |
|
1118
|
|
|
if (dol_strlen($phone) == 10) { |
|
1119
|
|
|
$newphone = substr($newphone, 0, 2) . $separ . substr($newphone, 2, 2) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2); |
|
1120
|
|
|
} elseif (dol_strlen($phone) == 7) { |
|
1121
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 2); |
|
1122
|
|
|
} elseif (dol_strlen($phone) == 9) { |
|
1123
|
|
|
$newphone = substr($newphone, 0, 2) . $separ . substr($newphone, 2, 3) . $separ . substr($newphone, 5, 2) . $separ . substr($newphone, 7, 2); |
|
1124
|
|
|
} elseif (dol_strlen($phone) == 11) { |
|
1125
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 2) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2); |
|
1126
|
|
|
} elseif (dol_strlen($phone) == 12) { |
|
1127
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 1) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2); |
|
1128
|
|
|
} elseif (dol_strlen($phone) == 13) { |
|
1129
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 3) . $separ . substr($newphone, 11, 2); |
|
1130
|
|
|
} |
|
1131
|
|
|
} elseif (strtoupper($countrycode) == "CA") { |
|
1132
|
|
|
if (dol_strlen($phone) == 10) { |
|
1133
|
|
|
$newphone = ($separ != '' ? '(' : '') . substr($newphone, 0, 3) . ($separ != '' ? ')' : '') . $separ . substr($newphone, 3, 3) . ($separ != '' ? '-' : '') . substr($newphone, 6, 4); |
|
1134
|
|
|
} |
|
1135
|
|
|
} elseif (strtoupper($countrycode) == "PT") {//Portugal |
|
1136
|
|
|
if (dol_strlen($phone) == 13) {//ex: +351_ABC_DEF_GHI |
|
1137
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 3); |
|
1138
|
|
|
} |
|
1139
|
|
|
} elseif (strtoupper($countrycode) == "SR") {//Suriname |
|
1140
|
|
|
if (dol_strlen($phone) == 10) {//ex: +597_ABC_DEF |
|
1141
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 3); |
|
1142
|
|
|
} elseif (dol_strlen($phone) == 11) {//ex: +597_ABC_DEFG |
|
1143
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 4); |
|
1144
|
|
|
} |
|
1145
|
|
|
} elseif (strtoupper($countrycode) == "DE") {//Allemagne |
|
1146
|
|
|
if (dol_strlen($phone) == 14) {//ex: +49_ABCD_EFGH_IJK |
|
1147
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 4) . $separ . substr($newphone, 7, 4) . $separ . substr($newphone, 11, 3); |
|
1148
|
|
|
} elseif (dol_strlen($phone) == 13) {//ex: +49_ABC_DEFG_HIJ |
|
1149
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 4) . $separ . substr($newphone, 10, 3); |
|
1150
|
|
|
} |
|
1151
|
|
|
} elseif (strtoupper($countrycode) == "ES") {//Espagne |
|
1152
|
|
|
if (dol_strlen($phone) == 12) {//ex: +34_ABC_DEF_GHI |
|
1153
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 3); |
|
1154
|
|
|
} |
|
1155
|
|
|
} elseif (strtoupper($countrycode) == "BF") {// Burkina Faso |
|
1156
|
|
|
if (dol_strlen($phone) == 12) {//ex : +22 A BC_DE_FG_HI |
|
1157
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 1) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2); |
|
1158
|
|
|
} |
|
1159
|
|
|
} elseif (strtoupper($countrycode) == "RO") {// Roumanie |
|
1160
|
|
|
if (dol_strlen($phone) == 12) {//ex : +40 AB_CDE_FG_HI |
|
1161
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2); |
|
1162
|
|
|
} |
|
1163
|
|
|
} elseif (strtoupper($countrycode) == "TR") {//Turquie |
|
1164
|
|
|
if (dol_strlen($phone) == 13) {//ex : +90 ABC_DEF_GHIJ |
|
1165
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 4); |
|
1166
|
|
|
} |
|
1167
|
|
|
} elseif (strtoupper($countrycode) == "US") {//Etat-Unis |
|
1168
|
|
|
if (dol_strlen($phone) == 12) {//ex: +1 ABC_DEF_GHIJ |
|
1169
|
|
|
$newphone = substr($newphone, 0, 2) . $separ . substr($newphone, 2, 3) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 8, 4); |
|
1170
|
|
|
} |
|
1171
|
|
|
} elseif (strtoupper($countrycode) == "MX") {//Mexique |
|
1172
|
|
|
if (dol_strlen($phone) == 12) {//ex: +52 ABCD_EFG_HI |
|
1173
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 4) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 2); |
|
1174
|
|
|
} elseif (dol_strlen($phone) == 11) {//ex: +52 AB_CD_EF_GH |
|
1175
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 2) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2); |
|
1176
|
|
|
} elseif (dol_strlen($phone) == 13) {//ex: +52 ABC_DEF_GHIJ |
|
1177
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 4); |
|
1178
|
|
|
} |
|
1179
|
|
|
} elseif (strtoupper($countrycode) == "ML") {//Mali |
|
1180
|
|
|
if (dol_strlen($phone) == 12) {//ex: +223 AB_CD_EF_GH |
|
1181
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2); |
|
1182
|
|
|
} |
|
1183
|
|
|
} elseif (strtoupper($countrycode) == "TH") {//Thaïlande |
|
1184
|
|
|
if (dol_strlen($phone) == 11) {//ex: +66_ABC_DE_FGH |
|
1185
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 3); |
|
1186
|
|
|
} elseif (dol_strlen($phone) == 12) {//ex: +66_A_BCD_EF_GHI |
|
1187
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 1) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 3); |
|
1188
|
|
|
} |
|
1189
|
|
|
} elseif (strtoupper($countrycode) == "MU") { |
|
1190
|
|
|
//Maurice |
|
1191
|
|
|
if (dol_strlen($phone) == 11) {//ex: +230_ABC_DE_FG |
|
1192
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2); |
|
1193
|
|
|
} elseif (dol_strlen($phone) == 12) {//ex: +230_ABCD_EF_GH |
|
1194
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 4) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2); |
|
1195
|
|
|
} |
|
1196
|
|
|
} elseif (strtoupper($countrycode) == "ZA") {//Afrique du sud |
|
1197
|
|
|
if (dol_strlen($phone) == 12) {//ex: +27_AB_CDE_FG_HI |
|
1198
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2); |
|
1199
|
|
|
} |
|
1200
|
|
|
} elseif (strtoupper($countrycode) == "SY") {//Syrie |
|
1201
|
|
|
if (dol_strlen($phone) == 12) {//ex: +963_AB_CD_EF_GH |
|
1202
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2); |
|
1203
|
|
|
} elseif (dol_strlen($phone) == 13) {//ex: +963_AB_CD_EF_GHI |
|
1204
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 3); |
|
1205
|
|
|
} |
|
1206
|
|
|
} elseif (strtoupper($countrycode) == "AE") {//Emirats Arabes Unis |
|
1207
|
|
|
if (dol_strlen($phone) == 12) {//ex: +971_ABC_DEF_GH |
|
1208
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 2); |
|
1209
|
|
|
} elseif (dol_strlen($phone) == 13) {//ex: +971_ABC_DEF_GHI |
|
1210
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 3); |
|
1211
|
|
|
} elseif (dol_strlen($phone) == 14) {//ex: +971_ABC_DEF_GHIK |
|
1212
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 4); |
|
1213
|
|
|
} |
|
1214
|
|
|
} elseif (strtoupper($countrycode) == "DZ") {//Algérie |
|
1215
|
|
|
if (dol_strlen($phone) == 13) {//ex: +213_ABC_DEF_GHI |
|
1216
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 3); |
|
1217
|
|
|
} |
|
1218
|
|
|
} elseif (strtoupper($countrycode) == "BE") {//Belgique |
|
1219
|
|
|
if (dol_strlen($phone) == 11) {//ex: +32_ABC_DE_FGH |
|
1220
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 3); |
|
1221
|
|
|
} elseif (dol_strlen($phone) == 12) {//ex: +32_ABC_DEF_GHI |
|
1222
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 3); |
|
1223
|
|
|
} |
|
1224
|
|
|
} elseif (strtoupper($countrycode) == "PF") {//Polynésie française |
|
1225
|
|
|
if (dol_strlen($phone) == 12) {//ex: +689_AB_CD_EF_GH |
|
1226
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2); |
|
1227
|
|
|
} |
|
1228
|
|
|
} elseif (strtoupper($countrycode) == "CO") {//Colombie |
|
1229
|
|
|
if (dol_strlen($phone) == 13) {//ex: +57_ABC_DEF_GH_IJ |
|
1230
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 2) . $separ . substr($newphone, 11, 2); |
|
1231
|
|
|
} |
|
1232
|
|
|
} elseif (strtoupper($countrycode) == "JO") {//Jordanie |
|
1233
|
|
|
if (dol_strlen($phone) == 12) {//ex: +962_A_BCD_EF_GH |
|
1234
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 1) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2); |
|
1235
|
|
|
} |
|
1236
|
|
|
} elseif (strtoupper($countrycode) == "JM") {//Jamaïque |
|
1237
|
|
|
if (dol_strlen($newphone) == 12) {//ex: +1867_ABC_DEFG |
|
1238
|
|
|
$newphone = substr($newphone, 0, 5) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 8, 4); |
|
1239
|
|
|
} |
|
1240
|
|
|
} elseif (strtoupper($countrycode) == "MG") {//Madagascar |
|
1241
|
|
|
if (dol_strlen($phone) == 13) {//ex: +261_AB_CD_EFG_HI |
|
1242
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 3) . $separ . substr($newphone, 11, 2); |
|
1243
|
|
|
} |
|
1244
|
|
|
} elseif (strtoupper($countrycode) == "GB") {//Royaume uni |
|
1245
|
|
|
if (dol_strlen($phone) == 13) {//ex: +44_ABCD_EFG_HIJ |
|
1246
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 4) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 3); |
|
1247
|
|
|
} |
|
1248
|
|
|
} elseif (strtoupper($countrycode) == "CH") {//Suisse |
|
1249
|
|
|
if (dol_strlen($phone) == 12) {//ex: +41_AB_CDE_FG_HI |
|
1250
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2); |
|
1251
|
|
|
} elseif (dol_strlen($phone) == 15) {// +41_AB_CDE_FGH_IJKL |
|
1252
|
|
|
$newphone = $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 8, 3) . $separ . substr($newphone, 11, 4); |
|
1253
|
|
|
} |
|
1254
|
|
|
} elseif (strtoupper($countrycode) == "TN") {//Tunisie |
|
1255
|
|
|
if (dol_strlen($phone) == 12) {//ex: +216_AB_CDE_FGH |
|
1256
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 3); |
|
1257
|
|
|
} |
|
1258
|
|
|
} elseif (strtoupper($countrycode) == "GF") {//Guyane francaise |
|
1259
|
|
|
if (dol_strlen($phone) == 13) {//ex: +594_ABC_DE_FG_HI (ABC=594 de nouveau) |
|
1260
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2) . $separ . substr($newphone, 11, 2); |
|
1261
|
|
|
} |
|
1262
|
|
|
} elseif (strtoupper($countrycode) == "GP") {//Guadeloupe |
|
1263
|
|
|
if (dol_strlen($phone) == 13) {//ex: +590_ABC_DE_FG_HI (ABC=590 de nouveau) |
|
1264
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2) . $separ . substr($newphone, 11, 2); |
|
1265
|
|
|
} |
|
1266
|
|
|
} elseif (strtoupper($countrycode) == "MQ") {//Martinique |
|
1267
|
|
|
if (dol_strlen($phone) == 13) {//ex: +596_ABC_DE_FG_HI (ABC=596 de nouveau) |
|
1268
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2) . $separ . substr($newphone, 11, 2); |
|
1269
|
|
|
} |
|
1270
|
|
|
} elseif (strtoupper($countrycode) == "IT") {//Italie |
|
1271
|
|
|
if (dol_strlen($phone) == 12) {//ex: +39_ABC_DEF_GHI |
|
1272
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 3); |
|
1273
|
|
|
} elseif (dol_strlen($phone) == 13) {//ex: +39_ABC_DEF_GH_IJ |
|
1274
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 2) . $separ . substr($newphone, 11, 2); |
|
1275
|
|
|
} |
|
1276
|
|
|
} elseif (strtoupper($countrycode) == "AU") { |
|
1277
|
|
|
//Australie |
|
1278
|
|
|
if (dol_strlen($phone) == 12) { |
|
1279
|
|
|
//ex: +61_A_BCDE_FGHI |
|
1280
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 1) . $separ . substr($newphone, 4, 4) . $separ . substr($newphone, 8, 4); |
|
1281
|
|
|
} |
|
1282
|
|
|
} elseif (strtoupper($countrycode) == "LU") { |
|
1283
|
|
|
// Luxembourg |
|
1284
|
|
|
if (dol_strlen($phone) == 10) {// fix 6 digits +352_AA_BB_CC |
|
1285
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2); |
|
1286
|
|
|
} elseif (dol_strlen($phone) == 11) {// fix 7 digits +352_AA_BB_CC_D |
|
1287
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 1); |
|
1288
|
|
|
} elseif (dol_strlen($phone) == 12) {// fix 8 digits +352_AA_BB_CC_DD |
|
1289
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2); |
|
1290
|
|
|
} elseif (dol_strlen($phone) == 13) {// mobile +352_AAA_BB_CC_DD |
|
1291
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2) . $separ . substr($newphone, 11, 2); |
|
1292
|
|
|
} |
|
1293
|
|
|
} elseif (strtoupper($countrycode) == "PE") { |
|
1294
|
|
|
// Peru |
|
1295
|
|
|
if (dol_strlen($phone) == 7) {// fix 7 chiffres without code AAA_BBBB |
|
1296
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 4); |
|
1297
|
|
|
} elseif (dol_strlen($phone) == 9) {// mobile add code and fix 9 chiffres +51_AAA_BBB_CCC |
|
1298
|
|
|
$newphonewa = '+51' . $newphone; |
|
1299
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 10, 3); |
|
1300
|
|
|
} elseif (dol_strlen($phone) == 11) {// fix 11 chiffres +511_AAA_BBBB |
|
1301
|
|
|
$newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 8, 4); |
|
1302
|
|
|
} elseif (dol_strlen($phone) == 12) {// mobile +51_AAA_BBB_CCC |
|
1303
|
|
|
$newphonewa = $newphone; |
|
1304
|
|
|
$newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 10, 3) . $separ . substr($newphone, 14, 3); |
|
1305
|
|
|
} |
|
1306
|
|
|
} |
|
1307
|
|
|
|
|
1308
|
|
|
$newphoneastart = $newphoneaend = ''; |
|
1309
|
|
|
if (!empty($addlink)) { // Link on phone number (+ link to add action if conf->global->AGENDA_ADDACTIONFORPHONE set) |
|
1310
|
|
|
if ($addlink == 'tel' || $conf->browser->layout == 'phone' || (isModEnabled('clicktodial') && getDolGlobalString('CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS'))) { // If phone or option for, we use link of phone |
|
1311
|
|
|
$newphoneastart = '<a href="tel:' . urlencode($phone) . '">'; |
|
1312
|
|
|
$newphoneaend .= '</a>'; |
|
1313
|
|
|
} elseif (isModEnabled('clicktodial') && $addlink == 'AC_TEL') { // If click to dial, we use click to dial url |
|
1314
|
|
|
if (empty($user->clicktodial_loaded)) { |
|
1315
|
|
|
$user->fetch_clicktodial(); |
|
1316
|
|
|
} |
|
1317
|
|
|
|
|
1318
|
|
|
// Define urlmask |
|
1319
|
|
|
$urlmask = getDolGlobalString('CLICKTODIAL_URL', 'ErrorClickToDialModuleNotConfigured'); |
|
1320
|
|
|
if (!empty($user->clicktodial_url)) { |
|
1321
|
|
|
$urlmask = $user->clicktodial_url; |
|
1322
|
|
|
} |
|
1323
|
|
|
|
|
1324
|
|
|
$clicktodial_poste = (!empty($user->clicktodial_poste) ? urlencode($user->clicktodial_poste) : ''); |
|
1325
|
|
|
$clicktodial_login = (!empty($user->clicktodial_login) ? urlencode($user->clicktodial_login) : ''); |
|
1326
|
|
|
$clicktodial_password = (!empty($user->clicktodial_password) ? urlencode($user->clicktodial_password) : ''); |
|
1327
|
|
|
// This line is for backward compatibility @phan-suppress-next-line PhanPluginPrintfVariableFormatString |
|
1328
|
|
|
$url = sprintf($urlmask, urlencode($phone), $clicktodial_poste, $clicktodial_login, $clicktodial_password); |
|
1329
|
|
|
// Those lines are for substitution |
|
1330
|
|
|
$substitarray = array('__PHONEFROM__' => $clicktodial_poste, |
|
1331
|
|
|
'__PHONETO__' => urlencode($phone), |
|
1332
|
|
|
'__LOGIN__' => $clicktodial_login, |
|
1333
|
|
|
'__PASS__' => $clicktodial_password); |
|
1334
|
|
|
$url = make_substitutions($url, $substitarray); |
|
1335
|
|
|
if (!getDolGlobalString('CLICKTODIAL_DO_NOT_USE_AJAX_CALL')) { |
|
1336
|
|
|
// Default and recommended: New method using ajax without submitting a page making a javascript history.go(-1) back |
|
1337
|
|
|
$newphoneastart = '<a href="' . $url . '" class="cssforclicktodial">'; // Call of ajax is handled by the lib_foot.js.php on class 'cssforclicktodial' |
|
1338
|
|
|
$newphoneaend = '</a>'; |
|
1339
|
|
|
} else { |
|
1340
|
|
|
// Old method |
|
1341
|
|
|
$newphoneastart = '<a href="' . $url . '"'; |
|
1342
|
|
|
if (getDolGlobalString('CLICKTODIAL_FORCENEWTARGET')) { |
|
1343
|
|
|
$newphoneastart .= ' target="_blank" rel="noopener noreferrer"'; |
|
1344
|
|
|
} |
|
1345
|
|
|
$newphoneastart .= '>'; |
|
1346
|
|
|
$newphoneaend .= '</a>'; |
|
1347
|
|
|
} |
|
1348
|
|
|
} |
|
1349
|
|
|
|
|
1350
|
|
|
//if (($cid || $socid) && isModEnabled('agenda') && $user->hasRight('agenda', 'myactions', 'create')) |
|
1351
|
|
|
if (isModEnabled('agenda') && $user->hasRight("agenda", "myactions", "create")) { |
|
1352
|
|
|
$type = 'AC_TEL'; |
|
1353
|
|
|
$addlinktoagenda = ''; |
|
1354
|
|
|
if ($addlink == 'AC_FAX') { |
|
1355
|
|
|
$type = 'AC_FAX'; |
|
1356
|
|
|
} |
|
1357
|
|
|
if (getDolGlobalString('AGENDA_ADDACTIONFORPHONE')) { |
|
1358
|
|
|
$addlinktoagenda = '<a href="' . constant('BASE_URL') . '/comm/action/card.php?action=create&backtopage=' . urlencode($_SERVER['REQUEST_URI']) . '&actioncode=' . $type . ($cid ? '&contactid=' . $cid : '') . ($socid ? '&socid=' . $socid : '') . '">' . img_object($langs->trans("AddAction"), "calendar") . '</a>'; |
|
1359
|
|
|
} |
|
1360
|
|
|
if ($addlinktoagenda) { |
|
1361
|
|
|
$newphone = '<span>' . $newphone . ' ' . $addlinktoagenda . '</span>'; |
|
1362
|
|
|
} |
|
1363
|
|
|
} |
|
1364
|
|
|
} |
|
1365
|
|
|
|
|
1366
|
|
|
if (getDolGlobalString('CONTACT_PHONEMOBILE_SHOW_LINK_TO_WHATSAPP') && $withpicto == 'mobile') { |
|
1367
|
|
|
// Link to Whatsapp |
|
1368
|
|
|
$newphone .= ' <a href="https://wa.me/' . $newphonewa . '" target="_blank"';// Use api to whatasapp contacts |
|
1369
|
|
|
$newphone .= '><span class="paddingright fab fa-whatsapp" style="color:#25D366;" title="WhatsApp"></span></a>'; |
|
1370
|
|
|
} |
|
1371
|
|
|
|
|
1372
|
|
|
if (empty($titlealt)) { |
|
1373
|
|
|
$titlealt = ($withpicto == 'fax' ? $langs->trans("Fax") : $langs->trans("Phone")); |
|
1374
|
|
|
} |
|
1375
|
|
|
$rep = ''; |
|
1376
|
|
|
|
|
1377
|
|
|
if ($hookmanager) { |
|
1378
|
|
|
$parameters = array('countrycode' => $countrycode, 'cid' => $cid, 'socid' => $socid, 'titlealt' => $titlealt, 'picto' => $withpicto); |
|
1379
|
|
|
$reshook = $hookmanager->executeHooks('printPhone', $parameters, $phone); |
|
1380
|
|
|
$rep .= $hookmanager->resPrint; |
|
1381
|
|
|
} |
|
1382
|
|
|
if (empty($reshook)) { |
|
1383
|
|
|
$picto = ''; |
|
1384
|
|
|
if ($withpicto) { |
|
1385
|
|
|
if ($withpicto == 'fax') { |
|
1386
|
|
|
$picto = 'phoning_fax'; |
|
1387
|
|
|
} elseif ($withpicto == 'phone') { |
|
1388
|
|
|
$picto = 'phoning'; |
|
1389
|
|
|
} elseif ($withpicto == 'mobile') { |
|
1390
|
|
|
$picto = 'phoning_mobile'; |
|
1391
|
|
|
} else { |
|
1392
|
|
|
$picto = ''; |
|
1393
|
|
|
} |
|
1394
|
|
|
} |
|
1395
|
|
|
if ($adddivfloat == 1) { |
|
1396
|
|
|
$rep .= '<div class="nospan float' . ($morecss ? ' ' . $morecss : '') . '" style="margin-right: 10px">'; |
|
1397
|
|
|
} elseif (empty($adddivfloat)) { |
|
1398
|
|
|
$rep .= '<span' . ($morecss ? ' class="' . $morecss . '"' : '') . ' style="margin-right: 10px;">'; |
|
1399
|
|
|
} |
|
1400
|
|
|
|
|
1401
|
|
|
$rep .= $newphoneastart; |
|
1402
|
|
|
$rep .= ($withpicto ? img_picto($titlealt, 'object_' . $picto . '.png') : ''); |
|
1403
|
|
|
if ($separ != 'hidenum') { |
|
1404
|
|
|
$rep .= ($withpicto ? ' ' : '') . $newphone; |
|
1405
|
|
|
} |
|
1406
|
|
|
$rep .= $newphoneaend; |
|
1407
|
|
|
|
|
1408
|
|
|
if ($adddivfloat == 1) { |
|
1409
|
|
|
$rep .= '</div>'; |
|
1410
|
|
|
} elseif (empty($adddivfloat)) { |
|
1411
|
|
|
$rep .= '</span>'; |
|
1412
|
|
|
} |
|
1413
|
|
|
} |
|
1414
|
|
|
|
|
1415
|
|
|
return $rep; |
|
1416
|
|
|
} |
|
1417
|
|
|
|
|
1418
|
|
|
/** |
|
1419
|
|
|
* Show warning logo |
|
1420
|
|
|
* |
|
1421
|
|
|
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. |
|
1422
|
|
|
* @param string $moreatt Add more attribute on img tag (For example 'style="float: right"'). If 1, add float: right. Can't be "class" attribute. |
|
1423
|
|
|
* @param string $morecss Add more CSS |
|
1424
|
|
|
* @return string Return img tag |
|
1425
|
|
|
*/ |
|
1426
|
|
|
function img_warning($titlealt = 'default', $moreatt = '', $morecss = 'pictowarning') |
|
1427
|
|
|
{ |
|
1428
|
|
|
global $langs; |
|
1429
|
|
|
|
|
1430
|
|
|
if ($titlealt == 'default') { |
|
1431
|
|
|
$titlealt = $langs->trans('Warning'); |
|
1432
|
|
|
} |
|
1433
|
|
|
|
|
1434
|
|
|
//return '<div class="imglatecoin">'.img_picto($titlealt, 'warning_white.png', 'class="pictowarning valignmiddle"'.($moreatt ? ($moreatt == '1' ? ' style="float: right"' : ' '.$moreatt): '')).'</div>'; |
|
1435
|
|
|
return img_picto($titlealt, 'warning.png', 'class="' . $morecss . '"' . ($moreatt ? ($moreatt == '1' ? ' style="float: right"' : ' ' . $moreatt) : '')); |
|
1436
|
|
|
} |
|
1437
|
|
|
|
|
1438
|
|
|
/** |
|
1439
|
|
|
* Show error logo |
|
1440
|
|
|
* |
|
1441
|
|
|
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. |
|
1442
|
|
|
* @return string Return img tag |
|
1443
|
|
|
*/ |
|
1444
|
|
|
function img_error($titlealt = 'default') |
|
1445
|
|
|
{ |
|
1446
|
|
|
global $langs; |
|
1447
|
|
|
|
|
1448
|
|
|
if ($titlealt == 'default') { |
|
1449
|
|
|
$titlealt = $langs->trans('Error'); |
|
1450
|
|
|
} |
|
1451
|
|
|
|
|
1452
|
|
|
return img_picto($titlealt, 'error.png'); |
|
1453
|
|
|
} |
|
1454
|
|
|
|
|
1455
|
|
|
/** |
|
1456
|
|
|
* Show next logo |
|
1457
|
|
|
* |
|
1458
|
|
|
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. |
|
1459
|
|
|
* @param string $moreatt Add more attribute on img tag (For example 'style="float: right"') |
|
1460
|
|
|
* @return string Return img tag |
|
1461
|
|
|
*/ |
|
1462
|
|
|
function img_next($titlealt = 'default', $moreatt = '') |
|
1463
|
|
|
{ |
|
1464
|
|
|
global $langs; |
|
1465
|
|
|
|
|
1466
|
|
|
if ($titlealt == 'default') { |
|
1467
|
|
|
$titlealt = $langs->trans('Next'); |
|
1468
|
|
|
} |
|
1469
|
|
|
|
|
1470
|
|
|
//return img_picto($titlealt, 'next.png', $moreatt); |
|
1471
|
|
|
return '<span class="fa fa-chevron-right paddingright paddingleft" title="' . dol_escape_htmltag($titlealt) . '"></span>'; |
|
1472
|
|
|
} |
|
1473
|
|
|
|
|
1474
|
|
|
/** |
|
1475
|
|
|
* Show previous logo |
|
1476
|
|
|
* |
|
1477
|
|
|
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. |
|
1478
|
|
|
* @param string $moreatt Add more attribute on img tag (For example 'style="float: right"') |
|
1479
|
|
|
* @return string Return img tag |
|
1480
|
|
|
*/ |
|
1481
|
|
|
function img_previous($titlealt = 'default', $moreatt = '') |
|
1482
|
|
|
{ |
|
1483
|
|
|
global $langs; |
|
1484
|
|
|
|
|
1485
|
|
|
if ($titlealt == 'default') { |
|
1486
|
|
|
$titlealt = $langs->trans('Previous'); |
|
1487
|
|
|
} |
|
1488
|
|
|
|
|
1489
|
|
|
//return img_picto($titlealt, 'previous.png', $moreatt); |
|
1490
|
|
|
return '<span class="fa fa-chevron-left paddingright paddingleft" title="' . dol_escape_htmltag($titlealt) . '"></span>'; |
|
1491
|
|
|
} |
|
1492
|
|
|
|
|
1493
|
|
|
/** |
|
1494
|
|
|
* Show down arrow logo |
|
1495
|
|
|
* |
|
1496
|
|
|
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. |
|
1497
|
|
|
* @param int $selected Selected |
|
1498
|
|
|
* @param string $moreclass Add more CSS classes |
|
1499
|
|
|
* @return string Return img tag |
|
1500
|
|
|
*/ |
|
1501
|
|
|
function img_down($titlealt = 'default', $selected = 0, $moreclass = '') |
|
1502
|
|
|
{ |
|
1503
|
|
|
global $langs; |
|
1504
|
|
|
|
|
1505
|
|
|
if ($titlealt == 'default') { |
|
1506
|
|
|
$titlealt = $langs->trans('Down'); |
|
1507
|
|
|
} |
|
1508
|
|
|
|
|
1509
|
|
|
return img_picto($titlealt, ($selected ? '1downarrow_selected.png' : '1downarrow.png'), 'class="imgdown' . ($moreclass ? " " . $moreclass : "") . '"'); |
|
1510
|
|
|
} |
|
1511
|
|
|
|
|
1512
|
|
|
/** |
|
1513
|
|
|
* Show top arrow logo |
|
1514
|
|
|
* |
|
1515
|
|
|
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. |
|
1516
|
|
|
* @param int $selected Selected |
|
1517
|
|
|
* @param string $moreclass Add more CSS classes |
|
1518
|
|
|
* @return string Return img tag |
|
1519
|
|
|
*/ |
|
1520
|
|
|
function img_up($titlealt = 'default', $selected = 0, $moreclass = '') |
|
1521
|
|
|
{ |
|
1522
|
|
|
global $langs; |
|
1523
|
|
|
|
|
1524
|
|
|
if ($titlealt == 'default') { |
|
1525
|
|
|
$titlealt = $langs->trans('Up'); |
|
1526
|
|
|
} |
|
1527
|
|
|
|
|
1528
|
|
|
return img_picto($titlealt, ($selected ? '1uparrow_selected.png' : '1uparrow.png'), 'class="imgup' . ($moreclass ? " " . $moreclass : "") . '"'); |
|
1529
|
|
|
} |
|
1530
|
|
|
|
|
1531
|
|
|
/** |
|
1532
|
|
|
* Show left arrow logo |
|
1533
|
|
|
* |
|
1534
|
|
|
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. |
|
1535
|
|
|
* @param int $selected Selected |
|
1536
|
|
|
* @param string $moreatt Add more attribute on img tag (For example 'style="float: right"') |
|
1537
|
|
|
* @return string Return img tag |
|
1538
|
|
|
*/ |
|
1539
|
|
|
function img_left($titlealt = 'default', $selected = 0, $moreatt = '') |
|
1540
|
|
|
{ |
|
1541
|
|
|
global $langs; |
|
1542
|
|
|
|
|
1543
|
|
|
if ($titlealt == 'default') { |
|
1544
|
|
|
$titlealt = $langs->trans('Left'); |
|
1545
|
|
|
} |
|
1546
|
|
|
|
|
1547
|
|
|
return img_picto($titlealt, ($selected ? '1leftarrow_selected.png' : '1leftarrow.png'), $moreatt); |
|
1548
|
|
|
} |
|
1549
|
|
|
|
|
1550
|
|
|
/** |
|
1551
|
|
|
* Show right arrow logo |
|
1552
|
|
|
* |
|
1553
|
|
|
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. |
|
1554
|
|
|
* @param int $selected Selected |
|
1555
|
|
|
* @param string $moreatt Add more attribute on img tag (For example 'style="float: right"') |
|
1556
|
|
|
* @return string Return img tag |
|
1557
|
|
|
*/ |
|
1558
|
|
|
function img_right($titlealt = 'default', $selected = 0, $moreatt = '') |
|
1559
|
|
|
{ |
|
1560
|
|
|
global $langs; |
|
1561
|
|
|
|
|
1562
|
|
|
if ($titlealt == 'default') { |
|
1563
|
|
|
$titlealt = $langs->trans('Right'); |
|
1564
|
|
|
} |
|
1565
|
|
|
|
|
1566
|
|
|
return img_picto($titlealt, ($selected ? '1rightarrow_selected.png' : '1rightarrow.png'), $moreatt); |
|
1567
|
|
|
} |
|
1568
|
|
|
|
|
1569
|
|
|
/** |
|
1570
|
|
|
* Show tick logo if allowed |
|
1571
|
|
|
* |
|
1572
|
|
|
* @param string $allow Allow |
|
1573
|
|
|
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. |
|
1574
|
|
|
* @return string Return img tag |
|
1575
|
|
|
*/ |
|
1576
|
|
|
function img_allow($allow, $titlealt = 'default') |
|
1577
|
|
|
{ |
|
1578
|
|
|
global $langs; |
|
1579
|
|
|
|
|
1580
|
|
|
if ($titlealt == 'default') { |
|
1581
|
|
|
$titlealt = $langs->trans('Active'); |
|
1582
|
|
|
} |
|
1583
|
|
|
|
|
1584
|
|
|
if ($allow == 1) { |
|
1585
|
|
|
return img_picto($titlealt, 'tick.png'); |
|
1586
|
|
|
} |
|
1587
|
|
|
|
|
1588
|
|
|
return '-'; |
|
1589
|
|
|
} |
|
1590
|
|
|
|
|
1591
|
|
|
/** |
|
1592
|
|
|
* Return image of a credit card according to its brand name |
|
1593
|
|
|
* |
|
1594
|
|
|
* @param string $brand Brand name of credit card |
|
1595
|
|
|
* @param string $morecss More CSS |
|
1596
|
|
|
* @return string Return img tag |
|
1597
|
|
|
*/ |
|
1598
|
|
|
function img_credit_card($brand, $morecss = null) |
|
1599
|
|
|
{ |
|
1600
|
|
|
if (is_null($morecss)) { |
|
1601
|
|
|
$morecss = 'fa-2x'; |
|
1602
|
|
|
} |
|
1603
|
|
|
|
|
1604
|
|
|
if ($brand == 'visa' || $brand == 'Visa') { |
|
1605
|
|
|
$brand = 'cc-visa'; |
|
1606
|
|
|
} elseif ($brand == 'mastercard' || $brand == 'MasterCard') { |
|
1607
|
|
|
$brand = 'cc-mastercard'; |
|
1608
|
|
|
} elseif ($brand == 'amex' || $brand == 'American Express') { |
|
1609
|
|
|
$brand = 'cc-amex'; |
|
1610
|
|
|
} elseif ($brand == 'discover' || $brand == 'Discover') { |
|
1611
|
|
|
$brand = 'cc-discover'; |
|
1612
|
|
|
} elseif ($brand == 'jcb' || $brand == 'JCB') { |
|
1613
|
|
|
$brand = 'cc-jcb'; |
|
1614
|
|
|
} elseif ($brand == 'diners' || $brand == 'Diners club') { |
|
1615
|
|
|
$brand = 'cc-diners-club'; |
|
1616
|
|
|
} elseif (!in_array($brand, array('cc-visa', 'cc-mastercard', 'cc-amex', 'cc-discover', 'cc-jcb', 'cc-diners-club'))) { |
|
1617
|
|
|
$brand = 'credit-card'; |
|
1618
|
|
|
} |
|
1619
|
|
|
|
|
1620
|
|
|
return '<span class="fa fa-' . $brand . ' fa-fw' . ($morecss ? ' ' . $morecss : '') . '"></span>'; |
|
1621
|
|
|
} |
|
1622
|
|
|
|
|
1623
|
|
|
/** |
|
1624
|
|
|
* Show MIME img of a file |
|
1625
|
|
|
* |
|
1626
|
|
|
* @param string $file Filename |
|
1627
|
|
|
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. |
|
1628
|
|
|
* @param string $morecss More css |
|
1629
|
|
|
* @return string Return img tag |
|
1630
|
|
|
*/ |
|
1631
|
|
|
function img_mime($file, $titlealt = '', $morecss = '') |
|
1632
|
|
|
{ |
|
1633
|
|
|
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php'; |
|
1634
|
|
|
|
|
1635
|
|
|
$mimetype = dol_mimetype($file, '', 1); |
|
1636
|
|
|
$mimeimg = dol_mimetype($file, '', 2); |
|
1637
|
|
|
$mimefa = dol_mimetype($file, '', 4); |
|
1638
|
|
|
|
|
1639
|
|
|
if (empty($titlealt)) { |
|
1640
|
|
|
$titlealt = 'Mime type: ' . $mimetype; |
|
1641
|
|
|
} |
|
1642
|
|
|
|
|
1643
|
|
|
//return img_picto_common($titlealt, 'mime/'.$mimeimg, 'class="'.$morecss.'"'); |
|
1644
|
|
|
return '<i class="fa fa-' . $mimefa . ' paddingright' . ($morecss ? ' ' . $morecss : '') . '"' . ($titlealt ? ' title="' . $titlealt . '"' : '') . '></i>'; |
|
1645
|
|
|
} |
|
1646
|
|
|
|
|
1647
|
|
|
|
|
1648
|
|
|
/** |
|
1649
|
|
|
* Show search logo |
|
1650
|
|
|
* |
|
1651
|
|
|
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. |
|
1652
|
|
|
* @param string $other Add more attributes on img |
|
1653
|
|
|
* @return string Retourne tag img |
|
1654
|
|
|
*/ |
|
1655
|
|
|
function img_search($titlealt = 'default', $other = '') |
|
1656
|
|
|
{ |
|
1657
|
|
|
global $langs; |
|
1658
|
|
|
|
|
1659
|
|
|
if ($titlealt == 'default') { |
|
1660
|
|
|
$titlealt = $langs->trans('Search'); |
|
1661
|
|
|
} |
|
1662
|
|
|
|
|
1663
|
|
|
$img = img_picto($titlealt, 'search.png', $other, 0, 1); |
|
1664
|
|
|
|
|
1665
|
|
|
$input = '<input type="image" class="liste_titre" name="button_search" src="' . $img . '" '; |
|
1666
|
|
|
$input .= 'value="' . dol_escape_htmltag($titlealt) . '" title="' . dol_escape_htmltag($titlealt) . '" >'; |
|
1667
|
|
|
|
|
1668
|
|
|
return $input; |
|
1669
|
|
|
} |
|
1670
|
|
|
|
|
1671
|
|
|
/** |
|
1672
|
|
|
* Show search logo |
|
1673
|
|
|
* |
|
1674
|
|
|
* @param string $titlealt Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title. |
|
1675
|
|
|
* @param string $other Add more attributes on img |
|
1676
|
|
|
* @return string Retourne tag img |
|
1677
|
|
|
*/ |
|
1678
|
|
|
function img_searchclear($titlealt = 'default', $other = '') |
|
1679
|
|
|
{ |
|
1680
|
|
|
global $langs; |
|
1681
|
|
|
|
|
1682
|
|
|
if ($titlealt == 'default') { |
|
1683
|
|
|
$titlealt = $langs->trans('Search'); |
|
1684
|
|
|
} |
|
1685
|
|
|
|
|
1686
|
|
|
$img = img_picto($titlealt, 'searchclear.png', $other, 0, 1); |
|
1687
|
|
|
|
|
1688
|
|
|
$input = '<input type="image" class="liste_titre" name="button_removefilter" src="' . $img . '" '; |
|
1689
|
|
|
$input .= 'value="' . dol_escape_htmltag($titlealt) . '" title="' . dol_escape_htmltag($titlealt) . '" >'; |
|
1690
|
|
|
|
|
1691
|
|
|
return $input; |
|
1692
|
|
|
} |
|
1693
|
|
|
|
|
1694
|
|
|
/** |
|
1695
|
|
|
* Show information in HTML for admin users or standard users |
|
1696
|
|
|
* |
|
1697
|
|
|
* @param string $text Text info |
|
1698
|
|
|
* @param integer $infoonimgalt Info is shown only on alt of star picto, otherwise it is show on output after the star picto |
|
1699
|
|
|
* @param int $nodiv No div |
|
1700
|
|
|
* @param string $admin '1'=Info for admin users. '0'=Info for standard users (change only the look), 'error', 'warning', 'xxx'=Other |
|
1701
|
|
|
* @param string $morecss More CSS ('', 'warning', 'error') |
|
1702
|
|
|
* @param string $textfordropdown Show a text to click to dropdown the info box. |
|
1703
|
|
|
* @return string String with info text |
|
1704
|
|
|
*/ |
|
1705
|
|
|
function info_admin($text, $infoonimgalt = 0, $nodiv = 0, $admin = '1', $morecss = 'hideonsmartphone', $textfordropdown = '') |
|
1706
|
|
|
{ |
|
1707
|
|
|
global $conf, $langs; |
|
1708
|
|
|
|
|
1709
|
|
|
if ($infoonimgalt) { |
|
1710
|
|
|
$result = img_picto($text, 'info', 'class="' . ($morecss ? ' ' . $morecss : '') . '"'); |
|
1711
|
|
|
} else { |
|
1712
|
|
|
if (empty($conf->use_javascript_ajax)) { |
|
1713
|
|
|
$textfordropdown = ''; |
|
1714
|
|
|
} |
|
1715
|
|
|
|
|
1716
|
|
|
$class = (empty($admin) ? 'undefined' : ($admin == '1' ? 'info' : $admin)); |
|
1717
|
|
|
$result = ($nodiv ? '' : '<div class="wordbreak ' . $class . ($morecss ? ' ' . $morecss : '') . ($textfordropdown ? ' hidden' : '') . '">') . '<span class="fa fa-info-circle" title="' . dol_escape_htmltag($admin ? $langs->trans('InfoAdmin') : $langs->trans('Note')) . '"></span> '; |
|
1718
|
|
|
$result .= dol_escape_htmltag($text, 1, 0, 'div,span,b,br,a'); |
|
1719
|
|
|
$result .= ($nodiv ? '' : '</div>'); |
|
1720
|
|
|
|
|
1721
|
|
|
if ($textfordropdown) { |
|
1722
|
|
|
$tmpresult = '<span class="' . $class . 'text opacitymedium cursorpointer">' . $langs->trans($textfordropdown) . ' ' . img_picto($langs->trans($textfordropdown), '1downarrow') . '</span>'; |
|
1723
|
|
|
$tmpresult .= '<script nonce="' . getNonce() . '" type="text/javascript"> |
|
1724
|
|
|
jQuery(document).ready(function() { |
|
1725
|
|
|
jQuery(".' . $class . 'text").click(function() { |
|
1726
|
|
|
console.log("toggle text"); |
|
1727
|
|
|
jQuery(".' . $class . '").toggle(); |
|
1728
|
|
|
}); |
|
1729
|
|
|
}); |
|
1730
|
|
|
</script>'; |
|
1731
|
|
|
|
|
1732
|
|
|
$result = $tmpresult . $result; |
|
1733
|
|
|
} |
|
1734
|
|
|
} |
|
1735
|
|
|
|
|
1736
|
|
|
return $result; |
|
1737
|
|
|
} |
|
1738
|
|
|
|
|
1739
|
|
|
|
|
1740
|
|
|
/** |
|
1741
|
|
|
* Displays error message system with all the information to facilitate the diagnosis and the escalation of the bugs. |
|
1742
|
|
|
* This function must be called when a blocking technical error is encountered. |
|
1743
|
|
|
* However, one must try to call it only within php pages, classes must return their error through their property "error". |
|
1744
|
|
|
* |
|
1745
|
|
|
* @param DoliDB|null $db Database handler |
|
1746
|
|
|
* @param string|string[] $error String or array of errors strings to show |
|
1747
|
|
|
* @param string[]|null $errors Array of errors |
|
1748
|
|
|
* @return void |
|
1749
|
|
|
* @see dol_htmloutput_errors() |
|
1750
|
|
|
*/ |
|
1751
|
|
|
function dol_print_error($db = null, $error = '', $errors = null) |
|
1752
|
|
|
{ |
|
1753
|
|
|
global $conf, $langs, $argv; |
|
1754
|
|
|
global $dolibarr_main_prod; |
|
1755
|
|
|
|
|
1756
|
|
|
$out = ''; |
|
1757
|
|
|
$syslog = ''; |
|
1758
|
|
|
|
|
1759
|
|
|
// If error occurs before the $lang object was loaded |
|
1760
|
|
|
if (!$langs) { |
|
1761
|
|
|
$langs = new Translate('', $conf); |
|
1762
|
|
|
$langs->load("main"); |
|
1763
|
|
|
} |
|
1764
|
|
|
|
|
1765
|
|
|
// Load translation files required by the error messages |
|
1766
|
|
|
$langs->loadLangs(array('main', 'errors')); |
|
1767
|
|
|
|
|
1768
|
|
|
if ($_SERVER['DOCUMENT_ROOT']) { // Mode web |
|
1769
|
|
|
$out .= $langs->trans("DolibarrHasDetectedError") . ".<br>\n"; |
|
1770
|
|
|
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') > 0) { |
|
1771
|
|
|
$out .= "You use an experimental or develop level of features, so please do NOT report any bugs or vulnerability, except if problem is confirmed after moving option MAIN_FEATURES_LEVEL back to 0.<br>\n"; |
|
1772
|
|
|
} |
|
1773
|
|
|
$out .= $langs->trans("InformationToHelpDiagnose") . ":<br>\n"; |
|
1774
|
|
|
|
|
1775
|
|
|
$out .= "<b>" . $langs->trans("Date") . ":</b> " . dol_print_date(time(), 'dayhourlog') . "<br>\n"; |
|
1776
|
|
|
$out .= "<b>" . $langs->trans("Dolibarr") . ":</b> " . DOL_VERSION . " - https://www.dolibarr.org<br>\n"; |
|
1777
|
|
|
if (isset($conf->global->MAIN_FEATURES_LEVEL)) { |
|
1778
|
|
|
$out .= "<b>" . $langs->trans("LevelOfFeature") . ":</b> " . getDolGlobalInt('MAIN_FEATURES_LEVEL') . "<br>\n"; |
|
1779
|
|
|
} |
|
1780
|
|
|
if (function_exists("phpversion")) { |
|
1781
|
|
|
$out .= "<b>" . $langs->trans("PHP") . ":</b> " . phpversion() . "<br>\n"; |
|
1782
|
|
|
} |
|
1783
|
|
|
$out .= "<b>" . $langs->trans("Server") . ":</b> " . (isset($_SERVER["SERVER_SOFTWARE"]) ? dol_htmlentities($_SERVER["SERVER_SOFTWARE"], ENT_COMPAT) : '') . "<br>\n"; |
|
1784
|
|
|
if (function_exists("php_uname")) { |
|
1785
|
|
|
$out .= "<b>" . $langs->trans("OS") . ":</b> " . php_uname() . "<br>\n"; |
|
1786
|
|
|
} |
|
1787
|
|
|
$out .= "<b>" . $langs->trans("UserAgent") . ":</b> " . (isset($_SERVER["HTTP_USER_AGENT"]) ? dol_htmlentities($_SERVER["HTTP_USER_AGENT"], ENT_COMPAT) : '') . "<br>\n"; |
|
1788
|
|
|
$out .= "<br>\n"; |
|
1789
|
|
|
$out .= "<b>" . $langs->trans("RequestedUrl") . ":</b> " . dol_htmlentities($_SERVER["REQUEST_URI"], ENT_COMPAT) . "<br>\n"; |
|
1790
|
|
|
$out .= "<b>" . $langs->trans("Referer") . ":</b> " . (isset($_SERVER["HTTP_REFERER"]) ? dol_htmlentities($_SERVER["HTTP_REFERER"], ENT_COMPAT) : '') . "<br>\n"; |
|
1791
|
|
|
$out .= "<b>" . $langs->trans("MenuManager") . ":</b> " . (isset($conf->standard_menu) ? dol_htmlentities($conf->standard_menu, ENT_COMPAT) : '') . "<br>\n"; |
|
1792
|
|
|
$out .= "<br>\n"; |
|
1793
|
|
|
$syslog .= "url=" . dol_escape_htmltag($_SERVER["REQUEST_URI"]); |
|
1794
|
|
|
$syslog .= ", query_string=" . dol_escape_htmltag($_SERVER["QUERY_STRING"]); |
|
1795
|
|
|
} else { // Mode CLI |
|
1796
|
|
|
$out .= '> ' . $langs->transnoentities("ErrorInternalErrorDetected") . ":\n" . $argv[0] . "\n"; |
|
1797
|
|
|
$syslog .= "pid=" . dol_getmypid(); |
|
1798
|
|
|
} |
|
1799
|
|
|
|
|
1800
|
|
|
if (!empty($conf->modules)) { |
|
1801
|
|
|
$out .= "<b>" . $langs->trans("Modules") . ":</b> " . implode(', ', $conf->modules) . "<br>\n"; |
|
1802
|
|
|
} |
|
1803
|
|
|
|
|
1804
|
|
|
if (is_object($db)) { |
|
1805
|
|
|
if ($_SERVER['DOCUMENT_ROOT']) { // Mode web |
|
1806
|
|
|
$out .= "<b>" . $langs->trans("DatabaseTypeManager") . ":</b> " . $db->type . "<br>\n"; |
|
1807
|
|
|
$lastqueryerror = $db->lastqueryerror(); |
|
1808
|
|
|
if (!utf8_check($lastqueryerror)) { |
|
1809
|
|
|
$lastqueryerror = "SQL error string is not a valid UTF8 string. We can't show it."; |
|
1810
|
|
|
} |
|
1811
|
|
|
$out .= "<b>" . $langs->trans("RequestLastAccessInError") . ":</b> " . ($lastqueryerror ? dol_escape_htmltag($lastqueryerror) : $langs->trans("ErrorNoRequestInError")) . "<br>\n"; |
|
1812
|
|
|
$out .= "<b>" . $langs->trans("ReturnCodeLastAccessInError") . ":</b> " . ($db->lasterrno() ? dol_escape_htmltag($db->lasterrno()) : $langs->trans("ErrorNoRequestInError")) . "<br>\n"; |
|
1813
|
|
|
$out .= "<b>" . $langs->trans("InformationLastAccessInError") . ":</b> " . ($db->lasterror() ? dol_escape_htmltag($db->lasterror()) : $langs->trans("ErrorNoRequestInError")) . "<br>\n"; |
|
1814
|
|
|
$out .= "<br>\n"; |
|
1815
|
|
|
} else { // Mode CLI |
|
1816
|
|
|
// No dol_escape_htmltag for output, we are in CLI mode |
|
1817
|
|
|
$out .= '> ' . $langs->transnoentities("DatabaseTypeManager") . ":\n" . $db->type . "\n"; |
|
1818
|
|
|
$out .= '> ' . $langs->transnoentities("RequestLastAccessInError") . ":\n" . ($db->lastqueryerror() ? $db->lastqueryerror() : $langs->transnoentities("ErrorNoRequestInError")) . "\n"; |
|
1819
|
|
|
$out .= '> ' . $langs->transnoentities("ReturnCodeLastAccessInError") . ":\n" . ($db->lasterrno() ? $db->lasterrno() : $langs->transnoentities("ErrorNoRequestInError")) . "\n"; |
|
1820
|
|
|
$out .= '> ' . $langs->transnoentities("InformationLastAccessInError") . ":\n" . ($db->lasterror() ? $db->lasterror() : $langs->transnoentities("ErrorNoRequestInError")) . "\n"; |
|
1821
|
|
|
} |
|
1822
|
|
|
$syslog .= ", sql=" . $db->lastquery(); |
|
1823
|
|
|
$syslog .= ", db_error=" . $db->lasterror(); |
|
1824
|
|
|
} |
|
1825
|
|
|
|
|
1826
|
|
|
if ($error || $errors) { |
|
1827
|
|
|
// Merge all into $errors array |
|
1828
|
|
|
if (is_array($error) && is_array($errors)) { |
|
1829
|
|
|
$errors = array_merge($error, $errors); |
|
1830
|
|
|
} elseif (is_array($error)) { // deprecated, use second parameters |
|
1831
|
|
|
$errors = $error; |
|
1832
|
|
|
} elseif (is_array($errors) && !empty($error)) { |
|
1833
|
|
|
$errors = array_merge(array($error), $errors); |
|
1834
|
|
|
} elseif (!empty($error)) { |
|
1835
|
|
|
$errors = array_merge(array($error), array($errors)); |
|
1836
|
|
|
} |
|
1837
|
|
|
|
|
1838
|
|
|
$langs->load("errors"); |
|
1839
|
|
|
|
|
1840
|
|
|
foreach ($errors as $msg) { |
|
1841
|
|
|
if (empty($msg)) { |
|
1842
|
|
|
continue; |
|
1843
|
|
|
} |
|
1844
|
|
|
if ($_SERVER['DOCUMENT_ROOT']) { // Mode web |
|
1845
|
|
|
$out .= "<b>" . $langs->trans("Message") . ":</b> " . dol_escape_htmltag($msg) . "<br>\n"; |
|
1846
|
|
|
} else { // Mode CLI |
|
1847
|
|
|
$out .= '> ' . $langs->transnoentities("Message") . ":\n" . $msg . "\n"; |
|
1848
|
|
|
} |
|
1849
|
|
|
$syslog .= ", msg=" . $msg; |
|
1850
|
|
|
} |
|
1851
|
|
|
} |
|
1852
|
|
|
if (empty($dolibarr_main_prod) && $_SERVER['DOCUMENT_ROOT'] && function_exists('xdebug_print_function_stack') && function_exists('xdebug_call_file')) { |
|
1853
|
|
|
xdebug_print_function_stack(); |
|
1854
|
|
|
$out .= '<b>XDebug information:</b>' . "<br>\n"; |
|
1855
|
|
|
$out .= 'File: ' . xdebug_call_file() . "<br>\n"; |
|
1856
|
|
|
$out .= 'Line: ' . xdebug_call_line() . "<br>\n"; |
|
1857
|
|
|
$out .= 'Function: ' . xdebug_call_function() . "<br>\n"; |
|
1858
|
|
|
$out .= "<br>\n"; |
|
1859
|
|
|
} |
|
1860
|
|
|
|
|
1861
|
|
|
// Return a http header with error code if possible |
|
1862
|
|
|
if (!headers_sent()) { |
|
1863
|
|
|
if (function_exists('top_httphead')) { // In CLI context, the method does not exists |
|
1864
|
|
|
ViewMain::topHttpHead(); |
|
1865
|
|
|
} |
|
1866
|
|
|
//http_response_code(500); // If we use 500, message is not output with some command line tools |
|
1867
|
|
|
http_response_code(202); // If we use 202, this is not really an error message, but this allow to output message on command line tools |
|
1868
|
|
|
} |
|
1869
|
|
|
|
|
1870
|
|
|
if (empty($dolibarr_main_prod)) { |
|
1871
|
|
|
print $out; |
|
1872
|
|
|
} else { |
|
1873
|
|
|
if (empty($langs->defaultlang)) { |
|
1874
|
|
|
$langs->setDefaultLang(); |
|
1875
|
|
|
} |
|
1876
|
|
|
$langs->loadLangs(array("main", "errors")); // Reload main because language may have been set only on previous line so we have to reload files we need. |
|
1877
|
|
|
// This should not happen, except if there is a bug somewhere. Enabled and check log in such case. |
|
1878
|
|
|
print 'This website or feature is currently temporarily not available or failed after a technical error.<br><br>This may be due to a maintenance operation. Current status of operation (' . dol_print_date(dol_now(), 'dayhourrfc') . ') are on next line...<br><br>' . "\n"; |
|
1879
|
|
|
print $langs->trans("DolibarrHasDetectedError") . '. '; |
|
1880
|
|
|
print $langs->trans("YouCanSetOptionDolibarrMainProdToZero"); |
|
1881
|
|
|
if (!defined("MAIN_CORE_ERROR")) { |
|
1882
|
|
|
define("MAIN_CORE_ERROR", 1); |
|
1883
|
|
|
} |
|
1884
|
|
|
} |
|
1885
|
|
|
|
|
1886
|
|
|
dol_syslog("Error " . $syslog, LOG_ERR); |
|
1887
|
|
|
} |
|
1888
|
|
|
|
|
1889
|
|
|
/** |
|
1890
|
|
|
* Show a public email and error code to contact if technical error |
|
1891
|
|
|
* |
|
1892
|
|
|
* @param string $prefixcode Prefix of public error code |
|
1893
|
|
|
* @param string $errormessage Complete error message |
|
1894
|
|
|
* @param string[] $errormessages Array of error messages |
|
1895
|
|
|
* @param string $morecss More css |
|
1896
|
|
|
* @param string $email Email |
|
1897
|
|
|
* @return void |
|
1898
|
|
|
*/ |
|
1899
|
|
|
function dol_print_error_email($prefixcode, $errormessage = '', $errormessages = array(), $morecss = 'error', $email = '') |
|
1900
|
|
|
{ |
|
1901
|
|
|
global $langs; |
|
1902
|
|
|
|
|
1903
|
|
|
if (empty($email)) { |
|
1904
|
|
|
$email = getDolGlobalString('MAIN_INFO_SOCIETE_MAIL'); |
|
1905
|
|
|
} |
|
1906
|
|
|
|
|
1907
|
|
|
$langs->load("errors"); |
|
1908
|
|
|
$now = dol_now(); |
|
1909
|
|
|
|
|
1910
|
|
|
print '<br><div class="center login_main_message"><div class="' . $morecss . '">'; |
|
1911
|
|
|
print $langs->trans("ErrorContactEMail", $email, $prefixcode . '-' . dol_print_date($now, '%Y%m%d%H%M%S')); |
|
1912
|
|
|
if ($errormessage) { |
|
1913
|
|
|
print '<br><br>' . $errormessage; |
|
1914
|
|
|
} |
|
1915
|
|
|
if (is_array($errormessages) && count($errormessages)) { |
|
1916
|
|
|
foreach ($errormessages as $mesgtoshow) { |
|
1917
|
|
|
print '<br><br>' . $mesgtoshow; |
|
1918
|
|
|
} |
|
1919
|
|
|
} |
|
1920
|
|
|
print '</div></div>'; |
|
1921
|
|
|
} |
|
1922
|
|
|
|
|
1923
|
|
|
/** |
|
1924
|
|
|
* Show title line of an array |
|
1925
|
|
|
* |
|
1926
|
|
|
* @param string $name Label of field |
|
1927
|
|
|
* @param string $file Url used when we click on sort picto |
|
1928
|
|
|
* @param string $field Field to use for new sorting |
|
1929
|
|
|
* @param string $begin ("" by default) |
|
1930
|
|
|
* @param string $moreparam Add more parameters on sort url links ("" by default) |
|
1931
|
|
|
* @param string $moreattrib Options of attribute td ("" by default) |
|
1932
|
|
|
* @param string $sortfield Current field used to sort |
|
1933
|
|
|
* @param string $sortorder Current sort order |
|
1934
|
|
|
* @param string $prefix Prefix for css. Use space after prefix to add your own CSS tag, for example 'mycss '. |
|
1935
|
|
|
* @param string $tooltip Tooltip |
|
1936
|
|
|
* @param int $forcenowrapcolumntitle No need for use 'wrapcolumntitle' css style |
|
1937
|
|
|
* @return void |
|
1938
|
|
|
*/ |
|
1939
|
|
|
function print_liste_field_titre($name, $file = "", $field = "", $begin = "", $moreparam = "", $moreattrib = "", $sortfield = "", $sortorder = "", $prefix = "", $tooltip = "", $forcenowrapcolumntitle = 0) |
|
1940
|
|
|
{ |
|
1941
|
|
|
print getTitleFieldOfList($name, 0, $file, $field, $begin, $moreparam, $moreattrib, $sortfield, $sortorder, $prefix, 0, $tooltip, $forcenowrapcolumntitle); |
|
1942
|
|
|
} |
|
1943
|
|
|
|
|
1944
|
|
|
/** |
|
1945
|
|
|
* Get title line of an array |
|
1946
|
|
|
* |
|
1947
|
|
|
* @param string $name Translation key of field to show or complete HTML string to show |
|
1948
|
|
|
* @param int $thead 0=To use with standard table format, 1=To use inside <thead><tr>, 2=To use with <div> |
|
1949
|
|
|
* @param string $file Url used when we click on sort picto |
|
1950
|
|
|
* @param string $field Field to use for new sorting. Empty if this field is not sortable. Example "t.abc" or "t.abc,t.def" |
|
1951
|
|
|
* @param string $begin ("" by default) |
|
1952
|
|
|
* @param string $moreparam Add more parameters on sort url links ("" by default) |
|
1953
|
|
|
* @param string $moreattrib Add more attributes on th ("" by default). To add more css class, use param $prefix. |
|
1954
|
|
|
* @param string $sortfield Current field used to sort (Ex: 'd.datep,d.id') |
|
1955
|
|
|
* @param string $sortorder Current sort order (Ex: 'asc,desc') |
|
1956
|
|
|
* @param string $prefix Prefix for css. Use space after prefix to add your own CSS tag, for example 'mycss '. |
|
1957
|
|
|
* @param int $disablesortlink 1=Disable sort link |
|
1958
|
|
|
* @param string $tooltip Tooltip |
|
1959
|
|
|
* @param int $forcenowrapcolumntitle No need for use 'wrapcolumntitle' css style |
|
1960
|
|
|
* @return string |
|
1961
|
|
|
*/ |
|
1962
|
|
|
function getTitleFieldOfList($name, $thead = 0, $file = "", $field = "", $begin = "", $moreparam = "", $moreattrib = "", $sortfield = "", $sortorder = "", $prefix = "", $disablesortlink = 0, $tooltip = '', $forcenowrapcolumntitle = 0) |
|
1963
|
|
|
{ |
|
1964
|
|
|
global $langs, $form; |
|
1965
|
|
|
//print "$name, $file, $field, $begin, $options, $moreattrib, $sortfield, $sortorder<br>\n"; |
|
1966
|
|
|
|
|
1967
|
|
|
if ($moreattrib == 'class="right"') { |
|
1968
|
|
|
$prefix .= 'right '; // For backward compatibility |
|
1969
|
|
|
} |
|
1970
|
|
|
|
|
1971
|
|
|
$sortorder = strtoupper($sortorder); |
|
1972
|
|
|
$out = ''; |
|
1973
|
|
|
$sortimg = ''; |
|
1974
|
|
|
|
|
1975
|
|
|
$tag = 'th'; |
|
1976
|
|
|
if ($thead == 2) { |
|
1977
|
|
|
$tag = 'div'; |
|
1978
|
|
|
} |
|
1979
|
|
|
|
|
1980
|
|
|
$tmpsortfield = explode(',', $sortfield); |
|
1981
|
|
|
$sortfield1 = trim($tmpsortfield[0]); // If $sortfield is 'd.datep,d.id', it becomes 'd.datep' |
|
1982
|
|
|
$tmpfield = explode(',', $field); |
|
1983
|
|
|
$field1 = trim($tmpfield[0]); // If $field is 'd.datep,d.id', it becomes 'd.datep' |
|
1984
|
|
|
|
|
1985
|
|
|
if (!getDolGlobalString('MAIN_DISABLE_WRAPPING_ON_COLUMN_TITLE') && empty($forcenowrapcolumntitle)) { |
|
1986
|
|
|
$prefix = 'wrapcolumntitle ' . $prefix; |
|
1987
|
|
|
} |
|
1988
|
|
|
|
|
1989
|
|
|
//var_dump('field='.$field.' field1='.$field1.' sortfield='.$sortfield.' sortfield1='.$sortfield1); |
|
1990
|
|
|
// If field is used as sort criteria we use a specific css class liste_titre_sel |
|
1991
|
|
|
// Example if (sortfield,field)=("nom","xxx.nom") or (sortfield,field)=("nom","nom") |
|
1992
|
|
|
$liste_titre = 'liste_titre'; |
|
1993
|
|
|
if ($field1 && ($sortfield1 == $field1 || $sortfield1 == preg_replace("/^[^\.]+\./", "", $field1))) { |
|
1994
|
|
|
$liste_titre = 'liste_titre_sel'; |
|
1995
|
|
|
} |
|
1996
|
|
|
|
|
1997
|
|
|
$tagstart = '<' . $tag . ' class="' . $prefix . $liste_titre . '" ' . $moreattrib; |
|
1998
|
|
|
//$out .= (($field && empty($conf->global->MAIN_DISABLE_WRAPPING_ON_COLUMN_TITLE) && preg_match('/^[a-zA-Z_0-9\s\.\-:&;]*$/', $name)) ? ' title="'.dol_escape_htmltag($langs->trans($name)).'"' : ''); |
|
1999
|
|
|
$tagstart .= ($name && !getDolGlobalString('MAIN_DISABLE_WRAPPING_ON_COLUMN_TITLE') && empty($forcenowrapcolumntitle) && !dol_textishtml($name)) ? ' title="' . dol_escape_htmltag($langs->trans($name)) . '"' : ''; |
|
2000
|
|
|
$tagstart .= '>'; |
|
2001
|
|
|
|
|
2002
|
|
|
if (empty($thead) && $field && empty($disablesortlink)) { // If this is a sort field |
|
2003
|
|
|
$options = preg_replace('/sortfield=([a-zA-Z0-9,\s\.]+)/i', '', (is_scalar($moreparam) ? $moreparam : '')); |
|
2004
|
|
|
$options = preg_replace('/sortorder=([a-zA-Z0-9,\s\.]+)/i', '', $options); |
|
2005
|
|
|
$options = preg_replace('/&+/i', '&', $options); |
|
2006
|
|
|
if (!preg_match('/^&/', $options)) { |
|
2007
|
|
|
$options = '&' . $options; |
|
2008
|
|
|
} |
|
2009
|
|
|
|
|
2010
|
|
|
$sortordertouseinlink = ''; |
|
2011
|
|
|
if ($field1 != $sortfield1) { // We are on another field than current sorted field |
|
2012
|
|
|
if (preg_match('/^DESC/i', $sortorder)) { |
|
2013
|
|
|
$sortordertouseinlink .= str_repeat('desc,', count(explode(',', $field))); |
|
2014
|
|
|
} else { // We reverse the var $sortordertouseinlink |
|
2015
|
|
|
$sortordertouseinlink .= str_repeat('asc,', count(explode(',', $field))); |
|
2016
|
|
|
} |
|
2017
|
|
|
} else { // We are on field that is the first current sorting criteria |
|
2018
|
|
|
if (preg_match('/^ASC/i', $sortorder)) { // We reverse the var $sortordertouseinlink |
|
2019
|
|
|
$sortordertouseinlink .= str_repeat('desc,', count(explode(',', $field))); |
|
2020
|
|
|
} else { |
|
2021
|
|
|
$sortordertouseinlink .= str_repeat('asc,', count(explode(',', $field))); |
|
2022
|
|
|
} |
|
2023
|
|
|
} |
|
2024
|
|
|
$sortordertouseinlink = preg_replace('/,$/', '', $sortordertouseinlink); |
|
2025
|
|
|
$out .= '<a class="reposition" href="' . $file . '?sortfield=' . $field . '&sortorder=' . $sortordertouseinlink . '&begin=' . $begin . $options . '"'; |
|
2026
|
|
|
//$out .= (empty($conf->global->MAIN_DISABLE_WRAPPING_ON_COLUMN_TITLE) ? ' title="'.dol_escape_htmltag($langs->trans($name)).'"' : ''); |
|
2027
|
|
|
$out .= '>'; |
|
2028
|
|
|
} |
|
2029
|
|
|
if ($tooltip) { |
|
2030
|
|
|
// You can also use 'TranslationString:keyfortooltiponclick' for a tooltip on click. |
|
2031
|
|
|
if (preg_match('/:\w+$/', $tooltip)) { |
|
2032
|
|
|
$tmptooltip = explode(':', $tooltip); |
|
2033
|
|
|
} else { |
|
2034
|
|
|
$tmptooltip = array($tooltip); |
|
2035
|
|
|
} |
|
2036
|
|
|
$out .= $form->textwithpicto($langs->trans($name), $langs->trans($tmptooltip[0]), 1, 'help', '', 0, 3, (empty($tmptooltip[1]) ? '' : 'extra_' . str_replace('.', '_', $field) . '_' . $tmptooltip[1])); |
|
2037
|
|
|
} else { |
|
2038
|
|
|
$out .= $langs->trans($name); |
|
2039
|
|
|
} |
|
2040
|
|
|
|
|
2041
|
|
|
if (empty($thead) && $field && empty($disablesortlink)) { // If this is a sort field |
|
2042
|
|
|
$out .= '</a>'; |
|
2043
|
|
|
} |
|
2044
|
|
|
|
|
2045
|
|
|
if (empty($thead) && $field) { // If this is a sort field |
|
2046
|
|
|
$options = preg_replace('/sortfield=([a-zA-Z0-9,\s\.]+)/i', '', (is_scalar($moreparam) ? $moreparam : '')); |
|
2047
|
|
|
$options = preg_replace('/sortorder=([a-zA-Z0-9,\s\.]+)/i', '', $options); |
|
2048
|
|
|
$options = preg_replace('/&+/i', '&', $options); |
|
2049
|
|
|
if (!preg_match('/^&/', $options)) { |
|
2050
|
|
|
$options = '&' . $options; |
|
2051
|
|
|
} |
|
2052
|
|
|
|
|
2053
|
|
|
if (!$sortorder || ($field1 != $sortfield1)) { |
|
2054
|
|
|
//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",0).'</a>'; |
|
2055
|
|
|
//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",0).'</a>'; |
|
2056
|
|
|
} else { |
|
2057
|
|
|
if (preg_match('/^DESC/', $sortorder)) { |
|
2058
|
|
|
//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",0).'</a>'; |
|
2059
|
|
|
//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",1).'</a>'; |
|
2060
|
|
|
$sortimg .= '<span class="nowrap">' . img_up("Z-A", 0, 'paddingright') . '</span>'; |
|
2061
|
|
|
} |
|
2062
|
|
|
if (preg_match('/^ASC/', $sortorder)) { |
|
2063
|
|
|
//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",1).'</a>'; |
|
2064
|
|
|
//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",0).'</a>'; |
|
2065
|
|
|
$sortimg .= '<span class="nowrap">' . img_down("A-Z", 0, 'paddingright') . '</span>'; |
|
2066
|
|
|
} |
|
2067
|
|
|
} |
|
2068
|
|
|
} |
|
2069
|
|
|
|
|
2070
|
|
|
$tagend = '</' . $tag . '>'; |
|
2071
|
|
|
|
|
2072
|
|
|
$out = $tagstart . $sortimg . $out . $tagend; |
|
2073
|
|
|
|
|
2074
|
|
|
return $out; |
|
2075
|
|
|
} |
|
2076
|
|
|
|
|
2077
|
|
|
/** |
|
2078
|
|
|
* Show a title. |
|
2079
|
|
|
* |
|
2080
|
|
|
* @param string $title Title to show |
|
2081
|
|
|
* @return void |
|
2082
|
|
|
* @deprecated Use load_fiche_titre instead |
|
2083
|
|
|
* @see load_fiche_titre() |
|
2084
|
|
|
*/ |
|
2085
|
|
|
function print_titre($title) |
|
2086
|
|
|
{ |
|
2087
|
|
|
dol_syslog(__FUNCTION__ . " is deprecated", LOG_WARNING); |
|
2088
|
|
|
|
|
2089
|
|
|
print '<div class="titre">' . $title . '</div>'; |
|
2090
|
|
|
} |
|
2091
|
|
|
|
|
2092
|
|
|
/** |
|
2093
|
|
|
* Show a title with picto |
|
2094
|
|
|
* |
|
2095
|
|
|
* @param string $title Title to show |
|
2096
|
|
|
* @param string $mesg Added message to show on right |
|
2097
|
|
|
* @param string $picto Icon to use before title (should be a 32x32 transparent png file) |
|
2098
|
|
|
* @param int $pictoisfullpath 1=Icon name is a full absolute url of image |
|
2099
|
|
|
* @param string $id To force an id on html objects by example id="name" where name is id |
|
2100
|
|
|
* @return void |
|
2101
|
|
|
* @deprecated Use print load_fiche_titre instead |
|
2102
|
|
|
*/ |
|
2103
|
|
|
function print_fiche_titre($title, $mesg = '', $picto = 'generic', $pictoisfullpath = 0, $id = '') |
|
2104
|
|
|
{ |
|
2105
|
|
|
print load_fiche_titre($title, $mesg, $picto, $pictoisfullpath, $id); |
|
2106
|
|
|
} |
|
2107
|
|
|
|
|
2108
|
|
|
/** |
|
2109
|
|
|
* Load a title with picto |
|
2110
|
|
|
* |
|
2111
|
|
|
* @param string $title Title to show (HTML sanitized content) |
|
2112
|
|
|
* @param string $morehtmlright Added message to show on right |
|
2113
|
|
|
* @param string $picto Icon to use before title (should be a 32x32 transparent png file) |
|
2114
|
|
|
* @param int $pictoisfullpath 1=Icon name is a full absolute url of image |
|
2115
|
|
|
* @param string $id To force an id on html objects |
|
2116
|
|
|
* @param string $morecssontable More css on table |
|
2117
|
|
|
* @param string $morehtmlcenter Added message to show on center |
|
2118
|
|
|
* @return string |
|
2119
|
|
|
* @see print_barre_liste() |
|
2120
|
|
|
*/ |
|
2121
|
|
|
function load_fiche_titre($title, $morehtmlright = '', $picto = 'generic', $pictoisfullpath = 0, $id = '', $morecssontable = '', $morehtmlcenter = '') |
|
2122
|
|
|
{ |
|
2123
|
|
|
$return = ''; |
|
2124
|
|
|
|
|
2125
|
|
|
if ($picto == 'setup') { |
|
2126
|
|
|
$picto = 'generic'; |
|
2127
|
|
|
} |
|
2128
|
|
|
|
|
2129
|
|
|
$return .= "\n"; |
|
2130
|
|
|
$return .= '<table ' . ($id ? 'id="' . $id . '" ' : '') . 'class="centpercent notopnoleftnoright table-fiche-title' . ($morecssontable ? ' ' . $morecssontable : '') . '">'; // maring bottom must be same than into print_barre_list |
|
2131
|
|
|
$return .= '<tr class="titre">'; |
|
2132
|
|
|
if ($picto) { |
|
2133
|
|
|
$return .= '<td class="nobordernopadding widthpictotitle valignmiddle col-picto">' . img_picto('', $picto, 'class="valignmiddle widthpictotitle pictotitle"', $pictoisfullpath) . '</td>'; |
|
2134
|
|
|
} |
|
2135
|
|
|
$return .= '<td class="nobordernopadding valignmiddle col-title">'; |
|
2136
|
|
|
$return .= '<div class="titre inline-block">'; |
|
2137
|
|
|
$return .= $title; // $title is already HTML sanitized content |
|
2138
|
|
|
$return .= '</div>'; |
|
2139
|
|
|
$return .= '</td>'; |
|
2140
|
|
|
if (dol_strlen($morehtmlcenter)) { |
|
2141
|
|
|
$return .= '<td class="nobordernopadding center valignmiddle col-center">' . $morehtmlcenter . '</td>'; |
|
2142
|
|
|
} |
|
2143
|
|
|
if (dol_strlen($morehtmlright)) { |
|
2144
|
|
|
$return .= '<td class="nobordernopadding titre_right wordbreakimp right valignmiddle col-right">' . $morehtmlright . '</td>'; |
|
2145
|
|
|
} |
|
2146
|
|
|
$return .= '</tr></table>' . "\n"; |
|
2147
|
|
|
|
|
2148
|
|
|
return $return; |
|
2149
|
|
|
} |
|
2150
|
|
|
|
|
2151
|
|
|
/** |
|
2152
|
|
|
* Print a title with navigation controls for pagination |
|
2153
|
|
|
* |
|
2154
|
|
|
* @param string $title Title to show (required) |
|
2155
|
|
|
* @param int|null $page Numero of page to show in navigation links (required) |
|
2156
|
|
|
* @param string $file Url of page (required) |
|
2157
|
|
|
* @param string $options More parameters for links ('' by default, does not include sortfield neither sortorder). Value must be 'urlencoded' before calling function. |
|
2158
|
|
|
* @param string $sortfield Field to sort on ('' by default) |
|
2159
|
|
|
* @param string $sortorder Order to sort ('' by default) |
|
2160
|
|
|
* @param string $morehtmlcenter String in the middle ('' by default). We often find here string $massaction coming from $form->selectMassAction() |
|
2161
|
|
|
* @param int $num Number of records found by select with limit+1 |
|
2162
|
|
|
* @param int|string $totalnboflines Total number of records/lines for all pages (if known). Use a negative value of number to not show number. Use '' if unknown. |
|
2163
|
|
|
* @param string $picto Icon to use before title (should be a 32x32 transparent png file) |
|
2164
|
|
|
* @param int $pictoisfullpath 1=Icon name is a full absolute url of image |
|
2165
|
|
|
* @param string $morehtmlright More html to show (after arrows) |
|
2166
|
|
|
* @param string $morecss More css to the table |
|
2167
|
|
|
* @param int $limit Max number of lines (-1 = use default, 0 = no limit, > 0 = limit). |
|
2168
|
|
|
* @param int $hideselectlimit Force to hide select limit |
|
2169
|
|
|
* @param int $hidenavigation Force to hide the arrows and page for navigation |
|
2170
|
|
|
* @param int $pagenavastextinput 1=Do not suggest list of pages to navigate but suggest the page number into an input field. |
|
2171
|
|
|
* @param string $morehtmlrightbeforearrow More html to show (before arrows) |
|
2172
|
|
|
* @return void |
|
2173
|
|
|
*/ |
|
2174
|
|
|
function print_barre_liste($title, $page, $file, $options = '', $sortfield = '', $sortorder = '', $morehtmlcenter = '', $num = -1, $totalnboflines = '', $picto = 'generic', $pictoisfullpath = 0, $morehtmlright = '', $morecss = '', $limit = -1, $hideselectlimit = 0, $hidenavigation = 0, $pagenavastextinput = 0, $morehtmlrightbeforearrow = '') |
|
2175
|
|
|
{ |
|
2176
|
|
|
global $conf; |
|
2177
|
|
|
|
|
2178
|
|
|
$savlimit = $limit; |
|
2179
|
|
|
$savtotalnboflines = $totalnboflines; |
|
2180
|
|
|
if (is_numeric($totalnboflines)) { |
|
2181
|
|
|
$totalnboflines = abs($totalnboflines); |
|
2182
|
|
|
} |
|
2183
|
|
|
|
|
2184
|
|
|
$page = (int)$page; |
|
2185
|
|
|
|
|
2186
|
|
|
if ($picto == 'setup') { |
|
2187
|
|
|
$picto = 'title_setup.png'; |
|
2188
|
|
|
} |
|
2189
|
|
|
if (($conf->browser->name == 'ie') && $picto == 'generic') { |
|
2190
|
|
|
$picto = 'title.gif'; |
|
2191
|
|
|
} |
|
2192
|
|
|
if ($limit < 0) { |
|
2193
|
|
|
$limit = $conf->liste_limit; |
|
2194
|
|
|
} |
|
2195
|
|
|
|
|
2196
|
|
|
if ($savlimit != 0 && (($num > $limit) || ($num == -1) || ($limit == 0))) { |
|
2197
|
|
|
$nextpage = 1; |
|
2198
|
|
|
} else { |
|
2199
|
|
|
$nextpage = 0; |
|
2200
|
|
|
} |
|
2201
|
|
|
//print 'totalnboflines='.$totalnboflines.'-savlimit='.$savlimit.'-limit='.$limit.'-num='.$num.'-nextpage='.$nextpage.'-hideselectlimit='.$hideselectlimit.'-hidenavigation='.$hidenavigation; |
|
2202
|
|
|
|
|
2203
|
|
|
print "\n"; |
|
2204
|
|
|
print "<!-- Begin title -->\n"; |
|
2205
|
|
|
print '<table class="centpercent notopnoleftnoright table-fiche-title' . ($morecss ? ' ' . $morecss : '') . '"><tr>'; // maring bottom must be same than into load_fiche_tire |
|
2206
|
|
|
|
|
2207
|
|
|
// Left |
|
2208
|
|
|
|
|
2209
|
|
|
if ($picto && $title) { |
|
2210
|
|
|
print '<td class="nobordernopadding widthpictotitle valignmiddle col-picto">' . img_picto('', $picto, 'class="valignmiddle pictotitle widthpictotitle"', $pictoisfullpath) . '</td>'; |
|
2211
|
|
|
} |
|
2212
|
|
|
|
|
2213
|
|
|
print '<td class="nobordernopadding valignmiddle col-title">'; |
|
2214
|
|
|
print '<div class="titre inline-block">'; |
|
2215
|
|
|
print $title; // $title may contains HTML |
|
2216
|
|
|
if (!empty($title) && $savtotalnboflines >= 0 && (string)$savtotalnboflines != '') { |
|
2217
|
|
|
print '<span class="opacitymedium colorblack paddingleft">(' . $totalnboflines . ')</span>'; |
|
2218
|
|
|
} |
|
2219
|
|
|
print '</div></td>'; |
|
2220
|
|
|
|
|
2221
|
|
|
// Center |
|
2222
|
|
|
if ($morehtmlcenter && empty($conf->dol_optimize_smallscreen)) { |
|
2223
|
|
|
print '<td class="nobordernopadding center valignmiddle col-center">' . $morehtmlcenter . '</td>'; |
|
2224
|
|
|
} |
|
2225
|
|
|
|
|
2226
|
|
|
// Right |
|
2227
|
|
|
print '<td class="nobordernopadding valignmiddle right col-right">'; |
|
2228
|
|
|
print '<input type="hidden" name="pageplusoneold" value="' . ((int)$page + 1) . '">'; |
|
2229
|
|
|
if ($sortfield) { |
|
2230
|
|
|
$options .= "&sortfield=" . urlencode($sortfield); |
|
2231
|
|
|
} |
|
2232
|
|
|
if ($sortorder) { |
|
2233
|
|
|
$options .= "&sortorder=" . urlencode($sortorder); |
|
2234
|
|
|
} |
|
2235
|
|
|
// Show navigation bar |
|
2236
|
|
|
$pagelist = ''; |
|
2237
|
|
|
if ($savlimit != 0 && ($page > 0 || $num > $limit)) { |
|
2238
|
|
|
if ($totalnboflines) { // If we know total nb of lines |
|
2239
|
|
|
// Define nb of extra page links before and after selected page + ... + first or last |
|
2240
|
|
|
$maxnbofpage = (empty($conf->dol_optimize_smallscreen) ? 4 : 0); |
|
2241
|
|
|
|
|
2242
|
|
|
if ($limit > 0) { |
|
2243
|
|
|
$nbpages = ceil($totalnboflines / $limit); |
|
2244
|
|
|
} else { |
|
2245
|
|
|
$nbpages = 1; |
|
2246
|
|
|
} |
|
2247
|
|
|
$cpt = ($page - $maxnbofpage); |
|
2248
|
|
|
if ($cpt < 0) { |
|
2249
|
|
|
$cpt = 0; |
|
2250
|
|
|
} |
|
2251
|
|
|
|
|
2252
|
|
|
if ($cpt >= 1) { |
|
2253
|
|
|
if (empty($pagenavastextinput)) { |
|
2254
|
|
|
$pagelist .= '<li class="pagination"><a class="reposition" href="' . $file . '?page=0' . $options . '">1</a></li>'; |
|
2255
|
|
|
if ($cpt > 2) { |
|
2256
|
|
|
$pagelist .= '<li class="pagination"><span class="inactive">...</span></li>'; |
|
2257
|
|
|
} elseif ($cpt == 2) { |
|
2258
|
|
|
$pagelist .= '<li class="pagination"><a class="reposition" href="' . $file . '?page=1' . $options . '">2</a></li>'; |
|
2259
|
|
|
} |
|
2260
|
|
|
} |
|
2261
|
|
|
} |
|
2262
|
|
|
|
|
2263
|
|
|
do { |
|
2264
|
|
|
if ($pagenavastextinput) { |
|
2265
|
|
|
if ($cpt == $page) { |
|
2266
|
|
|
$pagelist .= '<li class="pagination"><input type="text" class="' . ($totalnboflines > 100 ? 'width40' : 'width25') . ' center pageplusone" name="pageplusone" value="' . ($page + 1) . '"></li>'; |
|
2267
|
|
|
$pagelist .= '/'; |
|
2268
|
|
|
} |
|
2269
|
|
|
} else { |
|
2270
|
|
|
if ($cpt == $page) { |
|
2271
|
|
|
$pagelist .= '<li class="pagination"><span class="active">' . ($page + 1) . '</span></li>'; |
|
2272
|
|
|
} else { |
|
2273
|
|
|
$pagelist .= '<li class="pagination"><a class="reposition" href="' . $file . '?page=' . $cpt . $options . '">' . ($cpt + 1) . '</a></li>'; |
|
2274
|
|
|
} |
|
2275
|
|
|
} |
|
2276
|
|
|
$cpt++; |
|
2277
|
|
|
} while ($cpt < $nbpages && $cpt <= ($page + $maxnbofpage)); |
|
2278
|
|
|
|
|
2279
|
|
|
if (empty($pagenavastextinput)) { |
|
2280
|
|
|
if ($cpt < $nbpages) { |
|
2281
|
|
|
if ($cpt < $nbpages - 2) { |
|
2282
|
|
|
$pagelist .= '<li class="pagination"><span class="inactive">...</span></li>'; |
|
2283
|
|
|
} elseif ($cpt == $nbpages - 2) { |
|
2284
|
|
|
$pagelist .= '<li class="pagination"><a class="reposition" href="' . $file . '?page=' . ($nbpages - 2) . $options . '">' . ($nbpages - 1) . '</a></li>'; |
|
2285
|
|
|
} |
|
2286
|
|
|
$pagelist .= '<li class="pagination"><a class="reposition" href="' . $file . '?page=' . ($nbpages - 1) . $options . '">' . $nbpages . '</a></li>'; |
|
2287
|
|
|
} |
|
2288
|
|
|
} else { |
|
2289
|
|
|
//var_dump($page.' '.$cpt.' '.$nbpages); |
|
2290
|
|
|
$pagelist .= '<li class="pagination paginationlastpage"><a class="reposition" href="' . $file . '?page=' . ($nbpages - 1) . $options . '">' . $nbpages . '</a></li>'; |
|
2291
|
|
|
} |
|
2292
|
|
|
} else { |
|
2293
|
|
|
$pagelist .= '<li class="pagination"><span class="active">' . ($page + 1) . "</li>"; |
|
2294
|
|
|
} |
|
2295
|
|
|
} |
|
2296
|
|
|
|
|
2297
|
|
|
if ($savlimit || $morehtmlright || $morehtmlrightbeforearrow) { |
|
2298
|
|
|
print_fleche_navigation($page, $file, $options, $nextpage, $pagelist, $morehtmlright, $savlimit, $totalnboflines, $hideselectlimit, $morehtmlrightbeforearrow, $hidenavigation); // output the div and ul for previous/last completed with page numbers into $pagelist |
|
2299
|
|
|
} |
|
2300
|
|
|
|
|
2301
|
|
|
// js to autoselect page field on focus |
|
2302
|
|
|
if ($pagenavastextinput) { |
|
2303
|
|
|
print ajax_autoselect('.pageplusone'); |
|
2304
|
|
|
} |
|
2305
|
|
|
|
|
2306
|
|
|
print '</td>'; |
|
2307
|
|
|
print '</tr>'; |
|
2308
|
|
|
|
|
2309
|
|
|
print '</table>' . "\n"; |
|
2310
|
|
|
|
|
2311
|
|
|
// Center |
|
2312
|
|
|
if ($morehtmlcenter && !empty($conf->dol_optimize_smallscreen)) { |
|
2313
|
|
|
print '<div class="nobordernopadding marginbottomonly center valignmiddle col-center centpercent">' . $morehtmlcenter . '</div>'; |
|
2314
|
|
|
} |
|
2315
|
|
|
|
|
2316
|
|
|
print "<!-- End title -->\n\n"; |
|
2317
|
|
|
} |
|
2318
|
|
|
|
|
2319
|
|
|
/** |
|
2320
|
|
|
* Function to show navigation arrows into lists |
|
2321
|
|
|
* |
|
2322
|
|
|
* @param int $page Number of page |
|
2323
|
|
|
* @param string $file Page URL (in most cases provided with $_SERVER["PHP_SELF"]) |
|
2324
|
|
|
* @param string $options Other url parameters to propagate ("" by default, may include sortfield and sortorder) |
|
2325
|
|
|
* @param integer $nextpage Do we show a next page button |
|
2326
|
|
|
* @param string $betweenarrows HTML content to show between arrows. MUST contains '<li> </li>' tags or '<li><span> </span></li>'. |
|
2327
|
|
|
* @param string $afterarrows HTML content to show after arrows. Must NOT contains '<li> </li>' tags. |
|
2328
|
|
|
* @param int $limit Max nb of record to show (-1 = no combo with limit, 0 = no limit, > 0 = limit) |
|
2329
|
|
|
* @param int $totalnboflines Total number of records/lines for all pages (if known) |
|
2330
|
|
|
* @param int $hideselectlimit Force to hide select limit |
|
2331
|
|
|
* @param string $beforearrows HTML content to show before arrows. Must NOT contains '<li> </li>' tags. |
|
2332
|
|
|
* @param int $hidenavigation Force to hide the switch mode view and the navigation tool (hide limit section, html in $betweenarrows and $afterarrows but not $beforearrows) |
|
2333
|
|
|
* @return void |
|
2334
|
|
|
*/ |
|
2335
|
|
|
function print_fleche_navigation($page, $file, $options = '', $nextpage = 0, $betweenarrows = '', $afterarrows = '', $limit = -1, $totalnboflines = 0, $hideselectlimit = 0, $beforearrows = '', $hidenavigation = 0) |
|
2336
|
|
|
{ |
|
2337
|
|
|
global $conf, $langs; |
|
2338
|
|
|
|
|
2339
|
|
|
print '<div class="pagination"><ul>'; |
|
2340
|
|
|
if ($beforearrows) { |
|
2341
|
|
|
print '<li class="paginationbeforearrows">'; |
|
2342
|
|
|
print $beforearrows; |
|
2343
|
|
|
print '</li>'; |
|
2344
|
|
|
} |
|
2345
|
|
|
|
|
2346
|
|
|
if (empty($hidenavigation)) { |
|
2347
|
|
|
if ((int)$limit > 0 && empty($hideselectlimit)) { |
|
2348
|
|
|
$pagesizechoices = '10:10,15:15,20:20,25:25,50:50,100:100,250:250,500:500,1000:1000'; |
|
2349
|
|
|
$pagesizechoices .= ',5000:5000,10000:10000,20000:20000'; |
|
2350
|
|
|
//$pagesizechoices.=',0:'.$langs->trans("All"); // Not yet supported |
|
2351
|
|
|
//$pagesizechoices.=',2:2'; |
|
2352
|
|
|
if (getDolGlobalString('MAIN_PAGESIZE_CHOICES')) { |
|
2353
|
|
|
$pagesizechoices = getDolGlobalString('MAIN_PAGESIZE_CHOICES'); |
|
2354
|
|
|
} |
|
2355
|
|
|
|
|
2356
|
|
|
if (getDolGlobalString('MAIN_USE_HTML5_LIMIT_SELECTOR')) { |
|
2357
|
|
|
print '<li class="pagination">'; |
|
2358
|
|
|
print '<input onfocus="this.value=null;" onchange="this.blur();" class="flat selectlimit nopadding maxwidth75 right pageplusone" id="limit" name="limit" list="limitlist" title="' . dol_escape_htmltag($langs->trans("MaxNbOfRecordPerPage")) . '" value="' . $limit . '">'; |
|
2359
|
|
|
print '<datalist id="limitlist">'; |
|
2360
|
|
|
} else { |
|
2361
|
|
|
print '<li class="paginationxxx valignmiddle">'; |
|
2362
|
|
|
print '<select id="limit" class="flat selectlimit nopadding maxwidth75 center" name="limit" title="' . dol_escape_htmltag($langs->trans("MaxNbOfRecordPerPage")) . '">'; |
|
2363
|
|
|
} |
|
2364
|
|
|
$tmpchoice = explode(',', $pagesizechoices); |
|
2365
|
|
|
$tmpkey = $limit . ':' . $limit; |
|
2366
|
|
|
if (!in_array($tmpkey, $tmpchoice)) { |
|
2367
|
|
|
$tmpchoice[] = $tmpkey; |
|
2368
|
|
|
} |
|
2369
|
|
|
$tmpkey = $conf->liste_limit . ':' . $conf->liste_limit; |
|
2370
|
|
|
if (!in_array($tmpkey, $tmpchoice)) { |
|
2371
|
|
|
$tmpchoice[] = $tmpkey; |
|
2372
|
|
|
} |
|
2373
|
|
|
asort($tmpchoice, SORT_NUMERIC); |
|
2374
|
|
|
foreach ($tmpchoice as $val) { |
|
2375
|
|
|
$selected = ''; |
|
2376
|
|
|
$tmp = explode(':', $val); |
|
2377
|
|
|
$key = $tmp[0]; |
|
2378
|
|
|
$val = $tmp[1]; |
|
2379
|
|
|
if ($key != '' && $val != '') { |
|
2380
|
|
|
if ((int)$key == (int)$limit) { |
|
2381
|
|
|
$selected = ' selected="selected"'; |
|
2382
|
|
|
} |
|
2383
|
|
|
print '<option name="' . $key . '"' . $selected . '>' . dol_escape_htmltag($val) . '</option>' . "\n"; |
|
2384
|
|
|
} |
|
2385
|
|
|
} |
|
2386
|
|
|
if (getDolGlobalString('MAIN_USE_HTML5_LIMIT_SELECTOR')) { |
|
2387
|
|
|
print '</datalist>'; |
|
2388
|
|
|
} else { |
|
2389
|
|
|
print '</select>'; |
|
2390
|
|
|
print ajax_combobox("limit", array(), 0, 0, 'resolve', -1, 'limit'); |
|
2391
|
|
|
//print ajax_combobox("limit"); |
|
2392
|
|
|
} |
|
2393
|
|
|
|
|
2394
|
|
|
if ($conf->use_javascript_ajax) { |
|
2395
|
|
|
print '<!-- JS CODE TO ENABLE select limit to launch submit of page --> |
|
2396
|
|
|
<script> |
|
2397
|
|
|
jQuery(document).ready(function () { |
|
2398
|
|
|
jQuery(".selectlimit").change(function() { |
|
2399
|
|
|
console.log("Change limit. Send submit"); |
|
2400
|
|
|
$(this).parents(\'form:first\').submit(); |
|
2401
|
|
|
}); |
|
2402
|
|
|
}); |
|
2403
|
|
|
</script> |
|
2404
|
|
|
'; |
|
2405
|
|
|
} |
|
2406
|
|
|
print '</li>'; |
|
2407
|
|
|
} |
|
2408
|
|
|
if ($page > 0) { |
|
2409
|
|
|
print '<li class="pagination paginationpage paginationpageleft"><a class="paginationprevious reposition" href="' . $file . '?page=' . ($page - 1) . $options . '"><i class="fa fa-chevron-left" title="' . dol_escape_htmltag($langs->trans("Previous")) . '"></i></a></li>'; |
|
2410
|
|
|
} |
|
2411
|
|
|
if ($betweenarrows) { |
|
2412
|
|
|
print '<!--<div class="betweenarrows nowraponall inline-block">-->'; |
|
2413
|
|
|
print $betweenarrows; |
|
2414
|
|
|
print '<!--</div>-->'; |
|
2415
|
|
|
} |
|
2416
|
|
|
if ($nextpage > 0) { |
|
2417
|
|
|
print '<li class="pagination paginationpage paginationpageright"><a class="paginationnext reposition" href="' . $file . '?page=' . ($page + 1) . $options . '"><i class="fa fa-chevron-right" title="' . dol_escape_htmltag($langs->trans("Next")) . '"></i></a></li>'; |
|
2418
|
|
|
} |
|
2419
|
|
|
if ($afterarrows) { |
|
2420
|
|
|
print '<li class="paginationafterarrows">'; |
|
2421
|
|
|
print $afterarrows; |
|
2422
|
|
|
print '</li>'; |
|
2423
|
|
|
} |
|
2424
|
|
|
} |
|
2425
|
|
|
print '</ul></div>' . "\n"; |
|
2426
|
|
|
} |
|
2427
|
|
|
|
|
2428
|
|
|
/** |
|
2429
|
|
|
* Displays an error page when a record is not found. It allows customization of the message, |
|
2430
|
|
|
* whether to include the header and footer, and if only the message should be shown without additional details. |
|
2431
|
|
|
* The function also supports executing additional hooks for customized handling of error pages. |
|
2432
|
|
|
* |
|
2433
|
|
|
* @param string $message Custom error message to display. If empty, a default "Record Not Found" message is shown. |
|
2434
|
|
|
* @param int<0,1> $printheader Determines if the page header should be printed (1 = yes, 0 = no). |
|
2435
|
|
|
* @param int<0,1> $printfooter Determines if the page footer should be printed (1 = yes, 0 = no). |
|
2436
|
|
|
* @param int<0,1> $showonlymessage If set to 1, only the error message is displayed without any additional information or hooks. |
|
2437
|
|
|
* @param mixed $params Optional parameters to pass to hooks for further processing or customization. |
|
2438
|
|
|
* @return void This function terminates script execution after outputting the error page. |
|
2439
|
|
|
* @global Conf $conf Dolibarr configuration object (global) |
|
2440
|
|
|
* @global DoliDB $db Database connection object (global) |
|
2441
|
|
|
* @global User $user Current user object (global) |
|
2442
|
|
|
* @global Translate $langs Language translation object, initialized within the function if not already. |
|
2443
|
|
|
* @global HookManager $hookmanager Hook manager object, initialized within the function if not already for executing hooks. |
|
2444
|
|
|
* @global string $action Current action, can be modified by hooks. |
|
2445
|
|
|
* @global object $object Current object, can be modified by hooks. |
|
2446
|
|
|
*/ |
|
2447
|
|
|
function recordNotFound($message = '', $printheader = 1, $printfooter = 1, $showonlymessage = 0, $params = null) |
|
2448
|
|
|
{ |
|
2449
|
|
|
global $conf, $db, $langs, $hookmanager; |
|
2450
|
|
|
global $action, $object; |
|
2451
|
|
|
|
|
2452
|
|
|
if (!is_object($langs)) { |
|
2453
|
|
|
$langs = new Translate('', $conf); |
|
2454
|
|
|
$langs->setDefaultLang(); |
|
2455
|
|
|
} |
|
2456
|
|
|
|
|
2457
|
|
|
$langs->load("errors"); |
|
2458
|
|
|
|
|
2459
|
|
|
if ($printheader) { |
|
2460
|
|
|
if (function_exists("llxHeader")) { |
|
2461
|
|
|
ViewMain::llxHeader(''); |
|
2462
|
|
|
} elseif (function_exists("llxHeaderVierge")) { |
|
2463
|
|
|
llxHeaderVierge(''); |
|
2464
|
|
|
} |
|
2465
|
|
|
} |
|
2466
|
|
|
|
|
2467
|
|
|
print '<div class="error">'; |
|
2468
|
|
|
if (empty($message)) { |
|
2469
|
|
|
print $langs->trans("ErrorRecordNotFound"); |
|
2470
|
|
|
} else { |
|
2471
|
|
|
print $langs->trans($message); |
|
2472
|
|
|
} |
|
2473
|
|
|
print '</div>'; |
|
2474
|
|
|
print '<br>'; |
|
2475
|
|
|
|
|
2476
|
|
|
if (empty($showonlymessage)) { |
|
2477
|
|
|
if (empty($hookmanager)) { |
|
2478
|
|
|
$hookmanager = new HookManager($db); |
|
2479
|
|
|
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context |
|
2480
|
|
|
$hookmanager->initHooks(array('main')); |
|
2481
|
|
|
} |
|
2482
|
|
|
|
|
2483
|
|
|
$parameters = array('message' => $message, 'params' => $params); |
|
2484
|
|
|
$reshook = $hookmanager->executeHooks('getErrorRecordNotFound', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks |
|
2485
|
|
|
print $hookmanager->resPrint; |
|
2486
|
|
|
} |
|
2487
|
|
|
|
|
2488
|
|
|
if ($printfooter && function_exists("llxFooter")) { |
|
2489
|
|
|
ViewMain::llxFooter(); |
|
2490
|
|
|
} |
|
2491
|
|
|
exit(0); |
|
|
|
|
|
|
2492
|
|
|
} |
|
2493
|
|
|
|
|
2494
|
|
|
/** |
|
2495
|
|
|
* Show html area with actions in messaging format. |
|
2496
|
|
|
* Note: Global parameter $param must be defined. |
|
2497
|
|
|
* |
|
2498
|
|
|
* @param Conf $conf Object conf |
|
2499
|
|
|
* @param Translate $langs Object langs |
|
2500
|
|
|
* @param DoliDB $db Object db |
|
2501
|
|
|
* @param ?CommonObject $filterobj Filter on object Adherent|Societe|Project|Product|CommandeFournisseur|Dolresource|Ticket|... to list events linked to an object |
|
2502
|
|
|
* @param ?Contact $objcon Filter on object contact to filter events on a contact |
|
2503
|
|
|
* @param int $noprint Return string but does not output it |
|
2504
|
|
|
* @param string $actioncode Filter on actioncode |
|
2505
|
|
|
* @param string $donetodo Filter on event 'done' or 'todo' or ''=nofilter (all). |
|
2506
|
|
|
* @param array<string,string> $filters Filter on other fields |
|
2507
|
|
|
* @param string $sortfield Sort field |
|
2508
|
|
|
* @param string $sortorder Sort order |
|
2509
|
|
|
* @return string|void Return html part or void if noprint is 1 |
|
2510
|
|
|
*/ |
|
2511
|
|
|
function show_actions_messaging($conf, $langs, $db, $filterobj, $objcon = null, $noprint = 0, $actioncode = '', $donetodo = 'done', $filters = array(), $sortfield = 'a.datep,a.id', $sortorder = 'DESC') |
|
2512
|
|
|
{ |
|
2513
|
|
|
global $user, $conf; |
|
2514
|
|
|
global $form; |
|
2515
|
|
|
|
|
2516
|
|
|
global $param, $massactionbutton; |
|
2517
|
|
|
|
|
2518
|
|
|
|
|
2519
|
|
|
// Check parameters |
|
2520
|
|
|
if (!is_object($filterobj) && !is_object($objcon)) { |
|
2521
|
|
|
dol_print_error(null, 'BadParameter'); |
|
2522
|
|
|
} |
|
2523
|
|
|
|
|
2524
|
|
|
$histo = array(); |
|
2525
|
|
|
'@phan-var-force array<int,array{type:string,tododone:string,id:string,datestart:int|string,dateend:int|string,note:string,message:string,percent:string,userid:string,login:string,userfirstname:string,userlastname:string,userphoto:string,msg_from?:string,contact_id?:string,socpeopleassigned?:int[],lastname?:string,firstname?:string,fk_element?:int,elementtype?:string,acode:string,alabel?:string,libelle?:string,apicto?:string}> $histo'; |
|
2526
|
|
|
|
|
2527
|
|
|
$numaction = 0; |
|
2528
|
|
|
$now = dol_now(); |
|
2529
|
|
|
|
|
2530
|
|
|
$sortfield_list = explode(',', $sortfield); |
|
2531
|
|
|
$sortfield_label_list = array('a.id' => 'id', 'a.datep' => 'dp', 'a.percent' => 'percent'); |
|
2532
|
|
|
$sortfield_new_list = array(); |
|
2533
|
|
|
foreach ($sortfield_list as $sortfield_value) { |
|
2534
|
|
|
$sortfield_new_list[] = $sortfield_label_list[trim($sortfield_value)]; |
|
2535
|
|
|
} |
|
2536
|
|
|
$sortfield_new = implode(',', $sortfield_new_list); |
|
2537
|
|
|
|
|
2538
|
|
|
$sql = null; |
|
2539
|
|
|
$sql2 = null; |
|
2540
|
|
|
|
|
2541
|
|
|
if (isModEnabled('agenda')) { |
|
2542
|
|
|
// Search histo on actioncomm |
|
2543
|
|
|
if (is_object($objcon) && $objcon->id > 0) { |
|
2544
|
|
|
$sql = "SELECT DISTINCT a.id, a.label as label,"; |
|
2545
|
|
|
} else { |
|
2546
|
|
|
$sql = "SELECT a.id, a.label as label,"; |
|
2547
|
|
|
} |
|
2548
|
|
|
$sql .= " a.datep as dp,"; |
|
2549
|
|
|
$sql .= " a.note as message,"; |
|
2550
|
|
|
$sql .= " a.datep2 as dp2,"; |
|
2551
|
|
|
$sql .= " a.percent as percent, 'action' as type,"; |
|
2552
|
|
|
$sql .= " a.fk_element, a.elementtype,"; |
|
2553
|
|
|
$sql .= " a.fk_contact,"; |
|
2554
|
|
|
$sql .= " a.email_from as msg_from,"; |
|
2555
|
|
|
$sql .= " c.code as acode, c.libelle as alabel, c.picto as apicto,"; |
|
2556
|
|
|
$sql .= " u.rowid as user_id, u.login as user_login, u.photo as user_photo, u.firstname as user_firstname, u.lastname as user_lastname"; |
|
2557
|
|
|
if (is_object($filterobj) && get_only_class($filterobj) == 'Societe') { |
|
2558
|
|
|
$sql .= ", sp.lastname, sp.firstname"; |
|
2559
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Adherent') { |
|
2560
|
|
|
$sql .= ", m.lastname, m.firstname"; |
|
2561
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'CommandeFournisseur') { |
|
2562
|
|
|
$sql .= ", o.ref"; |
|
2563
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Product') { |
|
2564
|
|
|
$sql .= ", o.ref"; |
|
2565
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Ticket') { |
|
2566
|
|
|
$sql .= ", o.ref"; |
|
2567
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'BOM') { |
|
2568
|
|
|
$sql .= ", o.ref"; |
|
2569
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Contrat') { |
|
2570
|
|
|
$sql .= ", o.ref"; |
|
2571
|
|
|
} |
|
2572
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "actioncomm as a"; |
|
2573
|
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user as u on u.rowid = a.fk_user_action"; |
|
2574
|
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_actioncomm as c ON a.fk_action = c.id"; |
|
2575
|
|
|
|
|
2576
|
|
|
$force_filter_contact = $filterobj instanceof User; |
|
2577
|
|
|
|
|
2578
|
|
|
if (is_object($objcon) && $objcon->id > 0) { |
|
2579
|
|
|
$force_filter_contact = true; |
|
2580
|
|
|
$sql .= " INNER JOIN " . MAIN_DB_PREFIX . "actioncomm_resources as r ON a.id = r.fk_actioncomm"; |
|
2581
|
|
|
$sql .= " AND r.element_type = '" . $db->escape($objcon->table_element) . "' AND r.fk_element = " . ((int)$objcon->id); |
|
2582
|
|
|
} |
|
2583
|
|
|
|
|
2584
|
|
|
if (is_object($filterobj) && get_only_class($filterobj) == 'Societe') { |
|
2585
|
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "socpeople as sp ON a.fk_contact = sp.rowid"; |
|
2586
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Dolresource') { |
|
2587
|
|
|
$sql .= " INNER JOIN " . MAIN_DB_PREFIX . "element_resources as er"; |
|
2588
|
|
|
$sql .= " ON er.resource_type = 'dolresource'"; |
|
2589
|
|
|
$sql .= " AND er.element_id = a.id"; |
|
2590
|
|
|
$sql .= " AND er.resource_id = " . ((int)$filterobj->id); |
|
2591
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Adherent') { |
|
2592
|
|
|
$sql .= ", " . MAIN_DB_PREFIX . "adherent as m"; |
|
2593
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'CommandeFournisseur') { |
|
2594
|
|
|
$sql .= ", " . MAIN_DB_PREFIX . "commande_fournisseur as o"; |
|
2595
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Product') { |
|
2596
|
|
|
$sql .= ", " . MAIN_DB_PREFIX . "product as o"; |
|
2597
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Ticket') { |
|
2598
|
|
|
$sql .= ", " . MAIN_DB_PREFIX . "ticket as o"; |
|
2599
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'BOM') { |
|
2600
|
|
|
$sql .= ", " . MAIN_DB_PREFIX . "bom_bom as o"; |
|
2601
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Contrat') { |
|
2602
|
|
|
$sql .= ", " . MAIN_DB_PREFIX . "contrat as o"; |
|
2603
|
|
|
} |
|
2604
|
|
|
|
|
2605
|
|
|
$sql .= " WHERE a.entity IN (" . getEntity('agenda') . ")"; |
|
2606
|
|
|
if (!$force_filter_contact) { |
|
2607
|
|
|
if (is_object($filterobj) && in_array(get_only_class($filterobj), array('Societe', 'Client', 'Fournisseur')) && $filterobj->id) { |
|
2608
|
|
|
$sql .= " AND a.fk_soc = " . ((int)$filterobj->id); |
|
2609
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Project' && $filterobj->id) { |
|
2610
|
|
|
$sql .= " AND a.fk_project = " . ((int)$filterobj->id); |
|
2611
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Adherent') { |
|
2612
|
|
|
$sql .= " AND a.fk_element = m.rowid AND a.elementtype = 'member'"; |
|
2613
|
|
|
if ($filterobj->id) { |
|
2614
|
|
|
$sql .= " AND a.fk_element = " . ((int)$filterobj->id); |
|
2615
|
|
|
} |
|
2616
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'CommandeFournisseur') { |
|
2617
|
|
|
$sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'order_supplier'"; |
|
2618
|
|
|
if ($filterobj->id) { |
|
2619
|
|
|
$sql .= " AND a.fk_element = " . ((int)$filterobj->id); |
|
2620
|
|
|
} |
|
2621
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Product') { |
|
2622
|
|
|
$sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'product'"; |
|
2623
|
|
|
if ($filterobj->id) { |
|
2624
|
|
|
$sql .= " AND a.fk_element = " . ((int)$filterobj->id); |
|
2625
|
|
|
} |
|
2626
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Ticket') { |
|
2627
|
|
|
$sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'ticket'"; |
|
2628
|
|
|
if ($filterobj->id) { |
|
2629
|
|
|
$sql .= " AND a.fk_element = " . ((int)$filterobj->id); |
|
2630
|
|
|
} |
|
2631
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'BOM') { |
|
2632
|
|
|
$sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'bom'"; |
|
2633
|
|
|
if ($filterobj->id) { |
|
2634
|
|
|
$sql .= " AND a.fk_element = " . ((int)$filterobj->id); |
|
2635
|
|
|
} |
|
2636
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Contrat') { |
|
2637
|
|
|
$sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'contract'"; |
|
2638
|
|
|
if ($filterobj->id) { |
|
2639
|
|
|
$sql .= " AND a.fk_element = " . ((int)$filterobj->id); |
|
2640
|
|
|
} |
|
2641
|
|
|
} |
|
2642
|
|
|
} else { |
|
2643
|
|
|
$sql .= " AND u.rowid = " . ((int)$filterobj->id); |
|
2644
|
|
|
} |
|
2645
|
|
|
|
|
2646
|
|
|
// Condition on actioncode |
|
2647
|
|
|
if (!empty($actioncode)) { |
|
2648
|
|
|
if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE')) { |
|
2649
|
|
|
if ($actioncode == 'AC_NON_AUTO') { |
|
2650
|
|
|
$sql .= " AND c.type != 'systemauto'"; |
|
2651
|
|
|
} elseif ($actioncode == 'AC_ALL_AUTO') { |
|
2652
|
|
|
$sql .= " AND c.type = 'systemauto'"; |
|
2653
|
|
|
} else { |
|
2654
|
|
|
if ($actioncode == 'AC_OTH') { |
|
2655
|
|
|
$sql .= " AND c.type != 'systemauto'"; |
|
2656
|
|
|
} elseif ($actioncode == 'AC_OTH_AUTO') { |
|
2657
|
|
|
$sql .= " AND c.type = 'systemauto'"; |
|
2658
|
|
|
} |
|
2659
|
|
|
} |
|
2660
|
|
|
} else { |
|
2661
|
|
|
if ($actioncode == 'AC_NON_AUTO') { |
|
2662
|
|
|
$sql .= " AND c.type != 'systemauto'"; |
|
2663
|
|
|
} elseif ($actioncode == 'AC_ALL_AUTO') { |
|
2664
|
|
|
$sql .= " AND c.type = 'systemauto'"; |
|
2665
|
|
|
} else { |
|
2666
|
|
|
$sql .= " AND c.code = '" . $db->escape($actioncode) . "'"; |
|
2667
|
|
|
} |
|
2668
|
|
|
} |
|
2669
|
|
|
} |
|
2670
|
|
|
if ($donetodo == 'todo') { |
|
2671
|
|
|
$sql .= " AND ((a.percent >= 0 AND a.percent < 100) OR (a.percent = -1 AND a.datep > '" . $db->idate($now) . "'))"; |
|
2672
|
|
|
} elseif ($donetodo == 'done') { |
|
2673
|
|
|
$sql .= " AND (a.percent = 100 OR (a.percent = -1 AND a.datep <= '" . $db->idate($now) . "'))"; |
|
2674
|
|
|
} |
|
2675
|
|
|
if (is_array($filters) && $filters['search_agenda_label']) { |
|
2676
|
|
|
$sql .= natural_search('a.label', $filters['search_agenda_label']); |
|
2677
|
|
|
} |
|
2678
|
|
|
} |
|
2679
|
|
|
|
|
2680
|
|
|
// Add also event from emailings. TODO This should be replaced by an automatic event ? May be it's too much for very large emailing. |
|
2681
|
|
|
if ( |
|
2682
|
|
|
isModEnabled('mailing') && !empty($objcon->email) |
|
2683
|
|
|
&& (empty($actioncode) || $actioncode == 'AC_OTH_AUTO' || $actioncode == 'AC_EMAILING') |
|
2684
|
|
|
) { |
|
2685
|
|
|
$langs->load("mails"); |
|
2686
|
|
|
|
|
2687
|
|
|
$sql2 = "SELECT m.rowid as id, m.titre as label, mc.date_envoi as dp, mc.date_envoi as dp2, '100' as percent, 'mailing' as type"; |
|
2688
|
|
|
$sql2 .= ", null as fk_element, '' as elementtype, null as contact_id"; |
|
2689
|
|
|
$sql2 .= ", 'AC_EMAILING' as acode, '' as alabel, '' as apicto"; |
|
2690
|
|
|
$sql2 .= ", u.rowid as user_id, u.login as user_login, u.photo as user_photo, u.firstname as user_firstname, u.lastname as user_lastname"; // User that valid action |
|
2691
|
|
|
if (is_object($filterobj) && get_only_class($filterobj) == 'Societe') { |
|
2692
|
|
|
$sql2 .= ", '' as lastname, '' as firstname"; |
|
2693
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Adherent') { |
|
2694
|
|
|
$sql2 .= ", '' as lastname, '' as firstname"; |
|
2695
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'CommandeFournisseur') { |
|
2696
|
|
|
$sql2 .= ", '' as ref"; |
|
2697
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Product') { |
|
2698
|
|
|
$sql2 .= ", '' as ref"; |
|
2699
|
|
|
} elseif (is_object($filterobj) && get_only_class($filterobj) == 'Ticket') { |
|
2700
|
|
|
$sql2 .= ", '' as ref"; |
|
2701
|
|
|
} |
|
2702
|
|
|
$sql2 .= " FROM " . MAIN_DB_PREFIX . "mailing as m, " . MAIN_DB_PREFIX . "mailing_cibles as mc, " . MAIN_DB_PREFIX . "user as u"; |
|
2703
|
|
|
$sql2 .= " WHERE mc.email = '" . $db->escape($objcon->email) . "'"; // Search is done on email. |
|
2704
|
|
|
$sql2 .= " AND mc.statut = 1"; |
|
2705
|
|
|
$sql2 .= " AND u.rowid = m.fk_user_valid"; |
|
2706
|
|
|
$sql2 .= " AND mc.fk_mailing=m.rowid"; |
|
2707
|
|
|
} |
|
2708
|
|
|
|
|
2709
|
|
|
if ($sql || $sql2) { // May not be defined if module Agenda is not enabled and mailing module disabled too |
|
2710
|
|
|
if (!empty($sql) && !empty($sql2)) { |
|
2711
|
|
|
$sql = $sql . " UNION " . $sql2; |
|
2712
|
|
|
} elseif (empty($sql) && !empty($sql2)) { |
|
2713
|
|
|
$sql = $sql2; |
|
2714
|
|
|
} |
|
2715
|
|
|
|
|
2716
|
|
|
//TODO Add navigation with this limits... |
|
2717
|
|
|
$offset = 0; |
|
2718
|
|
|
$limit = 1000; |
|
2719
|
|
|
|
|
2720
|
|
|
// Complete request and execute it with limit |
|
2721
|
|
|
$sql .= $db->order($sortfield_new, $sortorder); |
|
2722
|
|
|
if ($limit) { |
|
2723
|
|
|
$sql .= $db->plimit($limit + 1, $offset); |
|
2724
|
|
|
} |
|
2725
|
|
|
|
|
2726
|
|
|
dol_syslog("function.lib::show_actions_messaging", LOG_DEBUG); |
|
2727
|
|
|
$resql = $db->query($sql); |
|
2728
|
|
|
if ($resql) { |
|
2729
|
|
|
$i = 0; |
|
2730
|
|
|
$num = $db->num_rows($resql); |
|
2731
|
|
|
|
|
2732
|
|
|
$imaxinloop = ($limit ? min($num, $limit) : $num); |
|
2733
|
|
|
while ($i < $imaxinloop) { |
|
2734
|
|
|
$obj = $db->fetch_object($resql); |
|
2735
|
|
|
|
|
2736
|
|
|
if ($obj->type == 'action') { |
|
2737
|
|
|
$contactaction = new ActionComm($db); |
|
2738
|
|
|
$contactaction->id = $obj->id; |
|
2739
|
|
|
$result = $contactaction->fetchResources(); |
|
2740
|
|
|
if ($result < 0) { |
|
2741
|
|
|
dol_print_error($db); |
|
2742
|
|
|
setEventMessage("actions.lib::show_actions_messaging Error fetch resource", 'errors'); |
|
2743
|
|
|
} |
|
2744
|
|
|
|
|
2745
|
|
|
//if ($donetodo == 'todo') $sql.= " AND ((a.percent >= 0 AND a.percent < 100) OR (a.percent = -1 AND a.datep > '".$db->idate($now)."'))"; |
|
2746
|
|
|
//elseif ($donetodo == 'done') $sql.= " AND (a.percent = 100 OR (a.percent = -1 AND a.datep <= '".$db->idate($now)."'))"; |
|
2747
|
|
|
$tododone = ''; |
|
2748
|
|
|
if (($obj->percent >= 0 and $obj->percent < 100) || ($obj->percent == -1 && $obj->dp > $now)) { |
|
2749
|
|
|
$tododone = 'todo'; |
|
2750
|
|
|
} |
|
2751
|
|
|
|
|
2752
|
|
|
$histo[$numaction] = array( |
|
2753
|
|
|
'type' => $obj->type, |
|
2754
|
|
|
'tododone' => $tododone, |
|
2755
|
|
|
'id' => $obj->id, |
|
2756
|
|
|
'datestart' => $db->jdate($obj->dp), |
|
2757
|
|
|
'dateend' => $db->jdate($obj->dp2), |
|
2758
|
|
|
'note' => $obj->label, |
|
2759
|
|
|
'message' => dol_htmlentitiesbr($obj->message), |
|
2760
|
|
|
'percent' => $obj->percent, |
|
2761
|
|
|
|
|
2762
|
|
|
'userid' => $obj->user_id, |
|
2763
|
|
|
'login' => $obj->user_login, |
|
2764
|
|
|
'userfirstname' => $obj->user_firstname, |
|
2765
|
|
|
'userlastname' => $obj->user_lastname, |
|
2766
|
|
|
'userphoto' => $obj->user_photo, |
|
2767
|
|
|
'msg_from' => $obj->msg_from, |
|
2768
|
|
|
|
|
2769
|
|
|
'contact_id' => $obj->fk_contact, |
|
2770
|
|
|
'socpeopleassigned' => $contactaction->socpeopleassigned, |
|
2771
|
|
|
'lastname' => (empty($obj->lastname) ? '' : $obj->lastname), |
|
2772
|
|
|
'firstname' => (empty($obj->firstname) ? '' : $obj->firstname), |
|
2773
|
|
|
'fk_element' => $obj->fk_element, |
|
2774
|
|
|
'elementtype' => $obj->elementtype, |
|
2775
|
|
|
// Type of event |
|
2776
|
|
|
'acode' => $obj->acode, |
|
2777
|
|
|
'alabel' => $obj->alabel, |
|
2778
|
|
|
'libelle' => $obj->alabel, // deprecated |
|
2779
|
|
|
'apicto' => $obj->apicto |
|
2780
|
|
|
); |
|
2781
|
|
|
} else { |
|
2782
|
|
|
$histo[$numaction] = array( |
|
2783
|
|
|
'type' => $obj->type, |
|
2784
|
|
|
'tododone' => 'done', |
|
2785
|
|
|
'id' => $obj->id, |
|
2786
|
|
|
'datestart' => $db->jdate($obj->dp), |
|
2787
|
|
|
'dateend' => $db->jdate($obj->dp2), |
|
2788
|
|
|
'note' => $obj->label, |
|
2789
|
|
|
'message' => dol_htmlentitiesbr($obj->message), |
|
2790
|
|
|
'percent' => $obj->percent, |
|
2791
|
|
|
'acode' => $obj->acode, |
|
2792
|
|
|
|
|
2793
|
|
|
'userid' => $obj->user_id, |
|
2794
|
|
|
'login' => $obj->user_login, |
|
2795
|
|
|
'userfirstname' => $obj->user_firstname, |
|
2796
|
|
|
'userlastname' => $obj->user_lastname, |
|
2797
|
|
|
'userphoto' => $obj->user_photo |
|
2798
|
|
|
); |
|
2799
|
|
|
} |
|
2800
|
|
|
|
|
2801
|
|
|
$numaction++; |
|
2802
|
|
|
$i++; |
|
2803
|
|
|
} |
|
2804
|
|
|
} else { |
|
2805
|
|
|
dol_print_error($db); |
|
2806
|
|
|
} |
|
2807
|
|
|
} |
|
2808
|
|
|
|
|
2809
|
|
|
// Set $out to show events |
|
2810
|
|
|
$out = ''; |
|
2811
|
|
|
|
|
2812
|
|
|
if (!isModEnabled('agenda')) { |
|
2813
|
|
|
$langs->loadLangs(array("admin", "errors")); |
|
2814
|
|
|
$out = info_admin($langs->trans("WarningModuleXDisabledSoYouMayMissEventHere", $langs->transnoentitiesnoconv("Module2400Name")), 0, 0, 'warning'); |
|
2815
|
|
|
} |
|
2816
|
|
|
|
|
2817
|
|
|
if (isModEnabled('agenda') || (isModEnabled('mailing') && !empty($objcon->email))) { |
|
2818
|
|
|
$delay_warning = $conf->global->MAIN_DELAY_ACTIONS_TODO * 24 * 60 * 60; |
|
2819
|
|
|
|
|
2820
|
|
|
include_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php'; |
|
2821
|
|
|
|
|
2822
|
|
|
$formactions = new FormActions($db); |
|
2823
|
|
|
$actionstatic = new ActionComm($db); |
|
2824
|
|
|
$userstatic = new User($db); |
|
2825
|
|
|
$contactstatic = new Contact($db); |
|
2826
|
|
|
$userGetNomUrlCache = array(); |
|
2827
|
|
|
$contactGetNomUrlCache = array(); |
|
2828
|
|
|
|
|
2829
|
|
|
$out .= '<div class="filters-container" >'; |
|
2830
|
|
|
$out .= '<form name="listactionsfilter" class="listactionsfilter" action="' . $_SERVER["PHP_SELF"] . '" method="POST">'; |
|
2831
|
|
|
$out .= '<input type="hidden" name="token" value="' . newToken() . '">'; |
|
2832
|
|
|
|
|
2833
|
|
|
if ( |
|
2834
|
|
|
$objcon && get_only_class($objcon) == 'Contact' && |
|
2835
|
|
|
(is_null($filterobj) || get_only_class($filterobj) == 'Societe') |
|
2836
|
|
|
) { |
|
2837
|
|
|
$out .= '<input type="hidden" name="id" value="' . $objcon->id . '" />'; |
|
2838
|
|
|
} else { |
|
2839
|
|
|
$out .= '<input type="hidden" name="id" value="' . $filterobj->id . '" />'; |
|
2840
|
|
|
} |
|
2841
|
|
|
if (($filterobj && get_only_class($filterobj) == 'Societe')) { |
|
2842
|
|
|
$out .= '<input type="hidden" name="socid" value="' . $filterobj->id . '" />'; |
|
2843
|
|
|
} else { |
|
2844
|
|
|
$out .= '<input type="hidden" name="userid" value="' . $filterobj->id . '" />'; |
|
2845
|
|
|
} |
|
2846
|
|
|
|
|
2847
|
|
|
$out .= "\n"; |
|
2848
|
|
|
|
|
2849
|
|
|
$out .= '<div class="div-table-responsive-no-min">'; |
|
2850
|
|
|
$out .= '<table class="noborder borderbottom centpercent">'; |
|
2851
|
|
|
|
|
2852
|
|
|
$out .= '<tr class="liste_titre">'; |
|
2853
|
|
|
|
|
2854
|
|
|
// Action column |
|
2855
|
|
|
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { |
|
2856
|
|
|
$out .= '<th class="liste_titre width50 middle">'; |
|
2857
|
|
|
$searchpicto = $form->showFilterAndCheckAddButtons($massactionbutton ? 1 : 0, 'checkforselect', 1); |
|
2858
|
|
|
$out .= $searchpicto; |
|
2859
|
|
|
$out .= '</th>'; |
|
2860
|
|
|
} |
|
2861
|
|
|
|
|
2862
|
|
|
$out .= getTitleFieldOfList('Date', 0, $_SERVER["PHP_SELF"], 'a.datep', '', $param, '', $sortfield, $sortorder, '') . "\n"; |
|
2863
|
|
|
|
|
2864
|
|
|
$out .= '<th class="liste_titre"><strong class="hideonsmartphone">' . $langs->trans("Search") . ' : </strong></th>'; |
|
2865
|
|
|
if ($donetodo) { |
|
2866
|
|
|
$out .= '<th class="liste_titre"></th>'; |
|
2867
|
|
|
} |
|
2868
|
|
|
$out .= '<th class="liste_titre">'; |
|
2869
|
|
|
$out .= '<span class="fas fa-square inline-block fawidth30" style=" color: #ddd;" title="' . $langs->trans("ActionType") . '"></span>'; |
|
2870
|
|
|
//$out .= img_picto($langs->trans("Type"), 'type'); |
|
2871
|
|
|
$out .= $formactions->select_type_actions($actioncode, "actioncode", '', !getDolGlobalString('AGENDA_USE_EVENT_TYPE') ? 1 : -1, 0, 0, 1, 'minwidth200imp'); |
|
2872
|
|
|
$out .= '</th>'; |
|
2873
|
|
|
$out .= '<th class="liste_titre maxwidth100onsmartphone">'; |
|
2874
|
|
|
$out .= '<input type="text" class="maxwidth100onsmartphone" name="search_agenda_label" value="' . $filters['search_agenda_label'] . '" placeholder="' . $langs->trans("Label") . '">'; |
|
2875
|
|
|
$out .= '</th>'; |
|
2876
|
|
|
|
|
2877
|
|
|
// Action column |
|
2878
|
|
|
if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { |
|
2879
|
|
|
$out .= '<th class="liste_titre width50 middle">'; |
|
2880
|
|
|
$searchpicto = $form->showFilterAndCheckAddButtons($massactionbutton ? 1 : 0, 'checkforselect', 1); |
|
2881
|
|
|
$out .= $searchpicto; |
|
2882
|
|
|
$out .= '</th>'; |
|
2883
|
|
|
} |
|
2884
|
|
|
|
|
2885
|
|
|
$out .= '</tr>'; |
|
2886
|
|
|
|
|
2887
|
|
|
|
|
2888
|
|
|
$out .= '</table>'; |
|
2889
|
|
|
|
|
2890
|
|
|
$out .= '</form>'; |
|
2891
|
|
|
$out .= '</div>'; |
|
2892
|
|
|
|
|
2893
|
|
|
$out .= "\n"; |
|
2894
|
|
|
|
|
2895
|
|
|
$out .= '<ul class="timeline">'; |
|
2896
|
|
|
|
|
2897
|
|
|
if ($donetodo) { |
|
2898
|
|
|
$tmp = ''; |
|
2899
|
|
|
if ($filterobj instanceof Societe) { |
|
2900
|
|
|
$tmp .= '<a href="' . constant('BASE_URL') . '/comm/action/list.php?mode=show_list&socid=' . $filterobj->id . '&status=done">'; |
|
2901
|
|
|
} |
|
2902
|
|
|
if ($filterobj instanceof User) { |
|
2903
|
|
|
$tmp .= '<a href="' . constant('BASE_URL') . '/comm/action/list.php?mode=show_list&socid=' . $filterobj->id . '&status=done">'; |
|
2904
|
|
|
} |
|
2905
|
|
|
$tmp .= ($donetodo != 'done' ? $langs->trans("ActionsToDoShort") : ''); |
|
2906
|
|
|
$tmp .= ($donetodo != 'done' && $donetodo != 'todo' ? ' / ' : ''); |
|
2907
|
|
|
$tmp .= ($donetodo != 'todo' ? $langs->trans("ActionsDoneShort") : ''); |
|
2908
|
|
|
//$out.=$langs->trans("ActionsToDoShort").' / '.$langs->trans("ActionsDoneShort"); |
|
2909
|
|
|
if ($filterobj instanceof Societe) { |
|
2910
|
|
|
$tmp .= '</a>'; |
|
2911
|
|
|
} |
|
2912
|
|
|
if ($filterobj instanceof User) { |
|
2913
|
|
|
$tmp .= '</a>'; |
|
2914
|
|
|
} |
|
2915
|
|
|
$out .= getTitleFieldOfList($tmp); |
|
2916
|
|
|
} |
|
2917
|
|
|
|
|
2918
|
|
|
$caction = new CActionComm($db); |
|
2919
|
|
|
$arraylist = $caction->liste_array(1, 'code', '', (!getDolGlobalString('AGENDA_USE_EVENT_TYPE') ? 1 : 0), '', 1); |
|
2920
|
|
|
|
|
2921
|
|
|
$actualCycleDate = false; |
|
2922
|
|
|
|
|
2923
|
|
|
// Loop on each event to show it |
|
2924
|
|
|
foreach ($histo as $key => $value) { |
|
2925
|
|
|
$actionstatic->fetch($histo[$key]['id']); // TODO Do we need this, we already have a lot of data of line into $histo |
|
2926
|
|
|
|
|
2927
|
|
|
$actionstatic->type_picto = $histo[$key]['apicto']; |
|
2928
|
|
|
$actionstatic->type_code = $histo[$key]['acode']; |
|
2929
|
|
|
|
|
2930
|
|
|
$labeltype = $actionstatic->type_code; |
|
2931
|
|
|
if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE') && empty($arraylist[$labeltype])) { |
|
2932
|
|
|
$labeltype = 'AC_OTH'; |
|
2933
|
|
|
} |
|
2934
|
|
|
if (!empty($actionstatic->code) && preg_match('/^TICKET_MSG/', $actionstatic->code)) { |
|
2935
|
|
|
$labeltype = $langs->trans("Message"); |
|
2936
|
|
|
} else { |
|
2937
|
|
|
if (!empty($arraylist[$labeltype])) { |
|
2938
|
|
|
$labeltype = $arraylist[$labeltype]; |
|
2939
|
|
|
} |
|
2940
|
|
|
if ($actionstatic->type_code == 'AC_OTH_AUTO' && ($actionstatic->type_code != $actionstatic->code) && $labeltype && !empty($arraylist[$actionstatic->code])) { |
|
2941
|
|
|
$labeltype .= ' - ' . $arraylist[$actionstatic->code]; // Use code in priority on type_code |
|
2942
|
|
|
} |
|
2943
|
|
|
} |
|
2944
|
|
|
|
|
2945
|
|
|
$url = constant('BASE_URL') . '/comm/action/card.php?id=' . $histo[$key]['id']; |
|
2946
|
|
|
|
|
2947
|
|
|
$tmpa = dol_getdate($histo[$key]['datestart'], false); |
|
2948
|
|
|
|
|
2949
|
|
|
if (isset($tmpa['year']) && isset($tmpa['yday']) && $actualCycleDate !== $tmpa['year'] . '-' . $tmpa['yday']) { |
|
2950
|
|
|
$actualCycleDate = $tmpa['year'] . '-' . $tmpa['yday']; |
|
2951
|
|
|
$out .= '<!-- timeline time label -->'; |
|
2952
|
|
|
$out .= '<li class="time-label">'; |
|
2953
|
|
|
$out .= '<span class="timeline-badge-date">'; |
|
2954
|
|
|
$out .= dol_print_date($histo[$key]['datestart'], 'daytext', 'tzuserrel', $langs); |
|
2955
|
|
|
$out .= '</span>'; |
|
2956
|
|
|
$out .= '</li>'; |
|
2957
|
|
|
$out .= '<!-- /.timeline-label -->'; |
|
2958
|
|
|
} |
|
2959
|
|
|
|
|
2960
|
|
|
|
|
2961
|
|
|
$out .= '<!-- timeline item -->' . "\n"; |
|
2962
|
|
|
$out .= '<li class="timeline-code-' . strtolower($actionstatic->code) . '">'; |
|
2963
|
|
|
|
|
2964
|
|
|
//$timelineicon = getTimelineIcon($actionstatic, $histo, $key); |
|
2965
|
|
|
$typeicon = $actionstatic->getTypePicto('pictofixedwidth timeline-icon-not-applicble', $labeltype); |
|
2966
|
|
|
//$out .= $timelineicon; |
|
2967
|
|
|
//var_dump($timelineicon); |
|
2968
|
|
|
$out .= $typeicon; |
|
2969
|
|
|
|
|
2970
|
|
|
$out .= '<div class="timeline-item">' . "\n"; |
|
2971
|
|
|
|
|
2972
|
|
|
$out .= '<span class="time timeline-header-action2">'; |
|
2973
|
|
|
|
|
2974
|
|
|
if (isset($histo[$key]['type']) && $histo[$key]['type'] == 'mailing') { |
|
2975
|
|
|
$out .= '<a class="paddingleft paddingright timeline-btn2 editfielda" href="' . constant('BASE_URL') . '/comm/mailing/card.php?id=' . $histo[$key]['id'] . '">' . img_object($langs->trans("ShowEMailing"), "email") . ' '; |
|
2976
|
|
|
$out .= $histo[$key]['id']; |
|
2977
|
|
|
$out .= '</a> '; |
|
2978
|
|
|
} else { |
|
2979
|
|
|
$out .= $actionstatic->getNomUrl(1, -1, 'valignmiddle') . ' '; |
|
2980
|
|
|
} |
|
2981
|
|
|
|
|
2982
|
|
|
if ( |
|
2983
|
|
|
$user->hasRight('agenda', 'allactions', 'create') || |
|
2984
|
|
|
(($actionstatic->authorid == $user->id || $actionstatic->userownerid == $user->id) && $user->hasRight('agenda', 'myactions', 'create')) |
|
2985
|
|
|
) { |
|
2986
|
|
|
$out .= '<a class="paddingleft paddingright timeline-btn2 editfielda" href="' . DOL_MAIN_URL_ROOT . '/comm/action/card.php?action=edit&token=' . newToken() . '&id=' . $actionstatic->id . '&backtopage=' . $_SERVER["PHP_SELF"] . ('?' . $param) . '">'; |
|
2987
|
|
|
//$out .= '<i class="fa fa-pencil" title="'.$langs->trans("Modify").'" ></i>'; |
|
2988
|
|
|
$out .= img_picto($langs->trans("Modify"), 'edit', 'class="edita"'); |
|
2989
|
|
|
$out .= '</a>'; |
|
2990
|
|
|
} |
|
2991
|
|
|
|
|
2992
|
|
|
$out .= '</span>'; |
|
2993
|
|
|
|
|
2994
|
|
|
// Date |
|
2995
|
|
|
$out .= '<span class="time"><i class="fa fa-clock-o valignmiddle"></i> <span class="valignmiddle">'; |
|
2996
|
|
|
$out .= dol_print_date($histo[$key]['datestart'], 'dayhour', 'tzuserrel'); |
|
2997
|
|
|
if ($histo[$key]['dateend'] && $histo[$key]['dateend'] != $histo[$key]['datestart']) { |
|
2998
|
|
|
$tmpa = dol_getdate($histo[$key]['datestart'], true); |
|
2999
|
|
|
$tmpb = dol_getdate($histo[$key]['dateend'], true); |
|
3000
|
|
|
if ($tmpa['mday'] == $tmpb['mday'] && $tmpa['mon'] == $tmpb['mon'] && $tmpa['year'] == $tmpb['year']) { |
|
3001
|
|
|
$out .= '-' . dol_print_date($histo[$key]['dateend'], 'hour', 'tzuserrel'); |
|
3002
|
|
|
} else { |
|
3003
|
|
|
$out .= '-' . dol_print_date($histo[$key]['dateend'], 'dayhour', 'tzuserrel'); |
|
3004
|
|
|
} |
|
3005
|
|
|
} |
|
3006
|
|
|
$late = 0; |
|
3007
|
|
|
if ($histo[$key]['percent'] == 0 && $histo[$key]['datestart'] && $histo[$key]['datestart'] < ($now - $delay_warning)) { |
|
3008
|
|
|
$late = 1; |
|
3009
|
|
|
} |
|
3010
|
|
|
if ($histo[$key]['percent'] == 0 && !$histo[$key]['datestart'] && $histo[$key]['dateend'] && $histo[$key]['datestart'] < ($now - $delay_warning)) { |
|
3011
|
|
|
$late = 1; |
|
3012
|
|
|
} |
|
3013
|
|
|
if ($histo[$key]['percent'] > 0 && $histo[$key]['percent'] < 100 && $histo[$key]['dateend'] && $histo[$key]['dateend'] < ($now - $delay_warning)) { |
|
3014
|
|
|
$late = 1; |
|
3015
|
|
|
} |
|
3016
|
|
|
if ($histo[$key]['percent'] > 0 && $histo[$key]['percent'] < 100 && !$histo[$key]['dateend'] && $histo[$key]['datestart'] && $histo[$key]['datestart'] < ($now - $delay_warning)) { |
|
3017
|
|
|
$late = 1; |
|
3018
|
|
|
} |
|
3019
|
|
|
if ($late) { |
|
3020
|
|
|
$out .= img_warning($langs->trans("Late")) . ' '; |
|
3021
|
|
|
} |
|
3022
|
|
|
$out .= "</span></span>\n"; |
|
3023
|
|
|
|
|
3024
|
|
|
// Ref |
|
3025
|
|
|
$out .= '<h3 class="timeline-header">'; |
|
3026
|
|
|
|
|
3027
|
|
|
// Author of event |
|
3028
|
|
|
$out .= '<div class="messaging-author inline-block tdoverflowmax150 valignmiddle marginrightonly">'; |
|
3029
|
|
|
if ($histo[$key]['userid'] > 0) { |
|
3030
|
|
|
if (!isset($userGetNomUrlCache[$histo[$key]['userid']])) { // is in cache ? |
|
3031
|
|
|
$userstatic->fetch($histo[$key]['userid']); |
|
3032
|
|
|
$userGetNomUrlCache[$histo[$key]['userid']] = $userstatic->getNomUrl(-1, '', 0, 0, 16, 0, 'firstelselast', ''); |
|
3033
|
|
|
} |
|
3034
|
|
|
$out .= $userGetNomUrlCache[$histo[$key]['userid']]; |
|
3035
|
|
|
} elseif (!empty($histo[$key]['msg_from']) && $actionstatic->code == 'TICKET_MSG') { |
|
3036
|
|
|
if (!isset($contactGetNomUrlCache[$histo[$key]['msg_from']])) { |
|
3037
|
|
|
if ($contactstatic->fetch(0, null, '', $histo[$key]['msg_from']) > 0) { |
|
3038
|
|
|
$contactGetNomUrlCache[$histo[$key]['msg_from']] = $contactstatic->getNomUrl(-1, '', 16); |
|
3039
|
|
|
} else { |
|
3040
|
|
|
$contactGetNomUrlCache[$histo[$key]['msg_from']] = $histo[$key]['msg_from']; |
|
3041
|
|
|
} |
|
3042
|
|
|
} |
|
3043
|
|
|
$out .= $contactGetNomUrlCache[$histo[$key]['msg_from']]; |
|
3044
|
|
|
} |
|
3045
|
|
|
$out .= '</div>'; |
|
3046
|
|
|
|
|
3047
|
|
|
// Title |
|
3048
|
|
|
$out .= ' <div class="messaging-title inline-block">'; |
|
3049
|
|
|
//$out .= $actionstatic->getTypePicto(); |
|
3050
|
|
|
if (empty($conf->dol_optimize_smallscreen) && $actionstatic->type_code != 'AC_OTH_AUTO') { |
|
3051
|
|
|
$out .= $labeltype . ' - '; |
|
3052
|
|
|
} |
|
3053
|
|
|
|
|
3054
|
|
|
$libelle = ''; |
|
3055
|
|
|
if (preg_match('/^TICKET_MSG/', $actionstatic->code)) { |
|
3056
|
|
|
$out .= $langs->trans('TicketNewMessage'); |
|
3057
|
|
|
} elseif (preg_match('/^TICKET_MSG_PRIVATE/', $actionstatic->code)) { |
|
3058
|
|
|
$out .= $langs->trans('TicketNewMessage') . ' <em>(' . $langs->trans('Private') . ')</em>'; |
|
3059
|
|
|
} elseif (isset($histo[$key]['type'])) { |
|
3060
|
|
|
if ($histo[$key]['type'] == 'action') { |
|
3061
|
|
|
$transcode = $langs->transnoentitiesnoconv("Action" . $histo[$key]['acode']); |
|
3062
|
|
|
$libelle = ($transcode != "Action" . $histo[$key]['acode'] ? $transcode : $histo[$key]['alabel']); |
|
3063
|
|
|
$libelle = $histo[$key]['note']; |
|
3064
|
|
|
$actionstatic->id = $histo[$key]['id']; |
|
3065
|
|
|
$out .= dol_escape_htmltag(dol_trunc($libelle, 120)); |
|
3066
|
|
|
} elseif ($histo[$key]['type'] == 'mailing') { |
|
3067
|
|
|
$out .= '<a href="' . constant('BASE_URL') . '/comm/mailing/card.php?id=' . $histo[$key]['id'] . '">' . img_object($langs->trans("ShowEMailing"), "email") . ' '; |
|
3068
|
|
|
$transcode = $langs->transnoentitiesnoconv("Action" . $histo[$key]['acode']); |
|
3069
|
|
|
$libelle = ($transcode != "Action" . $histo[$key]['acode'] ? $transcode : 'Send mass mailing'); |
|
3070
|
|
|
$out .= dol_escape_htmltag(dol_trunc($libelle, 120)); |
|
3071
|
|
|
} else { |
|
3072
|
|
|
$libelle .= $histo[$key]['note']; |
|
3073
|
|
|
$out .= dol_escape_htmltag(dol_trunc($libelle, 120)); |
|
3074
|
|
|
} |
|
3075
|
|
|
} |
|
3076
|
|
|
|
|
3077
|
|
|
if (isset($histo[$key]['elementtype']) && !empty($histo[$key]['fk_element'])) { |
|
3078
|
|
|
if (isset($conf->cache['elementlinkcache'][$histo[$key]['elementtype']]) && isset($conf->cache['elementlinkcache'][$histo[$key]['elementtype']][$histo[$key]['fk_element']])) { |
|
3079
|
|
|
$link = $conf->cache['elementlinkcache'][$histo[$key]['elementtype']][$histo[$key]['fk_element']]; |
|
3080
|
|
|
} else { |
|
3081
|
|
|
if (!isset($conf->cache['elementlinkcache'][$histo[$key]['elementtype']])) { |
|
3082
|
|
|
$conf->cache['elementlinkcache'][$histo[$key]['elementtype']] = array(); |
|
3083
|
|
|
} |
|
3084
|
|
|
$link = dolGetElementUrl($histo[$key]['fk_element'], $histo[$key]['elementtype'], 1); |
|
3085
|
|
|
$conf->cache['elementlinkcache'][$histo[$key]['elementtype']][$histo[$key]['fk_element']] = $link; |
|
3086
|
|
|
} |
|
3087
|
|
|
if ($link) { |
|
3088
|
|
|
$out .= ' - ' . $link; |
|
3089
|
|
|
} |
|
3090
|
|
|
} |
|
3091
|
|
|
|
|
3092
|
|
|
$out .= '</div>'; |
|
3093
|
|
|
|
|
3094
|
|
|
$out .= '</h3>'; |
|
3095
|
|
|
|
|
3096
|
|
|
// Message |
|
3097
|
|
|
if ( |
|
3098
|
|
|
!empty($histo[$key]['message'] && $histo[$key]['message'] != $libelle) |
|
3099
|
|
|
&& $actionstatic->code != 'AC_TICKET_CREATE' |
|
3100
|
|
|
&& $actionstatic->code != 'AC_TICKET_MODIFY' |
|
3101
|
|
|
) { |
|
3102
|
|
|
$out .= '<div class="timeline-body wordbreak">'; |
|
3103
|
|
|
$truncateLines = getDolGlobalInt('MAIN_TRUNCATE_TIMELINE_MESSAGE', 3); |
|
3104
|
|
|
$truncatedText = dolGetFirstLineOfText($histo[$key]['message'], $truncateLines); |
|
3105
|
|
|
if ($truncateLines > 0 && strlen($histo[$key]['message']) > strlen($truncatedText)) { |
|
3106
|
|
|
$out .= '<div class="readmore-block --closed" >'; |
|
3107
|
|
|
$out .= ' <div class="readmore-block__excerpt" >'; |
|
3108
|
|
|
$out .= dolPrintHTML($truncatedText); |
|
3109
|
|
|
$out .= ' <br><a class="read-more-link" data-read-more-action="open" href="' . DOL_MAIN_URL_ROOT . '/comm/action/card.php?id=' . $actionstatic->id . '&backtopage=' . $_SERVER["PHP_SELF"] . ('?' . $param) . '" >' . $langs->trans("ReadMore") . ' <span class="fa fa-chevron-right" aria-hidden="true"></span></a>'; |
|
3110
|
|
|
$out .= ' </div>'; |
|
3111
|
|
|
$out .= ' <div class="readmore-block__full-text" >'; |
|
3112
|
|
|
$out .= dolPrintHTML($histo[$key]['message']); |
|
3113
|
|
|
$out .= ' <a class="read-less-link" data-read-more-action="close" href="#" ><span class="fa fa-chevron-up" aria-hidden="true"></span> ' . $langs->trans("ReadLess") . '</a>'; |
|
3114
|
|
|
$out .= ' </div>'; |
|
3115
|
|
|
$out .= '</div>'; |
|
3116
|
|
|
} else { |
|
3117
|
|
|
$out .= dolPrintHTML($histo[$key]['message']); |
|
3118
|
|
|
} |
|
3119
|
|
|
|
|
3120
|
|
|
$out .= '</div>'; |
|
3121
|
|
|
} |
|
3122
|
|
|
|
|
3123
|
|
|
// Timeline footer |
|
3124
|
|
|
$footer = ''; |
|
3125
|
|
|
|
|
3126
|
|
|
// Contact for this action |
|
3127
|
|
|
if (isset($histo[$key]['socpeopleassigned']) && is_array($histo[$key]['socpeopleassigned']) && count($histo[$key]['socpeopleassigned']) > 0) { |
|
3128
|
|
|
$contactList = ''; |
|
3129
|
|
|
foreach ($histo[$key]['socpeopleassigned'] as $cid => $Tab) { |
|
3130
|
|
|
if (empty($conf->cache['contact'][$histo[$key]['contact_id']])) { |
|
3131
|
|
|
$contact = new Contact($db); |
|
3132
|
|
|
$contact->fetch($cid); |
|
3133
|
|
|
$conf->cache['contact'][$histo[$key]['contact_id']] = $contact; |
|
3134
|
|
|
} else { |
|
3135
|
|
|
$contact = $conf->cache['contact'][$histo[$key]['contact_id']]; |
|
3136
|
|
|
} |
|
3137
|
|
|
|
|
3138
|
|
|
if ($contact) { |
|
3139
|
|
|
$contactList .= !empty($contactList) ? ', ' : ''; |
|
3140
|
|
|
$contactList .= $contact->getNomUrl(1); |
|
3141
|
|
|
if (isset($histo[$key]['acode']) && $histo[$key]['acode'] == 'AC_TEL') { |
|
3142
|
|
|
if (!empty($contact->phone_pro)) { |
|
3143
|
|
|
$contactList .= '(' . dol_print_phone($contact->phone_pro) . ')'; |
|
3144
|
|
|
} |
|
3145
|
|
|
} |
|
3146
|
|
|
} |
|
3147
|
|
|
} |
|
3148
|
|
|
|
|
3149
|
|
|
$footer .= $langs->trans('ActionOnContact') . ' : ' . $contactList; |
|
3150
|
|
|
} elseif (empty($objcon->id) && isset($histo[$key]['contact_id']) && $histo[$key]['contact_id'] > 0) { |
|
3151
|
|
|
if (empty($conf->cache['contact'][$histo[$key]['contact_id']])) { |
|
3152
|
|
|
$contact = new Contact($db); |
|
3153
|
|
|
$result = $contact->fetch($histo[$key]['contact_id']); |
|
3154
|
|
|
$conf->cache['contact'][$histo[$key]['contact_id']] = $contact; |
|
3155
|
|
|
} else { |
|
3156
|
|
|
$contact = $conf->cache['contact'][$histo[$key]['contact_id']]; |
|
3157
|
|
|
$result = ($contact instanceof Contact) ? $contact->id : 0; |
|
3158
|
|
|
} |
|
3159
|
|
|
|
|
3160
|
|
|
if ($result > 0) { |
|
3161
|
|
|
$footer .= $contact->getNomUrl(1); |
|
3162
|
|
|
if (isset($histo[$key]['acode']) && $histo[$key]['acode'] == 'AC_TEL') { |
|
3163
|
|
|
if (!empty($contact->phone_pro)) { |
|
3164
|
|
|
$footer .= '(' . dol_print_phone($contact->phone_pro) . ')'; |
|
3165
|
|
|
} |
|
3166
|
|
|
} |
|
3167
|
|
|
} |
|
3168
|
|
|
} |
|
3169
|
|
|
|
|
3170
|
|
|
$documents = getActionCommEcmList($actionstatic); |
|
3171
|
|
|
if (!empty($documents)) { |
|
3172
|
|
|
$footer .= '<div class="timeline-documents-container">'; |
|
3173
|
|
|
foreach ($documents as $doc) { |
|
3174
|
|
|
$footer .= '<span id="document_' . $doc->id . '" class="timeline-documents" '; |
|
3175
|
|
|
$footer .= ' data-id="' . $doc->id . '" '; |
|
3176
|
|
|
$footer .= ' data-path="' . $doc->filepath . '"'; |
|
3177
|
|
|
$footer .= ' data-filename="' . dol_escape_htmltag($doc->filename) . '" '; |
|
3178
|
|
|
$footer .= '>'; |
|
3179
|
|
|
|
|
3180
|
|
|
$filePath = DOL_DATA_ROOT . '/' . $doc->filepath . '/' . $doc->filename; |
|
3181
|
|
|
$mime = dol_mimetype($filePath); |
|
3182
|
|
|
$file = $actionstatic->id . '/' . $doc->filename; |
|
3183
|
|
|
$thumb = $actionstatic->id . '/thumbs/' . substr($doc->filename, 0, strrpos($doc->filename, '.')) . '_mini' . substr($doc->filename, strrpos($doc->filename, '.')); |
|
3184
|
|
|
$doclink = dol_buildpath('document.php', 1) . '?modulepart=actions&attachment=0&file=' . urlencode($file) . '&entity=' . $conf->entity; |
|
3185
|
|
|
$viewlink = dol_buildpath('viewimage.php', 1) . '?modulepart=actions&file=' . urlencode($thumb) . '&entity=' . $conf->entity; |
|
3186
|
|
|
|
|
3187
|
|
|
$mimeAttr = ' mime="' . $mime . '" '; |
|
3188
|
|
|
$class = ''; |
|
3189
|
|
|
if (in_array($mime, array('image/png', 'image/jpeg', 'application/pdf'))) { |
|
3190
|
|
|
$class .= ' documentpreview'; |
|
3191
|
|
|
} |
|
3192
|
|
|
|
|
3193
|
|
|
$footer .= '<a href="' . $doclink . '" class="btn-link ' . $class . '" target="_blank" rel="noopener noreferrer" ' . $mimeAttr . ' >'; |
|
3194
|
|
|
$footer .= img_mime($filePath) . ' ' . $doc->filename; |
|
3195
|
|
|
$footer .= '</a>'; |
|
3196
|
|
|
|
|
3197
|
|
|
$footer .= '</span>'; |
|
3198
|
|
|
} |
|
3199
|
|
|
$footer .= '</div>'; |
|
3200
|
|
|
} |
|
3201
|
|
|
|
|
3202
|
|
|
if (!empty($footer)) { |
|
3203
|
|
|
$out .= '<div class="timeline-footer">' . $footer . '</div>'; |
|
3204
|
|
|
} |
|
3205
|
|
|
|
|
3206
|
|
|
$out .= '</div>' . "\n"; // end timeline-item |
|
3207
|
|
|
|
|
3208
|
|
|
$out .= '</li>'; |
|
3209
|
|
|
$out .= '<!-- END timeline item -->'; |
|
3210
|
|
|
} |
|
3211
|
|
|
|
|
3212
|
|
|
$out .= "</ul>\n"; |
|
3213
|
|
|
|
|
3214
|
|
|
$out .= '<script> |
|
3215
|
|
|
jQuery(document).ready(function () { |
|
3216
|
|
|
$(document).on("click", "[data-read-more-action]", function(e){ |
|
3217
|
|
|
let readMoreBloc = $(this).closest(".readmore-block"); |
|
3218
|
|
|
if(readMoreBloc.length > 0){ |
|
3219
|
|
|
e.preventDefault(); |
|
3220
|
|
|
if($(this).attr("data-read-more-action") == "close"){ |
|
3221
|
|
|
readMoreBloc.addClass("--closed").removeClass("--open"); |
|
3222
|
|
|
$("html, body").animate({ |
|
3223
|
|
|
scrollTop: readMoreBloc.offset().top - 200 |
|
3224
|
|
|
}, 100); |
|
3225
|
|
|
}else{ |
|
3226
|
|
|
readMoreBloc.addClass("--open").removeClass("--closed"); |
|
3227
|
|
|
} |
|
3228
|
|
|
} |
|
3229
|
|
|
}); |
|
3230
|
|
|
}); |
|
3231
|
|
|
</script>'; |
|
3232
|
|
|
|
|
3233
|
|
|
|
|
3234
|
|
|
if (empty($histo)) { |
|
3235
|
|
|
$out .= '<span class="opacitymedium">' . $langs->trans("NoRecordFound") . '</span>'; |
|
3236
|
|
|
} |
|
3237
|
|
|
} |
|
3238
|
|
|
|
|
3239
|
|
|
if ($noprint) { |
|
3240
|
|
|
return $out; |
|
3241
|
|
|
} else { |
|
3242
|
|
|
print $out; |
|
3243
|
|
|
} |
|
3244
|
|
|
} |
|
3245
|
|
|
|
|
3246
|
|
|
/** |
|
3247
|
|
|
* Get timeline icon |
|
3248
|
|
|
* |
|
3249
|
|
|
* @param ActionComm $actionstatic actioncomm |
|
3250
|
|
|
* @param array<int,array{percent:int}> $histo histo |
|
3251
|
|
|
* @param int $key key |
|
3252
|
|
|
* @return string String with timeline icon |
|
3253
|
|
|
* @deprecated Use actioncomm->getPictoType() instead |
|
3254
|
|
|
*/ |
|
3255
|
|
|
function getTimelineIcon($actionstatic, &$histo, $key) |
|
3256
|
|
|
{ |
|
3257
|
|
|
global $langs; |
|
3258
|
|
|
|
|
3259
|
|
|
$out = '<!-- timeline icon -->' . "\n"; |
|
3260
|
|
|
$iconClass = 'fa fa-comments'; |
|
3261
|
|
|
$img_picto = ''; |
|
3262
|
|
|
$colorClass = ''; |
|
3263
|
|
|
$pictoTitle = ''; |
|
3264
|
|
|
|
|
3265
|
|
|
if ($histo[$key]['percent'] == -1) { |
|
3266
|
|
|
$colorClass = 'timeline-icon-not-applicble'; |
|
3267
|
|
|
$pictoTitle = $langs->trans('StatusNotApplicable'); |
|
3268
|
|
|
} elseif ($histo[$key]['percent'] == 0) { |
|
3269
|
|
|
$colorClass = 'timeline-icon-todo'; |
|
3270
|
|
|
$pictoTitle = $langs->trans('StatusActionToDo') . ' (0%)'; |
|
3271
|
|
|
} elseif ($histo[$key]['percent'] > 0 && $histo[$key]['percent'] < 100) { |
|
3272
|
|
|
$colorClass = 'timeline-icon-in-progress'; |
|
3273
|
|
|
$pictoTitle = $langs->trans('StatusActionInProcess') . ' (' . $histo[$key]['percent'] . '%)'; |
|
3274
|
|
|
} elseif ($histo[$key]['percent'] >= 100) { |
|
3275
|
|
|
$colorClass = 'timeline-icon-done'; |
|
3276
|
|
|
$pictoTitle = $langs->trans('StatusActionDone') . ' (100%)'; |
|
3277
|
|
|
} |
|
3278
|
|
|
|
|
3279
|
|
|
if ($actionstatic->code == 'AC_TICKET_CREATE') { |
|
3280
|
|
|
$iconClass = 'fa fa-ticket'; |
|
3281
|
|
|
} elseif ($actionstatic->code == 'AC_TICKET_MODIFY') { |
|
3282
|
|
|
$iconClass = 'fa fa-pencilxxx'; |
|
3283
|
|
|
} elseif (preg_match('/^TICKET_MSG/', $actionstatic->code)) { |
|
3284
|
|
|
$iconClass = 'fa fa-comments'; |
|
3285
|
|
|
} elseif (preg_match('/^TICKET_MSG_PRIVATE/', $actionstatic->code)) { |
|
3286
|
|
|
$iconClass = 'fa fa-mask'; |
|
3287
|
|
|
} elseif (getDolGlobalString('AGENDA_USE_EVENT_TYPE')) { |
|
3288
|
|
|
if ($actionstatic->type_picto) { |
|
3289
|
|
|
$img_picto = img_picto('', $actionstatic->type_picto); |
|
3290
|
|
|
} else { |
|
3291
|
|
|
if ($actionstatic->type_code == 'AC_RDV') { |
|
3292
|
|
|
$iconClass = 'fa fa-handshake'; |
|
3293
|
|
|
} elseif ($actionstatic->type_code == 'AC_TEL') { |
|
3294
|
|
|
$iconClass = 'fa fa-phone'; |
|
3295
|
|
|
} elseif ($actionstatic->type_code == 'AC_FAX') { |
|
3296
|
|
|
$iconClass = 'fa fa-fax'; |
|
3297
|
|
|
} elseif ($actionstatic->type_code == 'AC_EMAIL') { |
|
3298
|
|
|
$iconClass = 'fa fa-envelope'; |
|
3299
|
|
|
} elseif ($actionstatic->type_code == 'AC_INT') { |
|
3300
|
|
|
$iconClass = 'fa fa-shipping-fast'; |
|
3301
|
|
|
} elseif ($actionstatic->type_code == 'AC_OTH_AUTO') { |
|
3302
|
|
|
$iconClass = 'fa fa-robot'; |
|
3303
|
|
|
} elseif (!preg_match('/_AUTO/', $actionstatic->type_code)) { |
|
3304
|
|
|
$iconClass = 'fa fa-robot'; |
|
3305
|
|
|
} |
|
3306
|
|
|
} |
|
3307
|
|
|
} |
|
3308
|
|
|
|
|
3309
|
|
|
$out .= '<i class="' . $iconClass . ' ' . $colorClass . '" title="' . $pictoTitle . '">' . $img_picto . '</i>' . "\n"; |
|
3310
|
|
|
return $out; |
|
3311
|
|
|
} |
|
3312
|
|
|
|
|
3313
|
|
|
/** |
|
3314
|
|
|
* Create a button to copy $valuetocopy in the clipboard (for copy and paste feature). |
|
3315
|
|
|
* Code that handle the click is inside core/js/lib_foot.js.php. |
|
3316
|
|
|
* |
|
3317
|
|
|
* @param string $valuetocopy The value to print |
|
3318
|
|
|
* @param int<0,1> $showonlyonhover Show the copy-paste button only on hover |
|
3319
|
|
|
* @param string $texttoshow Replace the value to show with this text. Use 'none' to show no text (only the copy-paste picto) |
|
3320
|
|
|
* @return string The string to print for the button |
|
3321
|
|
|
*/ |
|
3322
|
|
|
function showValueWithClipboardCPButton($valuetocopy, $showonlyonhover = 1, $texttoshow = '') |
|
3323
|
|
|
{ |
|
3324
|
|
|
/* |
|
3325
|
|
|
global $conf; |
|
3326
|
|
|
|
|
3327
|
|
|
if (!empty($conf->dol_no_mouse_hover)) { |
|
3328
|
|
|
$showonlyonhover = 0; |
|
3329
|
|
|
}*/ |
|
3330
|
|
|
|
|
3331
|
|
|
$tag = 'span'; // Using div (like any style of type 'block') does not work when using the js copy code. |
|
3332
|
|
|
if ($texttoshow === 'none') { |
|
3333
|
|
|
$result = '<span class="clipboardCP' . ($showonlyonhover ? ' clipboardCPShowOnHover' : '') . '"><' . $tag . ' class="clipboardCPValue hidewithsize">' . dol_escape_htmltag($valuetocopy, 1, 1) . '</' . $tag . '><span class="clipboardCPValueToPrint"></span><span class="clipboardCPButton far fa-clipboard opacitymedium paddingleft paddingright"></span><span class="clipboardCPText"></span></span>'; |
|
3334
|
|
|
} elseif ($texttoshow) { |
|
3335
|
|
|
$result = '<span class="clipboardCP' . ($showonlyonhover ? ' clipboardCPShowOnHover' : '') . '"><' . $tag . ' class="clipboardCPValue hidewithsize">' . dol_escape_htmltag($valuetocopy, 1, 1) . '</' . $tag . '><span class="clipboardCPValueToPrint">' . dol_escape_htmltag($texttoshow, 1, 1) . '</span><span class="clipboardCPButton far fa-clipboard opacitymedium paddingleft paddingright"></span><span class="clipboardCPText"></span></span>'; |
|
3336
|
|
|
} else { |
|
3337
|
|
|
$result = '<span class="clipboardCP' . ($showonlyonhover ? ' clipboardCPShowOnHover' : '') . '"><' . $tag . ' class="clipboardCPValue">' . dol_escape_htmltag($valuetocopy, 1, 1) . '</' . $tag . '><span class="clipboardCPButton far fa-clipboard opacitymedium paddingleft paddingright"></span><span class="clipboardCPText"></span></span>'; |
|
3338
|
|
|
} |
|
3339
|
|
|
|
|
3340
|
|
|
return $result; |
|
3341
|
|
|
} |
|
3342
|
|
|
|
|
3343
|
|
|
/** |
|
3344
|
|
|
* Start a table with headers and a optional clickable number (don't forget to use "finishSimpleTable()" after the last table row) |
|
3345
|
|
|
* |
|
3346
|
|
|
* @param string $header The first left header of the table (automatic translated) |
|
3347
|
|
|
* @param string $link (optional) The link to a internal dolibarr page, where to go on clicking on the number or the ... (without the first "/") |
|
3348
|
|
|
* @param string $arguments (optional) Additional arguments for the link (e.g. "search_status=0") |
|
3349
|
|
|
* @param integer $emptyColumns (optional) Number of empty columns to add after the first column |
|
3350
|
|
|
* @param integer $number (optional) The number that is shown right after the first header, when -1 the link is shown as '...' |
|
3351
|
|
|
* @param string $pictofulllist (optional) The picto to use for the full list link |
|
3352
|
|
|
* @return void |
|
3353
|
|
|
* |
|
3354
|
|
|
* @see finishSimpleTable() |
|
3355
|
|
|
*/ |
|
3356
|
|
|
function startSimpleTable($header, $link = "", $arguments = "", $emptyColumns = 0, $number = -1, $pictofulllist = '') |
|
3357
|
|
|
{ |
|
3358
|
|
|
global $langs; |
|
3359
|
|
|
|
|
3360
|
|
|
print '<div class="div-table-responsive-no-min">'; |
|
3361
|
|
|
print '<table class="noborder centpercent">'; |
|
3362
|
|
|
print '<tr class="liste_titre">'; |
|
3363
|
|
|
|
|
3364
|
|
|
print ($emptyColumns < 1) ? '<th>' : '<th colspan="' . ($emptyColumns + 1) . '">'; |
|
3365
|
|
|
|
|
3366
|
|
|
print '<span class="valignmiddle">' . $langs->trans($header) . '</span>'; |
|
3367
|
|
|
|
|
3368
|
|
|
if (!empty($link)) { |
|
3369
|
|
|
if (!empty($arguments)) { |
|
3370
|
|
|
print '<a href="' . constant('BASE_URL') . '/' . $link . '?' . $arguments . '">'; |
|
3371
|
|
|
} else { |
|
3372
|
|
|
print '<a href="' . constant('BASE_URL') . '/' . $link . '">'; |
|
3373
|
|
|
} |
|
3374
|
|
|
} |
|
3375
|
|
|
|
|
3376
|
|
|
if ($number > -1) { |
|
3377
|
|
|
print '<span class="badge marginleftonlyshort">' . $number . '</span>'; |
|
3378
|
|
|
} elseif (!empty($link)) { |
|
3379
|
|
|
print '<span class="badge marginleftonlyshort">...</span>'; |
|
3380
|
|
|
} |
|
3381
|
|
|
|
|
3382
|
|
|
if (!empty($link)) { |
|
3383
|
|
|
print '</a>'; |
|
3384
|
|
|
} |
|
3385
|
|
|
|
|
3386
|
|
|
print '</th>'; |
|
3387
|
|
|
|
|
3388
|
|
|
if ($number < 0 && !empty($link)) { |
|
3389
|
|
|
print '<th class="right">'; |
|
3390
|
|
|
print '</th>'; |
|
3391
|
|
|
} |
|
3392
|
|
|
|
|
3393
|
|
|
print '</tr>'; |
|
3394
|
|
|
} |
|
3395
|
|
|
|
|
3396
|
|
|
/** |
|
3397
|
|
|
* Add the correct HTML close tags for "startSimpleTable(...)" (use after the last table line) |
|
3398
|
|
|
* |
|
3399
|
|
|
* @param bool $addLineBreak (optional) Add a extra line break after the complete table (\<br\>) |
|
3400
|
|
|
* @return void |
|
3401
|
|
|
* |
|
3402
|
|
|
* @see startSimpleTable() |
|
3403
|
|
|
*/ |
|
3404
|
|
|
function finishSimpleTable($addLineBreak = false) |
|
3405
|
|
|
{ |
|
3406
|
|
|
print '</table>'; |
|
3407
|
|
|
print '</div>'; |
|
3408
|
|
|
|
|
3409
|
|
|
if ($addLineBreak) { |
|
3410
|
|
|
print '<br>'; |
|
3411
|
|
|
} |
|
3412
|
|
|
} |
|
3413
|
|
|
|
|
3414
|
|
|
/** |
|
3415
|
|
|
* Add a summary line to the current open table ("None", "XMoreLines" or "Total xxx") |
|
3416
|
|
|
* |
|
3417
|
|
|
* @param integer $tableColumnCount The complete count columns of the table |
|
3418
|
|
|
* @param integer $num The count of the rows of the table, when it is zero (0) the "$noneWord" is shown instead |
|
3419
|
|
|
* @param integer $nbofloop (optional) The maximum count of rows thaht the table show (when it is zero (0) no summary line will show, expect "$noneWord" when $num === 0) |
|
3420
|
|
|
* @param integer $total (optional) The total value thaht is shown after when the table has minimum of one entire |
|
3421
|
|
|
* @param string $noneWord (optional) The word that is shown when the table has no entries ($num === 0) |
|
3422
|
|
|
* @param boolean $extraRightColumn (optional) Add a additional column after the summary word and total number |
|
3423
|
|
|
* @return void |
|
3424
|
|
|
*/ |
|
3425
|
|
|
function addSummaryTableLine($tableColumnCount, $num, $nbofloop = 0, $total = 0, $noneWord = "None", $extraRightColumn = false) |
|
3426
|
|
|
{ |
|
3427
|
|
|
global $langs; |
|
3428
|
|
|
|
|
3429
|
|
|
if ($num === 0) { |
|
3430
|
|
|
print '<tr class="oddeven">'; |
|
3431
|
|
|
print '<td colspan="' . $tableColumnCount . '"><span class="opacitymedium">' . $langs->trans($noneWord) . '</span></td>'; |
|
3432
|
|
|
print '</tr>'; |
|
3433
|
|
|
return; |
|
3434
|
|
|
} |
|
3435
|
|
|
|
|
3436
|
|
|
if ($nbofloop === 0) { |
|
3437
|
|
|
// don't show a summary line |
|
3438
|
|
|
return; |
|
3439
|
|
|
} |
|
3440
|
|
|
|
|
3441
|
|
|
if ($num === 0) { |
|
3442
|
|
|
$colspan = $tableColumnCount; |
|
3443
|
|
|
} elseif ($num > $nbofloop) { |
|
3444
|
|
|
$colspan = $tableColumnCount; |
|
3445
|
|
|
} else { |
|
3446
|
|
|
$colspan = $tableColumnCount - 1; |
|
3447
|
|
|
} |
|
3448
|
|
|
|
|
3449
|
|
|
if ($extraRightColumn) { |
|
3450
|
|
|
$colspan--; |
|
3451
|
|
|
} |
|
3452
|
|
|
|
|
3453
|
|
|
print '<tr class="liste_total">'; |
|
3454
|
|
|
|
|
3455
|
|
|
if ($nbofloop > 0 && $num > $nbofloop) { |
|
3456
|
|
|
print '<td colspan="' . $colspan . '" class="right">' . $langs->trans("XMoreLines", ($num - $nbofloop)) . '</td>'; |
|
3457
|
|
|
} else { |
|
3458
|
|
|
print '<td colspan="' . $colspan . '" class="right"> ' . $langs->trans("Total") . '</td>'; |
|
3459
|
|
|
print '<td class="right centpercent">' . price($total) . '</td>'; |
|
3460
|
|
|
} |
|
3461
|
|
|
|
|
3462
|
|
|
if ($extraRightColumn) { |
|
3463
|
|
|
print '<td></td>'; |
|
3464
|
|
|
} |
|
3465
|
|
|
|
|
3466
|
|
|
print '</tr>'; |
|
3467
|
|
|
} |
|
3468
|
|
|
|
|
3469
|
|
|
/** |
|
3470
|
|
|
* Add space between dolGetButtonTitle |
|
3471
|
|
|
* |
|
3472
|
|
|
* @param string $moreClass more css class label |
|
3473
|
|
|
* @return string html of title separator |
|
3474
|
|
|
*/ |
|
3475
|
|
|
function dolGetButtonTitleSeparator($moreClass = "") |
|
3476
|
|
|
{ |
|
3477
|
|
|
return '<span class="button-title-separator ' . $moreClass . '" ></span>'; |
|
3478
|
|
|
} |
|
3479
|
|
|
|
|
3480
|
|
|
/** |
|
3481
|
|
|
* get field error icon |
|
3482
|
|
|
* |
|
3483
|
|
|
* @param string $fieldValidationErrorMsg message to add in tooltip |
|
3484
|
|
|
* @return string html output |
|
3485
|
|
|
*/ |
|
3486
|
|
|
function getFieldErrorIcon($fieldValidationErrorMsg) |
|
3487
|
|
|
{ |
|
3488
|
|
|
$out = ''; |
|
3489
|
|
|
if (!empty($fieldValidationErrorMsg)) { |
|
3490
|
|
|
$out .= '<span class="field-error-icon classfortooltip" title="' . dol_escape_htmltag($fieldValidationErrorMsg, 1) . '" role="alert" >'; // role alert is used for accessibility |
|
3491
|
|
|
$out .= '<span class="fa fa-exclamation-circle" aria-hidden="true" ></span>'; // For accessibility icon is separated and aria-hidden |
|
3492
|
|
|
$out .= '</span>'; |
|
3493
|
|
|
} |
|
3494
|
|
|
|
|
3495
|
|
|
return $out; |
|
3496
|
|
|
} |
|
3497
|
|
|
|
|
3498
|
|
|
/** |
|
3499
|
|
|
* Function dolGetButtonTitle : this kind of buttons are used in title in list |
|
3500
|
|
|
* |
|
3501
|
|
|
* @param string $label label of button |
|
3502
|
|
|
* @param string $helpText optional : content for help tooltip |
|
3503
|
|
|
* @param string $iconClass class for icon element (Example: 'fa fa-file') |
|
3504
|
|
|
* @param string $url the url for link |
|
3505
|
|
|
* @param string $id attribute id of button |
|
3506
|
|
|
* @param int<-2,2> $status 0 no user rights, 1 active, 2 current action or selected, -1 Feature Disabled, -2 disable Other reason use param $helpText as tooltip help |
|
3507
|
|
|
* @param array<string,mixed> $params various params for future : recommended rather than adding more function arguments |
|
3508
|
|
|
* @return string html button |
|
3509
|
|
|
*/ |
|
3510
|
|
|
function dolGetButtonTitle($label, $helpText = '', $iconClass = 'fa fa-file', $url = '', $id = '', $status = 1, $params = array()) |
|
3511
|
|
|
{ |
|
3512
|
|
|
global $langs, $conf, $user; |
|
3513
|
|
|
|
|
3514
|
|
|
// Actually this conf is used in css too for external module compatibility and smooth transition to this function |
|
3515
|
|
|
if (getDolGlobalString('MAIN_BUTTON_HIDE_UNAUTHORIZED') && (!$user->admin) && $status <= 0) { |
|
3516
|
|
|
return ''; |
|
3517
|
|
|
} |
|
3518
|
|
|
|
|
3519
|
|
|
$class = 'btnTitle'; |
|
3520
|
|
|
if (in_array($iconClass, array('fa fa-plus-circle', 'fa fa-plus-circle size15x', 'fa fa-comment-dots', 'fa fa-paper-plane'))) { |
|
3521
|
|
|
$class .= ' btnTitlePlus'; |
|
3522
|
|
|
} |
|
3523
|
|
|
$useclassfortooltip = 1; |
|
3524
|
|
|
|
|
3525
|
|
|
if (!empty($params['morecss'])) { |
|
3526
|
|
|
$class .= ' ' . $params['morecss']; |
|
3527
|
|
|
} |
|
3528
|
|
|
|
|
3529
|
|
|
$attr = array( |
|
3530
|
|
|
'class' => $class, |
|
3531
|
|
|
'href' => empty($url) ? '' : $url |
|
3532
|
|
|
); |
|
3533
|
|
|
|
|
3534
|
|
|
if (!empty($helpText)) { |
|
3535
|
|
|
$attr['title'] = dol_escape_htmltag($helpText); |
|
3536
|
|
|
} elseif (empty($attr['title']) && $label) { |
|
3537
|
|
|
$attr['title'] = $label; |
|
3538
|
|
|
$useclassfortooltip = 0; |
|
3539
|
|
|
} |
|
3540
|
|
|
|
|
3541
|
|
|
if ($status == 2) { |
|
3542
|
|
|
$attr['class'] .= ' btnTitleSelected'; |
|
3543
|
|
|
} elseif ($status <= 0) { |
|
3544
|
|
|
$attr['class'] .= ' refused'; |
|
3545
|
|
|
|
|
3546
|
|
|
$attr['href'] = ''; |
|
3547
|
|
|
|
|
3548
|
|
|
if ($status == -1) { // disable |
|
3549
|
|
|
$attr['title'] = dol_escape_htmltag($langs->transnoentitiesnoconv("FeatureDisabled")); |
|
3550
|
|
|
} elseif ($status == 0) { // Not enough permissions |
|
3551
|
|
|
$attr['title'] = dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")); |
|
3552
|
|
|
} |
|
3553
|
|
|
} |
|
3554
|
|
|
|
|
3555
|
|
|
if (!empty($attr['title']) && $useclassfortooltip) { |
|
3556
|
|
|
$attr['class'] .= ' classfortooltip'; |
|
3557
|
|
|
} |
|
3558
|
|
|
|
|
3559
|
|
|
if (!empty($id)) { |
|
3560
|
|
|
$attr['id'] = $id; |
|
3561
|
|
|
} |
|
3562
|
|
|
|
|
3563
|
|
|
// Override attr |
|
3564
|
|
|
if (!empty($params['attr']) && is_array($params['attr'])) { |
|
3565
|
|
|
foreach ($params['attr'] as $key => $value) { |
|
3566
|
|
|
if ($key == 'class') { |
|
3567
|
|
|
$attr['class'] .= ' ' . $value; |
|
3568
|
|
|
} elseif ($key == 'classOverride') { |
|
3569
|
|
|
$attr['class'] = $value; |
|
3570
|
|
|
} else { |
|
3571
|
|
|
$attr[$key] = $value; |
|
3572
|
|
|
} |
|
3573
|
|
|
} |
|
3574
|
|
|
} |
|
3575
|
|
|
|
|
3576
|
|
|
if (isset($attr['href']) && empty($attr['href'])) { |
|
3577
|
|
|
unset($attr['href']); |
|
3578
|
|
|
} |
|
3579
|
|
|
|
|
3580
|
|
|
// TODO : add a hook |
|
3581
|
|
|
|
|
3582
|
|
|
// escape all attribute |
|
3583
|
|
|
$attr = array_map('dol_escape_htmltag', $attr); |
|
3584
|
|
|
|
|
3585
|
|
|
$TCompiledAttr = array(); |
|
3586
|
|
|
foreach ($attr as $key => $value) { |
|
3587
|
|
|
$TCompiledAttr[] = $key . '="' . $value . '"'; |
|
3588
|
|
|
} |
|
3589
|
|
|
|
|
3590
|
|
|
$compiledAttributes = (empty($TCompiledAttr) ? '' : implode(' ', $TCompiledAttr)); |
|
3591
|
|
|
|
|
3592
|
|
|
$tag = (empty($attr['href']) ? 'span' : 'a'); |
|
3593
|
|
|
|
|
3594
|
|
|
$button = '<' . $tag . ' ' . $compiledAttributes . '>'; |
|
3595
|
|
|
$button .= '<span class="' . $iconClass . ' valignmiddle btnTitle-icon"></span>'; |
|
3596
|
|
|
if (!empty($params['forcenohideoftext'])) { |
|
3597
|
|
|
$button .= '<span class="valignmiddle text-plus-circle btnTitle-label' . (empty($params['forcenohideoftext']) ? ' hideonsmartphone' : '') . '">' . $label . '</span>'; |
|
3598
|
|
|
} |
|
3599
|
|
|
$button .= '</' . $tag . '>'; |
|
3600
|
|
|
|
|
3601
|
|
|
return $button; |
|
3602
|
|
|
} |
|
3603
|
|
|
|
|
3604
|
|
|
/** |
|
3605
|
|
|
* Get an array with properties of an element. |
|
3606
|
|
|
* |
|
3607
|
|
|
* @param string $elementType Element type (Value of $object->element or value of $object->element@$object->module). Example: |
|
3608
|
|
|
* 'action', 'facture', 'project', 'project_task' or |
|
3609
|
|
|
* 'myobject@mymodule' (or old syntax 'mymodule_myobject' like 'project_task') |
|
3610
|
|
|
* @return array{module:string,element:string,table_element:string,subelement:string,classpath:string,classfile:string,classname:string,dir_output:string} array('module'=>, 'classpath'=>, 'element'=>, 'subelement'=>, 'classfile'=>, 'classname'=>, 'dir_output'=>) |
|
3611
|
|
|
* @see fetchObjectByElement(), getMultidirOutput() |
|
3612
|
|
|
*/ |
|
3613
|
|
|
function getElementProperties($elementType) |
|
3614
|
|
|
{ |
|
3615
|
|
|
global $conf, $db, $hookmanager; |
|
3616
|
|
|
|
|
3617
|
|
|
$regs = array(); |
|
3618
|
|
|
|
|
3619
|
|
|
//$element_type='facture'; |
|
3620
|
|
|
|
|
3621
|
|
|
$classfile = $classname = $classpath = $subdir = $dir_output = ''; |
|
3622
|
|
|
|
|
3623
|
|
|
// Parse element/subelement |
|
3624
|
|
|
$module = $elementType; |
|
3625
|
|
|
$element = $elementType; |
|
3626
|
|
|
$subelement = $elementType; |
|
3627
|
|
|
$table_element = $elementType; |
|
3628
|
|
|
|
|
3629
|
|
|
// If we ask a resource form external module (instead of default path) |
|
3630
|
|
|
if (preg_match('/^([^@]+)@([^@]+)$/i', $elementType, $regs)) { // 'myobject@mymodule' |
|
3631
|
|
|
$element = $subelement = $regs[1]; |
|
3632
|
|
|
$module = $regs[2]; |
|
3633
|
|
|
} |
|
3634
|
|
|
|
|
3635
|
|
|
// If we ask a resource for a string with an element and a subelement |
|
3636
|
|
|
// Example 'project_task' |
|
3637
|
|
|
if (preg_match('/^([^_]+)_([^_]+)/i', $element, $regs)) { // 'myobject_mysubobject' with myobject=mymodule |
|
3638
|
|
|
$module = $element = $regs[1]; |
|
3639
|
|
|
$subelement = $regs[2]; |
|
3640
|
|
|
} |
|
3641
|
|
|
|
|
3642
|
|
|
// Object lines will use parent classpath and module ref |
|
3643
|
|
|
if (substr($elementType, -3) == 'det') { |
|
3644
|
|
|
$module = preg_replace('/det$/', '', $element); |
|
3645
|
|
|
$subelement = preg_replace('/det$/', '', $subelement); |
|
3646
|
|
|
$classpath = $module . '/class'; |
|
3647
|
|
|
$classfile = $module; |
|
3648
|
|
|
$classname = preg_replace('/det$/', 'Line', $element); |
|
3649
|
|
|
if (in_array($module, array('expedition', 'propale', 'facture', 'contrat', 'fichinter', 'commandefournisseur'))) { |
|
3650
|
|
|
$classname = preg_replace('/det$/', 'Ligne', $element); |
|
3651
|
|
|
} |
|
3652
|
|
|
} |
|
3653
|
|
|
// For compatibility and to work with non standard path |
|
3654
|
|
|
if ($elementType == "action" || $elementType == "actioncomm") { |
|
3655
|
|
|
$classpath = 'comm/action/class'; |
|
3656
|
|
|
$subelement = 'Actioncomm'; |
|
3657
|
|
|
$module = 'agenda'; |
|
3658
|
|
|
$table_element = 'actioncomm'; |
|
3659
|
|
|
} elseif ($elementType == 'cronjob') { |
|
3660
|
|
|
$classpath = 'cron/class'; |
|
3661
|
|
|
$module = 'cron'; |
|
3662
|
|
|
$table_element = 'cron'; |
|
3663
|
|
|
} elseif ($elementType == 'adherent_type') { |
|
3664
|
|
|
$classpath = 'adherents/class'; |
|
3665
|
|
|
$classfile = 'adherent_type'; |
|
3666
|
|
|
$module = 'adherent'; |
|
3667
|
|
|
$subelement = 'adherent_type'; |
|
3668
|
|
|
$classname = 'AdherentType'; |
|
3669
|
|
|
$table_element = 'adherent_type'; |
|
3670
|
|
|
} elseif ($elementType == 'bank_account') { |
|
3671
|
|
|
$classpath = 'compta/bank/class'; |
|
3672
|
|
|
$module = 'bank'; // We need $conf->bank->dir_output and not $conf->banque->dir_output |
|
3673
|
|
|
$classfile = 'account'; |
|
3674
|
|
|
$classname = 'Account'; |
|
3675
|
|
|
} elseif ($elementType == 'category') { |
|
3676
|
|
|
$classpath = 'categories/class'; |
|
3677
|
|
|
$module = 'categorie'; |
|
3678
|
|
|
$subelement = 'categorie'; |
|
3679
|
|
|
$table_element = 'categorie'; |
|
3680
|
|
|
} elseif ($elementType == 'contact') { |
|
3681
|
|
|
$classpath = 'contact/class'; |
|
3682
|
|
|
$classfile = 'contact'; |
|
3683
|
|
|
$module = 'societe'; |
|
3684
|
|
|
$subelement = 'contact'; |
|
3685
|
|
|
$table_element = 'socpeople'; |
|
3686
|
|
|
} elseif ($elementType == 'inventory') { |
|
3687
|
|
|
$module = 'product'; |
|
3688
|
|
|
$classpath = 'product/inventory/class'; |
|
3689
|
|
|
} elseif ($elementType == 'stock' || $elementType == 'entrepot') { |
|
3690
|
|
|
$module = 'stock'; |
|
3691
|
|
|
$classpath = 'product/stock/class'; |
|
3692
|
|
|
$classfile = 'entrepot'; |
|
3693
|
|
|
$classname = 'Entrepot'; |
|
3694
|
|
|
$table_element = 'entrepot'; |
|
3695
|
|
|
} elseif ($elementType == 'project') { |
|
3696
|
|
|
$classpath = 'projet/class'; |
|
3697
|
|
|
$module = 'projet'; |
|
3698
|
|
|
$table_element = 'projet'; |
|
3699
|
|
|
} elseif ($elementType == 'project_task') { |
|
3700
|
|
|
$classpath = 'projet/class'; |
|
3701
|
|
|
$module = 'projet'; |
|
3702
|
|
|
$subelement = 'task'; |
|
3703
|
|
|
$table_element = 'projet_task'; |
|
3704
|
|
|
} elseif ($elementType == 'facture' || $elementType == 'invoice') { |
|
3705
|
|
|
$classpath = 'compta/facture/class'; |
|
3706
|
|
|
$module = 'facture'; |
|
3707
|
|
|
$subelement = 'facture'; |
|
3708
|
|
|
$table_element = 'facture'; |
|
3709
|
|
|
} elseif ($elementType == 'facturerec') { |
|
3710
|
|
|
$classpath = 'compta/facture/class'; |
|
3711
|
|
|
$module = 'facture'; |
|
3712
|
|
|
$classname = 'FactureRec'; |
|
3713
|
|
|
} elseif ($elementType == 'commande' || $elementType == 'order') { |
|
3714
|
|
|
$classpath = 'commande/class'; |
|
3715
|
|
|
$module = 'commande'; |
|
3716
|
|
|
$subelement = 'commande'; |
|
3717
|
|
|
$table_element = 'commande'; |
|
3718
|
|
|
} elseif ($elementType == 'propal') { |
|
3719
|
|
|
$classpath = 'comm/propal/class'; |
|
3720
|
|
|
$table_element = 'propal'; |
|
3721
|
|
|
} elseif ($elementType == 'shipping') { |
|
3722
|
|
|
$classpath = 'expedition/class'; |
|
3723
|
|
|
$classfile = 'expedition'; |
|
3724
|
|
|
$classname = 'Expedition'; |
|
3725
|
|
|
$module = 'expedition'; |
|
3726
|
|
|
$table_element = 'expedition'; |
|
3727
|
|
|
} elseif ($elementType == 'delivery_note') { |
|
3728
|
|
|
$classpath = 'delivery/class'; |
|
3729
|
|
|
$subelement = 'delivery'; |
|
3730
|
|
|
$module = 'expedition'; |
|
3731
|
|
|
} elseif ($elementType == 'delivery') { |
|
3732
|
|
|
$classpath = 'delivery/class'; |
|
3733
|
|
|
$subelement = 'delivery'; |
|
3734
|
|
|
$module = 'expedition'; |
|
3735
|
|
|
} elseif ($elementType == 'supplier_proposal') { |
|
3736
|
|
|
$classpath = 'supplier_proposal/class'; |
|
3737
|
|
|
$module = 'supplier_proposal'; |
|
3738
|
|
|
$element = 'supplierproposal'; |
|
3739
|
|
|
$classfile = 'supplier_proposal'; |
|
3740
|
|
|
$subelement = 'supplierproposal'; |
|
3741
|
|
|
} elseif ($elementType == 'contract') { |
|
3742
|
|
|
$classpath = 'contrat/class'; |
|
3743
|
|
|
$module = 'contrat'; |
|
3744
|
|
|
$subelement = 'contrat'; |
|
3745
|
|
|
$table_element = 'contract'; |
|
3746
|
|
|
} elseif ($elementType == 'mailing') { |
|
3747
|
|
|
$classpath = 'comm/mailing/class'; |
|
3748
|
|
|
$module = 'mailing'; |
|
3749
|
|
|
$classfile = 'mailing'; |
|
3750
|
|
|
$classname = 'Mailing'; |
|
3751
|
|
|
$subelement = ''; |
|
3752
|
|
|
} elseif ($elementType == 'member') { |
|
3753
|
|
|
$classpath = 'adherents/class'; |
|
3754
|
|
|
$module = 'adherent'; |
|
3755
|
|
|
$subelement = 'adherent'; |
|
3756
|
|
|
$table_element = 'adherent'; |
|
3757
|
|
|
} elseif ($elementType == 'usergroup') { |
|
3758
|
|
|
$classpath = 'user/class'; |
|
3759
|
|
|
$module = 'user'; |
|
3760
|
|
|
} elseif ($elementType == 'mo') { |
|
3761
|
|
|
$classpath = 'mrp/class'; |
|
3762
|
|
|
$classfile = 'mo'; |
|
3763
|
|
|
$classname = 'Mo'; |
|
3764
|
|
|
$module = 'mrp'; |
|
3765
|
|
|
$subelement = ''; |
|
3766
|
|
|
$table_element = 'mrp_mo'; |
|
3767
|
|
|
} elseif ($elementType == 'cabinetmed_cons') { |
|
3768
|
|
|
$classpath = 'cabinetmed/class'; |
|
3769
|
|
|
$module = 'cabinetmed'; |
|
3770
|
|
|
$subelement = 'cabinetmedcons'; |
|
3771
|
|
|
$table_element = 'cabinetmedcons'; |
|
3772
|
|
|
} elseif ($elementType == 'fichinter') { |
|
3773
|
|
|
$classpath = 'fichinter/class'; |
|
3774
|
|
|
$module = 'ficheinter'; |
|
3775
|
|
|
$subelement = 'fichinter'; |
|
3776
|
|
|
$table_element = 'fichinter'; |
|
3777
|
|
|
} elseif ($elementType == 'dolresource' || $elementType == 'resource') { |
|
3778
|
|
|
$classpath = 'resource/class'; |
|
3779
|
|
|
$module = 'resource'; |
|
3780
|
|
|
$subelement = 'dolresource'; |
|
3781
|
|
|
$table_element = 'resource'; |
|
3782
|
|
|
} elseif ($elementType == 'propaldet') { |
|
3783
|
|
|
$classpath = 'comm/propal/class'; |
|
3784
|
|
|
$module = 'propal'; |
|
3785
|
|
|
$subelement = 'propaleligne'; |
|
3786
|
|
|
} elseif ($elementType == 'opensurvey_sondage') { |
|
3787
|
|
|
$classpath = 'opensurvey/class'; |
|
3788
|
|
|
$module = 'opensurvey'; |
|
3789
|
|
|
$subelement = 'opensurveysondage'; |
|
3790
|
|
|
} elseif ($elementType == 'order_supplier') { |
|
3791
|
|
|
$classpath = 'fourn/class'; |
|
3792
|
|
|
$module = 'fournisseur'; |
|
3793
|
|
|
$classfile = 'fournisseur.commande'; |
|
3794
|
|
|
$element = 'order_supplier'; |
|
3795
|
|
|
$subelement = ''; |
|
3796
|
|
|
$classname = 'CommandeFournisseur'; |
|
3797
|
|
|
$table_element = 'commande_fournisseur'; |
|
3798
|
|
|
} elseif ($elementType == 'commande_fournisseurdet') { |
|
3799
|
|
|
$classpath = 'fourn/class'; |
|
3800
|
|
|
$module = 'fournisseur'; |
|
3801
|
|
|
$classfile = 'fournisseur.commande'; |
|
3802
|
|
|
$element = 'commande_fournisseurdet'; |
|
3803
|
|
|
$subelement = ''; |
|
3804
|
|
|
$classname = 'CommandeFournisseurLigne'; |
|
3805
|
|
|
$table_element = 'commande_fournisseurdet'; |
|
3806
|
|
|
} elseif ($elementType == 'invoice_supplier') { |
|
3807
|
|
|
$classpath = 'fourn/class'; |
|
3808
|
|
|
$module = 'fournisseur'; |
|
3809
|
|
|
$classfile = 'fournisseur.facture'; |
|
3810
|
|
|
$element = 'invoice_supplier'; |
|
3811
|
|
|
$subelement = ''; |
|
3812
|
|
|
$classname = 'FactureFournisseur'; |
|
3813
|
|
|
$table_element = 'facture_fourn'; |
|
3814
|
|
|
} elseif ($elementType == "service") { |
|
3815
|
|
|
$classpath = 'product/class'; |
|
3816
|
|
|
$subelement = 'product'; |
|
3817
|
|
|
$table_element = 'product'; |
|
3818
|
|
|
} elseif ($elementType == 'salary') { |
|
3819
|
|
|
$classpath = 'salaries/class'; |
|
3820
|
|
|
$module = 'salaries'; |
|
3821
|
|
|
} elseif ($elementType == 'payment_salary') { |
|
3822
|
|
|
$classpath = 'salaries/class'; |
|
3823
|
|
|
$classfile = 'paymentsalary'; |
|
3824
|
|
|
$classname = 'PaymentSalary'; |
|
3825
|
|
|
$module = 'salaries'; |
|
3826
|
|
|
} elseif ($elementType == 'productlot') { |
|
3827
|
|
|
$module = 'productbatch'; |
|
3828
|
|
|
$classpath = 'product/stock/class'; |
|
3829
|
|
|
$classfile = 'productlot'; |
|
3830
|
|
|
$classname = 'Productlot'; |
|
3831
|
|
|
$element = 'productlot'; |
|
3832
|
|
|
$subelement = ''; |
|
3833
|
|
|
$table_element = 'product_lot'; |
|
3834
|
|
|
} elseif ($elementType == 'societeaccount') { |
|
3835
|
|
|
$classpath = 'societe/class'; |
|
3836
|
|
|
$classfile = 'societeaccount'; |
|
3837
|
|
|
$classname = 'SocieteAccount'; |
|
3838
|
|
|
$module = 'societe'; |
|
3839
|
|
|
} elseif ($elementType == 'websitepage') { |
|
3840
|
|
|
$classpath = 'website/class'; |
|
3841
|
|
|
$classfile = 'websitepage'; |
|
3842
|
|
|
$classname = 'Websitepage'; |
|
3843
|
|
|
$module = 'website'; |
|
3844
|
|
|
$subelement = 'websitepage'; |
|
3845
|
|
|
$table_element = 'website_page'; |
|
3846
|
|
|
} elseif ($elementType == 'fiscalyear') { |
|
3847
|
|
|
$classpath = 'core/class'; |
|
3848
|
|
|
$module = 'accounting'; |
|
3849
|
|
|
$subelement = 'fiscalyear'; |
|
3850
|
|
|
} elseif ($elementType == 'chargesociales') { |
|
3851
|
|
|
$classpath = 'compta/sociales/class'; |
|
3852
|
|
|
$module = 'tax'; |
|
3853
|
|
|
$table_element = 'chargesociales'; |
|
3854
|
|
|
} elseif ($elementType == 'tva') { |
|
3855
|
|
|
$classpath = 'compta/tva/class'; |
|
3856
|
|
|
$module = 'tax'; |
|
3857
|
|
|
$subdir = '/vat'; |
|
3858
|
|
|
$table_element = 'tva'; |
|
3859
|
|
|
} elseif ($elementType == 'emailsenderprofile') { |
|
3860
|
|
|
$module = ''; |
|
3861
|
|
|
$classpath = 'core/class'; |
|
3862
|
|
|
$classfile = 'emailsenderprofile'; |
|
3863
|
|
|
$classname = 'EmailSenderProfile'; |
|
3864
|
|
|
$table_element = 'c_email_senderprofile'; |
|
3865
|
|
|
$subelement = ''; |
|
3866
|
|
|
} elseif ($elementType == 'conferenceorboothattendee') { |
|
3867
|
|
|
$classpath = 'eventorganization/class'; |
|
3868
|
|
|
$classfile = 'conferenceorboothattendee'; |
|
3869
|
|
|
$classname = 'ConferenceOrBoothAttendee'; |
|
3870
|
|
|
$module = 'eventorganization'; |
|
3871
|
|
|
} elseif ($elementType == 'conferenceorbooth') { |
|
3872
|
|
|
$classpath = 'eventorganization/class'; |
|
3873
|
|
|
$classfile = 'conferenceorbooth'; |
|
3874
|
|
|
$classname = 'ConferenceOrBooth'; |
|
3875
|
|
|
$module = 'eventorganization'; |
|
3876
|
|
|
} elseif ($elementType == 'ccountry') { |
|
3877
|
|
|
$module = ''; |
|
3878
|
|
|
$classpath = 'core/class'; |
|
3879
|
|
|
$classfile = 'ccountry'; |
|
3880
|
|
|
$classname = 'Ccountry'; |
|
3881
|
|
|
$table_element = 'c_country'; |
|
3882
|
|
|
$subelement = ''; |
|
3883
|
|
|
} elseif ($elementType == 'knowledgerecord') { |
|
3884
|
|
|
$module = ''; |
|
3885
|
|
|
$classpath = 'knowledgemanagement/class'; |
|
3886
|
|
|
$classfile = 'knowledgerecord'; |
|
3887
|
|
|
$classname = 'KnowledgeRecord'; |
|
3888
|
|
|
$table_element = 'knowledgemanagement_knowledgerecord'; |
|
3889
|
|
|
$subelement = ''; |
|
3890
|
|
|
} |
|
3891
|
|
|
|
|
3892
|
|
|
if (empty($classfile)) { |
|
3893
|
|
|
$classfile = strtolower($subelement); |
|
3894
|
|
|
} |
|
3895
|
|
|
if (empty($classname)) { |
|
3896
|
|
|
$classname = ucfirst($subelement); |
|
3897
|
|
|
} |
|
3898
|
|
|
if (empty($classpath)) { |
|
3899
|
|
|
$classpath = $module . '/class'; |
|
3900
|
|
|
} |
|
3901
|
|
|
|
|
3902
|
|
|
//print 'getElementProperties subdir='.$subdir; |
|
3903
|
|
|
|
|
3904
|
|
|
// Set dir_output |
|
3905
|
|
|
if ($module && isset($conf->$module)) { // The generic case |
|
3906
|
|
|
if (!empty($conf->$module->multidir_output[$conf->entity])) { |
|
3907
|
|
|
$dir_output = $conf->$module->multidir_output[$conf->entity]; |
|
3908
|
|
|
} elseif (!empty($conf->$module->output[$conf->entity])) { |
|
3909
|
|
|
$dir_output = $conf->$module->output[$conf->entity]; |
|
3910
|
|
|
} elseif (!empty($conf->$module->dir_output)) { |
|
3911
|
|
|
$dir_output = $conf->$module->dir_output; |
|
3912
|
|
|
} |
|
3913
|
|
|
} |
|
3914
|
|
|
|
|
3915
|
|
|
// Overwrite value for special cases |
|
3916
|
|
|
if ($element == 'order_supplier') { |
|
3917
|
|
|
$dir_output = $conf->fournisseur->commande->dir_output; |
|
3918
|
|
|
} elseif ($element == 'invoice_supplier') { |
|
3919
|
|
|
$dir_output = $conf->fournisseur->facture->dir_output; |
|
3920
|
|
|
} |
|
3921
|
|
|
$dir_output .= $subdir; |
|
3922
|
|
|
|
|
3923
|
|
|
$elementProperties = array( |
|
3924
|
|
|
'module' => $module, |
|
3925
|
|
|
'element' => $element, |
|
3926
|
|
|
'table_element' => $table_element, |
|
3927
|
|
|
'subelement' => $subelement, |
|
3928
|
|
|
'classpath' => $classpath, |
|
3929
|
|
|
'classfile' => $classfile, |
|
3930
|
|
|
'classname' => $classname, |
|
3931
|
|
|
'dir_output' => $dir_output |
|
3932
|
|
|
); |
|
3933
|
|
|
|
|
3934
|
|
|
|
|
3935
|
|
|
// Add hook |
|
3936
|
|
|
if (!is_object($hookmanager)) { |
|
3937
|
|
|
$hookmanager = new HookManager($db); |
|
3938
|
|
|
} |
|
3939
|
|
|
$hookmanager->initHooks(array('elementproperties')); |
|
3940
|
|
|
|
|
3941
|
|
|
|
|
3942
|
|
|
// Hook params |
|
3943
|
|
|
$parameters = array( |
|
3944
|
|
|
'elementType' => $elementType, |
|
3945
|
|
|
'elementProperties' => $elementProperties |
|
3946
|
|
|
); |
|
3947
|
|
|
|
|
3948
|
|
|
$reshook = $hookmanager->executeHooks('getElementProperties', $parameters); |
|
3949
|
|
|
|
|
3950
|
|
|
if ($reshook) { |
|
3951
|
|
|
$elementProperties = $hookmanager->resArray; |
|
3952
|
|
|
} elseif (!empty($hookmanager->resArray) && is_array($hookmanager->resArray)) { // resArray is always an array but for sécurity against misconfigured external modules |
|
3953
|
|
|
$elementProperties = array_replace($elementProperties, $hookmanager->resArray); |
|
3954
|
|
|
} |
|
3955
|
|
|
|
|
3956
|
|
|
// context of elementproperties doesn't need to exist out of this function so delete it to avoid elementproperties context is equal to all |
|
3957
|
|
|
if (($key = array_search('elementproperties', $hookmanager->contextarray)) !== false) { |
|
3958
|
|
|
unset($hookmanager->contextarray[$key]); |
|
3959
|
|
|
} |
|
3960
|
|
|
|
|
3961
|
|
|
return $elementProperties; |
|
3962
|
|
|
} |
|
3963
|
|
|
|
|
3964
|
|
|
/** |
|
3965
|
|
|
* Function dolGetBadge |
|
3966
|
|
|
* |
|
3967
|
|
|
* @param string $label label of badge no html : use in alt attribute for accessibility |
|
3968
|
|
|
* @param string $html optional : label of badge with html |
|
3969
|
|
|
* @param string $type type of badge : Primary Secondary Success Danger Warning Info Light Dark status0 status1 status2 status3 status4 status5 status6 status7 status8 status9 |
|
3970
|
|
|
* @param ''|'pill'|'dot' $mode Default '' , 'pill', 'dot' |
|
|
|
|
|
|
3971
|
|
|
* @param string $url the url for link |
|
3972
|
|
|
* @param array<string,mixed> $params Various params for future : recommended rather than adding more function arguments. array('attr'=>array('title'=>'abc')) |
|
3973
|
|
|
* @return string Html badge |
|
3974
|
|
|
*/ |
|
3975
|
|
|
function dolGetBadge($label, $html = '', $type = 'primary', $mode = '', $url = '', $params = array()) |
|
3976
|
|
|
{ |
|
3977
|
|
|
$csstouse = 'badge'; |
|
3978
|
|
|
$csstouse .= (!empty($mode) ? ' badge-' . $mode : ''); |
|
3979
|
|
|
$csstouse .= (!empty($type) ? ' badge-' . $type : ''); |
|
3980
|
|
|
$csstouse .= (empty($params['css']) ? '' : ' ' . $params['css']); |
|
3981
|
|
|
|
|
3982
|
|
|
$attr = array( |
|
3983
|
|
|
'class' => $csstouse |
|
3984
|
|
|
); |
|
3985
|
|
|
|
|
3986
|
|
|
if (empty($html)) { |
|
3987
|
|
|
$html = $label; |
|
3988
|
|
|
} |
|
3989
|
|
|
|
|
3990
|
|
|
if (!empty($url)) { |
|
3991
|
|
|
$attr['href'] = $url; |
|
3992
|
|
|
} |
|
3993
|
|
|
|
|
3994
|
|
|
if ($mode === 'dot') { |
|
3995
|
|
|
$attr['class'] .= ' classfortooltip'; |
|
3996
|
|
|
$attr['title'] = $html; |
|
3997
|
|
|
$attr['aria-label'] = $label; |
|
3998
|
|
|
$html = ''; |
|
3999
|
|
|
} |
|
4000
|
|
|
|
|
4001
|
|
|
// Override attr |
|
4002
|
|
|
if (!empty($params['attr']) && is_array($params['attr'])) { |
|
4003
|
|
|
foreach ($params['attr'] as $key => $value) { |
|
4004
|
|
|
if ($key == 'class') { |
|
4005
|
|
|
$attr['class'] .= ' ' . $value; |
|
4006
|
|
|
} elseif ($key == 'classOverride') { |
|
4007
|
|
|
$attr['class'] = $value; |
|
4008
|
|
|
} else { |
|
4009
|
|
|
$attr[$key] = $value; |
|
4010
|
|
|
} |
|
4011
|
|
|
} |
|
4012
|
|
|
} |
|
4013
|
|
|
|
|
4014
|
|
|
// TODO: add hook |
|
4015
|
|
|
|
|
4016
|
|
|
// escape all attribute |
|
4017
|
|
|
$attr = array_map('dol_escape_htmltag', $attr); |
|
4018
|
|
|
|
|
4019
|
|
|
$TCompiledAttr = array(); |
|
4020
|
|
|
foreach ($attr as $key => $value) { |
|
4021
|
|
|
$TCompiledAttr[] = $key . '="' . $value . '"'; |
|
4022
|
|
|
} |
|
4023
|
|
|
|
|
4024
|
|
|
$compiledAttributes = !empty($TCompiledAttr) ? implode(' ', $TCompiledAttr) : ''; |
|
4025
|
|
|
|
|
4026
|
|
|
$tag = !empty($url) ? 'a' : 'span'; |
|
4027
|
|
|
|
|
4028
|
|
|
return '<' . $tag . ' ' . $compiledAttributes . '>' . $html . '</' . $tag . '>'; |
|
4029
|
|
|
} |
|
4030
|
|
|
|
|
4031
|
|
|
|
|
4032
|
|
|
/** |
|
4033
|
|
|
* Output the badge of a status. |
|
4034
|
|
|
* |
|
4035
|
|
|
* @param string $statusLabel Label of badge no html : use in alt attribute for accessibility |
|
4036
|
|
|
* @param string $statusLabelShort Short label of badge no html |
|
4037
|
|
|
* @param string $html Optional : label of badge with html |
|
4038
|
|
|
* @param string $statusType status0 status1 status2 status3 status4 status5 status6 status7 status8 status9 : image name or badge name |
|
4039
|
|
|
* @param int<0,6> $displayMode 0=Long label, 1=Short label, 2=Picto + Short label, 3=Picto, 4=Picto + Long label, 5=Short label + Picto, 6=Long label + Picto |
|
4040
|
|
|
* @param string $url The url for link |
|
4041
|
|
|
* @param array<string,mixed> $params Various params. Example: array('tooltip'=>'no|...', 'badgeParams'=>...) |
|
4042
|
|
|
* @return string Html status string |
|
4043
|
|
|
*/ |
|
4044
|
|
|
function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $statusType = 'status0', $displayMode = 0, $url = '', $params = array()) |
|
4045
|
|
|
{ |
|
4046
|
|
|
global $conf; |
|
4047
|
|
|
|
|
4048
|
|
|
$return = ''; |
|
4049
|
|
|
$dolGetBadgeParams = array(); |
|
4050
|
|
|
|
|
4051
|
|
|
if (!empty($params['badgeParams'])) { |
|
4052
|
|
|
$dolGetBadgeParams = $params['badgeParams']; |
|
4053
|
|
|
} |
|
4054
|
|
|
|
|
4055
|
|
|
// TODO : add a hook |
|
4056
|
|
|
if ($displayMode == 0) { |
|
4057
|
|
|
$return = !empty($html) ? $html : (empty($conf->dol_optimize_smallscreen) ? $statusLabel : (empty($statusLabelShort) ? $statusLabel : $statusLabelShort)); |
|
4058
|
|
|
} elseif ($displayMode == 1) { |
|
4059
|
|
|
$return = !empty($html) ? $html : (empty($statusLabelShort) ? $statusLabel : $statusLabelShort); |
|
4060
|
|
|
} elseif (getDolGlobalString('MAIN_STATUS_USES_IMAGES')) { |
|
4061
|
|
|
// Use status with images (for backward compatibility) |
|
4062
|
|
|
$return = ''; |
|
4063
|
|
|
$htmlLabel = (in_array($displayMode, array(1, 2, 5)) ? '<span class="hideonsmartphone">' : '') . (!empty($html) ? $html : $statusLabel) . (in_array($displayMode, array(1, 2, 5)) ? '</span>' : ''); |
|
4064
|
|
|
$htmlLabelShort = (in_array($displayMode, array(1, 2, 5)) ? '<span class="hideonsmartphone">' : '') . (!empty($html) ? $html : (!empty($statusLabelShort) ? $statusLabelShort : $statusLabel)) . (in_array($displayMode, array(1, 2, 5)) ? '</span>' : ''); |
|
4065
|
|
|
|
|
4066
|
|
|
// For small screen, we always use the short label instead of long label. |
|
4067
|
|
|
if (!empty($conf->dol_optimize_smallscreen)) { |
|
4068
|
|
|
if ($displayMode == 0) { |
|
4069
|
|
|
$displayMode = 1; |
|
4070
|
|
|
} elseif ($displayMode == 4) { |
|
4071
|
|
|
$displayMode = 2; |
|
4072
|
|
|
} elseif ($displayMode == 6) { |
|
4073
|
|
|
$displayMode = 5; |
|
4074
|
|
|
} |
|
4075
|
|
|
} |
|
4076
|
|
|
|
|
4077
|
|
|
// For backward compatibility. Image's filename are still in French, so we use this array to convert |
|
4078
|
|
|
$statusImg = array( |
|
4079
|
|
|
'status0' => 'statut0', |
|
4080
|
|
|
'status1' => 'statut1', |
|
4081
|
|
|
'status2' => 'statut2', |
|
4082
|
|
|
'status3' => 'statut3', |
|
4083
|
|
|
'status4' => 'statut4', |
|
4084
|
|
|
'status5' => 'statut5', |
|
4085
|
|
|
'status6' => 'statut6', |
|
4086
|
|
|
'status7' => 'statut7', |
|
4087
|
|
|
'status8' => 'statut8', |
|
4088
|
|
|
'status9' => 'statut9' |
|
4089
|
|
|
); |
|
4090
|
|
|
|
|
4091
|
|
|
if (!empty($statusImg[$statusType])) { |
|
4092
|
|
|
$htmlImg = img_picto($statusLabel, $statusImg[$statusType]); |
|
4093
|
|
|
} else { |
|
4094
|
|
|
$htmlImg = img_picto($statusLabel, $statusType); |
|
4095
|
|
|
} |
|
4096
|
|
|
|
|
4097
|
|
|
if ($displayMode === 2) { |
|
4098
|
|
|
$return = $htmlImg . ' ' . $htmlLabelShort; |
|
4099
|
|
|
} elseif ($displayMode === 3) { |
|
4100
|
|
|
$return = $htmlImg; |
|
4101
|
|
|
} elseif ($displayMode === 4) { |
|
4102
|
|
|
$return = $htmlImg . ' ' . $htmlLabel; |
|
4103
|
|
|
} elseif ($displayMode === 5) { |
|
4104
|
|
|
$return = $htmlLabelShort . ' ' . $htmlImg; |
|
4105
|
|
|
} else { // $displayMode >= 6 |
|
4106
|
|
|
$return = $htmlLabel . ' ' . $htmlImg; |
|
4107
|
|
|
} |
|
4108
|
|
|
} elseif (!getDolGlobalString('MAIN_STATUS_USES_IMAGES') && !empty($displayMode)) { |
|
4109
|
|
|
// Use new badge |
|
4110
|
|
|
$statusLabelShort = (empty($statusLabelShort) ? $statusLabel : $statusLabelShort); |
|
4111
|
|
|
|
|
4112
|
|
|
$dolGetBadgeParams['attr']['class'] = 'badge-status'; |
|
4113
|
|
|
if (empty($dolGetBadgeParams['attr']['title'])) { |
|
4114
|
|
|
$dolGetBadgeParams['attr']['title'] = empty($params['tooltip']) ? $statusLabel : ($params['tooltip'] != 'no' ? $params['tooltip'] : ''); |
|
4115
|
|
|
} else { // If a title was forced from $params['badgeParams']['attr']['title'], we set the class to get it as a tooltip. |
|
4116
|
|
|
$dolGetBadgeParams['attr']['class'] .= ' classfortooltip'; |
|
4117
|
|
|
// And if we use tooltip, we can output title in HTML |
|
4118
|
|
|
$dolGetBadgeParams['attr']['title'] = dol_htmlentitiesbr($dolGetBadgeParams['attr']['title'], 1); |
|
4119
|
|
|
} |
|
4120
|
|
|
|
|
4121
|
|
|
if ($displayMode == 3) { |
|
4122
|
|
|
$return = dolGetBadge((empty($conf->dol_optimize_smallscreen) ? $statusLabel : (empty($statusLabelShort) ? $statusLabel : $statusLabelShort)), '', $statusType, 'dot', $url, $dolGetBadgeParams); |
|
4123
|
|
|
} elseif ($displayMode === 5) { |
|
4124
|
|
|
$return = dolGetBadge($statusLabelShort, $html, $statusType, '', $url, $dolGetBadgeParams); |
|
4125
|
|
|
} else { |
|
4126
|
|
|
$return = dolGetBadge((empty($conf->dol_optimize_smallscreen) ? $statusLabel : (empty($statusLabelShort) ? $statusLabel : $statusLabelShort)), $html, $statusType, '', $url, $dolGetBadgeParams); |
|
4127
|
|
|
} |
|
4128
|
|
|
} |
|
4129
|
|
|
|
|
4130
|
|
|
return $return; |
|
4131
|
|
|
} |
|
4132
|
|
|
|
|
4133
|
|
|
|
|
4134
|
|
|
/** |
|
4135
|
|
|
* Function dolGetButtonAction |
|
4136
|
|
|
* |
|
4137
|
|
|
* @param string $label Label or tooltip of button if $text is provided. Also used as tooltip in title attribute. Can be escaped HTML content or full simple text. |
|
4138
|
|
|
* @param string $text Optional : short label on button. Can be escaped HTML content or full simple text. |
|
4139
|
|
|
* @param string $actionType 'default', 'danger', 'email', 'clone', 'cancel', 'delete', ... |
|
4140
|
|
|
* |
|
4141
|
|
|
* @param string|array<int,array{lang:string,enabled:bool,perm:bool,label:string,url:string}> $url Url for link or array of subbutton description |
|
4142
|
|
|
* |
|
4143
|
|
|
* Example when an array is used: $arrayforbutaction = array( |
|
4144
|
|
|
* 10 => array('lang'=>'propal', 'enabled'=>isModEnabled("propal"), 'perm'=>$user->hasRight('propal', 'creer'), 'label' => 'AddProp', 'url'=>'/comm/propal/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid), |
|
4145
|
|
|
* 20 => array('lang'=>'orders', 'enabled'=>isModEnabled("order"), 'perm'=>$user->hasRight('commande', 'creer'), 'label' => 'CreateOrder', 'url'=>'/commande/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid), |
|
4146
|
|
|
* 30 => array('lang'=>'bills', 'enabled'=>isModEnabled("invoice"), 'perm'=>$user->hasRight('facture', 'creer'), 'label' => 'CreateBill', 'url'=>'/compta/facture/card.php?action=create&projectid='.$object->id.'&socid='.$object->socid), |
|
4147
|
|
|
* ); |
|
4148
|
|
|
* @param string $id Attribute id of action button. Example 'action-delete'. This can be used for full ajax confirm if this code is reused into the ->formconfirm() method. |
|
4149
|
|
|
* @param int|boolean $userRight User action right |
|
4150
|
|
|
* // phpcs:disable |
|
4151
|
|
|
* @param array<string,mixed> $params = [ // Various params for future : recommended rather than adding more function arguments |
|
4152
|
|
|
* 'attr' => [ // to add or override button attributes |
|
4153
|
|
|
* 'xxxxx' => '', // your xxxxx attribute you want |
|
4154
|
|
|
* 'class' => 'reposition', // to add more css class to the button class attribute |
|
4155
|
|
|
* 'classOverride' => '' // to replace class attribute of the button |
|
4156
|
|
|
* ], |
|
4157
|
|
|
* 'confirm' => [ |
|
4158
|
|
|
* 'url' => 'http://', // Override Url to go when user click on action btn, if empty default url is $url.?confirm=yes, for no js compatibility use $url for fallback confirm. |
|
4159
|
|
|
* 'title' => '', // Override title of modal, if empty default title use "ConfirmBtnCommonTitle" lang key |
|
4160
|
|
|
* 'action-btn-label' => '', // Override label of action button, if empty default label use "Confirm" lang key |
|
4161
|
|
|
* 'cancel-btn-label' => '', // Override label of cancel button, if empty default label use "CloseDialog" lang key |
|
4162
|
|
|
* 'content' => '', // Override text of content, if empty default content use "ConfirmBtnCommonContent" lang key |
|
4163
|
|
|
* 'modal' => true, // true|false to display dialog as a modal (with dark background) |
|
4164
|
|
|
* 'isDropDrown' => false, // true|false to display dialog as a dropdown (with dark background) |
|
4165
|
|
|
* ], |
|
4166
|
|
|
* ] |
|
4167
|
|
|
* // phpcs:enable |
|
4168
|
|
|
* @return string html button |
|
4169
|
|
|
*/ |
|
4170
|
|
|
function dolGetButtonAction($label, $text = '', $actionType = 'default', $url = '', $id = '', $userRight = 1, $params = array()) |
|
4171
|
|
|
{ |
|
4172
|
|
|
global $hookmanager, $action, $object, $langs; |
|
4173
|
|
|
|
|
4174
|
|
|
// If $url is an array, we must build a dropdown button or recursively iterate over each value |
|
4175
|
|
|
if (is_array($url)) { |
|
4176
|
|
|
// Loop on $url array to remove entries of disabled modules |
|
4177
|
|
|
foreach ($url as $key => $subbutton) { |
|
4178
|
|
|
if (isset($subbutton['enabled']) && empty($subbutton['enabled'])) { |
|
4179
|
|
|
unset($url[$key]); |
|
4180
|
|
|
} |
|
4181
|
|
|
} |
|
4182
|
|
|
|
|
4183
|
|
|
$out = ''; |
|
4184
|
|
|
|
|
4185
|
|
|
if (isset($params["areDropdownButtons"]) && $params["areDropdownButtons"] === false) { |
|
4186
|
|
|
foreach ($url as $button) { |
|
4187
|
|
|
if (!empty($button['lang'])) { |
|
4188
|
|
|
$langs->load($button['lang']); |
|
4189
|
|
|
} |
|
4190
|
|
|
$label = $langs->trans($button['label']); |
|
4191
|
|
|
$text = $button['text'] ?? ''; |
|
4192
|
|
|
$actionType = $button['actionType'] ?? ''; |
|
4193
|
|
|
$tmpUrl = DOL_URL_ROOT . $button['url'] . (empty($params['backtopage']) ? '' : '&backtopage=' . urlencode($params['backtopage'])); |
|
4194
|
|
|
$id = $button['$id'] ?? ''; |
|
4195
|
|
|
$userRight = $button['perm'] ?? 1; |
|
4196
|
|
|
$params = $button['$params'] ?? []; |
|
4197
|
|
|
|
|
4198
|
|
|
$out .= dolGetButtonAction($label, $text, $actionType, $tmpUrl, $id, $userRight, $params); |
|
4199
|
|
|
} |
|
4200
|
|
|
return $out; |
|
4201
|
|
|
} |
|
4202
|
|
|
|
|
4203
|
|
|
if (count($url) > 1) { |
|
4204
|
|
|
$out .= '<div class="dropdown inline-block dropdown-holder">'; |
|
4205
|
|
|
$out .= '<a style="margin-right: auto;" class="dropdown-toggle classfortooltip butAction' . ($userRight ? '' : 'Refused') . '" title="' . dol_escape_htmltag($label) . '" data-toggle="dropdown">' . ($text ? $text : $label) . '</a>'; |
|
4206
|
|
|
$out .= '<div class="dropdown-content">'; |
|
4207
|
|
|
foreach ($url as $subbutton) { |
|
4208
|
|
|
if (!empty($subbutton['lang'])) { |
|
4209
|
|
|
$langs->load($subbutton['lang']); |
|
4210
|
|
|
} |
|
4211
|
|
|
$tmpurl = DOL_URL_ROOT . $subbutton['url'] . (empty($params['backtopage']) ? '' : '&backtopage=' . urlencode($params['backtopage'])); |
|
4212
|
|
|
$out .= dolGetButtonAction('', $langs->trans($subbutton['label']), 'default', $tmpurl, '', $subbutton['perm'], array('isDropDown' => true)); |
|
4213
|
|
|
} |
|
4214
|
|
|
$out .= "</div>"; |
|
4215
|
|
|
$out .= "</div>"; |
|
4216
|
|
|
} else { |
|
4217
|
|
|
foreach ($url as $subbutton) { // Should loop on 1 record only |
|
4218
|
|
|
if (!empty($subbutton['lang'])) { |
|
4219
|
|
|
$langs->load($subbutton['lang']); |
|
4220
|
|
|
} |
|
4221
|
|
|
$tmpurl = DOL_URL_ROOT . $subbutton['url'] . (empty($params['backtopage']) ? '' : '&backtopage=' . urlencode($params['backtopage'])); |
|
4222
|
|
|
$out .= dolGetButtonAction('', $langs->trans($subbutton['label']), 'default', $tmpurl, '', $subbutton['perm']); |
|
4223
|
|
|
} |
|
4224
|
|
|
} |
|
4225
|
|
|
|
|
4226
|
|
|
return $out; |
|
4227
|
|
|
} |
|
4228
|
|
|
|
|
4229
|
|
|
// Here, $url is a simple link |
|
4230
|
|
|
|
|
4231
|
|
|
if (!empty($params['isDropdown'])) { |
|
4232
|
|
|
$class = "dropdown-item"; |
|
4233
|
|
|
} else { |
|
4234
|
|
|
$class = 'butAction'; |
|
4235
|
|
|
if ($actionType == 'danger' || $actionType == 'delete') { |
|
4236
|
|
|
$class = 'butActionDelete'; |
|
4237
|
|
|
if (!empty($url) && strpos($url, 'token=') === false) { |
|
4238
|
|
|
$url .= '&token=' . newToken(); |
|
4239
|
|
|
} |
|
4240
|
|
|
} |
|
4241
|
|
|
} |
|
4242
|
|
|
$attr = array( |
|
4243
|
|
|
'class' => $class, |
|
4244
|
|
|
'href' => empty($url) ? '' : $url, |
|
4245
|
|
|
'title' => $label |
|
4246
|
|
|
); |
|
4247
|
|
|
|
|
4248
|
|
|
if (empty($text)) { |
|
4249
|
|
|
$text = $label; |
|
4250
|
|
|
$attr['title'] = ''; // if html not set, leave label on title is redundant |
|
4251
|
|
|
} else { |
|
4252
|
|
|
$attr['title'] = $label; |
|
4253
|
|
|
$attr['aria-label'] = $label; |
|
4254
|
|
|
} |
|
4255
|
|
|
|
|
4256
|
|
|
if (empty($userRight)) { |
|
4257
|
|
|
$attr['class'] = 'butActionRefused'; |
|
4258
|
|
|
$attr['href'] = ''; |
|
4259
|
|
|
$attr['title'] = (($label && $text && $label != $text) ? $label : $langs->trans('NotEnoughPermissions')); |
|
4260
|
|
|
} |
|
4261
|
|
|
|
|
4262
|
|
|
if (!empty($id)) { |
|
4263
|
|
|
$attr['id'] = $id; |
|
4264
|
|
|
} |
|
4265
|
|
|
|
|
4266
|
|
|
// Override attr |
|
4267
|
|
|
if (!empty($params['attr']) && is_array($params['attr'])) { |
|
4268
|
|
|
foreach ($params['attr'] as $key => $value) { |
|
4269
|
|
|
if ($key == 'class') { |
|
4270
|
|
|
$attr['class'] .= ' ' . $value; |
|
4271
|
|
|
} elseif ($key == 'classOverride') { |
|
4272
|
|
|
$attr['class'] = $value; |
|
4273
|
|
|
} else { |
|
4274
|
|
|
$attr[$key] = $value; |
|
4275
|
|
|
} |
|
4276
|
|
|
} |
|
4277
|
|
|
} |
|
4278
|
|
|
|
|
4279
|
|
|
// automatic add tooltip when title is detected |
|
4280
|
|
|
if (!empty($attr['title']) && !empty($attr['class']) && strpos($attr['class'], 'classfortooltip') === false) { |
|
4281
|
|
|
$attr['class'] .= ' classfortooltip'; |
|
4282
|
|
|
} |
|
4283
|
|
|
|
|
4284
|
|
|
// Js Confirm button |
|
4285
|
|
|
if ($userRight && !empty($params['confirm'])) { |
|
4286
|
|
|
if (!is_array($params['confirm'])) { |
|
4287
|
|
|
$params['confirm'] = array(); |
|
4288
|
|
|
} |
|
4289
|
|
|
|
|
4290
|
|
|
if (empty($params['confirm']['url'])) { |
|
4291
|
|
|
$params['confirm']['url'] = $url . (strpos($url, '?') > 0 ? '&' : '?') . 'confirm=yes'; |
|
4292
|
|
|
} |
|
4293
|
|
|
|
|
4294
|
|
|
// for js disabled compatibility set $url as call to confirm action and $params['confirm']['url'] to confirmed action |
|
4295
|
|
|
$attr['data-confirm-url'] = $params['confirm']['url']; |
|
4296
|
|
|
$attr['data-confirm-title'] = !empty($params['confirm']['title']) ? $params['confirm']['title'] : $langs->trans('ConfirmBtnCommonTitle', $label); |
|
4297
|
|
|
$attr['data-confirm-content'] = !empty($params['confirm']['content']) ? $params['confirm']['content'] : $langs->trans('ConfirmBtnCommonContent', $label); |
|
4298
|
|
|
$attr['data-confirm-content'] = preg_replace("/\r|\n/", "", $attr['data-confirm-content']); |
|
4299
|
|
|
$attr['data-confirm-action-btn-label'] = !empty($params['confirm']['action-btn-label']) ? $params['confirm']['action-btn-label'] : $langs->trans('Confirm'); |
|
4300
|
|
|
$attr['data-confirm-cancel-btn-label'] = !empty($params['confirm']['cancel-btn-label']) ? $params['confirm']['cancel-btn-label'] : $langs->trans('CloseDialog'); |
|
4301
|
|
|
$attr['data-confirm-modal'] = !empty($params['confirm']['modal']) ? $params['confirm']['modal'] : true; |
|
4302
|
|
|
|
|
4303
|
|
|
$attr['class'] .= ' butActionConfirm'; |
|
4304
|
|
|
} |
|
4305
|
|
|
|
|
4306
|
|
|
if (isset($attr['href']) && empty($attr['href'])) { |
|
4307
|
|
|
unset($attr['href']); |
|
4308
|
|
|
} |
|
4309
|
|
|
|
|
4310
|
|
|
// escape all attribute |
|
4311
|
|
|
$attr = array_map('dol_escape_htmltag', $attr); |
|
4312
|
|
|
|
|
4313
|
|
|
$TCompiledAttr = array(); |
|
4314
|
|
|
foreach ($attr as $key => $value) { |
|
4315
|
|
|
$TCompiledAttr[] = $key . '= "' . $value . '"'; |
|
4316
|
|
|
} |
|
4317
|
|
|
|
|
4318
|
|
|
$compiledAttributes = empty($TCompiledAttr) ? '' : implode(' ', $TCompiledAttr); |
|
4319
|
|
|
|
|
4320
|
|
|
$tag = !empty($attr['href']) ? 'a' : 'span'; |
|
4321
|
|
|
|
|
4322
|
|
|
|
|
4323
|
|
|
$parameters = array( |
|
4324
|
|
|
'TCompiledAttr' => $TCompiledAttr, // array |
|
4325
|
|
|
'compiledAttributes' => $compiledAttributes, // string |
|
4326
|
|
|
'attr' => $attr, |
|
4327
|
|
|
'tag' => $tag, |
|
4328
|
|
|
'label' => $label, |
|
4329
|
|
|
'html' => $text, |
|
4330
|
|
|
'actionType' => $actionType, |
|
4331
|
|
|
'url' => $url, |
|
4332
|
|
|
'id' => $id, |
|
4333
|
|
|
'userRight' => $userRight, |
|
4334
|
|
|
'params' => $params |
|
4335
|
|
|
); |
|
4336
|
|
|
|
|
4337
|
|
|
$reshook = $hookmanager->executeHooks('dolGetButtonAction', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks |
|
4338
|
|
|
if ($reshook < 0) { |
|
4339
|
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); |
|
4340
|
|
|
} |
|
4341
|
|
|
|
|
4342
|
|
|
if (empty($reshook)) { |
|
4343
|
|
|
if (dol_textishtml($text)) { // If content already HTML encoded |
|
4344
|
|
|
return '<' . $tag . ' ' . $compiledAttributes . '>' . $text . '</' . $tag . '>'; |
|
4345
|
|
|
} else { |
|
4346
|
|
|
return '<' . $tag . ' ' . $compiledAttributes . '>' . dol_escape_htmltag($text) . '</' . $tag . '>'; |
|
4347
|
|
|
} |
|
4348
|
|
|
} else { |
|
4349
|
|
|
return $hookmanager->resPrint; |
|
4350
|
|
|
} |
|
4351
|
|
|
} |
|
4352
|
|
|
|
|
4353
|
|
|
|
|
4354
|
|
|
/** |
|
4355
|
|
|
* Return string with full Url. The file qualified is the one defined by relative path in $object->last_main_doc |
|
4356
|
|
|
* |
|
4357
|
|
|
* @param CommonObject $object Object |
|
4358
|
|
|
* @return string Url string |
|
4359
|
|
|
*/ |
|
4360
|
|
|
function showDirectDownloadLink($object) |
|
4361
|
|
|
{ |
|
4362
|
|
|
global $conf, $langs; |
|
4363
|
|
|
|
|
4364
|
|
|
$out = ''; |
|
4365
|
|
|
$url = $object->getLastMainDocLink($object->element); |
|
4366
|
|
|
|
|
4367
|
|
|
$out .= img_picto($langs->trans("PublicDownloadLinkDesc"), 'globe') . ' <span class="opacitymedium">' . $langs->trans("DirectDownloadLink") . '</span><br>'; |
|
4368
|
|
|
if ($url) { |
|
4369
|
|
|
$out .= '<div class="urllink"><input type="text" id="directdownloadlink" class="quatrevingtpercent" value="' . $url . '"></div>'; |
|
4370
|
|
|
$out .= ajax_autoselect("directdownloadlink", 0); |
|
4371
|
|
|
} else { |
|
4372
|
|
|
$out .= '<div class="urllink">' . $langs->trans("FileNotShared") . '</div>'; |
|
4373
|
|
|
} |
|
4374
|
|
|
|
|
4375
|
|
|
return $out; |
|
4376
|
|
|
} |
|
4377
|
|
|
|
|
4378
|
|
|
/** |
|
4379
|
|
|
* Set focus onto field with selector (similar behaviour of 'autofocus' HTML5 tag) |
|
4380
|
|
|
* |
|
4381
|
|
|
* @param string $selector Selector ('#id' or 'input[name="ref"]') to use to find the HTML input field that must get the autofocus. You must use a CSS selector, so unique id preceding with the '#' char. |
|
4382
|
|
|
* @return void |
|
4383
|
|
|
*/ |
|
4384
|
|
|
function dol_set_focus($selector) |
|
4385
|
|
|
{ |
|
4386
|
|
|
print "\n" . '<!-- Set focus onto a specific field -->' . "\n"; |
|
4387
|
|
|
print '<script nonce="' . getNonce() . '">jQuery(document).ready(function() { jQuery("' . dol_escape_js($selector) . '").focus(); });</script>' . "\n"; |
|
4388
|
|
|
} |
|
4389
|
|
|
|
|
4390
|
|
|
|
|
4391
|
|
|
/** |
|
4392
|
|
|
* Complete or removed entries into a head array (used to build tabs). |
|
4393
|
|
|
* For example, with value added by external modules. Such values are declared into $conf->modules_parts['tab']. |
|
4394
|
|
|
* Or by change using hook completeTabsHead |
|
4395
|
|
|
* |
|
4396
|
|
|
* @param Conf $conf Object conf |
|
4397
|
|
|
* @param Translate $langs Object langs |
|
4398
|
|
|
* @param object|null $object Object object |
|
4399
|
|
|
* @param array<array<int,string>> $head List of head tabs (updated by this function) |
|
4400
|
|
|
* @param int $h New position to fill (updated by this function) |
|
4401
|
|
|
* @param string $type Value for object where objectvalue can be |
|
4402
|
|
|
* 'thirdparty' to add a tab in third party view |
|
4403
|
|
|
* 'intervention' to add a tab in intervention view |
|
4404
|
|
|
* 'supplier_order' to add a tab in purchase order view |
|
4405
|
|
|
* 'supplier_invoice' to add a tab in purchase invoice view |
|
4406
|
|
|
* 'invoice' to add a tab in sales invoice view |
|
4407
|
|
|
* 'order' to add a tab in sales order view |
|
4408
|
|
|
* 'contract' to add a table in contract view |
|
4409
|
|
|
* 'product' to add a tab in product view |
|
4410
|
|
|
* 'propal' to add a tab in propal view |
|
4411
|
|
|
* 'user' to add a tab in user view |
|
4412
|
|
|
* 'group' to add a tab in group view |
|
4413
|
|
|
* 'member' to add a tab in foundation member view |
|
4414
|
|
|
* 'categories_x' to add a tab in category view ('x': type of category (0=product, 1=supplier, 2=customer, 3=member) |
|
4415
|
|
|
* 'ecm' to add a tab for another ecm view |
|
4416
|
|
|
* 'stock' to add a tab for warehouse view |
|
4417
|
|
|
* @param string $mode 'add' to complete head, 'remove' to remove entries |
|
4418
|
|
|
* @param string $filterorigmodule Filter on module origin: 'external' will show only external modules. 'core' only core modules. No filter (default) will add both. |
|
4419
|
|
|
* @return void |
|
4420
|
|
|
*/ |
|
4421
|
|
|
function complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode = 'add', $filterorigmodule = '') |
|
4422
|
|
|
{ |
|
4423
|
|
|
global $hookmanager, $db; |
|
4424
|
|
|
|
|
4425
|
|
|
if (isset($conf->modules_parts['tabs'][$type]) && is_array($conf->modules_parts['tabs'][$type])) { |
|
4426
|
|
|
foreach ($conf->modules_parts['tabs'][$type] as $value) { |
|
4427
|
|
|
$values = explode(':', $value); |
|
4428
|
|
|
|
|
4429
|
|
|
$reg = array(); |
|
4430
|
|
|
if ($mode == 'add' && !preg_match('/^\-/', $values[1])) { |
|
4431
|
|
|
$newtab = array(); |
|
4432
|
|
|
$postab = $h; |
|
4433
|
|
|
// detect if position set in $values[1] ie : +(2)mytab@mymodule (first tab is 0, second is one, ...) |
|
4434
|
|
|
$str = $values[1]; |
|
4435
|
|
|
$posstart = strpos($str, '('); |
|
4436
|
|
|
if ($posstart > 0) { |
|
4437
|
|
|
$posend = strpos($str, ')'); |
|
4438
|
|
|
if ($posstart > 0) { |
|
4439
|
|
|
$res1 = substr($str, $posstart + 1, $posend - $posstart - 1); |
|
4440
|
|
|
if (is_numeric($res1)) { |
|
4441
|
|
|
$postab = (int)$res1; |
|
4442
|
|
|
$values[1] = '+' . substr($str, $posend + 1); |
|
4443
|
|
|
} |
|
4444
|
|
|
} |
|
4445
|
|
|
} |
|
4446
|
|
|
if (count($values) == 6) { |
|
4447
|
|
|
// new declaration with permissions: |
|
4448
|
|
|
// $value='objecttype:+tabname1:Title1:langfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__' |
|
4449
|
|
|
// $value='objecttype:+tabname1:Title1,class,pathfile,method:langfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__' |
|
4450
|
|
|
if ($values[0] != $type) { |
|
4451
|
|
|
continue; |
|
4452
|
|
|
} |
|
4453
|
|
|
|
|
4454
|
|
|
if (verifCond($values[4], '2')) { |
|
4455
|
|
|
if ($values[3]) { |
|
4456
|
|
|
if ($filterorigmodule) { // If a filter of module origin has been requested |
|
4457
|
|
|
if (strpos($values[3], '@')) { // This is an external module |
|
4458
|
|
|
if ($filterorigmodule != 'external') { |
|
4459
|
|
|
continue; |
|
4460
|
|
|
} |
|
4461
|
|
|
} else { // This looks a core module |
|
4462
|
|
|
if ($filterorigmodule != 'core') { |
|
4463
|
|
|
continue; |
|
4464
|
|
|
} |
|
4465
|
|
|
} |
|
4466
|
|
|
} |
|
4467
|
|
|
$langs->load($values[3]); |
|
4468
|
|
|
} |
|
4469
|
|
|
if (preg_match('/SUBSTITUTION_([^_]+)/i', $values[2], $reg)) { |
|
4470
|
|
|
// If label is "SUBSTITUION_..." |
|
4471
|
|
|
$substitutionarray = array(); |
|
4472
|
|
|
complete_substitutions_array($substitutionarray, $langs, $object, array('needforkey' => $values[2])); |
|
4473
|
|
|
$label = make_substitutions($reg[1], $substitutionarray); |
|
4474
|
|
|
} else { |
|
4475
|
|
|
// If label is "Label,Class,File,Method", we call the method to show content inside the badge |
|
4476
|
|
|
$labeltemp = explode(',', $values[2]); |
|
4477
|
|
|
$label = $langs->trans($labeltemp[0]); |
|
4478
|
|
|
|
|
4479
|
|
|
if (!empty($labeltemp[1]) && is_object($object) && !empty($object->id)) { |
|
4480
|
|
|
dol_include_once($labeltemp[2]); |
|
4481
|
|
|
$classtoload = $labeltemp[1]; |
|
4482
|
|
|
if (class_exists($classtoload)) { |
|
4483
|
|
|
$obj = new $classtoload($db); |
|
4484
|
|
|
$function = $labeltemp[3]; |
|
4485
|
|
|
if ($obj && $function && method_exists($obj, $function)) { |
|
4486
|
|
|
// @phan-suppress-next-line PhanPluginUnknownObjectMethodCall |
|
4487
|
|
|
$nbrec = $obj->$function($object->id, $obj); |
|
4488
|
|
|
if (!empty($nbrec)) { |
|
4489
|
|
|
$label .= '<span class="badge marginleftonlyshort">' . $nbrec . '</span>'; |
|
4490
|
|
|
} |
|
4491
|
|
|
} |
|
4492
|
|
|
} |
|
4493
|
|
|
} |
|
4494
|
|
|
} |
|
4495
|
|
|
|
|
4496
|
|
|
$newtab[0] = dol_buildpath(preg_replace('/__ID__/i', ((is_object($object) && !empty($object->id)) ? $object->id : ''), $values[5]), 1); |
|
4497
|
|
|
$newtab[1] = $label; |
|
4498
|
|
|
$newtab[2] = str_replace('+', '', $values[1]); |
|
4499
|
|
|
$h++; |
|
4500
|
|
|
} else { |
|
4501
|
|
|
continue; |
|
4502
|
|
|
} |
|
4503
|
|
|
} elseif (count($values) == 5) { // case deprecated |
|
4504
|
|
|
dol_syslog('Passing 5 values in tabs module_parts is deprecated. Please update to 6 with permissions.', LOG_WARNING); |
|
4505
|
|
|
|
|
4506
|
|
|
if ($values[0] != $type) { |
|
4507
|
|
|
continue; |
|
4508
|
|
|
} |
|
4509
|
|
|
if ($values[3]) { |
|
4510
|
|
|
if ($filterorigmodule) { // If a filter of module origin has been requested |
|
4511
|
|
|
if (strpos($values[3], '@')) { // This is an external module |
|
4512
|
|
|
if ($filterorigmodule != 'external') { |
|
4513
|
|
|
continue; |
|
4514
|
|
|
} |
|
4515
|
|
|
} else { // This looks a core module |
|
4516
|
|
|
if ($filterorigmodule != 'core') { |
|
4517
|
|
|
continue; |
|
4518
|
|
|
} |
|
4519
|
|
|
} |
|
4520
|
|
|
} |
|
4521
|
|
|
$langs->load($values[3]); |
|
4522
|
|
|
} |
|
4523
|
|
|
if (preg_match('/SUBSTITUTION_([^_]+)/i', $values[2], $reg)) { |
|
4524
|
|
|
$substitutionarray = array(); |
|
4525
|
|
|
complete_substitutions_array($substitutionarray, $langs, $object, array('needforkey' => $values[2])); |
|
4526
|
|
|
$label = make_substitutions($reg[1], $substitutionarray); |
|
4527
|
|
|
} else { |
|
4528
|
|
|
$label = $langs->trans($values[2]); |
|
4529
|
|
|
} |
|
4530
|
|
|
|
|
4531
|
|
|
$newtab[0] = dol_buildpath(preg_replace('/__ID__/i', ((is_object($object) && !empty($object->id)) ? $object->id : ''), $values[4]), 1); |
|
4532
|
|
|
$newtab[1] = $label; |
|
4533
|
|
|
$newtab[2] = str_replace('+', '', $values[1]); |
|
4534
|
|
|
$h++; |
|
4535
|
|
|
} |
|
4536
|
|
|
// set tab at its position |
|
4537
|
|
|
$head = array_merge(array_slice($head, 0, $postab), array($newtab), array_slice($head, $postab)); |
|
4538
|
|
|
} elseif ($mode == 'remove' && preg_match('/^\-/', $values[1])) { |
|
4539
|
|
|
if ($values[0] != $type) { |
|
4540
|
|
|
continue; |
|
4541
|
|
|
} |
|
4542
|
|
|
$tabname = str_replace('-', '', $values[1]); |
|
4543
|
|
|
foreach ($head as $key => $val) { |
|
4544
|
|
|
$condition = (!empty($values[3]) ? verifCond($values[3], '2') : 1); |
|
4545
|
|
|
//var_dump($key.' - '.$tabname.' - '.$head[$key][2].' - '.$values[3].' - '.$condition); |
|
4546
|
|
|
if ($head[$key][2] == $tabname && $condition) { |
|
4547
|
|
|
unset($head[$key]); |
|
4548
|
|
|
break; |
|
4549
|
|
|
} |
|
4550
|
|
|
} |
|
4551
|
|
|
} |
|
4552
|
|
|
} |
|
4553
|
|
|
} |
|
4554
|
|
|
|
|
4555
|
|
|
// No need to make a return $head. Var is modified as a reference |
|
4556
|
|
|
if (!empty($hookmanager)) { |
|
4557
|
|
|
$parameters = array('object' => $object, 'mode' => $mode, 'head' => &$head, 'filterorigmodule' => $filterorigmodule); |
|
4558
|
|
|
$reshook = $hookmanager->executeHooks('completeTabsHead', $parameters, $object); |
|
4559
|
|
|
if ($reshook > 0) { // Hook ask to replace completely the array |
|
4560
|
|
|
$head = $hookmanager->resArray; |
|
4561
|
|
|
} else { // Hook |
|
4562
|
|
|
$head = array_merge($head, $hookmanager->resArray); |
|
4563
|
|
|
} |
|
4564
|
|
|
$h = count($head); |
|
4565
|
|
|
} |
|
4566
|
|
|
} |
|
4567
|
|
|
|
|
4568
|
|
|
/** |
|
4569
|
|
|
* Print common footer : |
|
4570
|
|
|
* conf->global->MAIN_HTML_FOOTER |
|
4571
|
|
|
* js for switch of menu hider |
|
4572
|
|
|
* js for conf->global->MAIN_GOOGLE_AN_ID |
|
4573
|
|
|
* js for conf->global->MAIN_SHOW_TUNING_INFO or $_SERVER["MAIN_SHOW_TUNING_INFO"] |
|
4574
|
|
|
* js for conf->logbuffer |
|
4575
|
|
|
* |
|
4576
|
|
|
* @param string $zone 'private' (for private pages) or 'public' (for public pages) |
|
4577
|
|
|
* @return void |
|
4578
|
|
|
*/ |
|
4579
|
|
|
function printCommonFooter($zone = 'private') |
|
4580
|
|
|
{ |
|
4581
|
|
|
global $conf, $hookmanager, $user, $debugbar; |
|
4582
|
|
|
global $action; |
|
4583
|
|
|
global $micro_start_time; |
|
4584
|
|
|
|
|
4585
|
|
|
if ($zone == 'private') { |
|
4586
|
|
|
print "\n" . '<!-- Common footer for private page -->' . "\n"; |
|
4587
|
|
|
} else { |
|
4588
|
|
|
print "\n" . '<!-- Common footer for public page -->' . "\n"; |
|
4589
|
|
|
} |
|
4590
|
|
|
|
|
4591
|
|
|
// A div to store page_y POST parameter so we can read it using javascript |
|
4592
|
|
|
print "\n<!-- A div to store page_y POST parameter -->\n"; |
|
4593
|
|
|
print '<div id="page_y" style="display: none;">' . (GETPOST('page_y') ? GETPOST('page_y') : '') . '</div>' . "\n"; |
|
4594
|
|
|
|
|
4595
|
|
|
$parameters = array(); |
|
4596
|
|
|
$reshook = $hookmanager->executeHooks('printCommonFooter', $parameters); // Note that $action and $object may have been modified by some hooks |
|
4597
|
|
|
if (empty($reshook)) { |
|
4598
|
|
|
if (getDolGlobalString('MAIN_HTML_FOOTER')) { |
|
4599
|
|
|
print getDolGlobalString('MAIN_HTML_FOOTER') . "\n"; |
|
4600
|
|
|
} |
|
4601
|
|
|
|
|
4602
|
|
|
print "\n"; |
|
4603
|
|
|
if (!empty($conf->use_javascript_ajax)) { |
|
4604
|
|
|
print "\n<!-- A script section to add menuhider handler on backoffice, manage focus and mandatory fields, tuning info, ... -->\n"; |
|
4605
|
|
|
print '<script>' . "\n"; |
|
4606
|
|
|
print 'jQuery(document).ready(function() {' . "\n"; |
|
4607
|
|
|
|
|
4608
|
|
|
if ($zone == 'private' && empty($conf->dol_use_jmobile)) { |
|
4609
|
|
|
print "\n"; |
|
4610
|
|
|
print '/* JS CODE TO ENABLE to manage handler to switch left menu page (menuhider) */' . "\n"; |
|
4611
|
|
|
print 'jQuery("li.menuhider").click(function(event) {'; |
|
4612
|
|
|
print ' if (!$( "body" ).hasClass( "sidebar-collapse" )){ event.preventDefault(); }' . "\n"; |
|
4613
|
|
|
print ' console.log("We click on .menuhider");' . "\n"; |
|
4614
|
|
|
print ' $("body").toggleClass("sidebar-collapse")' . "\n"; |
|
4615
|
|
|
print '});' . "\n"; |
|
4616
|
|
|
} |
|
4617
|
|
|
|
|
4618
|
|
|
// Management of focus and mandatory for fields |
|
4619
|
|
|
if ($action == 'create' || $action == 'edit' || (empty($action) && (preg_match('/new\.php/', $_SERVER["PHP_SELF"]))) || ((empty($action) || $action == 'addline') && (preg_match('/card\.php/', $_SERVER["PHP_SELF"])))) { |
|
4620
|
|
|
print '/* JS CODE TO ENABLE to manage focus and mandatory form fields */' . "\n"; |
|
4621
|
|
|
$relativepathstring = $_SERVER["PHP_SELF"]; |
|
4622
|
|
|
// Clean $relativepathstring |
|
4623
|
|
|
if (constant('DOL_URL_ROOT')) { |
|
4624
|
|
|
$relativepathstring = preg_replace('/^' . preg_quote(constant('DOL_URL_ROOT'), '/') . '/', '', $relativepathstring); |
|
4625
|
|
|
} |
|
4626
|
|
|
$relativepathstring = preg_replace('/^\//', '', $relativepathstring); |
|
4627
|
|
|
$relativepathstring = preg_replace('/^custom\//', '', $relativepathstring); |
|
4628
|
|
|
//$tmpqueryarraywehave = explode('&', dol_string_nohtmltag($_SERVER['QUERY_STRING'])); |
|
4629
|
|
|
if (!empty($user->default_values[$relativepathstring]['focus'])) { |
|
4630
|
|
|
foreach ($user->default_values[$relativepathstring]['focus'] as $defkey => $defval) { |
|
4631
|
|
|
$qualified = 0; |
|
4632
|
|
|
if ($defkey != '_noquery_') { |
|
4633
|
|
|
$tmpqueryarraytohave = explode('&', $defkey); |
|
4634
|
|
|
$foundintru = 0; |
|
4635
|
|
|
foreach ($tmpqueryarraytohave as $tmpquerytohave) { |
|
4636
|
|
|
$tmpquerytohaveparam = explode('=', $tmpquerytohave); |
|
4637
|
|
|
//print "console.log('".$tmpquerytohaveparam[0]." ".$tmpquerytohaveparam[1]." ".GETPOST($tmpquerytohaveparam[0])."');"; |
|
4638
|
|
|
if (!GETPOSTISSET($tmpquerytohaveparam[0]) || ($tmpquerytohaveparam[1] != GETPOST($tmpquerytohaveparam[0]))) { |
|
4639
|
|
|
$foundintru = 1; |
|
4640
|
|
|
} |
|
4641
|
|
|
} |
|
4642
|
|
|
if (!$foundintru) { |
|
4643
|
|
|
$qualified = 1; |
|
4644
|
|
|
} |
|
4645
|
|
|
//var_dump($defkey.'-'.$qualified); |
|
4646
|
|
|
} else { |
|
4647
|
|
|
$qualified = 1; |
|
4648
|
|
|
} |
|
4649
|
|
|
|
|
4650
|
|
|
if ($qualified) { |
|
4651
|
|
|
foreach ($defval as $paramkey => $paramval) { |
|
4652
|
|
|
// Set focus on field |
|
4653
|
|
|
print 'jQuery("input[name=\'' . $paramkey . '\']").focus();' . "\n"; |
|
4654
|
|
|
print 'jQuery("textarea[name=\'' . $paramkey . '\']").focus();' . "\n"; |
|
4655
|
|
|
print 'jQuery("select[name=\'' . $paramkey . '\']").focus();' . "\n"; // Not really useful, but we keep it in case of. |
|
4656
|
|
|
} |
|
4657
|
|
|
} |
|
4658
|
|
|
} |
|
4659
|
|
|
} |
|
4660
|
|
|
if (!empty($user->default_values[$relativepathstring]['mandatory'])) { |
|
4661
|
|
|
foreach ($user->default_values[$relativepathstring]['mandatory'] as $defkey => $defval) { |
|
4662
|
|
|
$qualified = 0; |
|
4663
|
|
|
if ($defkey != '_noquery_') { |
|
4664
|
|
|
$tmpqueryarraytohave = explode('&', $defkey); |
|
4665
|
|
|
$foundintru = 0; |
|
4666
|
|
|
foreach ($tmpqueryarraytohave as $tmpquerytohave) { |
|
4667
|
|
|
$tmpquerytohaveparam = explode('=', $tmpquerytohave); |
|
4668
|
|
|
//print "console.log('".$tmpquerytohaveparam[0]." ".$tmpquerytohaveparam[1]." ".GETPOST($tmpquerytohaveparam[0])."');"; |
|
4669
|
|
|
if (!GETPOSTISSET($tmpquerytohaveparam[0]) || ($tmpquerytohaveparam[1] != GETPOST($tmpquerytohaveparam[0]))) { |
|
4670
|
|
|
$foundintru = 1; |
|
4671
|
|
|
} |
|
4672
|
|
|
} |
|
4673
|
|
|
if (!$foundintru) { |
|
4674
|
|
|
$qualified = 1; |
|
4675
|
|
|
} |
|
4676
|
|
|
//var_dump($defkey.'-'.$qualified); |
|
4677
|
|
|
} else { |
|
4678
|
|
|
$qualified = 1; |
|
4679
|
|
|
} |
|
4680
|
|
|
|
|
4681
|
|
|
if ($qualified) { |
|
4682
|
|
|
foreach ($defval as $paramkey => $paramval) { |
|
4683
|
|
|
// Add property 'required' on input |
|
4684
|
|
|
print 'jQuery("input[name=\'' . $paramkey . '\']").prop(\'required\',true);' . "\n"; |
|
4685
|
|
|
print 'jQuery("textarea[name=\'' . $paramkey . '\']").prop(\'required\',true);' . "\n"; |
|
4686
|
|
|
print '// required on a select works only if key is "", so we add the required attributes but also we reset the key -1 or 0 to an empty string' . "\n"; |
|
4687
|
|
|
print 'jQuery("select[name=\'' . $paramkey . '\']").prop(\'required\',true);' . "\n"; |
|
4688
|
|
|
print 'jQuery("select[name=\'' . $paramkey . '\'] option[value=\'-1\']").prop(\'value\', \'\');' . "\n"; |
|
4689
|
|
|
print 'jQuery("select[name=\'' . $paramkey . '\'] option[value=\'0\']").prop(\'value\', \'\');' . "\n"; |
|
4690
|
|
|
|
|
4691
|
|
|
// Add 'field required' class on closest td for all input elements : input, textarea and select |
|
4692
|
|
|
print 'jQuery(":input[name=\'' . $paramkey . '\']").closest("tr").find("td:first").addClass("fieldrequired");' . "\n"; |
|
4693
|
|
|
} |
|
4694
|
|
|
// If we submit the cancel button we remove the required attributes |
|
4695
|
|
|
print 'jQuery("input[name=\'cancel\']").click(function() { |
|
4696
|
|
|
console.log("We click on cancel button so removed all required attribute"); |
|
4697
|
|
|
jQuery("input, textarea, select").each(function(){this.removeAttribute(\'required\');}); |
|
4698
|
|
|
});' . "\n"; |
|
4699
|
|
|
} |
|
4700
|
|
|
} |
|
4701
|
|
|
} |
|
4702
|
|
|
} |
|
4703
|
|
|
|
|
4704
|
|
|
print '});' . "\n"; |
|
4705
|
|
|
|
|
4706
|
|
|
// End of tuning |
|
4707
|
|
|
if (!empty($_SERVER['MAIN_SHOW_TUNING_INFO']) || getDolGlobalString('MAIN_SHOW_TUNING_INFO')) { |
|
4708
|
|
|
print "\n"; |
|
4709
|
|
|
print "/* JS CODE TO ENABLE to add memory info */\n"; |
|
4710
|
|
|
print 'window.console && console.log("'; |
|
4711
|
|
|
if (getDolGlobalString('MEMCACHED_SERVER')) { |
|
4712
|
|
|
print 'MEMCACHED_SERVER=' . getDolGlobalString('MEMCACHED_SERVER') . ' - '; |
|
4713
|
|
|
} |
|
4714
|
|
|
print 'MAIN_OPTIMIZE_SPEED=' . getDolGlobalString('MAIN_OPTIMIZE_SPEED', 'off'); |
|
4715
|
|
|
if (!empty($micro_start_time)) { // Works only if MAIN_SHOW_TUNING_INFO is defined at $_SERVER level. Not in global variable. |
|
4716
|
|
|
$micro_end_time = microtime(true); |
|
4717
|
|
|
print ' - Build time: ' . ceil(1000 * ($micro_end_time - $micro_start_time)) . ' ms'; |
|
4718
|
|
|
} |
|
4719
|
|
|
|
|
4720
|
|
|
if (function_exists("memory_get_usage")) { |
|
4721
|
|
|
print ' - Mem: ' . memory_get_usage(); // Do not use true here, it seems it takes the peak amount |
|
4722
|
|
|
} |
|
4723
|
|
|
if (function_exists("memory_get_peak_usage")) { |
|
4724
|
|
|
print ' - Real mem peak: ' . memory_get_peak_usage(true); |
|
4725
|
|
|
} |
|
4726
|
|
|
if (function_exists("zend_loader_file_encoded")) { |
|
4727
|
|
|
print ' - Zend encoded file: ' . (zend_loader_file_encoded() ? 'yes' : 'no'); |
|
4728
|
|
|
} |
|
4729
|
|
|
print '");' . "\n"; |
|
4730
|
|
|
} |
|
4731
|
|
|
|
|
4732
|
|
|
print "\n" . '</script>' . "\n"; |
|
4733
|
|
|
|
|
4734
|
|
|
// Google Analytics |
|
4735
|
|
|
// TODO Add a hook here |
|
4736
|
|
|
if (isModEnabled('google') && getDolGlobalString('MAIN_GOOGLE_AN_ID')) { |
|
4737
|
|
|
$tmptagarray = explode(',', getDolGlobalString('MAIN_GOOGLE_AN_ID')); |
|
4738
|
|
|
foreach ($tmptagarray as $tmptag) { |
|
4739
|
|
|
print "\n"; |
|
4740
|
|
|
print "<!-- JS CODE TO ENABLE for google analtics tag -->\n"; |
|
4741
|
|
|
print ' |
|
4742
|
|
|
<!-- Global site tag (gtag.js) - Google Analytics --> |
|
4743
|
|
|
<script nonce="' . getNonce() . '" async src="https://www.googletagmanager.com/gtag/js?id=' . trim($tmptag) . '"></script> |
|
4744
|
|
|
<script> |
|
4745
|
|
|
window.dataLayer = window.dataLayer || []; |
|
4746
|
|
|
function gtag(){dataLayer.push(arguments);} |
|
4747
|
|
|
gtag(\'js\', new Date()); |
|
4748
|
|
|
|
|
4749
|
|
|
gtag(\'config\', \'' . trim($tmptag) . '\'); |
|
4750
|
|
|
</script>'; |
|
4751
|
|
|
print "\n"; |
|
4752
|
|
|
} |
|
4753
|
|
|
} |
|
4754
|
|
|
} |
|
4755
|
|
|
|
|
4756
|
|
|
// Add Xdebug coverage of code |
|
4757
|
|
|
if (defined('XDEBUGCOVERAGE')) { |
|
4758
|
|
|
print_r(xdebug_get_code_coverage()); |
|
4759
|
|
|
} |
|
4760
|
|
|
|
|
4761
|
|
|
// Add DebugBar data |
|
4762
|
|
|
if ($user->hasRight('debugbar', 'read') && $debugbar instanceof DebugBar\DebugBar) { |
|
4763
|
|
|
if (isset($debugbar['time'])) { |
|
4764
|
|
|
// @phan-suppress-next-line PhanPluginUnknownObjectMethodCall |
|
4765
|
|
|
$debugbar['time']->stopMeasure('pageaftermaster'); |
|
|
|
|
|
|
4766
|
|
|
} |
|
4767
|
|
|
print '<!-- Output debugbar data -->' . "\n"; |
|
4768
|
|
|
$renderer = $debugbar->getJavascriptRenderer(); |
|
4769
|
|
|
print $renderer->render(); |
|
4770
|
|
|
} elseif (count($conf->logbuffer)) { // If there is some logs in buffer to show |
|
4771
|
|
|
print "\n"; |
|
4772
|
|
|
print "<!-- Start of log output\n"; |
|
4773
|
|
|
//print '<div class="hidden">'."\n"; |
|
4774
|
|
|
foreach ($conf->logbuffer as $logline) { |
|
4775
|
|
|
print $logline . "<br>\n"; |
|
4776
|
|
|
} |
|
4777
|
|
|
//print '</div>'."\n"; |
|
4778
|
|
|
print "End of log output -->\n"; |
|
4779
|
|
|
} |
|
4780
|
|
|
} |
|
4781
|
|
|
} |
|
4782
|
|
|
|
|
4783
|
|
|
/** |
|
4784
|
|
|
* Print formatted messages to output (Used to show messages on html output). |
|
4785
|
|
|
* Note: Calling dol_htmloutput_events is done into pages by standard ViewMain::llxFooter() function, so there is |
|
4786
|
|
|
* no need to call it explicitly. |
|
4787
|
|
|
* |
|
4788
|
|
|
* @param int $disabledoutputofmessages Clear all messages stored into session without displaying them |
|
4789
|
|
|
* @return void |
|
4790
|
|
|
* @see dol_htmloutput_mesg() |
|
4791
|
|
|
*/ |
|
4792
|
|
|
function dol_htmloutput_events($disabledoutputofmessages = 0) |
|
4793
|
|
|
{ |
|
4794
|
|
|
// Show mesgs |
|
4795
|
|
|
if (isset($_SESSION['dol_events']['mesgs'])) { |
|
4796
|
|
|
if (empty($disabledoutputofmessages)) { |
|
4797
|
|
|
dol_htmloutput_mesg('', $_SESSION['dol_events']['mesgs']); |
|
4798
|
|
|
} |
|
4799
|
|
|
unset($_SESSION['dol_events']['mesgs']); |
|
4800
|
|
|
} |
|
4801
|
|
|
// Show errors |
|
4802
|
|
|
if (isset($_SESSION['dol_events']['errors'])) { |
|
4803
|
|
|
if (empty($disabledoutputofmessages)) { |
|
4804
|
|
|
dol_htmloutput_mesg('', $_SESSION['dol_events']['errors'], 'error'); |
|
4805
|
|
|
} |
|
4806
|
|
|
unset($_SESSION['dol_events']['errors']); |
|
4807
|
|
|
} |
|
4808
|
|
|
|
|
4809
|
|
|
// Show warnings |
|
4810
|
|
|
if (isset($_SESSION['dol_events']['warnings'])) { |
|
4811
|
|
|
if (empty($disabledoutputofmessages)) { |
|
4812
|
|
|
dol_htmloutput_mesg('', $_SESSION['dol_events']['warnings'], 'warning'); |
|
4813
|
|
|
} |
|
4814
|
|
|
unset($_SESSION['dol_events']['warnings']); |
|
4815
|
|
|
} |
|
4816
|
|
|
} |
|
4817
|
|
|
|
|
4818
|
|
|
/** |
|
4819
|
|
|
* Get formatted messages to output (Used to show messages on html output). |
|
4820
|
|
|
* This include also the translation of the message key. |
|
4821
|
|
|
* |
|
4822
|
|
|
* @param string $mesgstring Message string or message key |
|
4823
|
|
|
* @param string[] $mesgarray Array of message strings or message keys |
|
4824
|
|
|
* @param string $style Style of message output ('ok' or 'error') |
|
4825
|
|
|
* @param int $keepembedded Set to 1 in error message must be kept embedded into its html place (this disable jnotify) |
|
4826
|
|
|
* @return string Return html output |
|
4827
|
|
|
* |
|
4828
|
|
|
* @see dol_print_error() |
|
4829
|
|
|
* @see dol_htmloutput_errors() |
|
4830
|
|
|
* @see setEventMessages() |
|
4831
|
|
|
*/ |
|
4832
|
|
|
function get_htmloutput_mesg($mesgstring = '', $mesgarray = [], $style = 'ok', $keepembedded = 0) |
|
4833
|
|
|
{ |
|
4834
|
|
|
global $conf, $langs; |
|
4835
|
|
|
|
|
4836
|
|
|
$ret = 0; |
|
4837
|
|
|
$return = ''; |
|
4838
|
|
|
$out = ''; |
|
4839
|
|
|
$divstart = $divend = ''; |
|
4840
|
|
|
|
|
4841
|
|
|
// If inline message with no format, we add it. |
|
4842
|
|
|
if ((empty($conf->use_javascript_ajax) || getDolGlobalString('MAIN_DISABLE_JQUERY_JNOTIFY') || $keepembedded) && !preg_match('/<div class=".*">/i', $out)) { |
|
4843
|
|
|
$divstart = '<div class="' . $style . ' clearboth">'; |
|
4844
|
|
|
$divend = '</div>'; |
|
4845
|
|
|
} |
|
4846
|
|
|
|
|
4847
|
|
|
if ((is_array($mesgarray) && count($mesgarray)) || $mesgstring) { |
|
4848
|
|
|
$langs->load("errors"); |
|
4849
|
|
|
$out .= $divstart; |
|
4850
|
|
|
if (is_array($mesgarray) && count($mesgarray)) { |
|
4851
|
|
|
foreach ($mesgarray as $message) { |
|
4852
|
|
|
$ret++; |
|
4853
|
|
|
$out .= $langs->trans($message); |
|
4854
|
|
|
if ($ret < count($mesgarray)) { |
|
4855
|
|
|
$out .= "<br>\n"; |
|
4856
|
|
|
} |
|
4857
|
|
|
} |
|
4858
|
|
|
} |
|
4859
|
|
|
if ($mesgstring) { |
|
4860
|
|
|
$ret++; |
|
4861
|
|
|
$out .= $langs->trans($mesgstring); |
|
4862
|
|
|
} |
|
4863
|
|
|
$out .= $divend; |
|
4864
|
|
|
} |
|
4865
|
|
|
|
|
4866
|
|
|
if ($out) { |
|
4867
|
|
|
if (!empty($conf->use_javascript_ajax) && !getDolGlobalString('MAIN_DISABLE_JQUERY_JNOTIFY') && empty($keepembedded)) { |
|
4868
|
|
|
$return = '<script nonce="' . getNonce() . '"> |
|
4869
|
|
|
$(document).ready(function() { |
|
4870
|
|
|
var block = ' . (getDolGlobalString('MAIN_USE_JQUERY_BLOCKUI') ? "true" : "false") . ' |
|
4871
|
|
|
if (block) { |
|
4872
|
|
|
$.dolEventValid("","' . dol_escape_js($out) . '"); |
|
4873
|
|
|
} else { |
|
4874
|
|
|
/* jnotify(message, preset of message type, keepmessage) */ |
|
4875
|
|
|
$.jnotify("' . dol_escape_js($out) . '", |
|
4876
|
|
|
"' . ($style == "ok" ? 3000 : $style) . '", |
|
4877
|
|
|
' . ($style == "ok" ? "false" : "true") . ', |
|
4878
|
|
|
{ remove: function (){} } ); |
|
4879
|
|
|
} |
|
4880
|
|
|
}); |
|
4881
|
|
|
</script>'; |
|
4882
|
|
|
} else { |
|
4883
|
|
|
$return = $out; |
|
4884
|
|
|
} |
|
4885
|
|
|
} |
|
4886
|
|
|
|
|
4887
|
|
|
return $return; |
|
4888
|
|
|
} |
|
4889
|
|
|
|
|
4890
|
|
|
/** |
|
4891
|
|
|
* Get formatted error messages to output (Used to show messages on html output). |
|
4892
|
|
|
* |
|
4893
|
|
|
* @param string $mesgstring Error message |
|
4894
|
|
|
* @param string[] $mesgarray Error messages array |
|
4895
|
|
|
* @param int $keepembedded Set to 1 in error message must be kept embedded into its html place (this disable jnotify) |
|
4896
|
|
|
* @return string Return html output |
|
4897
|
|
|
* |
|
4898
|
|
|
* @see dol_print_error() |
|
4899
|
|
|
* @see dol_htmloutput_mesg() |
|
4900
|
|
|
*/ |
|
4901
|
|
|
function get_htmloutput_errors($mesgstring = '', $mesgarray = array(), $keepembedded = 0) |
|
4902
|
|
|
{ |
|
4903
|
|
|
return get_htmloutput_mesg($mesgstring, $mesgarray, 'error', $keepembedded); |
|
4904
|
|
|
} |
|
4905
|
|
|
|
|
4906
|
|
|
/** |
|
4907
|
|
|
* Print formatted messages to output (Used to show messages on html output). |
|
4908
|
|
|
* |
|
4909
|
|
|
* @param string $mesgstring Message string or message key |
|
4910
|
|
|
* @param string[] $mesgarray Array of message strings or message keys |
|
4911
|
|
|
* @param string $style Which style to use ('ok', 'warning', 'error') |
|
4912
|
|
|
* @param int $keepembedded Set to 1 if message must be kept embedded into its html place (this disable jnotify) |
|
4913
|
|
|
* @return void |
|
4914
|
|
|
* |
|
4915
|
|
|
* @see dol_print_error() |
|
4916
|
|
|
* @see dol_htmloutput_errors() |
|
4917
|
|
|
* @see setEventMessages() |
|
4918
|
|
|
*/ |
|
4919
|
|
|
function dol_htmloutput_mesg($mesgstring = '', $mesgarray = array(), $style = 'ok', $keepembedded = 0) |
|
4920
|
|
|
{ |
|
4921
|
|
|
if (empty($mesgstring) && (!is_array($mesgarray) || count($mesgarray) == 0)) { |
|
4922
|
|
|
return; |
|
4923
|
|
|
} |
|
4924
|
|
|
|
|
4925
|
|
|
$iserror = 0; |
|
4926
|
|
|
$iswarning = 0; |
|
4927
|
|
|
if (is_array($mesgarray)) { |
|
4928
|
|
|
foreach ($mesgarray as $val) { |
|
4929
|
|
|
if ($val && preg_match('/class="error"/i', $val)) { |
|
4930
|
|
|
$iserror++; |
|
4931
|
|
|
break; |
|
4932
|
|
|
} |
|
4933
|
|
|
if ($val && preg_match('/class="warning"/i', $val)) { |
|
4934
|
|
|
$iswarning++; |
|
4935
|
|
|
break; |
|
4936
|
|
|
} |
|
4937
|
|
|
} |
|
4938
|
|
|
} elseif ($mesgstring && preg_match('/class="error"/i', $mesgstring)) { |
|
4939
|
|
|
$iserror++; |
|
4940
|
|
|
} elseif ($mesgstring && preg_match('/class="warning"/i', $mesgstring)) { |
|
4941
|
|
|
$iswarning++; |
|
4942
|
|
|
} |
|
4943
|
|
|
if ($style == 'error') { |
|
4944
|
|
|
$iserror++; |
|
4945
|
|
|
} |
|
4946
|
|
|
if ($style == 'warning') { |
|
4947
|
|
|
$iswarning++; |
|
4948
|
|
|
} |
|
4949
|
|
|
|
|
4950
|
|
|
if ($iserror || $iswarning) { |
|
4951
|
|
|
// Remove div from texts |
|
4952
|
|
|
$mesgstring = preg_replace('/<\/div><div class="(error|warning)">/', '<br>', $mesgstring); |
|
4953
|
|
|
$mesgstring = preg_replace('/<div class="(error|warning)">/', '', $mesgstring); |
|
4954
|
|
|
$mesgstring = preg_replace('/<\/div>/', '', $mesgstring); |
|
4955
|
|
|
// Remove div from texts array |
|
4956
|
|
|
if (is_array($mesgarray)) { |
|
4957
|
|
|
$newmesgarray = array(); |
|
4958
|
|
|
foreach ($mesgarray as $val) { |
|
4959
|
|
|
if (is_string($val)) { |
|
4960
|
|
|
$tmpmesgstring = preg_replace('/<\/div><div class="(error|warning)">/', '<br>', $val); |
|
4961
|
|
|
$tmpmesgstring = preg_replace('/<div class="(error|warning)">/', '', $tmpmesgstring); |
|
4962
|
|
|
$tmpmesgstring = preg_replace('/<\/div>/', '', $tmpmesgstring); |
|
4963
|
|
|
$newmesgarray[] = $tmpmesgstring; |
|
4964
|
|
|
} else { |
|
4965
|
|
|
dol_syslog("Error call of dol_htmloutput_mesg with an array with a value that is not a string", LOG_WARNING); |
|
4966
|
|
|
} |
|
4967
|
|
|
} |
|
4968
|
|
|
$mesgarray = $newmesgarray; |
|
4969
|
|
|
} |
|
4970
|
|
|
print get_htmloutput_mesg($mesgstring, $mesgarray, ($iserror ? 'error' : 'warning'), $keepembedded); |
|
4971
|
|
|
} else { |
|
4972
|
|
|
print get_htmloutput_mesg($mesgstring, $mesgarray, 'ok', $keepembedded); |
|
4973
|
|
|
} |
|
4974
|
|
|
} |
|
4975
|
|
|
|
|
4976
|
|
|
/** |
|
4977
|
|
|
* Print formatted error messages to output (Used to show messages on html output). |
|
4978
|
|
|
* |
|
4979
|
|
|
* @param string $mesgstring Error message |
|
4980
|
|
|
* @param string[] $mesgarray Error messages array |
|
4981
|
|
|
* @param int<0,1> $keepembedded Set to 1 in error message must be kept embedded into its html place (this disable jnotify) |
|
4982
|
|
|
* @return void |
|
4983
|
|
|
* |
|
4984
|
|
|
* @see dol_print_error() |
|
4985
|
|
|
* @see dol_htmloutput_mesg() |
|
4986
|
|
|
*/ |
|
4987
|
|
|
function dol_htmloutput_errors($mesgstring = '', $mesgarray = array(), $keepembedded = 0) |
|
4988
|
|
|
{ |
|
4989
|
|
|
dol_htmloutput_mesg($mesgstring, $mesgarray, 'error', $keepembedded); |
|
4990
|
|
|
} |
|
4991
|
|
|
|
|
4992
|
|
|
/** |
|
4993
|
|
|
* Sanitize a HTML to remove js, dangerous content and external link. |
|
4994
|
|
|
* This function is used by dolPrintHTML... function for example. |
|
4995
|
|
|
* |
|
4996
|
|
|
* @param string $stringtoencode String to encode |
|
4997
|
|
|
* @param int $nouseofiframesandbox 0=Default, 1=Allow use of option MAIN_SECURITY_USE_SANDBOX_FOR_HTMLWITHNOJS for html sanitizing (not yet working) |
|
4998
|
|
|
* @param string $check 'restricthtmlnolink' or 'restricthtml' or 'restricthtmlallowclass' or 'restricthtmlallowunvalid' |
|
4999
|
|
|
* @return string HTML sanitized |
|
5000
|
|
|
*/ |
|
5001
|
|
|
function dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox = 0, $check = 'restricthtml') |
|
5002
|
|
|
{ |
|
5003
|
|
|
if (empty($nouseofiframesandbox) && getDolGlobalString('MAIN_SECURITY_USE_SANDBOX_FOR_HTMLWITHNOJS')) { |
|
5004
|
|
|
// TODO using sandbox on inline html content is not possible yet with current browsers |
|
5005
|
|
|
//$s = '<iframe class="iframewithsandbox" sandbox><html><body>'; |
|
5006
|
|
|
//$s .= $stringtoencode; |
|
5007
|
|
|
//$s .= '</body></html></iframe>'; |
|
5008
|
|
|
return $stringtoencode; |
|
5009
|
|
|
} else { |
|
5010
|
|
|
$out = $stringtoencode; |
|
5011
|
|
|
|
|
5012
|
|
|
do { |
|
5013
|
|
|
$oldstringtoclean = $out; |
|
5014
|
|
|
|
|
5015
|
|
|
if (!empty($out) && getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML') && $check != 'restricthtmlallowunvalid') { |
|
5016
|
|
|
try { |
|
5017
|
|
|
libxml_use_internal_errors(false); // Avoid to fill memory with xml errors |
|
5018
|
|
|
if (LIBXML_VERSION < 20900) { |
|
5019
|
|
|
// Avoid load of external entities (security problem). |
|
5020
|
|
|
// Required only if LIBXML_VERSION < 20900 |
|
5021
|
|
|
// @phan-suppress-next-line PhanDeprecatedFunctionInternal |
|
5022
|
|
|
libxml_disable_entity_loader(true); |
|
5023
|
|
|
} |
|
5024
|
|
|
|
|
5025
|
|
|
$dom = new DOMDocument(); |
|
5026
|
|
|
// Add a trick to solve pb with text without parent tag |
|
5027
|
|
|
// like '<h1>Foo</h1><p>bar</p>' that wrongly ends up, without the trick, with '<h1>Foo<p>bar</p></h1>' |
|
5028
|
|
|
// like 'abc' that wrongly ends up, without the trick, with '<p>abc</p>' |
|
5029
|
|
|
|
|
5030
|
|
|
if (dol_textishtml($out)) { |
|
5031
|
|
|
$out = '<?xml encoding="UTF-8"><div class="tricktoremove">' . $out . '</div>'; |
|
5032
|
|
|
} else { |
|
5033
|
|
|
$out = '<?xml encoding="UTF-8"><div class="tricktoremove">' . dol_nl2br($out) . '</div>'; |
|
5034
|
|
|
} |
|
5035
|
|
|
|
|
5036
|
|
|
$dom->loadHTML($out, LIBXML_HTML_NODEFDTD | LIBXML_ERR_NONE | LIBXML_HTML_NOIMPLIED | LIBXML_NONET | LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NOXMLDECL); |
|
5037
|
|
|
$out = trim($dom->saveHTML()); |
|
5038
|
|
|
|
|
5039
|
|
|
// Remove the trick added to solve pb with text without parent tag |
|
5040
|
|
|
$out = preg_replace('/^<\?xml encoding="UTF-8"><div class="tricktoremove">/', '', $out); |
|
5041
|
|
|
$out = preg_replace('/<\/div>$/', '', $out); |
|
5042
|
|
|
} catch (Exception $e) { |
|
5043
|
|
|
// If error, invalid HTML string with no way to clean it |
|
5044
|
|
|
//print $e->getMessage(); |
|
5045
|
|
|
$out = 'InvalidHTMLStringCantBeCleaned ' . $e->getMessage(); |
|
5046
|
|
|
} |
|
5047
|
|
|
} |
|
5048
|
|
|
|
|
5049
|
|
|
if (!empty($out) && getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY') && $check != 'restricthtmlallowunvalid') { |
|
5050
|
|
|
try { |
|
5051
|
|
|
// Try cleaning using tidy |
|
5052
|
|
|
if (extension_loaded('tidy') && class_exists("tidy")) { |
|
5053
|
|
|
//print "aaa".$out."\n"; |
|
5054
|
|
|
|
|
5055
|
|
|
// See options at https://tidy.sourceforge.net/docs/quickref.html |
|
5056
|
|
|
$config = array( |
|
5057
|
|
|
'clean' => false, |
|
5058
|
|
|
'quote-marks' => false, // do not replace " that are used for real text content (not a string symbol for html attribute) into " |
|
5059
|
|
|
'doctype' => 'strict', |
|
5060
|
|
|
'show-body-only' => true, |
|
5061
|
|
|
"indent-attributes" => false, |
|
5062
|
|
|
"vertical-space" => false, |
|
5063
|
|
|
//'ident' => false, // Not always supported |
|
5064
|
|
|
"wrap" => 0 |
|
5065
|
|
|
// HTML5 tags |
|
5066
|
|
|
//'new-blocklevel-tags' => 'article aside audio bdi canvas details dialog figcaption figure footer header hgroup main menu menuitem nav section source summary template track video', |
|
5067
|
|
|
//'new-blocklevel-tags' => 'footer header section menu menuitem' |
|
5068
|
|
|
//'new-empty-tags' => 'command embed keygen source track wbr', |
|
5069
|
|
|
//'new-inline-tags' => 'audio command datalist embed keygen mark menuitem meter output progress source time video wbr', |
|
5070
|
|
|
); |
|
5071
|
|
|
|
|
5072
|
|
|
// Tidy |
|
5073
|
|
|
$tidy = new tidy(); |
|
5074
|
|
|
$out = $tidy->repairString($out, $config, 'utf8'); |
|
5075
|
|
|
|
|
5076
|
|
|
//print "xxx".$out;exit; |
|
5077
|
|
|
} |
|
5078
|
|
|
} catch (Exception $e) { |
|
5079
|
|
|
// If error, invalid HTML string with no way to clean it |
|
5080
|
|
|
//print $e->getMessage(); |
|
5081
|
|
|
$out = 'InvalidHTMLStringCantBeCleaned ' . $e->getMessage(); |
|
5082
|
|
|
} |
|
5083
|
|
|
} |
|
5084
|
|
|
|
|
5085
|
|
|
// Clean some html entities that are useless so text is cleaner |
|
5086
|
|
|
$out = preg_replace('/&(tab|newline);/i', ' ', $out); |
|
5087
|
|
|
|
|
5088
|
|
|
// Ckeditor uses the numeric entity for apostrophe so we force it to text entity (all other special chars are |
|
5089
|
|
|
// encoded using text entities) so we can then exclude all numeric entities. |
|
5090
|
|
|
$out = preg_replace('/'/i', ''', $out); |
|
5091
|
|
|
|
|
5092
|
|
|
// We replace chars from a/A to z/Z encoded with numeric HTML entities with the real char so we won't loose the chars at the next step (preg_replace). |
|
5093
|
|
|
// No need to use a loop here, this step is not to sanitize (this is done at next step, this is to try to save chars, even if they are |
|
5094
|
|
|
// using a non conventionnal way to be encoded, to not have them sanitized just after) |
|
5095
|
|
|
$out = preg_replace_callback( |
|
5096
|
|
|
'/&#(x?[0-9][0-9a-f]+;?)/i', |
|
5097
|
|
|
/** |
|
5098
|
|
|
* @param string[] $m |
|
5099
|
|
|
* @return string |
|
5100
|
|
|
*/ |
|
5101
|
|
|
static function ($m) { |
|
5102
|
|
|
return Filters::realCharForNumericEntities($m); |
|
5103
|
|
|
}, |
|
5104
|
|
|
$out |
|
5105
|
|
|
); |
|
5106
|
|
|
|
|
5107
|
|
|
// Now we remove all remaining HTML entities starting with a number. We don't want such entities. |
|
5108
|
|
|
$out = preg_replace('/&#x?[0-9]+/i', '', $out); // For example if we have javascript with an entities without the ; to hide the 'a' of 'javascript'. |
|
5109
|
|
|
|
|
5110
|
|
|
// Keep only some html tags and remove also some 'javascript:' strings |
|
5111
|
|
|
$out = dol_string_onlythesehtmltags($out, 0, ($check == 'restricthtmlallowclass' ? 0 : 1), 1); |
|
5112
|
|
|
|
|
5113
|
|
|
// Keep only some html attributes and exclude non expected HTML attributes and clean content of some attributes (keep only alt=, title=...). |
|
5114
|
|
|
if (getDolGlobalString('MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES')) { |
|
5115
|
|
|
$out = dol_string_onlythesehtmlattributes($out); |
|
5116
|
|
|
} |
|
5117
|
|
|
|
|
5118
|
|
|
// Restore entity ' into ' (restricthtml is for html content so we can use html entity) |
|
5119
|
|
|
$out = preg_replace('/'/i', "'", $out); |
|
5120
|
|
|
} while ($oldstringtoclean != $out); |
|
5121
|
|
|
|
|
5122
|
|
|
// Check the limit of external links that are automatically executed in a Rich text content. We count: |
|
5123
|
|
|
// '<img' to avoid <img src="http...">, we can only accept "<img src="data:..." |
|
5124
|
|
|
// 'url(' to avoid inline style like background: url(http... |
|
5125
|
|
|
// '<link' to avoid <link href="http..."> |
|
5126
|
|
|
$reg = array(); |
|
5127
|
|
|
$tmpout = preg_replace('/<img src="data:/mi', '<__IMG_SRC_DATA__ src="data:', $out); |
|
5128
|
|
|
preg_match_all('/(<img|url\(|<link)/i', $tmpout, $reg); |
|
5129
|
|
|
$nblinks = count($reg[0]); |
|
5130
|
|
|
if ($nblinks > getDolGlobalInt("MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT", 1000)) { |
|
5131
|
|
|
$out = 'ErrorTooManyLinksIntoHTMLString'; |
|
5132
|
|
|
} |
|
5133
|
|
|
|
|
5134
|
|
|
if (getDolGlobalInt('MAIN_DISALLOW_URL_INTO_DESCRIPTIONS') == 2 || $check == 'restricthtmlnolink') { |
|
5135
|
|
|
if ($nblinks > 0) { |
|
5136
|
|
|
$out = 'ErrorHTMLLinksNotAllowed'; |
|
5137
|
|
|
} |
|
5138
|
|
|
} elseif (getDolGlobalInt('MAIN_DISALLOW_URL_INTO_DESCRIPTIONS') == 1) { |
|
5139
|
|
|
$nblinks = 0; |
|
5140
|
|
|
// Loop on each url in src= and url( |
|
5141
|
|
|
$pattern = '/src=["\']?(http[^"\']+)|url\(["\']?(http[^\)]+)/'; |
|
5142
|
|
|
|
|
5143
|
|
|
$matches = array(); |
|
5144
|
|
|
if (preg_match_all($pattern, $out, $matches)) { |
|
5145
|
|
|
// URLs are into $matches[1] |
|
5146
|
|
|
$urls = $matches[1]; |
|
5147
|
|
|
|
|
5148
|
|
|
// Affiche les URLs |
|
5149
|
|
|
foreach ($urls as $url) { |
|
5150
|
|
|
$nblinks++; |
|
5151
|
|
|
echo "Found url = " . $url . "\n"; |
|
5152
|
|
|
} |
|
5153
|
|
|
if ($nblinks > 0) { |
|
5154
|
|
|
$out = 'ErrorHTMLExternalLinksNotAllowed'; |
|
5155
|
|
|
} |
|
5156
|
|
|
} |
|
5157
|
|
|
} |
|
5158
|
|
|
|
|
5159
|
|
|
return $out; |
|
5160
|
|
|
} |
|
5161
|
|
|
} |
|
5162
|
|
|
|
|
5163
|
|
|
/** |
|
5164
|
|
|
* This function is called to encode a string into a HTML string but differs from htmlentities because |
|
5165
|
|
|
* a detection is done before to see if text is already HTML or not. Also, all entities but &,<,>," are converted. |
|
5166
|
|
|
* This permits to encode special chars to entities with no double encoding for already encoded HTML strings. |
|
5167
|
|
|
* This function also remove last EOL or BR if $removelasteolbr=1 (default). |
|
5168
|
|
|
* For PDF usage, you can show text by 2 ways: |
|
5169
|
|
|
* - writeHTMLCell -> param must be encoded into HTML. |
|
5170
|
|
|
* - MultiCell -> param must not be encoded into HTML. |
|
5171
|
|
|
* Because writeHTMLCell convert also \n into <br>, if function is used to build PDF, nl2brmode must be 1. |
|
5172
|
|
|
* Note: When we output string on pages, we should use |
|
5173
|
|
|
* - dolPrintHTML... that is dol_escape_htmltag(dol_htmlwithnojs(dol_string_onlythesehtmltags(dol_htmlentitiesbr(), 1, 1, 1), 1, 1) for notes or descriptions, |
|
5174
|
|
|
* - dolPrintPassword that is abelhtmlspecialchars( , ENT_COMPAT, 'UTF-8') for passwords. |
|
5175
|
|
|
* |
|
5176
|
|
|
* @param string $stringtoencode String to encode |
|
5177
|
|
|
* @param int $nl2brmode 0=Adding br before \n, 1=Replacing \n by br (for use with FPDF writeHTMLCell function for example) |
|
5178
|
|
|
* @param string $pagecodefrom Pagecode stringtoencode is encoded |
|
5179
|
|
|
* @param int $removelasteolbr 1=Remove last br or lasts \n (default), 0=Do nothing |
|
5180
|
|
|
* @return string String encoded |
|
5181
|
|
|
* @see dol_escape_htmltag(), dolGetFirstLineOfText(), dol_string_onlythesehtmltags() |
|
5182
|
|
|
*/ |
|
5183
|
|
|
function dol_htmlentitiesbr($stringtoencode, $nl2brmode = 0, $pagecodefrom = 'UTF-8', $removelasteolbr = 1) |
|
5184
|
|
|
{ |
|
5185
|
|
|
if (is_null($stringtoencode)) { |
|
5186
|
|
|
return ''; |
|
5187
|
|
|
} |
|
5188
|
|
|
|
|
5189
|
|
|
$newstring = $stringtoencode; |
|
5190
|
|
|
if (dol_textishtml($stringtoencode)) { // Check if text is already HTML or not |
|
5191
|
|
|
$newstring = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>/i', '<br>', $newstring); // Replace "<br type="_moz" />" by "<br>". It's same and avoid pb with FPDF. |
|
5192
|
|
|
if ($removelasteolbr) { |
|
5193
|
|
|
$newstring = preg_replace('/<br>$/i', '', $newstring); // Remove last <br> (remove only last one) |
|
5194
|
|
|
} |
|
5195
|
|
|
$newstring = strtr($newstring, array('&' => '__and__', '<' => '__lt__', '>' => '__gt__', '"' => '__dquot__')); |
|
5196
|
|
|
$newstring = dol_htmlentities($newstring, ENT_COMPAT, $pagecodefrom); // Make entity encoding |
|
5197
|
|
|
$newstring = strtr($newstring, array('__and__' => '&', '__lt__' => '<', '__gt__' => '>', '__dquot__' => '"')); |
|
5198
|
|
|
} else { |
|
5199
|
|
|
if ($removelasteolbr) { |
|
5200
|
|
|
$newstring = preg_replace('/(\r\n|\r|\n)$/i', '', $newstring); // Remove last \n (may remove several) |
|
5201
|
|
|
} |
|
5202
|
|
|
$newstring = dol_nl2br(dol_htmlentities($newstring, ENT_COMPAT, $pagecodefrom), $nl2brmode); |
|
5203
|
|
|
} |
|
5204
|
|
|
// Other substitutions that htmlentities does not do |
|
5205
|
|
|
//$newstring=str_replace(chr(128),'€',$newstring); // 128 = 0x80. Not in html entity table. // Seems useles with TCPDF. Make bug with UTF8 languages |
|
5206
|
|
|
return $newstring; |
|
5207
|
|
|
} |
|
5208
|
|
|
|
|
5209
|
|
|
/** |
|
5210
|
|
|
* This function is called to decode a HTML string (it decodes entities and br tags) |
|
5211
|
|
|
* |
|
5212
|
|
|
* @param string $stringtodecode String to decode |
|
5213
|
|
|
* @param string $pagecodeto Page code for result |
|
5214
|
|
|
* @return string String decoded |
|
5215
|
|
|
*/ |
|
5216
|
|
|
function dol_htmlentitiesbr_decode($stringtodecode, $pagecodeto = 'UTF-8') |
|
5217
|
|
|
{ |
|
5218
|
|
|
$ret = dol_html_entity_decode($stringtodecode, ENT_COMPAT | ENT_HTML5, $pagecodeto); |
|
5219
|
|
|
$ret = preg_replace('/' . "\r\n" . '<br(\s[\sa-zA-Z_="]*)?\/?>/i', "<br>", $ret); |
|
5220
|
|
|
$ret = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>' . "\r\n" . '/i', "\r\n", $ret); |
|
5221
|
|
|
$ret = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>' . "\n" . '/i', "\n", $ret); |
|
5222
|
|
|
$ret = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>/i', "\n", $ret); |
|
5223
|
|
|
return $ret; |
|
5224
|
|
|
} |
|
5225
|
|
|
|
|
5226
|
|
|
/** |
|
5227
|
|
|
* This function remove all ending \n and br at end |
|
5228
|
|
|
* |
|
5229
|
|
|
* @param string $stringtodecode String to decode |
|
5230
|
|
|
* @return string String decoded |
|
5231
|
|
|
*/ |
|
5232
|
|
|
function dol_htmlcleanlastbr($stringtodecode) |
|
5233
|
|
|
{ |
|
5234
|
|
|
$ret = preg_replace('/ $/i', "", $stringtodecode); // Because wysiwyg editor may add a at end of last line |
|
5235
|
|
|
$ret = preg_replace('/(<br>|<br(\s[\sa-zA-Z_="]*)?\/?>|' . "\n" . '|' . "\r" . ')+$/i', "", $ret); |
|
5236
|
|
|
return $ret; |
|
5237
|
|
|
} |
|
5238
|
|
|
|
|
5239
|
|
|
/** |
|
5240
|
|
|
* Replace html_entity_decode functions to manage errors |
|
5241
|
|
|
* |
|
5242
|
|
|
* @param string $a Operand a |
|
5243
|
|
|
* @param string $b Operand b (ENT_QUOTES|ENT_HTML5=convert simple, double quotes, colon, e accent, ...) |
|
5244
|
|
|
* @param string $c Operand c |
|
5245
|
|
|
* @param int $keepsomeentities Entities but &, <, >, " are not converted. |
|
5246
|
|
|
* @return string String decoded |
|
5247
|
|
|
*/ |
|
5248
|
|
|
function dol_html_entity_decode($a, $b, $c = 'UTF-8', $keepsomeentities = 0) |
|
5249
|
|
|
{ |
|
5250
|
|
|
$newstring = $a; |
|
5251
|
|
|
if ($keepsomeentities) { |
|
5252
|
|
|
$newstring = strtr($newstring, array('&' => '__andamp__', '<' => '__andlt__', '>' => '__andgt__', '"' => '__dquot__')); |
|
5253
|
|
|
} |
|
5254
|
|
|
$newstring = html_entity_decode((string)$newstring, (int)$b, (string)$c); |
|
5255
|
|
|
if ($keepsomeentities) { |
|
5256
|
|
|
$newstring = strtr($newstring, array('__andamp__' => '&', '__andlt__' => '<', '__andgt__' => '>', '__dquot__' => '"')); |
|
5257
|
|
|
} |
|
5258
|
|
|
return $newstring; |
|
5259
|
|
|
} |
|
5260
|
|
|
|
|
5261
|
|
|
/** |
|
5262
|
|
|
* Replace htmlentities functions. |
|
5263
|
|
|
* Goal of this function is to be sure to have default values of htmlentities that match what we need. |
|
5264
|
|
|
* |
|
5265
|
|
|
* @param string $string The input string to encode |
|
5266
|
|
|
* @param int $flags Flags (see PHP doc above) |
|
5267
|
|
|
* @param string $encoding Encoding page code |
|
5268
|
|
|
* @param bool $double_encode When double_encode is turned off, PHP will not encode existing html entities |
|
5269
|
|
|
* @return string $ret Encoded string |
|
5270
|
|
|
* @see dol_htmlentitiesbr() |
|
5271
|
|
|
*/ |
|
5272
|
|
|
function dol_htmlentities($string, $flags = ENT_QUOTES | ENT_SUBSTITUTE, $encoding = 'UTF-8', $double_encode = false) |
|
5273
|
|
|
{ |
|
5274
|
|
|
return htmlentities($string, $flags, $encoding, $double_encode); |
|
5275
|
|
|
} |
|
5276
|
|
|
|
|
5277
|
|
|
/** |
|
5278
|
|
|
* Clean a string from some undesirable HTML tags. |
|
5279
|
|
|
* Note: Complementary to dol_string_onlythesehtmltags(). |
|
5280
|
|
|
* This method is used for example by dol_htmlwithnojs() when option MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES is set to 1. |
|
5281
|
|
|
* |
|
5282
|
|
|
* @param string $stringtoclean String to clean |
|
5283
|
|
|
* @param string[] $allowed_attributes Array of tags not allowed |
|
5284
|
|
|
* @return string String cleaned |
|
5285
|
|
|
* |
|
5286
|
|
|
* @see dol_escape_htmltag() strip_tags() dol_string_nohtmltag() dol_string_onlythesehtmltags() dol_string_neverthesehtmltags() |
|
5287
|
|
|
* @phan-suppress PhanUndeclaredProperty |
|
5288
|
|
|
*/ |
|
5289
|
|
|
function dol_string_onlythesehtmlattributes($stringtoclean, $allowed_attributes = null) |
|
5290
|
|
|
{ |
|
5291
|
|
|
if (is_null($allowed_attributes)) { |
|
5292
|
|
|
$allowed_attributes = array( |
|
5293
|
|
|
"allow", "allowfullscreen", "alt", "class", "contenteditable", "data-html", "frameborder", "height", "href", "id", "name", "src", "style", "target", "title", "width", |
|
5294
|
|
|
// HTML5 |
|
5295
|
|
|
"header", "footer", "nav", "section", "menu", "menuitem" |
|
5296
|
|
|
); |
|
5297
|
|
|
} |
|
5298
|
|
|
|
|
5299
|
|
|
if (class_exists('DOMDocument') && !empty($stringtoclean)) { |
|
5300
|
|
|
$stringtoclean = '<?xml encoding="UTF-8"><html><body>' . $stringtoclean . '</body></html>'; |
|
5301
|
|
|
|
|
5302
|
|
|
// Warning: loadHTML does not support HTML5 on old libxml versions. |
|
5303
|
|
|
$dom = new DOMDocument('', 'UTF-8'); |
|
5304
|
|
|
// If $stringtoclean is wrong, it will generates warnings. So we disable warnings and restore them later. |
|
5305
|
|
|
$savwarning = error_reporting(); |
|
5306
|
|
|
error_reporting(E_ALL & ~E_WARNING & ~E_NOTICE); |
|
5307
|
|
|
$dom->loadHTML($stringtoclean, LIBXML_ERR_NONE | LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NONET | LIBXML_NOWARNING | LIBXML_NOXMLDECL); |
|
5308
|
|
|
error_reporting($savwarning); |
|
5309
|
|
|
|
|
5310
|
|
|
if ($dom instanceof DOMDocument) { |
|
|
|
|
|
|
5311
|
|
|
for ($els = $dom->getElementsByTagname('*'), $i = $els->length - 1; $i >= 0; $i--) { |
|
5312
|
|
|
$el = $els->item($i); |
|
5313
|
|
|
if (!$el instanceof DOMElement) { |
|
5314
|
|
|
continue; |
|
5315
|
|
|
} |
|
5316
|
|
|
$attrs = $el->attributes; |
|
5317
|
|
|
for ($ii = $attrs->length - 1; $ii >= 0; $ii--) { |
|
5318
|
|
|
//var_dump($attrs->item($ii)); |
|
5319
|
|
|
if (!empty($attrs->item($ii)->name)) { |
|
|
|
|
|
|
5320
|
|
|
if (!in_array($attrs->item($ii)->name, $allowed_attributes)) { |
|
5321
|
|
|
// Delete attribute if not into allowed_attributes @phan-suppress-next-line PhanUndeclaredMethod |
|
5322
|
|
|
$els->item($i)->removeAttribute($attrs->item($ii)->name); |
|
5323
|
|
|
} elseif (in_array($attrs->item($ii)->name, array('style'))) { |
|
5324
|
|
|
// If attribute is 'style' |
|
5325
|
|
|
$valuetoclean = $attrs->item($ii)->value; |
|
5326
|
|
|
|
|
5327
|
|
|
if (isset($valuetoclean)) { |
|
5328
|
|
|
do { |
|
5329
|
|
|
$oldvaluetoclean = $valuetoclean; |
|
5330
|
|
|
$valuetoclean = preg_replace('/\/\*.*\*\//m', '', $valuetoclean); // clean css comments |
|
5331
|
|
|
$valuetoclean = preg_replace('/position\s*:\s*[a-z]+/mi', '', $valuetoclean); |
|
5332
|
|
|
if ($els->item($i)->tagName == 'a') { // more paranoiac cleaning for clickable tags. |
|
5333
|
|
|
$valuetoclean = preg_replace('/display\s*:/mi', '', $valuetoclean); |
|
5334
|
|
|
$valuetoclean = preg_replace('/z-index\s*:/mi', '', $valuetoclean); |
|
5335
|
|
|
$valuetoclean = preg_replace('/\s+(top|left|right|bottom)\s*:/mi', '', $valuetoclean); |
|
5336
|
|
|
} |
|
5337
|
|
|
|
|
5338
|
|
|
// We do not allow logout|passwordforgotten.php and action= into the content of a "style" tag |
|
5339
|
|
|
$valuetoclean = preg_replace('/(logout|passwordforgotten)\.php/mi', '', $valuetoclean); |
|
5340
|
|
|
$valuetoclean = preg_replace('/action=/mi', '', $valuetoclean); |
|
5341
|
|
|
} while ($oldvaluetoclean != $valuetoclean); |
|
5342
|
|
|
} |
|
5343
|
|
|
|
|
5344
|
|
|
$attrs->item($ii)->value = $valuetoclean; |
|
5345
|
|
|
} |
|
5346
|
|
|
} |
|
5347
|
|
|
} |
|
5348
|
|
|
} |
|
5349
|
|
|
} |
|
5350
|
|
|
|
|
5351
|
|
|
$return = $dom->saveHTML(); // This may add a LF at end of lines, so we will trim later |
|
5352
|
|
|
//$return = '<html><body>aaaa</p>bb<p>ssdd</p>'."\n<p>aaa</p>aa<p>bb</p>"; |
|
5353
|
|
|
|
|
5354
|
|
|
$return = preg_replace('/^' . preg_quote('<?xml encoding="UTF-8">', '/') . '/', '', $return); |
|
5355
|
|
|
$return = preg_replace('/^' . preg_quote('<html><body>', '/') . '/', '', $return); |
|
5356
|
|
|
$return = preg_replace('/' . preg_quote('</body></html>', '/') . '$/', '', $return); |
|
5357
|
|
|
return trim($return); |
|
5358
|
|
|
} else { |
|
5359
|
|
|
return $stringtoclean; |
|
5360
|
|
|
} |
|
5361
|
|
|
} |
|
5362
|
|
|
|
|
5363
|
|
|
/** |
|
5364
|
|
|
* Return picto saying a field is required |
|
5365
|
|
|
* |
|
5366
|
|
|
* @return string Chaine avec picto obligatoire |
|
5367
|
|
|
*/ |
|
5368
|
|
|
function picto_required() |
|
5369
|
|
|
{ |
|
5370
|
|
|
return '<span class="fieldrequired">*</span>'; |
|
5371
|
|
|
} |
|
5372
|
|
|
|
|
5373
|
|
|
|
|
5374
|
|
|
/** |
|
5375
|
|
|
* Clean a string from all HTML tags and entities. |
|
5376
|
|
|
* This function differs from strip_tags because: |
|
5377
|
|
|
* - <br> are replaced with \n if removelinefeed=0 or 1 |
|
5378
|
|
|
* - if entities are found, they are decoded BEFORE the strip |
|
5379
|
|
|
* - you can decide to convert line feed into a space |
|
5380
|
|
|
* |
|
5381
|
|
|
* @param string $stringtoclean String to clean |
|
5382
|
|
|
* @param integer $removelinefeed 1=Replace all new lines by 1 space, 0=Only ending new lines are removed others are replaced with \n, 2=The ending new line is removed but others are kept with the same number of \n than the nb of <br> when there is both "...<br>\n..." |
|
5383
|
|
|
* @param string $pagecodeto Encoding of input/output string |
|
5384
|
|
|
* @param integer $strip_tags 0=Use internal strip, 1=Use strip_tags() php function (bugged when text contains a < char that is not for a html tag or when tags is not closed like '<img onload=aaa') |
|
5385
|
|
|
* @param integer $removedoublespaces Replace double space into one space |
|
5386
|
|
|
* @return string String cleaned |
|
5387
|
|
|
* |
|
5388
|
|
|
* @see dol_escape_htmltag() strip_tags() dol_string_onlythesehtmltags() dol_string_neverthesehtmltags(), dolStripPhpCode() |
|
5389
|
|
|
*/ |
|
5390
|
|
|
function dol_string_nohtmltag($stringtoclean, $removelinefeed = 1, $pagecodeto = 'UTF-8', $strip_tags = 0, $removedoublespaces = 1) |
|
5391
|
|
|
{ |
|
5392
|
|
|
if (is_null($stringtoclean)) { |
|
5393
|
|
|
return ''; |
|
5394
|
|
|
} |
|
5395
|
|
|
|
|
5396
|
|
|
if ($removelinefeed == 2) { |
|
5397
|
|
|
$stringtoclean = preg_replace('/<br[^>]*>(\n|\r)+/ims', '<br>', $stringtoclean); |
|
5398
|
|
|
} |
|
5399
|
|
|
$temp = preg_replace('/<br[^>]*>/i', "\n", $stringtoclean); |
|
5400
|
|
|
|
|
5401
|
|
|
// We remove entities BEFORE stripping (in case of an open separator char that is entity encoded and not the closing other, the strip will fails) |
|
5402
|
|
|
$temp = dol_html_entity_decode($temp, ENT_COMPAT | ENT_HTML5, $pagecodeto); |
|
5403
|
|
|
|
|
5404
|
|
|
$temp = str_replace('< ', '__ltspace__', $temp); |
|
5405
|
|
|
$temp = str_replace('<:', '__lttwopoints__', $temp); |
|
5406
|
|
|
|
|
5407
|
|
|
if ($strip_tags) { |
|
5408
|
|
|
$temp = strip_tags($temp); |
|
5409
|
|
|
} else { |
|
5410
|
|
|
// Remove '<' into remaining, so remove non closing html tags like '<abc' or '<<abc'. Note: '<123abc' is not a html tag (can be kept), but '<abc123' is (must be removed). |
|
5411
|
|
|
$pattern = "/<[^<>]+>/"; |
|
5412
|
|
|
// Example of $temp: <a href="/myurl" title="<u>A title</u>">0000-021</a> |
|
5413
|
|
|
// pass 1 - $temp after pass 1: <a href="/myurl" title="A title">0000-021 |
|
5414
|
|
|
// pass 2 - $temp after pass 2: 0000-021 |
|
5415
|
|
|
$tempbis = $temp; |
|
5416
|
|
|
do { |
|
5417
|
|
|
$temp = $tempbis; |
|
5418
|
|
|
$tempbis = str_replace('<>', '', $temp); // No reason to have this into a text, except if value is to try bypass the next html cleaning |
|
5419
|
|
|
$tempbis = preg_replace($pattern, '', $tempbis); |
|
5420
|
|
|
//$idowhile++; print $temp.'-'.$tempbis."\n"; if ($idowhile > 100) break; |
|
5421
|
|
|
} while ($tempbis != $temp); |
|
5422
|
|
|
|
|
5423
|
|
|
$temp = $tempbis; |
|
5424
|
|
|
|
|
5425
|
|
|
// Remove '<' into remaining, so remove non closing html tags like '<abc' or '<<abc'. Note: '<123abc' is not a html tag (can be kept), but '<abc123' is (must be removed). |
|
5426
|
|
|
$temp = preg_replace('/<+([a-z]+)/i', '\1', $temp); |
|
5427
|
|
|
} |
|
5428
|
|
|
|
|
5429
|
|
|
$temp = dol_html_entity_decode($temp, ENT_COMPAT, $pagecodeto); |
|
5430
|
|
|
|
|
5431
|
|
|
// Remove also carriage returns |
|
5432
|
|
|
if ($removelinefeed == 1) { |
|
5433
|
|
|
$temp = str_replace(array("\r\n", "\r", "\n"), " ", $temp); |
|
5434
|
|
|
} |
|
5435
|
|
|
|
|
5436
|
|
|
// And double quotes |
|
5437
|
|
|
if ($removedoublespaces) { |
|
5438
|
|
|
while (strpos($temp, " ")) { |
|
5439
|
|
|
$temp = str_replace(" ", " ", $temp); |
|
5440
|
|
|
} |
|
5441
|
|
|
} |
|
5442
|
|
|
|
|
5443
|
|
|
$temp = str_replace('__ltspace__', '< ', $temp); |
|
5444
|
|
|
$temp = str_replace('__lttwopoints__', '<:', $temp); |
|
5445
|
|
|
|
|
5446
|
|
|
return trim($temp); |
|
5447
|
|
|
} |
|
5448
|
|
|
|
|
5449
|
|
|
/** |
|
5450
|
|
|
* Clean a string to keep only desirable HTML tags. |
|
5451
|
|
|
* WARNING: This also clean HTML comments (because they can be used to obfuscate tag name). |
|
5452
|
|
|
* |
|
5453
|
|
|
* @param string $stringtoclean String to clean |
|
5454
|
|
|
* @param int $cleanalsosomestyles Remove absolute/fixed positioning from inline styles |
|
5455
|
|
|
* @param int $removeclassattribute 1=Remove the class attribute from tags |
|
5456
|
|
|
* @param int $cleanalsojavascript Remove also occurrence of 'javascript:'. |
|
5457
|
|
|
* @param int $allowiframe Allow iframe tags. |
|
5458
|
|
|
* @param string[] $allowed_tags List of allowed tags to replace the default list |
|
5459
|
|
|
* @param int $allowlink Allow "link" tags. |
|
5460
|
|
|
* @return string String cleaned |
|
5461
|
|
|
* |
|
5462
|
|
|
* @see dol_htmlwithnojs() dol_escape_htmltag() strip_tags() dol_string_nohtmltag() dol_string_neverthesehtmltags() |
|
5463
|
|
|
*/ |
|
5464
|
|
|
function dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles = 1, $removeclassattribute = 1, $cleanalsojavascript = 0, $allowiframe = 0, $allowed_tags = array(), $allowlink = 0) |
|
5465
|
|
|
{ |
|
5466
|
|
|
if (empty($allowed_tags)) { |
|
5467
|
|
|
$allowed_tags = array( |
|
5468
|
|
|
"html", "head", "meta", "body", "article", "a", "abbr", "b", "blockquote", "br", "cite", "div", "dl", "dd", "dt", "em", "font", "img", "ins", "hr", "i", "li", |
|
5469
|
|
|
"ol", "p", "q", "s", "span", "strike", "strong", "title", "table", "tr", "th", "td", "u", "ul", "sup", "sub", "blockquote", "pre", "h1", "h2", "h3", "h4", "h5", "h6", |
|
5470
|
|
|
"header", "footer", "nav", "section", "menu", "menuitem" // html5 tags |
|
5471
|
|
|
); |
|
5472
|
|
|
} |
|
5473
|
|
|
$allowed_tags[] = "comment"; // this tags is added to manage comment <!--...--> that are replaced into <comment>...</comment> |
|
5474
|
|
|
if ($allowiframe) { |
|
5475
|
|
|
if (!in_array('iframe', $allowed_tags)) { |
|
5476
|
|
|
$allowed_tags[] = "iframe"; |
|
5477
|
|
|
} |
|
5478
|
|
|
} |
|
5479
|
|
|
if ($allowlink) { |
|
5480
|
|
|
if (!in_array('link', $allowed_tags)) { |
|
5481
|
|
|
$allowed_tags[] = "link"; |
|
5482
|
|
|
} |
|
5483
|
|
|
} |
|
5484
|
|
|
|
|
5485
|
|
|
$allowed_tags_string = implode("><", $allowed_tags); |
|
5486
|
|
|
$allowed_tags_string = '<' . $allowed_tags_string . '>'; |
|
5487
|
|
|
|
|
5488
|
|
|
$stringtoclean = str_replace('<!DOCTYPE html>', '__!DOCTYPE_HTML__', $stringtoclean); // Replace DOCTYPE to avoid to have it removed by the strip_tags |
|
5489
|
|
|
|
|
5490
|
|
|
$stringtoclean = dol_string_nounprintableascii($stringtoclean, 0); |
|
5491
|
|
|
|
|
5492
|
|
|
//$stringtoclean = preg_replace('/<!--[^>]*-->/', '', $stringtoclean); |
|
5493
|
|
|
$stringtoclean = preg_replace('/<!--([^>]*)-->/', '<comment>\1</comment>', $stringtoclean); |
|
5494
|
|
|
|
|
5495
|
|
|
$stringtoclean = preg_replace('/:/i', ':', $stringtoclean); |
|
5496
|
|
|
$stringtoclean = preg_replace('/:|�+58|:/i', '', $stringtoclean); // refused string ':' encoded (no reason to have a : encoded like this) to disable 'javascript:...' |
|
5497
|
|
|
|
|
5498
|
|
|
$temp = strip_tags($stringtoclean, $allowed_tags_string); // Warning: This remove also undesired </>, so may changes string obfuscated with </> that pass the injection detection into a harmfull string |
|
5499
|
|
|
|
|
5500
|
|
|
if ($cleanalsosomestyles) { // Clean for remaining html tags |
|
5501
|
|
|
$temp = preg_replace('/position\s*:\s*(absolute|fixed)\s*!\s*important/i', '', $temp); // Note: If hacker try to introduce css comment into string to bypass this regex, the string must also be encoded by the dol_htmlentitiesbr during output so it become harmless |
|
5502
|
|
|
} |
|
5503
|
|
|
if ($removeclassattribute) { // Clean for remaining html tags |
|
5504
|
|
|
$temp = preg_replace('/(<[^>]+)\s+class=((["\']).*?\\3|\\w*)/i', '\\1', $temp); |
|
5505
|
|
|
} |
|
5506
|
|
|
|
|
5507
|
|
|
// Remove 'javascript:' that we should not find into a text with |
|
5508
|
|
|
// Warning: This is not reliable to fight against obfuscated javascript, there is a lot of other solution to include js into a common html tag (only filtered by a GETPOST(.., powerfullfilter)). |
|
5509
|
|
|
if ($cleanalsojavascript) { |
|
5510
|
|
|
$temp = preg_replace('/j\s*a\s*v\s*a\s*s\s*c\s*r\s*i\s*p\s*t\s*:/i', '', $temp); |
|
5511
|
|
|
} |
|
5512
|
|
|
|
|
5513
|
|
|
$temp = str_replace('__!DOCTYPE_HTML__', '<!DOCTYPE html>', $temp); // Restore the DOCTYPE |
|
5514
|
|
|
|
|
5515
|
|
|
$temp = preg_replace('/<comment>([^>]*)<\/comment>/', '<!--\1-->', $temp); // Restore html comments |
|
5516
|
|
|
|
|
5517
|
|
|
|
|
5518
|
|
|
return $temp; |
|
5519
|
|
|
} |
|
5520
|
|
|
|
|
5521
|
|
|
/** |
|
5522
|
|
|
* Clean a string from some undesirable HTML tags. |
|
5523
|
|
|
* Note: You should use instead dol_string_onlythesehtmltags() that is more secured if you can. |
|
5524
|
|
|
* |
|
5525
|
|
|
* @param string $stringtoclean String to clean |
|
5526
|
|
|
* @param array $disallowed_tags Array of tags not allowed |
|
5527
|
|
|
* @param int $cleanalsosomestyles Clean also some tags |
|
5528
|
|
|
* @return string String cleaned |
|
5529
|
|
|
* |
|
5530
|
|
|
* @see dol_escape_htmltag() strip_tags() dol_string_nohtmltag() dol_string_onlythesehtmltags() dol_string_onlythesehtmlattributes() |
|
5531
|
|
|
*/ |
|
5532
|
|
|
function dol_string_neverthesehtmltags($stringtoclean, $disallowed_tags = array('textarea'), $cleanalsosomestyles = 0) |
|
5533
|
|
|
{ |
|
5534
|
|
|
$temp = $stringtoclean; |
|
5535
|
|
|
foreach ($disallowed_tags as $tagtoremove) { |
|
5536
|
|
|
$temp = preg_replace('/<\/?' . $tagtoremove . '>/', '', $temp); |
|
5537
|
|
|
$temp = preg_replace('/<\/?' . $tagtoremove . '\s+[^>]*>/', '', $temp); |
|
5538
|
|
|
} |
|
5539
|
|
|
|
|
5540
|
|
|
if ($cleanalsosomestyles) { |
|
5541
|
|
|
$temp = preg_replace('/position\s*:\s*(absolute|fixed)\s*!\s*important/', '', $temp); // Note: If hacker try to introduce css comment into string to avoid this, string should be encoded by the dol_htmlentitiesbr so be harmless |
|
5542
|
|
|
} |
|
5543
|
|
|
|
|
5544
|
|
|
return $temp; |
|
5545
|
|
|
} |
|
5546
|
|
|
|
|
5547
|
|
|
|
|
5548
|
|
|
/** |
|
5549
|
|
|
* Return yes or no in current language |
|
5550
|
|
|
* |
|
5551
|
|
|
* @param string|int $yesno Value to test (1, 'yes', 'true' or 0, 'no', 'false') |
|
5552
|
|
|
* @param integer $case 1=Yes/No, 0=yes/no, 2=Disabled checkbox, 3=Disabled checkbox + Yes/No |
|
5553
|
|
|
* @param int $color 0=texte only, 1=Text is formatted with a color font style ('ok' or 'error'), 2=Text is formatted with 'ok' color. |
|
5554
|
|
|
* @return string HTML string |
|
5555
|
|
|
*/ |
|
5556
|
|
|
function yn($yesno, $case = 1, $color = 0) |
|
5557
|
|
|
{ |
|
5558
|
|
|
global $langs; |
|
5559
|
|
|
|
|
5560
|
|
|
$result = 'unknown'; |
|
5561
|
|
|
$classname = ''; |
|
5562
|
|
|
if ($yesno == 1 || (isset($yesno) && (strtolower($yesno) == 'yes' || strtolower($yesno) == 'true'))) { // To set to 'no' before the test because of the '== 0' |
|
5563
|
|
|
$result = $langs->trans('yes'); |
|
5564
|
|
|
if ($case == 1 || $case == 3) { |
|
5565
|
|
|
$result = $langs->trans("Yes"); |
|
5566
|
|
|
} |
|
5567
|
|
|
if ($case == 2) { |
|
5568
|
|
|
$result = '<input type="checkbox" value="1" checked disabled>'; |
|
5569
|
|
|
} |
|
5570
|
|
|
if ($case == 3) { |
|
5571
|
|
|
$result = '<input type="checkbox" value="1" checked disabled> ' . $result; |
|
5572
|
|
|
} |
|
5573
|
|
|
if ($case == 4) { |
|
5574
|
|
|
$result = img_picto('check', 'check'); |
|
5575
|
|
|
} |
|
5576
|
|
|
|
|
5577
|
|
|
$classname = 'ok'; |
|
5578
|
|
|
} elseif ($yesno == 0 || strtolower($yesno) == 'no' || strtolower($yesno) == 'false') { |
|
5579
|
|
|
$result = $langs->trans("no"); |
|
5580
|
|
|
if ($case == 1 || $case == 3) { |
|
5581
|
|
|
$result = $langs->trans("No"); |
|
5582
|
|
|
} |
|
5583
|
|
|
if ($case == 2) { |
|
5584
|
|
|
$result = '<input type="checkbox" value="0" disabled>'; |
|
5585
|
|
|
} |
|
5586
|
|
|
if ($case == 3) { |
|
5587
|
|
|
$result = '<input type="checkbox" value="0" disabled> ' . $result; |
|
5588
|
|
|
} |
|
5589
|
|
|
if ($case == 4) { |
|
5590
|
|
|
$result = img_picto('uncheck', 'uncheck'); |
|
5591
|
|
|
} |
|
5592
|
|
|
|
|
5593
|
|
|
if ($color == 2) { |
|
5594
|
|
|
$classname = 'ok'; |
|
5595
|
|
|
} else { |
|
5596
|
|
|
$classname = 'error'; |
|
5597
|
|
|
} |
|
5598
|
|
|
} |
|
5599
|
|
|
if ($color) { |
|
5600
|
|
|
return '<span class="' . $classname . '">' . $result . '</span>'; |
|
5601
|
|
|
} |
|
5602
|
|
|
return $result; |
|
5603
|
|
|
} |
|
5604
|
|
|
|