Total Complexity | 449 |
Total Lines | 2391 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like ViewMain often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ViewMain, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
24 | abstract class ViewMain |
||
25 | { |
||
26 | /** |
||
27 | * Show HTML header HTML + BODY + Top menu + left menu + DIV |
||
28 | * |
||
29 | * @param string $head Optional head lines |
||
30 | * @param string $title HTML title |
||
31 | * @param string $help_url Url links to help page |
||
32 | * Syntax is: For a wiki page: EN:EnglishPage|FR:FrenchPage|ES:SpanishPage|DE:GermanPage |
||
33 | * For other external page: http://server/url |
||
34 | * @param string $target Target to use on links |
||
35 | * @param int $disablejs More content into html header |
||
36 | * @param int $disablehead More content into html header |
||
37 | * @param array|string $arrayofjs Array of complementary js files |
||
38 | * @param array|string $arrayofcss Array of complementary css files |
||
39 | * @param string $morequerystring Query string to add to the link "print" to get same parameters (use only if autodetect fails) |
||
40 | * @param string $morecssonbody More CSS on body tag. For example 'classforhorizontalscrolloftabs'. |
||
41 | * @param string $replacemainareaby Replace call to static::mainArea() by a print of this string |
||
42 | * @param int $disablenofollow Disable the "nofollow" on meta robot header |
||
43 | * @param int $disablenoindex Disable the "noindex" on meta robot header |
||
44 | * @return void |
||
45 | */ |
||
46 | public static function llxHeader($head = '', $title = '', $help_url = '', $target = '', $disablejs = 0, $disablehead = 0, $arrayofjs = '', $arrayofcss = '', $morequerystring = '', $morecssonbody = '', $replacemainareaby = '', $disablenofollow = 0, $disablenoindex = 0) |
||
47 | { |
||
48 | global $conf, $hookmanager; |
||
49 | |||
50 | $parameters = array( |
||
51 | 'head' => & $head, |
||
52 | 'title' => & $title, |
||
53 | 'help_url' => & $help_url, |
||
54 | 'target' => & $target, |
||
55 | 'disablejs' => & $disablejs, |
||
56 | 'disablehead' => & $disablehead, |
||
57 | 'arrayofjs' => & $arrayofjs, |
||
58 | 'arrayofcss' => & $arrayofcss, |
||
59 | 'morequerystring' => & $morequerystring, |
||
60 | 'morecssonbody' => & $morecssonbody, |
||
61 | 'replacemainareaby' => & $replacemainareaby, |
||
62 | 'disablenofollow' => & $disablenofollow, |
||
63 | 'disablenoindex' => & $disablenoindex |
||
64 | |||
65 | ); |
||
66 | $reshook = $hookmanager->executeHooks('llxHeader', $parameters); |
||
67 | if ($reshook > 0) { |
||
68 | print $hookmanager->resPrint; |
||
69 | return; |
||
70 | } |
||
71 | |||
72 | // html header |
||
73 | static::topHtmlHead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss, 0, $disablenofollow, $disablenoindex); |
||
74 | |||
75 | $tmpcsstouse = 'sidebar-collapse' . ($morecssonbody ? ' ' . $morecssonbody : ''); |
||
76 | // If theme MD and classic layer, we open the menulayer by default. |
||
77 | if ($conf->theme == 'md' && !in_array($conf->browser->layout, array('phone', 'tablet')) && !getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
||
78 | global $mainmenu; |
||
79 | if ($mainmenu != 'website') { |
||
80 | $tmpcsstouse = $morecssonbody; // We do not use sidebar-collpase by default to have menuhider open by default. |
||
81 | } |
||
82 | } |
||
83 | |||
84 | if (getDolGlobalString('MAIN_OPTIMIZEFORCOLORBLIND')) { |
||
85 | $tmpcsstouse .= ' colorblind-' . strip_tags($conf->global->MAIN_OPTIMIZEFORCOLORBLIND); |
||
86 | } |
||
87 | |||
88 | print '<body id="mainbody" class="' . $tmpcsstouse . '">' . "\n"; |
||
89 | |||
90 | // top menu and left menu area |
||
91 | if ((empty($conf->dol_hide_topmenu) || GETPOSTINT('dol_invisible_topmenu')) && !GETPOSTINT('dol_openinpopup')) { |
||
92 | static::topMenu($head, $title, $target, $disablejs, $disablehead, $arrayofjs, $arrayofcss, $morequerystring, $help_url); |
||
93 | } |
||
94 | |||
95 | if (empty($conf->dol_hide_leftmenu) && !GETPOST('dol_openinpopup', 'aZ09')) { |
||
96 | static::leftMenu(array(), $help_url, '', '', 1, $title, 1); // $menumanager is retrieved with a global $menumanager inside this function |
||
97 | } |
||
98 | |||
99 | // main area |
||
100 | if ($replacemainareaby) { |
||
101 | print $replacemainareaby; |
||
102 | return; |
||
103 | } |
||
104 | static::mainArea($title); |
||
105 | } |
||
106 | |||
107 | /** |
||
108 | * Show HTTP header. Called by static::topHtmlHead(). |
||
109 | * |
||
110 | * @param string $contenttype Content type. For example, 'text/html' |
||
111 | * @param int<0,1> $forcenocache Force disabling of cache for the page |
||
112 | * @return void |
||
113 | */ |
||
114 | public static function topHttpHead($contenttype = 'text/html', $forcenocache = 0) |
||
115 | { |
||
116 | global $db, $conf, $hookmanager; |
||
117 | |||
118 | if ($contenttype == 'text/html') { |
||
119 | header("Content-Type: text/html; charset=" . $conf->file->character_set_client); |
||
120 | } else { |
||
121 | header("Content-Type: " . $contenttype); |
||
122 | } |
||
123 | |||
124 | // Security options |
||
125 | |||
126 | // X-Content-Type-Options |
||
127 | header("X-Content-Type-Options: nosniff"); // With the nosniff option, if the server says the content is text/html, the browser will render it as text/html (note that most browsers now force this option to on) |
||
128 | |||
129 | // X-Frame-Options |
||
130 | if (!defined('XFRAMEOPTIONS_ALLOWALL')) { |
||
131 | header("X-Frame-Options: SAMEORIGIN"); // By default, frames allowed only if on same domain (stop some XSS attacks) |
||
132 | } else { |
||
133 | header("X-Frame-Options: ALLOWALL"); |
||
134 | } |
||
135 | |||
136 | if (getDolGlobalString('MAIN_SECURITY_FORCE_ACCESS_CONTROL_ALLOW_ORIGIN')) { |
||
137 | $tmpurl = constant('DOL_MAIN_URL_ROOT'); |
||
138 | $tmpurl = preg_replace('/^(https?:\/\/[^\/]+)\/.*$/', '\1', $tmpurl); |
||
139 | header('Access-Control-Allow-Origin: ' . $tmpurl); |
||
140 | header('Vary: Origin'); |
||
141 | } |
||
142 | |||
143 | // X-XSS-Protection |
||
144 | //header("X-XSS-Protection: 1"); // XSS filtering protection of some browsers (note: use of Content-Security-Policy is more efficient). Disabled as deprecated. |
||
145 | |||
146 | // Content-Security-Policy-Report-Only |
||
147 | if (!defined('MAIN_SECURITY_FORCECSPRO')) { |
||
148 | // If CSP not forced from the page |
||
149 | |||
150 | // A default security policy that keep usage of js external component like ckeditor, stripe, google, working |
||
151 | // For example: to restrict to only local resources, except for css (cloudflare+google), and js (transifex + google tags) and object/iframe (youtube) |
||
152 | // default-src 'self'; style-src: https://cdnjs.cloudflare.com https://fonts.googleapis.com; script-src: https://cdn.transifex.com https://www.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src: *; |
||
153 | // For example, to restrict everything to itself except img that can be on other servers: |
||
154 | // default-src 'self'; img-src *; |
||
155 | // Pre-existing site that uses too much js code to fix but wants to ensure resources are loaded only over https and disable plugins: |
||
156 | // default-src https: 'unsafe-inline' 'unsafe-eval'; object-src 'none' |
||
157 | // |
||
158 | // $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; font-src *; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googleapis.com *.google-analytics.com *.googletagmanager.com;"; |
||
159 | // $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; font-src *; default-src *; script-src 'self' 'unsafe-inline' *.paypal.com *.stripe.com *.google.com *.googleapis.com *.google-analytics.com *.googletagmanager.com; style-src 'self' 'unsafe-inline'; connect-src 'self';"; |
||
160 | $contentsecuritypolicy = getDolGlobalString('MAIN_SECURITY_FORCECSPRO'); |
||
161 | |||
162 | if (!is_object($hookmanager)) { |
||
163 | $hookmanager = new HookManager($db); |
||
164 | } |
||
165 | $hookmanager->initHooks(array("main")); |
||
166 | |||
167 | $parameters = array('contentsecuritypolicy' => $contentsecuritypolicy, 'mode' => 'reportonly'); |
||
168 | $result = $hookmanager->executeHooks('setContentSecurityPolicy', $parameters); // Note that $action and $object may have been modified by some hooks |
||
169 | if ($result > 0) { |
||
170 | $contentsecuritypolicy = $hookmanager->resPrint; // Replace CSP |
||
171 | } else { |
||
172 | $contentsecuritypolicy .= $hookmanager->resPrint; // Concat CSP |
||
173 | } |
||
174 | |||
175 | if (!empty($contentsecuritypolicy)) { |
||
176 | header("Content-Security-Policy-Report-Only: " . $contentsecuritypolicy); |
||
177 | } |
||
178 | } else { |
||
179 | header("Content-Security-Policy: " . constant('MAIN_SECURITY_FORCECSPRO')); |
||
180 | } |
||
181 | |||
182 | // Content-Security-Policy |
||
183 | if (!defined('MAIN_SECURITY_FORCECSP')) { |
||
184 | // If CSP not forced from the page |
||
185 | |||
186 | // A default security policy that keep usage of js external component like ckeditor, stripe, google, working |
||
187 | // For example: to restrict to only local resources, except for css (cloudflare+google), and js (transifex + google tags) and object/iframe (youtube) |
||
188 | // default-src 'self'; style-src: https://cdnjs.cloudflare.com https://fonts.googleapis.com; script-src: https://cdn.transifex.com https://www.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src: *; |
||
189 | // For example, to restrict everything to itself except img that can be on other servers: |
||
190 | // default-src 'self'; img-src *; |
||
191 | // Pre-existing site that uses too much js code to fix but wants to ensure resources are loaded only over https and disable plugins: |
||
192 | // default-src https: 'unsafe-inline' 'unsafe-eval'; object-src 'none' |
||
193 | // |
||
194 | // $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; font-src *; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googleapis.com *.google-analytics.com *.googletagmanager.com;"; |
||
195 | // $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; font-src *; default-src *; script-src 'self' 'unsafe-inline' *.paypal.com *.stripe.com *.google.com *.googleapis.com *.google-analytics.com *.googletagmanager.com; style-src 'self' 'unsafe-inline'; connect-src 'self';"; |
||
196 | $contentsecuritypolicy = getDolGlobalString('MAIN_SECURITY_FORCECSP'); |
||
197 | |||
198 | if (!is_object($hookmanager)) { |
||
199 | $hookmanager = new HookManager($db); |
||
200 | } |
||
201 | $hookmanager->initHooks(array("main")); |
||
202 | |||
203 | $parameters = array('contentsecuritypolicy' => $contentsecuritypolicy, 'mode' => 'active'); |
||
204 | $result = $hookmanager->executeHooks('setContentSecurityPolicy', $parameters); // Note that $action and $object may have been modified by some hooks |
||
205 | if ($result > 0) { |
||
206 | $contentsecuritypolicy = $hookmanager->resPrint; // Replace CSP |
||
207 | } else { |
||
208 | $contentsecuritypolicy .= $hookmanager->resPrint; // Concat CSP |
||
209 | } |
||
210 | |||
211 | if (!empty($contentsecuritypolicy)) { |
||
212 | header("Content-Security-Policy: " . $contentsecuritypolicy); |
||
213 | } |
||
214 | } else { |
||
215 | header("Content-Security-Policy: " . constant('MAIN_SECURITY_FORCECSP')); |
||
216 | } |
||
217 | |||
218 | // Referrer-Policy |
||
219 | // Say if we must provide the referrer when we jump onto another web page. |
||
220 | // Default browser are 'strict-origin-when-cross-origin' (only domain is sent on other domain switching), we want more so we use 'same-origin' so browser doesn't send any referrer at all when going into another web site domain. |
||
221 | // Note that we do not use 'strict-origin' as this breaks feature to restore filters when clicking on "back to page" link on some cases. |
||
222 | if (!defined('MAIN_SECURITY_FORCERP')) { |
||
223 | $referrerpolicy = getDolGlobalString('MAIN_SECURITY_FORCERP', "same-origin"); |
||
224 | |||
225 | header("Referrer-Policy: " . $referrerpolicy); |
||
226 | } |
||
227 | |||
228 | if ($forcenocache) { |
||
229 | header("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"); |
||
230 | } |
||
231 | |||
232 | // No need to add this token in header, we use instead the one into the forms. |
||
233 | //header("anti-csrf-token: ".newToken()); |
||
234 | } |
||
235 | |||
236 | |||
237 | /** |
||
238 | * Output html header of a page. It calls also static::topHttpHead() |
||
239 | * This code is also duplicated into security2.lib.php::dol_loginfunction |
||
240 | * |
||
241 | * @param string $head Optional head lines |
||
242 | * @param string $title HTML title |
||
243 | * @param int<0,1> $disablejs Disable js output |
||
244 | * @param int<0,1> $disablehead Disable head output |
||
245 | * @param string[] $arrayofjs Array of complementary js files |
||
246 | * @param string[] $arrayofcss Array of complementary css files |
||
247 | * @param int<0,1> $disableforlogin Do not load heavy js and css for login pages |
||
248 | * @param int<0,1> $disablenofollow Disable nofollow tag for meta robots |
||
249 | * @param int<0,1> $disablenoindex Disable noindex tag for meta robots |
||
250 | * @return void |
||
251 | */ |
||
252 | public static function topHtmlHead($head, $title = '', $disablejs = 0, $disablehead = 0, $arrayofjs = array(), $arrayofcss = array(), $disableforlogin = 0, $disablenofollow = 0, $disablenoindex = 0) |
||
253 | { |
||
254 | global $db, $conf, $langs, $user, $mysoc, $hookmanager; |
||
255 | |||
256 | static::topHttpHead(); |
||
257 | |||
258 | if (empty($conf->css)) { |
||
259 | $conf->css = '/theme/eldy/style.css.php'; // If not defined, eldy by default |
||
260 | } |
||
261 | |||
262 | print '<!doctype html>' . "\n"; |
||
263 | |||
264 | print '<html lang="' . substr($langs->defaultlang, 0, 2) . '">' . "\n"; |
||
265 | |||
266 | //print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">'."\n"; |
||
267 | if (empty($disablehead)) { |
||
268 | if (!is_object($hookmanager)) { |
||
269 | $hookmanager = new HookManager($db); |
||
270 | } |
||
271 | $hookmanager->initHooks(array("main")); |
||
272 | |||
273 | $ext = 'layout=' . (empty($conf->browser->layout) ? '' : $conf->browser->layout) . '&version=' . urlencode(DOL_VERSION); |
||
274 | |||
275 | print "<head>\n"; |
||
276 | |||
277 | if (GETPOST('dol_basehref', 'alpha')) { |
||
278 | print '<base href="' . dol_escape_htmltag(GETPOST('dol_basehref', 'alpha')) . '">' . "\n"; |
||
279 | } |
||
280 | |||
281 | // Displays meta |
||
282 | print '<meta charset="utf-8">' . "\n"; |
||
283 | print '<meta name="robots" content="' . ($disablenoindex ? 'index' : 'noindex') . ($disablenofollow ? ',follow' : ',nofollow') . '">' . "\n"; // Do not index |
||
284 | print '<meta name="viewport" content="width=device-width, initial-scale=1.0">' . "\n"; // Scale for mobile device |
||
285 | print '<meta name="author" content="Dolibarr Development Team">' . "\n"; |
||
286 | print '<meta name="anti-csrf-newtoken" content="' . newToken() . '">' . "\n"; |
||
287 | print '<meta name="anti-csrf-currenttoken" content="' . currentToken() . '">' . "\n"; |
||
288 | if (getDolGlobalInt('MAIN_FEATURES_LEVEL')) { |
||
289 | print '<meta name="MAIN_FEATURES_LEVEL" content="' . getDolGlobalInt('MAIN_FEATURES_LEVEL') . '">' . "\n"; |
||
290 | } |
||
291 | // Favicon |
||
292 | $favicon = constant('DOL_URL_ROOT') . '/theme/alixar_square_logo_256x256_color.png'; |
||
293 | if (!empty($mysoc->logo_squarred_mini)) { |
||
294 | $favicon = constant('BASE_URL') . '/viewimage.php?cache=1&modulepart=mycompany&file=' . urlencode('logos/thumbs/' . $mysoc->logo_squarred_mini); |
||
295 | } |
||
296 | if (getDolGlobalString('MAIN_FAVICON_URL')) { |
||
297 | $favicon = getDolGlobalString('MAIN_FAVICON_URL'); |
||
298 | } |
||
299 | if (empty($conf->dol_use_jmobile)) { |
||
300 | print '<link rel="shortcut icon" type="image/x-icon" href="' . $favicon . '"/>' . "\n"; // Not required into an Android webview |
||
301 | } |
||
302 | |||
303 | // Mobile appli like icon |
||
304 | $manifest = constant('DOL_URL_ROOT') . '/theme/' . $conf->theme . '/manifest.json.php'; |
||
305 | $parameters = array('manifest' => $manifest); |
||
306 | $resHook = $hookmanager->executeHooks('hookSetManifest', $parameters); // Note that $action and $object may have been modified by some hooks |
||
307 | if ($resHook > 0) { |
||
308 | $manifest = $hookmanager->resPrint; // Replace manifest.json |
||
309 | } else { |
||
310 | $manifest .= $hookmanager->resPrint; // Concat to actual manifest declaration |
||
311 | } |
||
312 | if (!empty($manifest)) { |
||
313 | print '<link rel="manifest" href="' . $manifest . '" />' . "\n"; |
||
314 | } |
||
315 | |||
316 | if (getDolGlobalString('THEME_ELDY_TOPMENU_BACK1')) { |
||
317 | // TODO: use auto theme color switch |
||
318 | print '<meta name="theme-color" content="rgb(' . getDolGlobalString('THEME_ELDY_TOPMENU_BACK1') . ')">' . "\n"; |
||
319 | } |
||
320 | |||
321 | // Auto refresh page |
||
322 | if (GETPOSTINT('autorefresh') > 0) { |
||
323 | print '<meta http-equiv="refresh" content="' . GETPOSTINT('autorefresh') . '">'; |
||
324 | } |
||
325 | |||
326 | // Displays title |
||
327 | $appli = constant('DOL_APPLICATION_TITLE'); |
||
328 | if (getDolGlobalString('MAIN_APPLICATION_TITLE')) { |
||
329 | $appli = getDolGlobalString('MAIN_APPLICATION_TITLE'); |
||
330 | } |
||
331 | |||
332 | print '<title>'; |
||
333 | $titletoshow = ''; |
||
334 | if ($title && preg_match('/showapp/', getDolGlobalString('MAIN_HTML_TITLE'))) { |
||
335 | $titletoshow = dol_htmlentities($appli . ' - ' . $title); |
||
336 | } elseif ($title) { |
||
337 | $titletoshow = dol_htmlentities($title); |
||
338 | } else { |
||
339 | $titletoshow = dol_htmlentities($appli); |
||
340 | } |
||
341 | |||
342 | $parameters = array('title' => $titletoshow); |
||
343 | $result = $hookmanager->executeHooks('setHtmlTitle', $parameters); // Note that $action and $object may have been modified by some hooks |
||
344 | if ($result > 0) { |
||
345 | $titletoshow = $hookmanager->resPrint; // Replace Title to show |
||
346 | } else { |
||
347 | $titletoshow .= $hookmanager->resPrint; // Concat to Title to show |
||
348 | } |
||
349 | |||
350 | print $titletoshow; |
||
351 | print '</title>'; |
||
352 | |||
353 | print "\n"; |
||
354 | |||
355 | if (GETPOSTINT('version')) { |
||
356 | $ext = 'version=' . GETPOSTINT('version'); // useful to force no cache on css/js |
||
357 | } |
||
358 | // Refresh value of MAIN_IHM_PARAMS_REV before forging the parameter line. |
||
359 | if (GETPOST('dol_resetcache')) { |
||
360 | dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity); |
||
361 | } |
||
362 | |||
363 | $themeparam = '?lang=' . $langs->defaultlang . '&theme=' . $conf->theme . (GETPOST('optioncss', 'aZ09') ? '&optioncss=' . GETPOST('optioncss', 'aZ09', 1) : '') . (empty($user->id) ? '' : ('&userid=' . $user->id)) . '&entity=' . $conf->entity; |
||
364 | |||
365 | $themeparam .= ($ext ? '&' . $ext : '') . '&revision=' . getDolGlobalInt("MAIN_IHM_PARAMS_REV"); |
||
366 | if (GETPOSTISSET('dol_hide_topmenu')) { |
||
367 | $themeparam .= '&dol_hide_topmenu=' . GETPOSTINT('dol_hide_topmenu'); |
||
368 | } |
||
369 | if (GETPOSTISSET('dol_hide_leftmenu')) { |
||
370 | $themeparam .= '&dol_hide_leftmenu=' . GETPOSTINT('dol_hide_leftmenu'); |
||
371 | } |
||
372 | if (GETPOSTISSET('dol_optimize_smallscreen')) { |
||
373 | $themeparam .= '&dol_optimize_smallscreen=' . GETPOSTINT('dol_optimize_smallscreen'); |
||
374 | } |
||
375 | if (GETPOSTISSET('dol_no_mouse_hover')) { |
||
376 | $themeparam .= '&dol_no_mouse_hover=' . GETPOSTINT('dol_no_mouse_hover'); |
||
377 | } |
||
378 | if (GETPOSTISSET('dol_use_jmobile')) { |
||
379 | $themeparam .= '&dol_use_jmobile=' . GETPOSTINT('dol_use_jmobile'); |
||
380 | $conf->dol_use_jmobile = GETPOSTINT('dol_use_jmobile'); |
||
381 | } |
||
382 | if (GETPOSTISSET('THEME_DARKMODEENABLED')) { |
||
383 | $themeparam .= '&THEME_DARKMODEENABLED=' . GETPOSTINT('THEME_DARKMODEENABLED'); |
||
384 | } |
||
385 | if (GETPOSTISSET('THEME_SATURATE_RATIO')) { |
||
386 | $themeparam .= '&THEME_SATURATE_RATIO=' . GETPOSTINT('THEME_SATURATE_RATIO'); |
||
387 | } |
||
388 | |||
389 | if (getDolGlobalString('MAIN_ENABLE_FONT_ROBOTO')) { |
||
390 | print '<link rel="preconnect" href="https://fonts.gstatic.com">' . "\n"; |
||
391 | print '<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@200;300;400;500;600&display=swap" rel="stylesheet">' . "\n"; |
||
392 | } |
||
393 | |||
394 | if (!defined('DISABLE_JQUERY') && !$disablejs && $conf->use_javascript_ajax) { |
||
395 | print '<!-- Includes CSS for JQuery (Ajax library) -->' . "\n"; |
||
396 | $jquerytheme = 'base'; |
||
397 | if (getDolGlobalString('MAIN_USE_JQUERY_THEME')) { |
||
398 | $jquerytheme = getDolGlobalString('MAIN_USE_JQUERY_THEME'); |
||
399 | } |
||
400 | if (constant('JS_JQUERY_UI')) { |
||
401 | print '<link rel="stylesheet" type="text/css" href="' . JS_JQUERY_UI . 'css/' . $jquerytheme . '/jquery-ui.min.css' . ($ext ? '?' . $ext : '') . '">' . "\n"; // Forced JQuery |
||
402 | } else { |
||
403 | print '<link rel="stylesheet" type="text/css" href="' . constant('DOL_URL_ROOT') . '/includes/jquery/css/' . $jquerytheme . '/jquery-ui.css' . ($ext ? '?' . $ext : '') . '">' . "\n"; // JQuery |
||
404 | } |
||
405 | if (!defined('DISABLE_JQUERY_JNOTIFY')) { |
||
406 | print '<link rel="stylesheet" type="text/css" href="' . constant('DOL_URL_ROOT') . '/includes/jquery/plugins/jnotify/jquery.jnotify-alt.min.css' . ($ext ? '?' . $ext : '') . '">' . "\n"; // JNotify |
||
407 | } |
||
408 | if (!defined('DISABLE_SELECT2') && (getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT'))) { // jQuery plugin "mutiselect", "multiple-select", "select2"... |
||
409 | $tmpplugin = !getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') ? constant('REQUIRE_JQUERY_MULTISELECT') : $conf->global->MAIN_USE_JQUERY_MULTISELECT; |
||
410 | print '<link rel="stylesheet" type="text/css" href="' . constant('DOL_URL_ROOT') . '/includes/jquery/plugins/' . $tmpplugin . '/dist/css/' . $tmpplugin . '.css' . ($ext ? '?' . $ext : '') . '">' . "\n"; |
||
411 | } |
||
412 | } |
||
413 | |||
414 | if (!defined('DISABLE_FONT_AWSOME')) { |
||
415 | print '<!-- Includes CSS for font awesome -->' . "\n"; |
||
416 | $fontawesome_directory = getDolGlobalString('MAIN_FONTAWESOME_DIRECTORY', '/theme/common/fontawesome-5'); |
||
417 | print '<link rel="stylesheet" type="text/css" href="' . constant('DOL_URL_ROOT') . $fontawesome_directory . '/css/all.min.css' . ($ext ? '?' . $ext : '') . '">' . "\n"; |
||
418 | } |
||
419 | |||
420 | print '<!-- Includes CSS for Dolibarr theme -->' . "\n"; |
||
421 | // Output style sheets (optioncss='print' or ''). Note: $conf->css looks like '/theme/eldy/style.css.php' |
||
422 | $themepath = dol_buildpath($conf->css, 1); |
||
423 | $themesubdir = ''; |
||
424 | if (!empty($conf->modules_parts['theme'])) { // This slow down |
||
425 | foreach ($conf->modules_parts['theme'] as $reldir) { |
||
426 | if (file_exists(dol_buildpath($reldir . $conf->css, 0))) { |
||
427 | $themepath = dol_buildpath($reldir . $conf->css, 1); |
||
428 | $themesubdir = $reldir; |
||
429 | break; |
||
430 | } |
||
431 | } |
||
432 | } |
||
433 | |||
434 | //print 'themepath='.$themepath.' themeparam='.$themeparam;exit; |
||
435 | print '<link rel="stylesheet" type="text/css" href="' . $themepath . $themeparam . '">' . "\n"; |
||
436 | if (getDolGlobalString('MAIN_FIX_FLASH_ON_CHROME')) { |
||
437 | print '<!-- Includes CSS that does not exists as a workaround of flash bug of chrome -->' . "\n" . '<link rel="stylesheet" type="text/css" href="filethatdoesnotexiststosolvechromeflashbug">' . "\n"; |
||
438 | } |
||
439 | |||
440 | // LEAFLET AND GEOMAN |
||
441 | if (getDolGlobalString('MAIN_USE_GEOPHP')) { |
||
442 | print '<link rel="stylesheet" href="' . constant('BASE_URL') . '/includes/leaflet/leaflet.css' . ($ext ? '?' . $ext : '') . "\">\n"; |
||
443 | print '<link rel="stylesheet" href="' . constant('BASE_URL') . '/includes/leaflet/leaflet-geoman.css' . ($ext ? '?' . $ext : '') . "\">\n"; |
||
444 | } |
||
445 | |||
446 | // CSS forced by modules (relative url starting with /) |
||
447 | if (!empty($conf->modules_parts['css'])) { |
||
448 | $arraycss = (array)$conf->modules_parts['css']; |
||
449 | foreach ($arraycss as $modcss => $filescss) { |
||
450 | $filescss = (array)$filescss; // To be sure filecss is an array |
||
451 | foreach ($filescss as $cssfile) { |
||
452 | if (empty($cssfile)) { |
||
453 | dol_syslog("Warning: module " . $modcss . " declared a css path file into its descriptor that is empty.", LOG_WARNING); |
||
454 | } |
||
455 | // cssfile is a relative path |
||
456 | $urlforcss = dol_buildpath($cssfile, 1); |
||
457 | if ($urlforcss && $urlforcss != '/') { |
||
458 | print '<!-- Includes CSS added by module ' . $modcss . ' -->' . "\n" . '<link rel="stylesheet" type="text/css" href="' . $urlforcss; |
||
459 | // We add params only if page is not static, because some web server setup does not return content type text/css if url has parameters, so browser cache is not used. |
||
460 | if (!preg_match('/\.css$/i', $cssfile)) { |
||
461 | print $themeparam; |
||
462 | } |
||
463 | print '">' . "\n"; |
||
464 | } else { |
||
465 | dol_syslog("Warning: module " . $modcss . " declared a css path file for a file we can't find.", LOG_WARNING); |
||
466 | } |
||
467 | } |
||
468 | } |
||
469 | } |
||
470 | // CSS forced by page in static::topHtmlHead( call (relative url starting with /) |
||
471 | if (is_array($arrayofcss)) { |
||
472 | foreach ($arrayofcss as $cssfile) { |
||
473 | // $cssfile = '/htdocs' . $cssfile; |
||
474 | if (preg_match('/^(http|\/\/)/i', $cssfile)) { |
||
475 | $urltofile = $cssfile; |
||
476 | } else { |
||
477 | $urltofile = dol_buildpath($cssfile, 1); |
||
478 | } |
||
479 | print '<!-- Includes CSS added by page -->' . "\n" . '<link rel="stylesheet" type="text/css" title="default" href="' . $urltofile; |
||
480 | // We add params only if page is not static, because some web server setup does not return content type text/css if url has parameters and browser cache is not used. |
||
481 | if (!preg_match('/\.css$/i', $cssfile)) { |
||
482 | print $themeparam; |
||
483 | } |
||
484 | print '">' . "\n"; |
||
485 | } |
||
486 | } |
||
487 | |||
488 | // Custom CSS |
||
489 | if (getDolGlobalString('MAIN_IHM_CUSTOM_CSS')) { |
||
490 | // If a custom CSS was set, we add link to the custom css php file |
||
491 | print '<link rel="stylesheet" type="text/css" href="' . constant('DOL_URL_ROOT') . '/theme/custom.css.php' . ($ext ? '?' . $ext : '') . '&revision=' . getDolGlobalInt("MAIN_IHM_PARAMS_REV") . '">' . "\n"; |
||
492 | } |
||
493 | |||
494 | // Output standard javascript links |
||
495 | if (!defined('DISABLE_JQUERY') && !$disablejs && !empty($conf->use_javascript_ajax)) { |
||
496 | // JQuery. Must be before other includes |
||
497 | print '<!-- Includes JS for JQuery -->' . "\n"; |
||
498 | if (defined('JS_JQUERY') && constant('JS_JQUERY')) { |
||
499 | print '<script nonce="' . getNonce() . '" src="' . JS_JQUERY . 'jquery.min.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
500 | } else { |
||
501 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/jquery/js/jquery.min.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
502 | } |
||
503 | if (defined('JS_JQUERY_UI') && constant('JS_JQUERY_UI')) { |
||
504 | print '<script nonce="' . getNonce() . '" src="' . JS_JQUERY_UI . 'jquery-ui.min.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
505 | } else { |
||
506 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/jquery/js/jquery-ui.min.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
507 | } |
||
508 | // jQuery jnotify |
||
509 | if (!getDolGlobalString('MAIN_DISABLE_JQUERY_JNOTIFY') && !defined('DISABLE_JQUERY_JNOTIFY')) { |
||
510 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/jquery/plugins/jnotify/jquery.jnotify.min.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
511 | } |
||
512 | // Table drag and drop lines |
||
513 | if (empty($disableforlogin) && !defined('DISABLE_JQUERY_TABLEDND')) { |
||
514 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/jquery/plugins/tablednd/jquery.tablednd.min.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
515 | } |
||
516 | // Chart |
||
517 | if (empty($disableforlogin) && (!getDolGlobalString('MAIN_JS_GRAPH') || getDolGlobalString('MAIN_JS_GRAPH') == 'chart') && !defined('DISABLE_JS_GRAPH')) { |
||
518 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/nnnick/chartjs/dist/chart.min.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
519 | } |
||
520 | |||
521 | // jQuery jeditable for Edit In Place features |
||
522 | if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !defined('DISABLE_JQUERY_JEDITABLE')) { |
||
523 | print '<!-- JS to manage editInPlace feature -->' . "\n"; |
||
524 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/jquery/plugins/jeditable/jquery.jeditable.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
525 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/jquery/plugins/jeditable/jquery.jeditable.ui-datepicker.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
526 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/jquery/plugins/jeditable/jquery.jeditable.ui-autocomplete.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
527 | print '<script>' . "\n"; |
||
528 | print 'var urlSaveInPlace = \'' . constant('DOL_URL_ROOT') . '/core/ajax/saveinplace.php\';' . "\n"; |
||
529 | print 'var urlLoadInPlace = \'' . constant('DOL_URL_ROOT') . '/core/ajax/loadinplace.php\';' . "\n"; |
||
530 | print 'var tooltipInPlace = \'' . $langs->transnoentities('ClickToEdit') . '\';' . "\n"; // Added in title attribute of span |
||
531 | print 'var placeholderInPlace = \' \';' . "\n"; // If we put another string than $langs->trans("ClickToEdit") here, nothing is shown. If we put empty string, there is error, Why ? |
||
532 | print 'var cancelInPlace = \'' . $langs->trans("Cancel") . '\';' . "\n"; |
||
533 | print 'var submitInPlace = \'' . $langs->trans('Ok') . '\';' . "\n"; |
||
534 | print 'var indicatorInPlace = \'<img src="' . constant('DOL_URL_ROOT') . "/theme/" . $conf->theme . "/img/working.gif" . '">\';' . "\n"; |
||
535 | print 'var withInPlace = 300;'; // width in pixel for default string edit |
||
536 | print '</script>' . "\n"; |
||
537 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/core/js/editinplace.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
538 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/jquery/plugins/jeditable/jquery.jeditable.ckeditor.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
539 | } |
||
540 | // jQuery Timepicker |
||
541 | if (getDolGlobalString('MAIN_USE_JQUERY_TIMEPICKER') || defined('REQUIRE_JQUERY_TIMEPICKER')) { |
||
542 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/jquery/plugins/timepicker/jquery-ui-timepicker-addon.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
543 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/core/js/timepicker.js.php?lang=' . $langs->defaultlang . ($ext ? '&' . $ext : '') . '"></script>' . "\n"; |
||
544 | } |
||
545 | if (!defined('DISABLE_SELECT2') && (getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT'))) { |
||
546 | // jQuery plugin "mutiselect", "multiple-select", "select2", ... |
||
547 | $tmpplugin = !getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') ? constant('REQUIRE_JQUERY_MULTISELECT') : $conf->global->MAIN_USE_JQUERY_MULTISELECT; |
||
548 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/jquery/plugins/' . $tmpplugin . '/dist/js/' . $tmpplugin . '.full.min.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; // We include full because we need the support of containerCssClass |
||
549 | } |
||
550 | if (!defined('DISABLE_MULTISELECT')) { // jQuery plugin "mutiselect" to select with checkboxes. Can be removed once we have an enhanced search tool |
||
551 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/jquery/plugins/multiselect/jquery.multi-select.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
552 | } |
||
553 | } |
||
554 | |||
555 | if (!$disablejs && !empty($conf->use_javascript_ajax)) { |
||
556 | // CKEditor |
||
557 | if (empty($disableforlogin) && (isModEnabled('fckeditor') && (!getDolGlobalString('FCKEDITOR_EDITORNAME') || getDolGlobalString('FCKEDITOR_EDITORNAME') == 'ckeditor') && !defined('DISABLE_CKEDITOR')) || defined('FORCE_CKEDITOR')) { |
||
|
|||
558 | print '<!-- Includes JS for CKEditor -->' . "\n"; |
||
559 | $pathckeditor = constant('DOL_URL_ROOT') . '/includes/ckeditor/ckeditor/'; |
||
560 | $jsckeditor = 'ckeditor.js'; |
||
561 | if (constant('JS_CKEDITOR')) { |
||
562 | // To use external ckeditor 4 js lib |
||
563 | $pathckeditor = constant('JS_CKEDITOR'); |
||
564 | } |
||
565 | print '<script nonce="' . getNonce() . '">'; |
||
566 | print '/* enable ckeditor by main.inc.php */'; |
||
567 | print 'var CKEDITOR_BASEPATH = \'' . dol_escape_js($pathckeditor) . '\';' . "\n"; |
||
568 | print 'var ckeditorConfig = \'' . dol_escape_js(dol_buildpath('/htdocs' . $themesubdir . '/theme/' . $conf->theme . '/ckeditor/config.js' . ($ext ? '?' . $ext : ''), 1)) . '\';' . "\n"; // $themesubdir='' in standard usage |
||
569 | print 'var ckeditorFilebrowserBrowseUrl = \'' . constant('DOL_URL_ROOT') . '/core/filemanagerdol/browser/default/browser.php?Connector=' . constant('BASE_URL') . '/core/filemanagerdol/connectors/php/connector.php\';' . "\n"; |
||
570 | print 'var ckeditorFilebrowserImageBrowseUrl = \'' . constant('DOL_URL_ROOT') . '/core/filemanagerdol/browser/default/browser.php?Type=Image&Connector=' . constant('BASE_URL') . '/core/filemanagerdol/connectors/php/connector.php\';' . "\n"; |
||
571 | print '</script>' . "\n"; |
||
572 | print '<script src="' . $pathckeditor . $jsckeditor . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
573 | print '<script>'; |
||
574 | if (GETPOST('mode', 'aZ09') == 'Full_inline') { |
||
575 | print 'CKEDITOR.disableAutoInline = false;' . "\n"; |
||
576 | } else { |
||
577 | print 'CKEDITOR.disableAutoInline = true;' . "\n"; |
||
578 | } |
||
579 | print '</script>' . "\n"; |
||
580 | } |
||
581 | |||
582 | // Browser notifications (if NOREQUIREMENU is on, it is mostly a page for popup, so we do not enable notif too. We hide also for public pages). |
||
583 | if (!defined('NOBROWSERNOTIF') && !defined('NOREQUIREMENU') && !defined('NOLOGIN')) { |
||
584 | $enablebrowsernotif = false; |
||
585 | if (isModEnabled('agenda') && getDolGlobalString('AGENDA_REMINDER_BROWSER')) { |
||
586 | $enablebrowsernotif = true; |
||
587 | } |
||
588 | if ($conf->browser->layout == 'phone') { |
||
589 | $enablebrowsernotif = false; |
||
590 | } |
||
591 | if ($enablebrowsernotif) { |
||
592 | print '<!-- Includes JS of Dolibarr (browser layout = ' . $conf->browser->layout . ')-->' . "\n"; |
||
593 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/core/js/lib_notification.js.php' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
594 | } |
||
595 | } |
||
596 | |||
597 | // Global js function |
||
598 | print '<!-- Includes JS of Dolibarr -->' . "\n"; |
||
599 | print '<script nonce="' . getNonce() . '" src="' . BASE_URL . '/core/js/lib_head.js.php?lang=' . $langs->defaultlang . ($ext ? '&' . $ext : '') . '"></script>' . "\n"; |
||
600 | |||
601 | // Leaflet TODO use dolibarr files |
||
602 | if (getDolGlobalString('MAIN_USE_GEOPHP')) { |
||
603 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/leaflet/leaflet.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
604 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/includes/leaflet/leaflet-geoman.min.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
605 | } |
||
606 | |||
607 | // JS forced by modules (relative url starting with /) |
||
608 | if (!empty($conf->modules_parts['js'])) { // $conf->modules_parts['js'] is array('module'=>array('file1','file2')) |
||
609 | $arrayjs = (array)$conf->modules_parts['js']; |
||
610 | foreach ($arrayjs as $modjs => $filesjs) { |
||
611 | $filesjs = (array)$filesjs; // To be sure filejs is an array |
||
612 | foreach ($filesjs as $jsfile) { |
||
613 | // jsfile is a relative path |
||
614 | $urlforjs = dol_buildpath($jsfile, 3); |
||
615 | if ($urlforjs && $urlforjs != '/') { |
||
616 | print '<!-- Include JS added by module ' . $modjs . '-->' . "\n"; |
||
617 | print '<script nonce="' . getNonce() . '" src="' . $urlforjs . ((strpos($jsfile, '?') === false) ? '?' : '&') . 'lang=' . $langs->defaultlang . '"></script>' . "\n"; |
||
618 | } else { |
||
619 | dol_syslog("Warning: module " . $modjs . " declared a js path file for a file we can't find.", LOG_WARNING); |
||
620 | } |
||
621 | } |
||
622 | } |
||
623 | } |
||
624 | // JS forced by page in static::topHtmlHead( (relative url starting with /) |
||
625 | if (is_array($arrayofjs)) { |
||
626 | print '<!-- Includes JS added by page -->' . "\n"; |
||
627 | foreach ($arrayofjs as $jsfile) { |
||
628 | // $jsfile = '/htdocs' . $jsfile; |
||
629 | if (preg_match('/^(http|\/\/)/i', $jsfile)) { |
||
630 | print '<script nonce="' . getNonce() . '" src="' . $jsfile . ((strpos($jsfile, '?') === false) ? '?' : '&') . 'lang=' . $langs->defaultlang . '"></script>' . "\n"; |
||
631 | } else { |
||
632 | print '<script nonce="' . getNonce() . '" src="' . dol_buildpath($jsfile, 3) . ((strpos($jsfile, '?') === false) ? '?' : '&') . 'lang=' . $langs->defaultlang . '"></script>' . "\n"; |
||
633 | } |
||
634 | } |
||
635 | } |
||
636 | } |
||
637 | |||
638 | //If you want to load custom javascript file from your selected theme directory |
||
639 | if (getDolGlobalString('ALLOW_THEME_JS')) { |
||
640 | $theme_js = dol_buildpath('/theme/' . $conf->theme . '/' . $conf->theme . '.js', 0); |
||
641 | if (file_exists($theme_js)) { |
||
642 | print '<script nonce="' . getNonce() . '" src="' . constant('DOL_URL_ROOT') . '/theme/' . $conf->theme . '/' . $conf->theme . '.js' . ($ext ? '?' . $ext : '') . '"></script>' . "\n"; |
||
643 | } |
||
644 | } |
||
645 | |||
646 | if (!empty($head)) { |
||
647 | print $head . "\n"; |
||
648 | } |
||
649 | if (getDolGlobalString('MAIN_HTML_HEADER')) { |
||
650 | print getDolGlobalString('MAIN_HTML_HEADER') . "\n"; |
||
651 | } |
||
652 | |||
653 | $parameters = array(); |
||
654 | $result = $hookmanager->executeHooks('addHtmlHeader', $parameters); // Note that $action and $object may have been modified by some hooks |
||
655 | print $hookmanager->resPrint; // Replace Title to show |
||
656 | |||
657 | print "</head>\n\n"; |
||
658 | } |
||
659 | |||
660 | $conf->headerdone = 1; // To tell header was output |
||
661 | } |
||
662 | |||
663 | |||
664 | /** |
||
665 | * Show an HTML header + a BODY + The top menu bar |
||
666 | * |
||
667 | * @param string $head Lines in the HEAD |
||
668 | * @param string $title Title of web page |
||
669 | * @param string $target Target to use in menu links (Example: '' or '_top') |
||
670 | * @param int<0,1> $disablejs Do not output links to js (Ex: qd fonction utilisee par sous formulaire Ajax) |
||
671 | * @param int<0,1> $disablehead Do not output head section |
||
672 | * @param string[] $arrayofjs Array of js files to add in header |
||
673 | * @param string[] $arrayofcss Array of css files to add in header |
||
674 | * @param string $morequerystring Query string to add to the link "print" to get same parameters (use only if autodetect fails) |
||
675 | * @param string $helppagename Name of wiki page for help ('' by default). |
||
676 | * Syntax is: For a wiki page: EN:EnglishPage|FR:FrenchPage|ES:SpanishPage|DE:GermanPage |
||
677 | * For other external page: http://server/url |
||
678 | * @return void |
||
679 | */ |
||
680 | public static function topMenu($head, $title = '', $target = '', $disablejs = 0, $disablehead = 0, $arrayofjs = array(), $arrayofcss = array(), $morequerystring = '', $helppagename = '') |
||
681 | { |
||
682 | global $user, $conf, $langs, $db, $form; |
||
683 | global $dolibarr_main_authentication, $dolibarr_main_demo; |
||
684 | global $hookmanager, $menumanager; |
||
685 | |||
686 | $searchform = ''; |
||
687 | |||
688 | // Instantiate hooks for external modules |
||
689 | $hookmanager->initHooks(array('toprightmenu')); |
||
690 | |||
691 | $toprightmenu = ''; |
||
692 | |||
693 | // For backward compatibility with old modules |
||
694 | if (empty($conf->headerdone)) { |
||
695 | $disablenofollow = 0; |
||
696 | static::topHtmlHead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss, 0, $disablenofollow); |
||
697 | print '<body id="mainbody">'; |
||
698 | } |
||
699 | |||
700 | /* |
||
701 | * Top menu |
||
702 | */ |
||
703 | if ((empty($conf->dol_hide_topmenu) || GETPOSTINT('dol_invisible_topmenu')) && (!defined('NOREQUIREMENU') || !constant('NOREQUIREMENU'))) { |
||
704 | if (!isset($form) || !is_object($form)) { |
||
705 | $form = new Form($db); |
||
706 | } |
||
707 | |||
708 | print "\n" . '<!-- Start top horizontal -->' . "\n"; |
||
709 | |||
710 | print '<header id="id-top" class="side-nav-vert' . (GETPOSTINT('dol_invisible_topmenu') ? ' hidden' : '') . '">'; // dol_invisible_topmenu differs from dol_hide_topmenu: dol_invisible_topmenu means we output menu but we make it invisible. |
||
711 | |||
712 | // Show menu entries |
||
713 | print '<div id="tmenu_tooltip' . (!getDolGlobalString('MAIN_MENU_INVERT') ? '' : 'invert') . '" class="tmenu">' . "\n"; |
||
714 | $menumanager->atarget = $target; |
||
715 | $menumanager->showmenu('top', array('searchform' => $searchform)); // This contains a \n |
||
716 | print "</div>\n"; |
||
717 | |||
718 | // Define link to login card |
||
719 | $appli = constant('DOL_APPLICATION_TITLE'); |
||
720 | if (getDolGlobalString('MAIN_APPLICATION_TITLE')) { |
||
721 | $appli = getDolGlobalString('MAIN_APPLICATION_TITLE'); |
||
722 | if (preg_match('/\d\.\d/', $appli)) { |
||
723 | if (!preg_match('/' . preg_quote(DOL_VERSION) . '/', $appli)) { |
||
724 | $appli .= " (" . DOL_VERSION . ")"; // If new title contains a version that is different than core |
||
725 | } |
||
726 | } else { |
||
727 | $appli .= " " . DOL_VERSION; |
||
728 | } |
||
729 | } else { |
||
730 | $appli .= " " . DOL_VERSION; |
||
731 | } |
||
732 | |||
733 | if (getDolGlobalInt('MAIN_FEATURES_LEVEL')) { |
||
734 | $appli .= "<br>" . $langs->trans("LevelOfFeature") . ': ' . getDolGlobalInt('MAIN_FEATURES_LEVEL'); |
||
735 | } |
||
736 | |||
737 | $logouttext = ''; |
||
738 | $logouthtmltext = ''; |
||
739 | if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
||
740 | //$logouthtmltext=$appli.'<br>'; |
||
741 | $stringforfirstkey = $langs->trans("KeyboardShortcut"); |
||
742 | if ($conf->browser->name == 'chrome') { |
||
743 | $stringforfirstkey .= ' ALT +'; |
||
744 | } elseif ($conf->browser->name == 'firefox') { |
||
745 | $stringforfirstkey .= ' ALT + SHIFT +'; |
||
746 | } else { |
||
747 | $stringforfirstkey .= ' CTL +'; |
||
748 | } |
||
749 | if ($_SESSION["dol_authmode"] != 'forceuser' && $_SESSION["dol_authmode"] != 'http') { |
||
750 | $logouthtmltext .= $langs->trans("Logout") . '<br>'; |
||
751 | $logouttext .= '<a accesskey="l" href="' . constant('BASE_URL') . '/user/logout.php?token=' . newToken() . '">'; |
||
752 | $logouttext .= img_picto($langs->trans('Logout') . ' (' . $stringforfirstkey . ' l)', 'sign-out', '', false, 0, 0, '', 'atoplogin valignmiddle'); |
||
753 | $logouttext .= '</a>'; |
||
754 | } else { |
||
755 | $logouthtmltext .= $langs->trans("NoLogoutProcessWithAuthMode", $_SESSION["dol_authmode"]); |
||
756 | $logouttext .= img_picto($langs->trans('Logout') . ' (' . $stringforfirstkey . ' l)', 'sign-out', '', false, 0, 0, '', 'atoplogin valignmiddle opacitymedium'); |
||
757 | } |
||
758 | } |
||
759 | |||
760 | print '<div class="login_block usedropdown">' . "\n"; |
||
761 | |||
762 | $toprightmenu .= '<div class="login_block_other">'; |
||
763 | |||
764 | // Execute hook printTopRightMenu (hooks should output string like '<div class="login"><a href="">mylink</a></div>') |
||
765 | $parameters = array(); |
||
766 | $result = $hookmanager->executeHooks('printTopRightMenu', $parameters); // Note that $action and $object may have been modified by some hooks |
||
767 | if (is_numeric($result)) { |
||
768 | if ($result == 0) { |
||
769 | $toprightmenu .= $hookmanager->resPrint; // add |
||
770 | } else { |
||
771 | $toprightmenu = $hookmanager->resPrint; // replace |
||
772 | } |
||
773 | } else { |
||
774 | $toprightmenu .= $result; // For backward compatibility |
||
775 | } |
||
776 | |||
777 | // Link to module builder |
||
778 | if (isModEnabled('modulebuilder')) { |
||
779 | $text = '<a href="' . constant('BASE_URL') . '/modulebuilder/index.php?mainmenu=home&leftmenu=admintools" target="modulebuilder">'; |
||
780 | //$text.= img_picto(":".$langs->trans("ModuleBuilder"), 'printer_top.png', 'class="printer"'); |
||
781 | $text .= '<span class="fa fa-bug atoplogin valignmiddle"></span>'; |
||
782 | $text .= '</a>'; |
||
783 | // @phan-suppress-next-line PhanPluginSuspiciousParamPosition |
||
784 | $toprightmenu .= $form->textwithtooltip('', $langs->trans("ModuleBuilder"), 2, 1, $text, 'login_block_elem', 2); |
||
785 | } |
||
786 | |||
787 | // Link to print main content area (optioncss=print) |
||
788 | if (!getDolGlobalString('MAIN_PRINT_DISABLELINK') && !getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
||
789 | $qs = dol_escape_htmltag($_SERVER["QUERY_STRING"]); |
||
790 | |||
791 | if (isset($_POST) && is_array($_POST)) { |
||
792 | foreach ($_POST as $key => $value) { |
||
793 | $key = preg_replace('/[^a-z0-9_\.\-\[\]]/i', '', $key); |
||
794 | if (in_array($key, array('action', 'massaction', 'password'))) { |
||
795 | continue; |
||
796 | } |
||
797 | if (!is_array($value)) { |
||
798 | if ($value !== '') { |
||
799 | $qs .= '&' . urlencode($key) . '=' . urlencode($value); |
||
800 | } |
||
801 | } else { |
||
802 | foreach ($value as $value2) { |
||
803 | if (($value2 !== '') && (!is_array($value2))) { |
||
804 | $qs .= '&' . urlencode($key) . '[]=' . urlencode($value2); |
||
805 | } |
||
806 | } |
||
807 | } |
||
808 | } |
||
809 | } |
||
810 | $qs .= (($qs && $morequerystring) ? '&' : '') . $morequerystring; |
||
811 | $text = '<a href="' . dol_escape_htmltag($_SERVER["PHP_SELF"]) . '?' . $qs . ($qs ? '&' : '') . 'optioncss=print" target="_blank" rel="noopener noreferrer">'; |
||
812 | //$text.= img_picto(":".$langs->trans("PrintContentArea"), 'printer_top.png', 'class="printer"'); |
||
813 | $text .= '<span class="fa fa-print atoplogin valignmiddle"></span>'; |
||
814 | $text .= '</a>'; |
||
815 | // @phan-suppress-next-line PhanPluginSuspiciousParamPosition |
||
816 | $toprightmenu .= $form->textwithtooltip('', $langs->trans("PrintContentArea"), 2, 1, $text, 'login_block_elem', 2); |
||
817 | } |
||
818 | |||
819 | // Link to Dolibarr wiki pages |
||
820 | if (!getDolGlobalString('MAIN_HELP_DISABLELINK') && !getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
||
821 | $langs->load("help"); |
||
822 | |||
823 | $helpbaseurl = ''; |
||
824 | $helppage = ''; |
||
825 | $mode = ''; |
||
826 | $helppresent = ''; |
||
827 | |||
828 | if (empty($helppagename)) { |
||
829 | $helppagename = 'EN:User_documentation|FR:Documentation_utilisateur|ES:Documentación_usuarios|DE:Benutzerdokumentation'; |
||
830 | } else { |
||
831 | $helppresent = 'helppresent'; |
||
832 | } |
||
833 | |||
834 | // Get helpbaseurl, helppage and mode from helppagename and langs |
||
835 | $arrayres = static::getHelpParamFor($helppagename, $langs); |
||
836 | $helpbaseurl = $arrayres['helpbaseurl']; |
||
837 | $helppage = $arrayres['helppage']; |
||
838 | $mode = $arrayres['mode']; |
||
839 | |||
840 | // Link to help pages |
||
841 | if ($helpbaseurl && $helppage) { |
||
842 | $text = ''; |
||
843 | $title = $langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage' : 'GoToHelpPage') . ', '; |
||
844 | if ($mode == 'wiki') { |
||
845 | $title .= '<br>' . img_picto('', 'globe', 'class="pictofixedwidth"') . $langs->trans("PageWiki") . ' ' . dol_escape_htmltag('"' . strtr($helppage, '_', ' ') . '"'); |
||
846 | if ($helppresent) { |
||
847 | $title .= ' <span class="opacitymedium">(' . $langs->trans("DedicatedPageAvailable") . ')</span>'; |
||
848 | } else { |
||
849 | $title .= ' <span class="opacitymedium">(' . $langs->trans("HomePage") . ')</span>'; |
||
850 | } |
||
851 | } |
||
852 | $text .= '<a class="help" target="_blank" rel="noopener noreferrer" href="'; |
||
853 | if ($mode == 'wiki') { |
||
854 | // @phan-suppress-next-line PhanPluginPrintfVariableFormatString |
||
855 | $text .= sprintf($helpbaseurl, urlencode(html_entity_decode($helppage))); |
||
856 | } else { |
||
857 | // @phan-suppress-next-line PhanPluginPrintfVariableFormatString |
||
858 | $text .= sprintf($helpbaseurl, $helppage); |
||
859 | } |
||
860 | $text .= '">'; |
||
861 | $text .= '<span class="fa fa-question-circle atoplogin valignmiddle' . ($helppresent ? ' ' . $helppresent : '') . '"></span>'; |
||
862 | $text .= '<span class="fa fa-long-arrow-alt-up helppresentcircle' . ($helppresent ? '' : ' unvisible') . '"></span>'; |
||
863 | $text .= '</a>'; |
||
864 | // @phan-suppress-next-line PhanPluginSuspiciousParamPosition |
||
865 | $toprightmenu .= $form->textwithtooltip('', $title, 2, 1, $text, 'login_block_elem', 2); |
||
866 | } |
||
867 | |||
868 | // Version |
||
869 | if (getDolGlobalString('MAIN_SHOWDATABASENAMEINHELPPAGESLINK')) { |
||
870 | $langs->load('admin'); |
||
871 | $appli .= '<br>' . $langs->trans("Database") . ': ' . $db->database_name; |
||
872 | } |
||
873 | } |
||
874 | |||
875 | if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
||
876 | $text = '<span class="aversion"><span class="hideonsmartphone small">' . DOL_VERSION . '</span></span>'; |
||
877 | // @phan-suppress-next-line PhanPluginSuspiciousParamPosition |
||
878 | $toprightmenu .= $form->textwithtooltip('', $appli, 2, 1, $text, 'login_block_elem', 2); |
||
879 | } |
||
880 | |||
881 | // Logout link |
||
882 | $toprightmenu .= $form->textwithtooltip('', $logouthtmltext, 2, 1, $logouttext, 'login_block_elem logout-btn', 2); |
||
883 | |||
884 | $toprightmenu .= '</div>'; // end div class="login_block_other" |
||
885 | |||
886 | |||
887 | // Add login user link |
||
888 | $toprightmenu .= '<div class="login_block_user">'; |
||
889 | |||
890 | // Login name with photo and tooltip |
||
891 | $mode = -1; |
||
892 | $toprightmenu .= '<div class="inline-block login_block_elem login_block_elem_name nowrap centpercent" style="padding: 0px;">'; |
||
893 | |||
894 | if (getDolGlobalString('MAIN_USE_TOP_MENU_SEARCH_DROPDOWN')) { |
||
895 | // Add search dropdown |
||
896 | $toprightmenu .= static::topSearchMenu(); |
||
897 | } |
||
898 | |||
899 | if (getDolGlobalString('MAIN_USE_TOP_MENU_QUICKADD_DROPDOWN')) { |
||
900 | // Add search dropdown |
||
901 | $toprightmenu .= static::topMenuQuickAdd(); |
||
902 | } |
||
903 | |||
904 | // Add bookmark dropdown |
||
905 | $toprightmenu .= static::topMenuBookmark(); |
||
906 | |||
907 | // Add user dropdown |
||
908 | $toprightmenu .= static::topMenuUser(); |
||
909 | |||
910 | $toprightmenu .= '</div>'; |
||
911 | |||
912 | $toprightmenu .= '</div>' . "\n"; |
||
913 | |||
914 | |||
915 | print $toprightmenu; |
||
916 | |||
917 | print "</div>\n"; // end div class="login_block" |
||
918 | |||
919 | print '</header>'; |
||
920 | //print '<header class="header2"> </header>'; |
||
921 | |||
922 | print '<div style="clear: both;"></div>'; |
||
923 | print "<!-- End top horizontal menu -->\n\n"; |
||
924 | } |
||
925 | |||
926 | if (empty($conf->dol_hide_leftmenu) && empty($conf->dol_use_jmobile)) { |
||
927 | print '<!-- Begin div id-container --><div id="id-container" class="id-container">'; |
||
928 | } |
||
929 | } |
||
930 | |||
931 | /** |
||
932 | * Build the tooltip on user login |
||
933 | * |
||
934 | * @param int<0,1> $hideloginname Hide login name. Show only the image. |
||
935 | * @param string $urllogout URL for logout (Will use DOL_URL_ROOT.'/user/logout.php?token=...' if empty) |
||
936 | * @return string HTML content |
||
937 | */ |
||
938 | public static function topMenuUser($hideloginname = 0, $urllogout = '') |
||
939 | { |
||
940 | global $langs, $conf, $db, $hookmanager, $user, $mysoc; |
||
941 | global $dolibarr_main_authentication, $dolibarr_main_demo; |
||
942 | global $menumanager; |
||
943 | |||
944 | $langs->load('companies'); |
||
945 | |||
946 | $userImage = $userDropDownImage = ''; |
||
947 | if (!empty($user->photo)) { |
||
948 | $userImage = Form::showphoto('userphoto', $user, 0, 0, 0, 'photouserphoto userphoto', 'small', 0, 1); |
||
949 | $userDropDownImage = Form::showphoto('userphoto', $user, 0, 0, 0, 'dropdown-user-image', 'small', 0, 1); |
||
950 | } else { |
||
951 | $nophoto = '/public/theme/common/user_anonymous.png'; |
||
952 | if ($user->gender == 'man') { |
||
953 | $nophoto = '/public/theme/common/user_man.png'; |
||
954 | } |
||
955 | if ($user->gender == 'woman') { |
||
956 | $nophoto = '/public/theme/common/user_woman.png'; |
||
957 | } |
||
958 | |||
959 | $userImage = '<img class="photo photouserphoto userphoto" alt="" src="' . constant('DOL_URL_ROOT') . $nophoto . '">'; |
||
960 | $userDropDownImage = '<img class="photo dropdown-user-image" alt="" src="' . constant('DOL_URL_ROOT') . $nophoto . '">'; |
||
961 | } |
||
962 | |||
963 | $dropdownBody = ''; |
||
964 | $dropdownBody .= '<span id="topmenulogincompanyinfo-btn"><i class="fa fa-caret-right"></i> ' . $langs->trans("ShowCompanyInfos") . '</span>'; |
||
965 | $dropdownBody .= '<div id="topmenulogincompanyinfo" >'; |
||
966 | |||
967 | $dropdownBody .= '<br><b>' . $langs->trans("Company") . '</b>: <span>' . dol_escape_htmltag($mysoc->name) . '</span>'; |
||
968 | if ($langs->transcountry("ProfId1", $mysoc->country_code) != '-') { |
||
969 | $dropdownBody .= '<br><b>' . $langs->transcountry("ProfId1", $mysoc->country_code) . '</b>: <span>' . dol_print_profids(getDolGlobalString("MAIN_INFO_SIREN"), 1) . '</span>'; |
||
970 | } |
||
971 | if ($langs->transcountry("ProfId2", $mysoc->country_code) != '-') { |
||
972 | $dropdownBody .= '<br><b>' . $langs->transcountry("ProfId2", $mysoc->country_code) . '</b>: <span>' . dol_print_profids(getDolGlobalString("MAIN_INFO_SIRET"), 2) . '</span>'; |
||
973 | } |
||
974 | if ($langs->transcountry("ProfId3", $mysoc->country_code) != '-') { |
||
975 | $dropdownBody .= '<br><b>' . $langs->transcountry("ProfId3", $mysoc->country_code) . '</b>: <span>' . dol_print_profids(getDolGlobalString("MAIN_INFO_APE"), 3) . '</span>'; |
||
976 | } |
||
977 | if ($langs->transcountry("ProfId4", $mysoc->country_code) != '-') { |
||
978 | $dropdownBody .= '<br><b>' . $langs->transcountry("ProfId4", $mysoc->country_code) . '</b>: <span>' . dol_print_profids(getDolGlobalString("MAIN_INFO_RCS"), 4) . '</span>'; |
||
979 | } |
||
980 | if ($langs->transcountry("ProfId5", $mysoc->country_code) != '-') { |
||
981 | $dropdownBody .= '<br><b>' . $langs->transcountry("ProfId5", $mysoc->country_code) . '</b>: <span>' . dol_print_profids(getDolGlobalString("MAIN_INFO_PROFID5"), 5) . '</span>'; |
||
982 | } |
||
983 | if ($langs->transcountry("ProfId6", $mysoc->country_code) != '-') { |
||
984 | $dropdownBody .= '<br><b>' . $langs->transcountry("ProfId6", $mysoc->country_code) . '</b>: <span>' . dol_print_profids(getDolGlobalString("MAIN_INFO_PROFID6"), 6) . '</span>'; |
||
985 | } |
||
986 | $dropdownBody .= '<br><b>' . $langs->trans("VATIntraShort") . '</b>: <span>' . dol_print_profids(getDolGlobalString("MAIN_INFO_TVAINTRA"), 'VAT') . '</span>'; |
||
987 | $dropdownBody .= '<br><b>' . $langs->trans("Country") . '</b>: <span>' . ($mysoc->country_code ? $langs->trans("Country" . $mysoc->country_code) : '') . '</span>'; |
||
988 | if (isModEnabled('multicurrency')) { |
||
989 | $dropdownBody .= '<br><b>' . $langs->trans("Currency") . '</b>: <span>' . $conf->currency . '</span>'; |
||
990 | } |
||
991 | $dropdownBody .= '</div>'; |
||
992 | |||
993 | $dropdownBody .= '<br>'; |
||
994 | $dropdownBody .= '<span id="topmenuloginmoreinfo-btn"><i class="fa fa-caret-right"></i> ' . $langs->trans("ShowMoreInfos") . '</span>'; |
||
995 | $dropdownBody .= '<div id="topmenuloginmoreinfo" >'; |
||
996 | |||
997 | // login infos |
||
998 | if (!empty($user->admin)) { |
||
999 | $dropdownBody .= '<br><b>' . $langs->trans("Administrator") . '</b>: ' . yn($user->admin); |
||
1000 | } |
||
1001 | if (!empty($user->socid)) { // Add thirdparty for external users |
||
1002 | $thirdpartystatic = new Societe($db); |
||
1003 | $thirdpartystatic->fetch($user->socid); |
||
1004 | $companylink = ' ' . $thirdpartystatic->getNomUrl(2); // picto only of company |
||
1005 | $company = ' (' . $langs->trans("Company") . ': ' . $thirdpartystatic->name . ')'; |
||
1006 | } |
||
1007 | $type = ($user->socid ? $langs->trans("External") . $company : $langs->trans("Internal")); |
||
1008 | $dropdownBody .= '<br><b>' . $langs->trans("Type") . ':</b> ' . $type; |
||
1009 | $dropdownBody .= '<br><b>' . $langs->trans("Status") . '</b>: ' . $user->getLibStatut(0); |
||
1010 | $dropdownBody .= '<br>'; |
||
1011 | |||
1012 | $dropdownBody .= '<br><u>' . $langs->trans("Session") . '</u>'; |
||
1013 | $dropdownBody .= '<br><b>' . $langs->trans("IPAddress") . '</b>: ' . dol_escape_htmltag($_SERVER["REMOTE_ADDR"]); |
||
1014 | if (getDolGlobalString('MAIN_MODULE_MULTICOMPANY')) { |
||
1015 | $dropdownBody .= '<br><b>' . $langs->trans("ConnectedOnMultiCompany") . ':</b> ' . $conf->entity . ' (user entity ' . $user->entity . ')'; |
||
1016 | } |
||
1017 | $dropdownBody .= '<br><b>' . $langs->trans("AuthenticationMode") . ':</b> ' . $_SESSION["dol_authmode"] . (empty($dolibarr_main_demo) ? '' : ' (demo)'); |
||
1018 | $dropdownBody .= '<br><b>' . $langs->trans("ConnectedSince") . ':</b> ' . dol_print_date($user->datelastlogin, "dayhour", 'tzuser'); |
||
1019 | $dropdownBody .= '<br><b>' . $langs->trans("PreviousConnexion") . ':</b> ' . dol_print_date($user->datepreviouslogin, "dayhour", 'tzuser'); |
||
1020 | $dropdownBody .= '<br><b>' . $langs->trans("CurrentTheme") . ':</b> ' . $conf->theme; |
||
1021 | $dropdownBody .= '<br><b>' . $langs->trans("CurrentMenuManager") . ':</b> ' . (isset($menumanager) ? $menumanager->name : 'unknown'); |
||
1022 | $langFlag = picto_from_langcode($langs->getDefaultLang()); |
||
1023 | $dropdownBody .= '<br><b>' . $langs->trans("CurrentUserLanguage") . ':</b> ' . ($langFlag ? $langFlag . ' ' : '') . $langs->getDefaultLang(); |
||
1024 | |||
1025 | $tz = (int)$_SESSION['dol_tz'] + (int)$_SESSION['dol_dst']; |
||
1026 | $dropdownBody .= '<br><b>' . $langs->trans("ClientTZ") . ':</b> ' . ($tz ? ($tz >= 0 ? '+' : '') . $tz : ''); |
||
1027 | $dropdownBody .= ' (' . $_SESSION['dol_tz_string'] . ')'; |
||
1028 | //$dropdownBody .= ' '.$langs->trans("DaylingSavingTime").': '; |
||
1029 | //if ($_SESSION['dol_dst'] > 0) $dropdownBody .= yn(1); |
||
1030 | //else $dropdownBody .= yn(0); |
||
1031 | |||
1032 | $dropdownBody .= '<br><b>' . $langs->trans("Browser") . ':</b> ' . $conf->browser->name . ($conf->browser->version ? ' ' . $conf->browser->version : '') . ' <small class="opacitymedium">(' . dol_escape_htmltag($_SERVER['HTTP_USER_AGENT']) . ')</small>'; |
||
1033 | $dropdownBody .= '<br><b>' . $langs->trans("Layout") . ':</b> ' . $conf->browser->layout; |
||
1034 | $dropdownBody .= '<br><b>' . $langs->trans("Screen") . ':</b> ' . $_SESSION['dol_screenwidth'] . ' x ' . $_SESSION['dol_screenheight']; |
||
1035 | if ($conf->browser->layout == 'phone') { |
||
1036 | $dropdownBody .= '<br><b>' . $langs->trans("Phone") . ':</b> ' . $langs->trans("Yes"); |
||
1037 | } |
||
1038 | if (!empty($_SESSION["disablemodules"])) { |
||
1039 | $dropdownBody .= '<br><b>' . $langs->trans("DisabledModules") . ':</b> <br>' . implode(', ', explode(',', $_SESSION["disablemodules"])); |
||
1040 | } |
||
1041 | $dropdownBody .= '</div>'; |
||
1042 | |||
1043 | // Execute hook |
||
1044 | $parameters = array('user' => $user, 'langs' => $langs); |
||
1045 | $result = $hookmanager->executeHooks('printTopRightMenuLoginDropdownBody', $parameters); // Note that $action and $object may have been modified by some hooks |
||
1046 | if (is_numeric($result)) { |
||
1047 | if ($result == 0) { |
||
1048 | $dropdownBody .= $hookmanager->resPrint; // add |
||
1049 | } else { |
||
1050 | $dropdownBody = $hookmanager->resPrint; // replace |
||
1051 | } |
||
1052 | } |
||
1053 | |||
1054 | if (empty($urllogout)) { |
||
1055 | $urllogout = BASE_URL . '/user/logout.php?token=' . newToken(); |
||
1056 | } |
||
1057 | |||
1058 | // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox |
||
1059 | // accesskey is for Mac: CTRL + key for all browsers |
||
1060 | $stringforfirstkey = $langs->trans("KeyboardShortcut"); |
||
1061 | if ($conf->browser->name == 'chrome') { |
||
1062 | $stringforfirstkey .= ' ALT +'; |
||
1063 | } elseif ($conf->browser->name == 'firefox') { |
||
1064 | $stringforfirstkey .= ' ALT + SHIFT +'; |
||
1065 | } else { |
||
1066 | $stringforfirstkey .= ' CTL +'; |
||
1067 | } |
||
1068 | |||
1069 | // Defined the links for bottom of card |
||
1070 | $profilLink = '<a accesskey="u" href="' . BASE_URL . '/user/card.php?id=' . $user->id . '" class="button-top-menu-dropdown" title="' . dol_escape_htmltag($langs->trans("YourUserFile") . ' (' . $stringforfirstkey . ' u)') . '"><i class="fa fa-user"></i> ' . $langs->trans("Card") . '</a>'; |
||
1071 | $urltovirtualcard = '/user/virtualcard.php?id=' . ((int)$user->id); |
||
1072 | $virtuelcardLink = dolButtonToOpenUrlInDialogPopup('publicvirtualcardmenu', $langs->transnoentitiesnoconv("PublicVirtualCardUrl") . (is_object($user) ? ' - ' . $user->getFullName($langs) : '') . ' (' . $stringforfirstkey . ' v)', img_picto($langs->trans("PublicVirtualCardUrl") . ' (' . $stringforfirstkey . ' v)', 'card', ''), $urltovirtualcard, '', 'button-top-menu-dropdown marginleftonly nohover', "closeTopMenuLoginDropdown()", '', 'v'); |
||
1073 | $logoutLink = '<a accesskey="l" href="' . $urllogout . '" class="button-top-menu-dropdown" title="' . dol_escape_htmltag($langs->trans("Logout") . ' (' . $stringforfirstkey . ' l)') . '"><i class="fa fa-sign-out-alt padingright"></i><span class="hideonsmartphone">' . $langs->trans("Logout") . '</span></a>'; |
||
1074 | |||
1075 | $profilName = $user->getFullName($langs) . ' (' . $user->login . ')'; |
||
1076 | if (!empty($user->admin)) { |
||
1077 | $profilName = '<i class="far fa-star classfortooltip" title="' . $langs->trans("Administrator") . '" ></i> ' . $profilName; |
||
1078 | } |
||
1079 | |||
1080 | // Define version to show |
||
1081 | $appli = constant('DOL_APPLICATION_TITLE'); |
||
1082 | if (getDolGlobalString('MAIN_APPLICATION_TITLE')) { |
||
1083 | $appli = getDolGlobalString('MAIN_APPLICATION_TITLE'); |
||
1084 | if (preg_match('/\d\.\d/', $appli)) { |
||
1085 | if (!preg_match('/' . preg_quote(DOL_VERSION) . '/', $appli)) { |
||
1086 | $appli .= " (" . DOL_VERSION . ")"; // If new title contains a version that is different than core |
||
1087 | } |
||
1088 | } else { |
||
1089 | $appli .= " " . DOL_VERSION; |
||
1090 | } |
||
1091 | } else { |
||
1092 | $appli .= " " . DOL_VERSION; |
||
1093 | } |
||
1094 | |||
1095 | if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
||
1096 | $btnUser = '<!-- div for user link --> |
||
1097 | <div id="topmenu-login-dropdown" class="userimg atoplogin dropdown user user-menu inline-block"> |
||
1098 | <a href="' . constant('BASE_URL') . '/user/card.php?id=' . $user->id . '" class="dropdown-toggle login-dropdown-a valignmiddle" data-toggle="dropdown"> |
||
1099 | ' . $userImage . (empty($user->photo) ? '<!-- no photo so show also the login --><span class="hidden-xs maxwidth200 atoploginusername hideonsmartphone paddingleft valignmiddle small">' . dol_trunc($user->firstname ? $user->firstname : $user->login, 10) . '</span>' : '') . ' |
||
1100 | </a> |
||
1101 | <div class="dropdown-menu"> |
||
1102 | <!-- User image --> |
||
1103 | <div class="user-header"> |
||
1104 | ' . $userDropDownImage . ' |
||
1105 | <p> |
||
1106 | ' . $profilName . '<br>'; |
||
1107 | if ($user->datelastlogin) { |
||
1108 | $title = $langs->trans("ConnectedSince") . ' : ' . dol_print_date($user->datelastlogin, "dayhour", 'tzuser'); |
||
1109 | if ($user->datepreviouslogin) { |
||
1110 | $title .= '<br>' . $langs->trans("PreviousConnexion") . ' : ' . dol_print_date($user->datepreviouslogin, "dayhour", 'tzuser'); |
||
1111 | } |
||
1112 | } |
||
1113 | $btnUser .= '<small class="classfortooltip" title="' . dol_escape_htmltag($title) . '" ><i class="fa fa-user-clock"></i> ' . dol_print_date($user->datelastlogin, "dayhour", 'tzuser') . '</small><br>'; |
||
1114 | if ($user->datepreviouslogin) { |
||
1115 | $btnUser .= '<small class="classfortooltip" title="' . dol_escape_htmltag($title) . '" ><i class="fa fa-user-clock opacitymedium"></i> ' . dol_print_date($user->datepreviouslogin, "dayhour", 'tzuser') . '</small><br>'; |
||
1116 | } |
||
1117 | |||
1118 | //$btnUser .= '<small class="classfortooltip"><i class="fa fa-cog"></i> '.$langs->trans("Version").' '.$appli.'</small>'; |
||
1119 | $btnUser .= ' |
||
1120 | </p> |
||
1121 | </div> |
||
1122 | |||
1123 | <!-- Menu Body user--> |
||
1124 | <div class="user-body">' . $dropdownBody . '</div> |
||
1125 | |||
1126 | <!-- Menu Footer--> |
||
1127 | <div class="user-footer"> |
||
1128 | <div class="pull-left"> |
||
1129 | ' . $profilLink . ' |
||
1130 | </div> |
||
1131 | <div class="pull-left"> |
||
1132 | ' . $virtuelcardLink . ' |
||
1133 | </div> |
||
1134 | <div class="pull-right"> |
||
1135 | ' . $logoutLink . ' |
||
1136 | </div> |
||
1137 | <div class="clearboth"></div> |
||
1138 | </div> |
||
1139 | |||
1140 | </div> |
||
1141 | </div>'; |
||
1142 | } else { |
||
1143 | $btnUser = '<!-- div for user link text browser --> |
||
1144 | <div id="topmenu-login-dropdown" class="userimg atoplogin dropdown user user-menu inline-block"> |
||
1145 | <a href="' . constant('BASE_URL') . '/user/card.php?id=' . $user->id . '" class="valignmiddle" alt="' . $langs->trans("MyUserCard") . '"> |
||
1146 | ' . $userImage . (empty($user->photo) ? '<span class="hidden-xs maxwidth200 atoploginusername hideonsmartphone paddingleft small">' . dol_trunc($user->firstname ? $user->firstname : $user->login, 10) . '</span>' : '') . ' |
||
1147 | </a> |
||
1148 | </div>'; |
||
1149 | } |
||
1150 | |||
1151 | if (!defined('JS_JQUERY_DISABLE_DROPDOWN') && !empty($conf->use_javascript_ajax)) { // This may be set by some pages that use different jquery version to avoid errors |
||
1152 | $btnUser .= ' |
||
1153 | <!-- Code to show/hide the user drop-down --> |
||
1154 | <script> |
||
1155 | function closeTopMenuLoginDropdown() { |
||
1156 | //console.log("close login dropdown"); // This is call at each click on page, so we disable the log |
||
1157 | // Hide the menus. |
||
1158 | jQuery("#topmenu-login-dropdown").removeClass("open"); |
||
1159 | } |
||
1160 | jQuery(document).ready(function() { |
||
1161 | jQuery(document).on("click", function(event) { |
||
1162 | // console.log("Click somewhere on screen"); |
||
1163 | if (!$(event.target).closest("#topmenu-login-dropdown").length) { |
||
1164 | closeTopMenuLoginDropdown(); |
||
1165 | } |
||
1166 | }); |
||
1167 | '; |
||
1168 | |||
1169 | |||
1170 | //if ($conf->theme != 'md') { |
||
1171 | $btnUser .= ' |
||
1172 | jQuery("#topmenu-login-dropdown .dropdown-toggle").on("click", function(event) { |
||
1173 | console.log("Click on #topmenu-login-dropdown .dropdown-toggle"); |
||
1174 | event.preventDefault(); |
||
1175 | jQuery("#topmenu-login-dropdown").toggleClass("open"); |
||
1176 | }); |
||
1177 | |||
1178 | jQuery("#topmenulogincompanyinfo-btn").on("click", function() { |
||
1179 | console.log("Click on #topmenulogincompanyinfo-btn"); |
||
1180 | jQuery("#topmenulogincompanyinfo").slideToggle(); |
||
1181 | }); |
||
1182 | |||
1183 | jQuery("#topmenuloginmoreinfo-btn").on("click", function() { |
||
1184 | console.log("Click on #topmenuloginmoreinfo-btn"); |
||
1185 | jQuery("#topmenuloginmoreinfo").slideToggle(); |
||
1186 | });'; |
||
1187 | //} |
||
1188 | |||
1189 | $btnUser .= ' |
||
1190 | }); |
||
1191 | </script> |
||
1192 | '; |
||
1193 | } |
||
1194 | |||
1195 | return $btnUser; |
||
1196 | } |
||
1197 | |||
1198 | /** |
||
1199 | * Build the tooltip on top menu quick add |
||
1200 | * |
||
1201 | * @return string HTML content |
||
1202 | */ |
||
1203 | public static function topMenuQuickAdd() |
||
1204 | { |
||
1205 | global $conf, $langs; |
||
1206 | |||
1207 | // Button disabled on text browser |
||
1208 | if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
||
1209 | return ''; |
||
1210 | } |
||
1211 | |||
1212 | $html = ''; |
||
1213 | |||
1214 | // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox |
||
1215 | // accesskey is for Mac: CTRL + key for all browsers |
||
1216 | $stringforfirstkey = $langs->trans("KeyboardShortcut"); |
||
1217 | if ($conf->browser->os === 'macintosh') { |
||
1218 | $stringforfirstkey .= ' CTL +'; |
||
1219 | } else { |
||
1220 | if ($conf->browser->name == 'chrome') { |
||
1221 | $stringforfirstkey .= ' ALT +'; |
||
1222 | } elseif ($conf->browser->name == 'firefox') { |
||
1223 | $stringforfirstkey .= ' ALT + SHIFT +'; |
||
1224 | } else { |
||
1225 | $stringforfirstkey .= ' CTL +'; |
||
1226 | } |
||
1227 | } |
||
1228 | |||
1229 | if (!empty($conf->use_javascript_ajax)) { |
||
1230 | $html .= '<!-- div for quick add link --> |
||
1231 | <div id="topmenu-quickadd-dropdown" class="atoplogin dropdown inline-block"> |
||
1232 | <a accesskey="a" class="dropdown-toggle login-dropdown-a nofocusvisible" data-toggle="dropdown" href="#" title="' . $langs->trans('QuickAdd') . ' (' . $stringforfirstkey . ' a)"><i class="fa fa-plus-circle"></i></a> |
||
1233 | <div class="dropdown-menu">' . static::printDropdownQuickadd() . '</div> |
||
1234 | </div>'; |
||
1235 | if (!defined('JS_JQUERY_DISABLE_DROPDOWN')) { // This may be set by some pages that use different jquery version to avoid errors |
||
1236 | $html .= ' |
||
1237 | <!-- Code to show/hide the user drop-down for the quick add --> |
||
1238 | <script> |
||
1239 | jQuery(document).ready(function() { |
||
1240 | jQuery(document).on("click", function(event) { |
||
1241 | if (!$(event.target).closest("#topmenu-quickadd-dropdown").length) { |
||
1242 | // Hide the menus. |
||
1243 | $("#topmenu-quickadd-dropdown").removeClass("open"); |
||
1244 | } |
||
1245 | }); |
||
1246 | $("#topmenu-quickadd-dropdown .dropdown-toggle").on("click", function(event) { |
||
1247 | console.log("Click on #topmenu-quickadd-dropdown .dropdown-toggle"); |
||
1248 | openQuickAddDropDown(event); |
||
1249 | }); |
||
1250 | |||
1251 | // Key map shortcut |
||
1252 | $(document).keydown(function(event){ |
||
1253 | var ostype = \'' . dol_escape_js($conf->browser->os) . '\'; |
||
1254 | if (ostype === "macintosh") { |
||
1255 | if ( event.which === 65 && event.ctrlKey ) { |
||
1256 | console.log(\'control + a : trigger open quick add dropdown\'); |
||
1257 | openQuickAddDropDown(event); |
||
1258 | } |
||
1259 | } else { |
||
1260 | if ( event.which === 65 && event.ctrlKey && event.shiftKey ) { |
||
1261 | console.log(\'control + shift + a : trigger open quick add dropdown\'); |
||
1262 | openQuickAddDropDown(event); |
||
1263 | } |
||
1264 | } |
||
1265 | }); |
||
1266 | |||
1267 | var openQuickAddDropDown = function(event) { |
||
1268 | event.preventDefault(); |
||
1269 | $("#topmenu-quickadd-dropdown").toggleClass("open"); |
||
1270 | //$("#top-quickadd-search-input").focus(); |
||
1271 | } |
||
1272 | }); |
||
1273 | </script> |
||
1274 | '; |
||
1275 | } |
||
1276 | } |
||
1277 | |||
1278 | return $html; |
||
1279 | } |
||
1280 | |||
1281 | /** |
||
1282 | * Generate list of quickadd items |
||
1283 | * |
||
1284 | * @return string HTML output |
||
1285 | */ |
||
1286 | public static function printDropdownQuickadd() |
||
1287 | { |
||
1288 | global $user, $langs, $hookmanager; |
||
1289 | |||
1290 | $items = array( |
||
1291 | 'items' => array( |
||
1292 | array( |
||
1293 | "url" => "/adherents/card.php?action=create&mainmenu=members", |
||
1294 | "title" => "MenuNewMember@members", |
||
1295 | "name" => "Adherent@members", |
||
1296 | "picto" => "object_member", |
||
1297 | "activation" => isModEnabled('member') && $user->hasRight("adherent", "write"), // vs hooking |
||
1298 | "position" => 5, |
||
1299 | ), |
||
1300 | array( |
||
1301 | "url" => "/societe/card.php?action=create&mainmenu=companies", |
||
1302 | "title" => "MenuNewThirdParty@companies", |
||
1303 | "name" => "ThirdParty@companies", |
||
1304 | "picto" => "object_company", |
||
1305 | "activation" => isModEnabled("societe") && $user->hasRight("societe", "write"), // vs hooking |
||
1306 | "position" => 10, |
||
1307 | ), |
||
1308 | array( |
||
1309 | "url" => "/contact/card.php?action=create&mainmenu=companies", |
||
1310 | "title" => "NewContactAddress@companies", |
||
1311 | "name" => "Contact@companies", |
||
1312 | "picto" => "object_contact", |
||
1313 | "activation" => isModEnabled("societe") && $user->hasRight("societe", "contact", "write"), // vs hooking |
||
1314 | "position" => 20, |
||
1315 | ), |
||
1316 | array( |
||
1317 | "url" => "/comm/propal/card.php?action=create&mainmenu=commercial", |
||
1318 | "title" => "NewPropal@propal", |
||
1319 | "name" => "Proposal@propal", |
||
1320 | "picto" => "object_propal", |
||
1321 | "activation" => isModEnabled("propal") && $user->hasRight("propal", "write"), // vs hooking |
||
1322 | "position" => 30, |
||
1323 | ), |
||
1324 | |||
1325 | array( |
||
1326 | "url" => "/commande/card.php?action=create&mainmenu=commercial", |
||
1327 | "title" => "NewOrder@orders", |
||
1328 | "name" => "Order@orders", |
||
1329 | "picto" => "object_order", |
||
1330 | "activation" => isModEnabled('order') && $user->hasRight("commande", "write"), // vs hooking |
||
1331 | "position" => 40, |
||
1332 | ), |
||
1333 | array( |
||
1334 | "url" => "/compta/facture/card.php?action=create&mainmenu=billing", |
||
1335 | "title" => "NewBill@bills", |
||
1336 | "name" => "Bill@bills", |
||
1337 | "picto" => "object_bill", |
||
1338 | "activation" => isModEnabled('invoice') && $user->hasRight("facture", "write"), // vs hooking |
||
1339 | "position" => 50, |
||
1340 | ), |
||
1341 | array( |
||
1342 | "url" => "/contrat/card.php?action=create&mainmenu=commercial", |
||
1343 | "title" => "NewContractSubscription@contracts", |
||
1344 | "name" => "Contract@contracts", |
||
1345 | "picto" => "object_contract", |
||
1346 | "activation" => isModEnabled('contract') && $user->hasRight("contrat", "write"), // vs hooking |
||
1347 | "position" => 60, |
||
1348 | ), |
||
1349 | array( |
||
1350 | "url" => "/supplier_proposal/card.php?action=create&mainmenu=commercial", |
||
1351 | "title" => "SupplierProposalNew@supplier_proposal", |
||
1352 | "name" => "SupplierProposal@supplier_proposal", |
||
1353 | "picto" => "supplier_proposal", |
||
1354 | "activation" => isModEnabled('supplier_proposal') && $user->hasRight("supplier_invoice", "write"), // vs hooking |
||
1355 | "position" => 70, |
||
1356 | ), |
||
1357 | array( |
||
1358 | "url" => "/fourn/commande/card.php?action=create&mainmenu=commercial", |
||
1359 | "title" => "NewSupplierOrderShort@orders", |
||
1360 | "name" => "SupplierOrder@orders", |
||
1361 | "picto" => "supplier_order", |
||
1362 | "activation" => (isModEnabled("fournisseur") && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "commande", "write")) || (isModEnabled("supplier_order") && $user->hasRight("supplier_invoice", "write")), // vs hooking |
||
1363 | "position" => 80, |
||
1364 | ), |
||
1365 | array( |
||
1366 | "url" => "/fourn/facture/card.php?action=create&mainmenu=billing", |
||
1367 | "title" => "NewBill@bills", |
||
1368 | "name" => "SupplierBill@bills", |
||
1369 | "picto" => "supplier_invoice", |
||
1370 | "activation" => (isModEnabled("fournisseur") && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "facture", "write")) || (isModEnabled("supplier_invoice") && $user->hasRight("supplier_invoice", "write")), // vs hooking |
||
1371 | "position" => 90, |
||
1372 | ), |
||
1373 | array( |
||
1374 | "url" => "/ticket/card.php?action=create&mainmenu=ticket", |
||
1375 | "title" => "NewTicket@ticket", |
||
1376 | "name" => "Ticket@ticket", |
||
1377 | "picto" => "ticket", |
||
1378 | "activation" => isModEnabled('ticket') && $user->hasRight("ticket", "write"), // vs hooking |
||
1379 | "position" => 100, |
||
1380 | ), |
||
1381 | array( |
||
1382 | "url" => "/fichinter/card.php?action=create&mainmenu=commercial", |
||
1383 | "title" => "NewIntervention@interventions", |
||
1384 | "name" => "Intervention@interventions", |
||
1385 | "picto" => "intervention", |
||
1386 | "activation" => isModEnabled('intervention') && $user->hasRight("ficheinter", "creer"), // vs hooking |
||
1387 | "position" => 110, |
||
1388 | ), |
||
1389 | array( |
||
1390 | "url" => "/product/card.php?action=create&type=0&mainmenu=products", |
||
1391 | "title" => "NewProduct@products", |
||
1392 | "name" => "Product@products", |
||
1393 | "picto" => "object_product", |
||
1394 | "activation" => isModEnabled("product") && $user->hasRight("produit", "write"), // vs hooking |
||
1395 | "position" => 400, |
||
1396 | ), |
||
1397 | array( |
||
1398 | "url" => "/product/card.php?action=create&type=1&mainmenu=products", |
||
1399 | "title" => "NewService@products", |
||
1400 | "name" => "Service@products", |
||
1401 | "picto" => "object_service", |
||
1402 | "activation" => isModEnabled("service") && $user->hasRight("service", "write"), // vs hooking |
||
1403 | "position" => 410, |
||
1404 | ), |
||
1405 | array( |
||
1406 | "url" => "/user/card.php?action=create&type=1&mainmenu=home", |
||
1407 | "title" => "AddUser@users", |
||
1408 | "name" => "User@users", |
||
1409 | "picto" => "user", |
||
1410 | "activation" => $user->hasRight("user", "user", "write"), // vs hooking |
||
1411 | "position" => 500, |
||
1412 | ), |
||
1413 | ), |
||
1414 | ); |
||
1415 | |||
1416 | $dropDownQuickAddHtml = ''; |
||
1417 | |||
1418 | // Define $dropDownQuickAddHtml |
||
1419 | $dropDownQuickAddHtml .= '<div class="quickadd-body dropdown-body">'; |
||
1420 | $dropDownQuickAddHtml .= '<div class="dropdown-quickadd-list">'; |
||
1421 | |||
1422 | // Allow the $items of the menu to be manipulated by modules |
||
1423 | $parameters = array(); |
||
1424 | $hook_items = $items; |
||
1425 | $reshook = $hookmanager->executeHooks('menuDropdownQuickaddItems', $parameters, $hook_items); // Note that $action and $object may have been modified by some hooks |
||
1426 | if (is_numeric($reshook) && !empty($hookmanager->resArray) && is_array($hookmanager->resArray)) { |
||
1427 | if ($reshook == 0) { |
||
1428 | $items['items'] = array_merge($items['items'], $hookmanager->resArray); // add |
||
1429 | } else { |
||
1430 | $items = $hookmanager->resArray; // replace |
||
1431 | } |
||
1432 | |||
1433 | // Sort menu items by 'position' value |
||
1434 | $position = array(); |
||
1435 | foreach ($items['items'] as $key => $row) { |
||
1436 | $position[$key] = $row['position']; |
||
1437 | } |
||
1438 | $array1_sort_order = SORT_ASC; |
||
1439 | array_multisort($position, $array1_sort_order, $items['items']); |
||
1440 | } |
||
1441 | |||
1442 | foreach ($items['items'] as $item) { |
||
1443 | if (!$item['activation']) { |
||
1444 | continue; |
||
1445 | } |
||
1446 | $langs->load(explode('@', $item['title'])[1]); |
||
1447 | $langs->load(explode('@', $item['name'])[1]); |
||
1448 | $dropDownQuickAddHtml .= ' |
||
1449 | <a class="dropdown-item quickadd-item" href="' . constant('DOL_URL_ROOT') . $item['url'] . '" title="' . $langs->trans(explode('@', $item['title'])[0]) . '"> |
||
1450 | ' . img_picto('', $item['picto'], 'style="width:18px;"') . ' ' . $langs->trans(explode('@', $item['name'])[0]) . '</a> |
||
1451 | '; |
||
1452 | } |
||
1453 | |||
1454 | $dropDownQuickAddHtml .= '</div>'; |
||
1455 | $dropDownQuickAddHtml .= '</div>'; |
||
1456 | |||
1457 | return $dropDownQuickAddHtml; |
||
1458 | } |
||
1459 | |||
1460 | /** |
||
1461 | * Build the tooltip on top menu bookmark |
||
1462 | * |
||
1463 | * @return string HTML content |
||
1464 | */ |
||
1465 | public static function topMenuBookmark() |
||
1466 | { |
||
1467 | global $langs, $conf, $db, $user; |
||
1468 | |||
1469 | $html = ''; |
||
1470 | |||
1471 | // Define $bookmarks |
||
1472 | if (!isModEnabled('bookmark') || !$user->hasRight('bookmark', 'lire')) { |
||
1473 | return $html; |
||
1474 | } |
||
1475 | |||
1476 | // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox |
||
1477 | // accesskey is for Mac: CTRL + key for all browsers |
||
1478 | $stringforfirstkey = $langs->trans("KeyboardShortcut"); |
||
1479 | if ($conf->browser->os === 'macintosh') { |
||
1480 | $stringforfirstkey .= ' CTL +'; |
||
1481 | } else { |
||
1482 | if ($conf->browser->name == 'chrome') { |
||
1483 | $stringforfirstkey .= ' ALT +'; |
||
1484 | } elseif ($conf->browser->name == 'firefox') { |
||
1485 | $stringforfirstkey .= ' ALT + SHIFT +'; |
||
1486 | } else { |
||
1487 | $stringforfirstkey .= ' CTL +'; |
||
1488 | } |
||
1489 | } |
||
1490 | |||
1491 | if (!defined('JS_JQUERY_DISABLE_DROPDOWN') && !empty($conf->use_javascript_ajax)) { // This may be set by some pages that use different jquery version to avoid errors |
||
1492 | include_once DOL_DOCUMENT_ROOT . '/bookmarks/lib/bookmarks.lib.php'; |
||
1493 | $langs->load("bookmarks"); |
||
1494 | |||
1495 | if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
||
1496 | $html .= '<div id="topmenu-bookmark-dropdown" class="dropdown inline-block">'; |
||
1497 | $html .= printDropdownBookmarksList(); |
||
1498 | $html .= '</div>'; |
||
1499 | } else { |
||
1500 | $html .= '<!-- div for bookmark link --> |
||
1501 | <div id="topmenu-bookmark-dropdown" class="dropdown inline-block"> |
||
1502 | <a accesskey="b" class="dropdown-toggle login-dropdown-a nofocusvisible" data-toggle="dropdown" href="#" title="' . $langs->trans('Bookmarks') . ' (' . $stringforfirstkey . ' b)"><i class="fa fa-star"></i></a> |
||
1503 | <div class="dropdown-menu"> |
||
1504 | ' . printDropdownBookmarksList() . ' |
||
1505 | </div> |
||
1506 | </div>'; |
||
1507 | |||
1508 | $html .= ' |
||
1509 | <!-- Code to show/hide the bookmark drop-down --> |
||
1510 | <script> |
||
1511 | jQuery(document).ready(function() { |
||
1512 | jQuery(document).on("click", function(event) { |
||
1513 | if (!$(event.target).closest("#topmenu-bookmark-dropdown").length) { |
||
1514 | //console.log("close bookmark dropdown - we click outside"); |
||
1515 | // Hide the menus. |
||
1516 | $("#topmenu-bookmark-dropdown").removeClass("open"); |
||
1517 | } |
||
1518 | }); |
||
1519 | |||
1520 | jQuery("#topmenu-bookmark-dropdown .dropdown-toggle").on("click", function(event) { |
||
1521 | console.log("Click on #topmenu-bookmark-dropdown .dropdown-toggle"); |
||
1522 | openBookMarkDropDown(event); |
||
1523 | }); |
||
1524 | |||
1525 | // Key map shortcut |
||
1526 | jQuery(document).keydown(function(event) { |
||
1527 | var ostype = \'' . dol_escape_js($conf->browser->os) . '\'; |
||
1528 | if (ostype === "macintosh") { |
||
1529 | if ( event.which === 66 && event.ctrlKey ) { |
||
1530 | console.log("Click on control + b : trigger open bookmark dropdown"); |
||
1531 | openBookMarkDropDown(event); |
||
1532 | } |
||
1533 | } else { |
||
1534 | if ( event.which === 66 && event.ctrlKey && event.shiftKey ) { |
||
1535 | console.log("Click on control + shift + b : trigger open bookmark dropdown"); |
||
1536 | openBookMarkDropDown(event); |
||
1537 | } |
||
1538 | } |
||
1539 | }); |
||
1540 | |||
1541 | var openBookMarkDropDown = function(event) { |
||
1542 | event.preventDefault(); |
||
1543 | jQuery("#topmenu-bookmark-dropdown").toggleClass("open"); |
||
1544 | jQuery("#top-bookmark-search-input").focus(); |
||
1545 | } |
||
1546 | |||
1547 | }); |
||
1548 | </script> |
||
1549 | '; |
||
1550 | } |
||
1551 | } |
||
1552 | return $html; |
||
1553 | } |
||
1554 | |||
1555 | /** |
||
1556 | * Build the tooltip on top menu tsearch |
||
1557 | * |
||
1558 | * @return string HTML content |
||
1559 | */ |
||
1560 | public static function topSearchMenu() |
||
1561 | { |
||
1562 | global $langs, $conf, $db, $user, $hookmanager; |
||
1563 | |||
1564 | $html = ''; |
||
1565 | |||
1566 | $usedbyinclude = 1; |
||
1567 | $arrayresult = array(); |
||
1568 | include DOL_DOCUMENT_ROOT . '/core/ajax/selectsearchbox.php'; // This sets $arrayresult |
||
1569 | |||
1570 | // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox |
||
1571 | // accesskey is for Mac: CTRL + key for all browsers |
||
1572 | $stringforfirstkey = $langs->trans("KeyboardShortcut"); |
||
1573 | if ($conf->browser->name == 'chrome') { |
||
1574 | $stringforfirstkey .= ' ALT +'; |
||
1575 | } elseif ($conf->browser->name == 'firefox') { |
||
1576 | $stringforfirstkey .= ' ALT + SHIFT +'; |
||
1577 | } else { |
||
1578 | $stringforfirstkey .= ' CTL +'; |
||
1579 | } |
||
1580 | |||
1581 | $searchInput = '<input type="search" name="search_all"' . ($stringforfirstkey ? ' title="' . dol_escape_htmltag($stringforfirstkey . ' s') . '"' : '') . ' id="top-global-search-input" class="dropdown-search-input search_component_input" placeholder="' . $langs->trans('Search') . '" autocomplete="off">'; |
||
1582 | |||
1583 | $defaultAction = ''; |
||
1584 | $buttonList = '<div class="dropdown-global-search-button-list" >'; |
||
1585 | // Menu with all searchable items |
||
1586 | foreach ($arrayresult as $keyItem => $item) { |
||
1587 | if (empty($defaultAction)) { |
||
1588 | $defaultAction = $item['url']; |
||
1589 | } |
||
1590 | $buttonList .= '<button class="dropdown-item global-search-item tdoverflowmax300" data-target="' . dol_escape_htmltag($item['url']) . '" >'; |
||
1591 | $buttonList .= $item['text']; |
||
1592 | $buttonList .= '</button>'; |
||
1593 | } |
||
1594 | $buttonList .= '</div>'; |
||
1595 | |||
1596 | $dropDownHtml = '<form role="search" id="top-menu-action-search" name="actionsearch" method="GET" action="' . $defaultAction . '">'; |
||
1597 | |||
1598 | $dropDownHtml .= ' |
||
1599 | <!-- search input --> |
||
1600 | <div class="dropdown-header search-dropdown-header"> |
||
1601 | ' . $searchInput . ' |
||
1602 | </div> |
||
1603 | '; |
||
1604 | |||
1605 | $dropDownHtml .= ' |
||
1606 | <!-- Menu Body search --> |
||
1607 | <div class="dropdown-body search-dropdown-body"> |
||
1608 | ' . $buttonList . ' |
||
1609 | </div> |
||
1610 | '; |
||
1611 | |||
1612 | $dropDownHtml .= '</form>'; |
||
1613 | |||
1614 | // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox |
||
1615 | // accesskey is for Mac: CTRL + key for all browsers |
||
1616 | $stringforfirstkey = $langs->trans("KeyboardShortcut"); |
||
1617 | if ($conf->browser->name == 'chrome') { |
||
1618 | $stringforfirstkey .= ' ALT +'; |
||
1619 | } elseif ($conf->browser->name == 'firefox') { |
||
1620 | $stringforfirstkey .= ' ALT + SHIFT +'; |
||
1621 | } else { |
||
1622 | $stringforfirstkey .= ' CTL +'; |
||
1623 | } |
||
1624 | |||
1625 | $html .= '<!-- div for Global Search --> |
||
1626 | <div id="topmenu-global-search-dropdown" class="atoplogin dropdown inline-block"> |
||
1627 | <a accesskey="s" class="dropdown-toggle login-dropdown-a nofocusvisible" data-toggle="dropdown" href="#" title="' . $langs->trans('Search') . ' (' . $stringforfirstkey . ' s)"> |
||
1628 | <i class="fa fa-search" aria-hidden="true" ></i> |
||
1629 | </a> |
||
1630 | <div class="dropdown-menu dropdown-search"> |
||
1631 | ' . $dropDownHtml . ' |
||
1632 | </div> |
||
1633 | </div>'; |
||
1634 | |||
1635 | $html .= ' |
||
1636 | <!-- Code to show/hide the user drop-down --> |
||
1637 | <script> |
||
1638 | jQuery(document).ready(function() { |
||
1639 | |||
1640 | // prevent submitting form on press ENTER |
||
1641 | jQuery("#top-global-search-input").keydown(function (e) { |
||
1642 | if (e.keyCode == 13 || e.keyCode == 40) { |
||
1643 | var inputs = $(this).parents("form").eq(0).find(":button"); |
||
1644 | if (inputs[inputs.index(this) + 1] != null) { |
||
1645 | inputs[inputs.index(this) + 1].focus(); |
||
1646 | if (e.keyCode == 13){ |
||
1647 | inputs[inputs.index(this) + 1].trigger("click"); |
||
1648 | } |
||
1649 | |||
1650 | } |
||
1651 | e.preventDefault(); |
||
1652 | return false; |
||
1653 | } |
||
1654 | }); |
||
1655 | |||
1656 | // arrow key nav |
||
1657 | jQuery(document).keydown(function(e) { |
||
1658 | // Get the focused element: |
||
1659 | var $focused = $(":focus"); |
||
1660 | if($focused.length && $focused.hasClass("global-search-item")){ |
||
1661 | |||
1662 | // UP - move to the previous line |
||
1663 | if (e.keyCode == 38) { |
||
1664 | e.preventDefault(); |
||
1665 | $focused.prev().focus(); |
||
1666 | } |
||
1667 | |||
1668 | // DOWN - move to the next line |
||
1669 | if (e.keyCode == 40) { |
||
1670 | e.preventDefault(); |
||
1671 | $focused.next().focus(); |
||
1672 | } |
||
1673 | } |
||
1674 | }); |
||
1675 | |||
1676 | |||
1677 | // submit form action |
||
1678 | jQuery(".dropdown-global-search-button-list .global-search-item").on("click", function(event) { |
||
1679 | jQuery("#top-menu-action-search").attr("action", $(this).data("target")); |
||
1680 | jQuery("#top-menu-action-search").submit(); |
||
1681 | }); |
||
1682 | |||
1683 | // close drop down |
||
1684 | jQuery(document).on("click", function(event) { |
||
1685 | if (!$(event.target).closest("#topmenu-global-search-dropdown").length) { |
||
1686 | console.log("click close search - we click outside"); |
||
1687 | // Hide the menus. |
||
1688 | jQuery("#topmenu-global-search-dropdown").removeClass("open"); |
||
1689 | } |
||
1690 | }); |
||
1691 | |||
1692 | // Open drop down |
||
1693 | jQuery("#topmenu-global-search-dropdown .dropdown-toggle").on("click", function(event) { |
||
1694 | console.log("click on toggle #topmenu-global-search-dropdown .dropdown-toggle"); |
||
1695 | openGlobalSearchDropDown(); |
||
1696 | }); |
||
1697 | |||
1698 | // Key map shortcut |
||
1699 | jQuery(document).keydown(function(e){ |
||
1700 | if ( e.which === 70 && e.ctrlKey && e.shiftKey ) { |
||
1701 | console.log(\'control + shift + f : trigger open global-search dropdown\'); |
||
1702 | openGlobalSearchDropDown(); |
||
1703 | } |
||
1704 | if ( e.which === 70 && e.alKey ) { |
||
1705 | console.log(\'alt + f : trigger open global-search dropdown\'); |
||
1706 | openGlobalSearchDropDown(); |
||
1707 | } |
||
1708 | }); |
||
1709 | |||
1710 | var openGlobalSearchDropDown = function() { |
||
1711 | jQuery("#topmenu-global-search-dropdown").toggleClass("open"); |
||
1712 | jQuery("#top-global-search-input").focus(); |
||
1713 | } |
||
1714 | |||
1715 | }); |
||
1716 | </script> |
||
1717 | '; |
||
1718 | |||
1719 | return $html; |
||
1720 | } |
||
1721 | |||
1722 | /** |
||
1723 | * Show left menu bar |
||
1724 | * |
||
1725 | * @param string $menu_array_before Table of menu entries to show before entries of menu handler. This param is deprecated and must be provided to ''. |
||
1726 | * @param string $helppagename Name of wiki page for help ('' by default). |
||
1727 | * Syntax is: For a wiki page: EN:EnglishPage|FR:FrenchPage|ES:SpanishPage|DE:GermanPage |
||
1728 | * For other external page: http://server/url |
||
1729 | * @param string $notused Deprecated. Used in past to add content into left menu. Hooks can be used now. |
||
1730 | * @param array $menu_array_after Table of menu entries to show after entries of menu handler |
||
1731 | * @param int $leftmenuwithoutmainarea Must be set to 1. 0 by default for backward compatibility with old modules. |
||
1732 | * @param string $title Title of web page |
||
1733 | * @param int<0,1> $acceptdelayedhtml 1 if caller request to have html delayed content not returned but saved into global $delayedhtmlcontent (so caller can show it at end of page to avoid flash FOUC effect) |
||
1734 | * @return void |
||
1735 | */ |
||
1736 | public static function leftMenu($menu_array_before, $helppagename = '', $notused = '', $menu_array_after = array(), $leftmenuwithoutmainarea = 0, $title = '', $acceptdelayedhtml = 0) |
||
1737 | { |
||
1738 | global $user, $conf, $langs, $db, $form; |
||
1739 | global $hookmanager, $menumanager; |
||
1740 | |||
1741 | $searchform = ''; |
||
1742 | |||
1743 | if (!empty($menu_array_before)) { |
||
1744 | dol_syslog("Deprecated parameter menu_array_before was used when calling main::left_menu function. Menu entries of module should now be defined into module descriptor and not provided when calling left_menu.", LOG_WARNING); |
||
1745 | } |
||
1746 | |||
1747 | if (empty($conf->dol_hide_leftmenu) && (!defined('NOREQUIREMENU') || !constant('NOREQUIREMENU'))) { |
||
1748 | // Instantiate hooks for external modules |
||
1749 | $hookmanager->initHooks(array('leftblock')); |
||
1750 | |||
1751 | print "\n" . '<!-- Begin side-nav id-left -->' . "\n" . '<div class="side-nav"><div id="id-left">' . "\n"; |
||
1752 | print "\n"; |
||
1753 | |||
1754 | if (!is_object($form)) { |
||
1755 | $form = new Form($db); |
||
1756 | } |
||
1757 | $selected = -1; |
||
1758 | if (!getDolGlobalString('MAIN_USE_TOP_MENU_SEARCH_DROPDOWN')) { |
||
1759 | // Select with select2 is awful on smartphone. TODO Is this still true with select2 v4 ? |
||
1760 | if ($conf->browser->layout == 'phone') { |
||
1761 | $conf->global->MAIN_USE_OLD_SEARCH_FORM = 1; |
||
1762 | } |
||
1763 | |||
1764 | $usedbyinclude = 1; |
||
1765 | $arrayresult = array(); |
||
1766 | include DOL_DOCUMENT_ROOT . '/core/ajax/selectsearchbox.php'; // This make initHooks('searchform') then set $arrayresult |
||
1767 | |||
1768 | if ($conf->use_javascript_ajax && !getDolGlobalString('MAIN_USE_OLD_SEARCH_FORM')) { |
||
1769 | // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox |
||
1770 | // accesskey is for Mac: CTRL + key for all browsers |
||
1771 | $stringforfirstkey = $langs->trans("KeyboardShortcut"); |
||
1772 | if ($conf->browser->name == 'chrome') { |
||
1773 | $stringforfirstkey .= ' ALT +'; |
||
1774 | } elseif ($conf->browser->name == 'firefox') { |
||
1775 | $stringforfirstkey .= ' ALT + SHIFT +'; |
||
1776 | } else { |
||
1777 | $stringforfirstkey .= ' CTL +'; |
||
1778 | } |
||
1779 | |||
1780 | //$textsearch = $langs->trans("Search"); |
||
1781 | $textsearch = '<span class="fa fa-search paddingright pictofixedwidth"></span>' . $langs->trans("Search"); |
||
1782 | $searchform .= $form->selectArrayFilter('searchselectcombo', $arrayresult, $selected, 'accesskey="s"', 1, 0, (!getDolGlobalString('MAIN_SEARCHBOX_CONTENT_LOADED_BEFORE_KEY') ? 1 : 0), 'vmenusearchselectcombo', 1, $textsearch, 1, $stringforfirstkey . ' s'); |
||
1783 | } else { |
||
1784 | if (is_array($arrayresult)) { |
||
1785 | foreach ($arrayresult as $key => $val) { |
||
1786 | $searchform .= static::printSearchForm($val['url'], $val['url'], $val['label'], 'maxwidth125', 'search_all', (empty($val['shortcut']) ? '' : $val['shortcut']), 'searchleft' . $key, $val['img']); |
||
1787 | } |
||
1788 | } |
||
1789 | } |
||
1790 | |||
1791 | // Execute hook printSearchForm |
||
1792 | $parameters = array('searchform' => $searchform); |
||
1793 | $reshook = $hookmanager->executeHooks('printSearchForm', $parameters); // Note that $action and $object may have been modified by some hooks |
||
1794 | if (empty($reshook)) { |
||
1795 | $searchform .= $hookmanager->resPrint; |
||
1796 | } else { |
||
1797 | $searchform = $hookmanager->resPrint; |
||
1798 | } |
||
1799 | |||
1800 | // Force special value for $searchform for text browsers or very old search form |
||
1801 | if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER') || empty($conf->use_javascript_ajax)) { |
||
1802 | $urltosearch = constant('BASE_URL') . '/core/search_page.php?showtitlebefore=1'; |
||
1803 | $searchform = '<div class="blockvmenuimpair blockvmenusearchphone"><div id="divsearchforms1"><a href="' . $urltosearch . '" accesskey="s" alt="' . dol_escape_htmltag($langs->trans("ShowSearchFields")) . '">' . $langs->trans("Search") . '...</a></div></div>'; |
||
1804 | } elseif ($conf->use_javascript_ajax && getDolGlobalString('MAIN_USE_OLD_SEARCH_FORM')) { |
||
1805 | $searchform = '<div class="blockvmenuimpair blockvmenusearchphone"><div id="divsearchforms1"><a href="#" alt="' . dol_escape_htmltag($langs->trans("ShowSearchFields")) . '">' . $langs->trans("Search") . '...</a></div><div id="divsearchforms2" style="display: none">' . $searchform . '</div>'; |
||
1806 | $searchform .= '<script> |
||
1807 | jQuery(document).ready(function () { |
||
1808 | jQuery("#divsearchforms1").click(function(){ |
||
1809 | jQuery("#divsearchforms2").toggle(); |
||
1810 | }); |
||
1811 | }); |
||
1812 | </script>' . "\n"; |
||
1813 | $searchform .= '</div>'; |
||
1814 | } |
||
1815 | |||
1816 | // Key map shortcut |
||
1817 | $searchform .= '<script> |
||
1818 | jQuery(document).keydown(function(e){ |
||
1819 | if( e.which === 70 && e.ctrlKey && e.shiftKey ){ |
||
1820 | console.log(\'control + shift + f : trigger open global-search dropdown\'); |
||
1821 | openGlobalSearchDropDown(); |
||
1822 | } |
||
1823 | if( (e.which === 83 || e.which === 115) && e.altKey ){ |
||
1824 | console.log(\'alt + s : trigger open global-search dropdown\'); |
||
1825 | openGlobalSearchDropDown(); |
||
1826 | } |
||
1827 | }); |
||
1828 | |||
1829 | var openGlobalSearchDropDown = function() { |
||
1830 | jQuery("#searchselectcombo").select2(\'open\'); |
||
1831 | } |
||
1832 | </script>'; |
||
1833 | } |
||
1834 | |||
1835 | // Left column |
||
1836 | print '<!-- Begin left menu -->' . "\n"; |
||
1837 | |||
1838 | print '<div class="vmenu"' . (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER') ? ' alt="Left menu"' : '') . '>' . "\n\n"; |
||
1839 | |||
1840 | // Show left menu with other forms |
||
1841 | $menumanager->menu_array = $menu_array_before; |
||
1842 | $menumanager->menu_array_after = $menu_array_after; |
||
1843 | $menumanager->showmenu('left', array('searchform' => $searchform)); // output menu_array and menu found in database |
||
1844 | |||
1845 | // Dolibarr version + help + bug report link |
||
1846 | print "\n"; |
||
1847 | print "<!-- Begin Help Block-->\n"; |
||
1848 | print '<div id="blockvmenuhelp" class="blockvmenuhelp">' . "\n"; |
||
1849 | |||
1850 | // Version |
||
1851 | if (getDolGlobalString('MAIN_SHOW_VERSION')) { // Version is already on help picto and on login page. |
||
1852 | $doliurl = 'https://www.dolibarr.org'; |
||
1853 | //local communities |
||
1854 | if (preg_match('/fr/i', $langs->defaultlang)) { |
||
1855 | $doliurl = 'https://www.dolibarr.fr'; |
||
1856 | } |
||
1857 | if (preg_match('/es/i', $langs->defaultlang)) { |
||
1858 | $doliurl = 'https://www.dolibarr.es'; |
||
1859 | } |
||
1860 | if (preg_match('/de/i', $langs->defaultlang)) { |
||
1861 | $doliurl = 'https://www.dolibarr.de'; |
||
1862 | } |
||
1863 | if (preg_match('/it/i', $langs->defaultlang)) { |
||
1864 | $doliurl = 'https://www.dolibarr.it'; |
||
1865 | } |
||
1866 | if (preg_match('/gr/i', $langs->defaultlang)) { |
||
1867 | $doliurl = 'https://www.dolibarr.gr'; |
||
1868 | } |
||
1869 | |||
1870 | $appli = constant('DOL_APPLICATION_TITLE'); |
||
1871 | if (getDolGlobalString('MAIN_APPLICATION_TITLE')) { |
||
1872 | $appli = getDolGlobalString('MAIN_APPLICATION_TITLE'); |
||
1873 | $doliurl = ''; |
||
1874 | if (preg_match('/\d\.\d/', $appli)) { |
||
1875 | if (!preg_match('/' . preg_quote(DOL_VERSION) . '/', $appli)) { |
||
1876 | $appli .= " (" . DOL_VERSION . ")"; // If new title contains a version that is different than core |
||
1877 | } |
||
1878 | } else { |
||
1879 | $appli .= " " . DOL_VERSION; |
||
1880 | } |
||
1881 | } else { |
||
1882 | $appli .= " " . DOL_VERSION; |
||
1883 | } |
||
1884 | print '<div id="blockvmenuhelpapp" class="blockvmenuhelp">'; |
||
1885 | if ($doliurl) { |
||
1886 | print '<a class="help" target="_blank" rel="noopener noreferrer" href="' . $doliurl . '">'; |
||
1887 | } else { |
||
1888 | print '<span class="help">'; |
||
1889 | } |
||
1890 | print $appli; |
||
1891 | if ($doliurl) { |
||
1892 | print '</a>'; |
||
1893 | } else { |
||
1894 | print '</span>'; |
||
1895 | } |
||
1896 | print '</div>' . "\n"; |
||
1897 | } |
||
1898 | |||
1899 | // Link to bugtrack |
||
1900 | if (getDolGlobalString('MAIN_BUGTRACK_ENABLELINK')) { |
||
1901 | require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/functions2.lib.php'; |
||
1902 | |||
1903 | if (getDolGlobalString('MAIN_BUGTRACK_ENABLELINK') == 'github') { |
||
1904 | $bugbaseurl = 'https://github.com/Dolibarr/dolibarr/issues/new?labels=Bug'; |
||
1905 | $bugbaseurl .= '&title='; |
||
1906 | $bugbaseurl .= urlencode("Bug: "); |
||
1907 | $bugbaseurl .= '&body='; |
||
1908 | $bugbaseurl .= urlencode("# Instructions\n"); |
||
1909 | $bugbaseurl .= urlencode("*This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.*\n"); |
||
1910 | $bugbaseurl .= urlencode("*Please:*\n"); |
||
1911 | $bugbaseurl .= urlencode("- *replace the bracket enclosed texts with meaningful information*\n"); |
||
1912 | $bugbaseurl .= urlencode("- *remove any unused sub-section*\n"); |
||
1913 | $bugbaseurl .= urlencode("\n"); |
||
1914 | $bugbaseurl .= urlencode("\n"); |
||
1915 | $bugbaseurl .= urlencode("# Bug\n"); |
||
1916 | $bugbaseurl .= urlencode("[*Short description*]\n"); |
||
1917 | $bugbaseurl .= urlencode("\n"); |
||
1918 | $bugbaseurl .= urlencode("## Environment\n"); |
||
1919 | $bugbaseurl .= urlencode("- **Version**: " . DOL_VERSION . "\n"); |
||
1920 | $bugbaseurl .= urlencode("- **OS**: " . php_uname('s') . "\n"); |
||
1921 | $bugbaseurl .= urlencode("- **Web server**: " . $_SERVER["SERVER_SOFTWARE"] . "\n"); |
||
1922 | $bugbaseurl .= urlencode("- **PHP**: " . php_sapi_name() . ' ' . phpversion() . "\n"); |
||
1923 | $bugbaseurl .= urlencode("- **Database**: " . $db::LABEL . ' ' . $db->getVersion() . "\n"); |
||
1924 | $bugbaseurl .= urlencode("- **URL(s)**: " . $_SERVER["REQUEST_URI"] . "\n"); |
||
1925 | $bugbaseurl .= urlencode("\n"); |
||
1926 | $bugbaseurl .= urlencode("## Expected and actual behavior\n"); |
||
1927 | $bugbaseurl .= urlencode("[*Verbose description*]\n"); |
||
1928 | $bugbaseurl .= urlencode("\n"); |
||
1929 | $bugbaseurl .= urlencode("## Steps to reproduce the behavior\n"); |
||
1930 | $bugbaseurl .= urlencode("[*Verbose description*]\n"); |
||
1931 | $bugbaseurl .= urlencode("\n"); |
||
1932 | $bugbaseurl .= urlencode("## [Attached files](https://help.github.com/articles/issue-attachments) (Screenshots, screencasts, alixar.log, debugging information…)\n"); |
||
1933 | $bugbaseurl .= urlencode("[*Files*]\n"); |
||
1934 | $bugbaseurl .= urlencode("\n"); |
||
1935 | |||
1936 | $bugbaseurl .= urlencode("\n"); |
||
1937 | $bugbaseurl .= urlencode("## Report\n"); |
||
1938 | } elseif (getDolGlobalString('MAIN_BUGTRACK_ENABLELINK')) { |
||
1939 | $bugbaseurl = getDolGlobalString('MAIN_BUGTRACK_ENABLELINK'); |
||
1940 | } else { |
||
1941 | $bugbaseurl = ""; |
||
1942 | } |
||
1943 | |||
1944 | // Execute hook printBugtrackInfo |
||
1945 | $parameters = array('bugbaseurl' => $bugbaseurl); |
||
1946 | $reshook = $hookmanager->executeHooks('printBugtrackInfo', $parameters); // Note that $action and $object may have been modified by some hooks |
||
1947 | if (empty($reshook)) { |
||
1948 | $bugbaseurl .= $hookmanager->resPrint; |
||
1949 | } else { |
||
1950 | $bugbaseurl = $hookmanager->resPrint; |
||
1951 | } |
||
1952 | |||
1953 | print '<div id="blockvmenuhelpbugreport" class="blockvmenuhelp">'; |
||
1954 | print '<a class="help" target="_blank" rel="noopener noreferrer" href="' . $bugbaseurl . '"><i class="fas fa-bug"></i> ' . $langs->trans("FindBug") . '</a>'; |
||
1955 | print '</div>'; |
||
1956 | } |
||
1957 | |||
1958 | print "</div>\n"; |
||
1959 | print "<!-- End Help Block-->\n"; |
||
1960 | print "\n"; |
||
1961 | |||
1962 | print "</div>\n"; |
||
1963 | print "<!-- End left menu -->\n"; |
||
1964 | print "\n"; |
||
1965 | |||
1966 | // Execute hook printLeftBlock |
||
1967 | $parameters = array(); |
||
1968 | $reshook = $hookmanager->executeHooks('printLeftBlock', $parameters); // Note that $action and $object may have been modified by some hooks |
||
1969 | print $hookmanager->resPrint; |
||
1970 | |||
1971 | print '</div></div> <!-- End side-nav id-left -->'; // End div id="side-nav" div id="id-left" |
||
1972 | } |
||
1973 | |||
1974 | print "\n"; |
||
1975 | print '<!-- Begin right area -->' . "\n"; |
||
1976 | |||
1977 | if (empty($leftmenuwithoutmainarea)) { |
||
1978 | static::mainArea($title); |
||
1979 | } |
||
1980 | } |
||
1981 | |||
1982 | /** |
||
1983 | * Begin main area |
||
1984 | * |
||
1985 | * @param string $title Title |
||
1986 | * @return void |
||
1987 | */ |
||
1988 | public static function mainArea($title = '') |
||
2038 | } |
||
2039 | } |
||
2040 | } |
||
2041 | |||
2042 | /** |
||
2043 | * Return helpbaseurl, helppage and mode |
||
2044 | * |
||
2045 | * @param string $helppagename Page name ('EN:xxx,ES:eee,FR:fff,DE:ddd...' or 'http://localpage') |
||
2046 | * @param Translate $langs Language |
||
2047 | * @return array{helpbaseurl:string,helppage:string,mode:string} Array of help urls |
||
2048 | */ |
||
2049 | public static function getHelpParamFor($helppagename, $langs) |
||
2090 | } |
||
2091 | |||
2092 | /** |
||
2093 | * Show a search area. |
||
2094 | * Used when the javascript quick search is not used. |
||
2095 | * |
||
2096 | * @param string $urlaction Url post |
||
2097 | * @param string $urlobject Url of the link under the search box |
||
2098 | * @param string $title Title search area |
||
2099 | * @param string $htmlmorecss Add more css |
||
2100 | * @param string $htmlinputname Field Name input form |
||
2101 | * @param string $accesskey Accesskey |
||
2102 | * @param string $prefhtmlinputname Complement for id to avoid multiple same id in the page |
||
2103 | * @param string $img Image to use |
||
2104 | * @param int $showtitlebefore Show title before input text instead of into placeholder. This can be set when output is dedicated for text browsers. |
||
2105 | * @param int $autofocus Set autofocus on field |
||
2106 | * @return string |
||
2107 | */ |
||
2108 | public static function printSearchForm($urlaction, $urlobject, $title, $htmlmorecss, $htmlinputname, $accesskey = '', $prefhtmlinputname = '', $img = '', $showtitlebefore = 0, $autofocus = 0) |
||
2109 | { |
||
2110 | global $langs, $user; |
||
2111 | |||
2112 | $ret = ''; |
||
2113 | $ret .= '<form action="' . $urlaction . '" method="post" class="searchform nowraponall tagtr">'; |
||
2114 | $ret .= '<input type="hidden" name="token" value="' . newToken() . '">'; |
||
2115 | $ret .= '<input type="hidden" name="savelogin" value="' . dol_escape_htmltag($user->login) . '">'; |
||
2116 | if ($showtitlebefore) { |
||
2117 | $ret .= '<div class="tagtd left">' . $title . '</div> '; |
||
2118 | } |
||
2119 | $ret .= '<div class="tagtd">'; |
||
2120 | $ret .= img_picto('', $img, '', false, 0, 0, '', 'paddingright width20'); |
||
2121 | $ret .= '<input type="text" class="flat ' . $htmlmorecss . '"'; |
||
2122 | $ret .= ' style="background-repeat: no-repeat; background-position: 3px;"'; |
||
2123 | $ret .= ($accesskey ? ' accesskey="' . $accesskey . '"' : ''); |
||
2124 | $ret .= ' placeholder="' . strip_tags($title) . '"'; |
||
2125 | $ret .= ($autofocus ? ' autofocus' : ''); |
||
2126 | $ret .= ' name="' . $htmlinputname . '" id="' . $prefhtmlinputname . $htmlinputname . '" />'; |
||
2127 | $ret .= '<button type="submit" class="button bordertransp" style="padding-top: 4px; padding-bottom: 4px; padding-left: 6px; padding-right: 6px">'; |
||
2128 | $ret .= '<span class="fa fa-search"></span>'; |
||
2129 | $ret .= '</button>'; |
||
2130 | $ret .= '</div>'; |
||
2131 | $ret .= "</form>\n"; |
||
2132 | return $ret; |
||
2133 | } |
||
2134 | |||
2135 | /** |
||
2136 | * Show HTML footer |
||
2137 | * Close div /DIV class=fiche + /DIV id-right + /DIV id-container + /BODY + /HTML. |
||
2138 | * If global var $delayedhtmlcontent was filled, we output it just before closing the body. |
||
2139 | * |
||
2140 | * @param string $comment A text to add as HTML comment into HTML generated page |
||
2141 | * @param string $zone 'private' (for private pages) or 'public' (for public pages) |
||
2142 | * @param int $disabledoutputofmessages Clear all messages stored into session without displaying them |
||
2143 | * @return void |
||
2144 | */ |
||
2145 | public static function llxFooter($comment = '', $zone = 'private', $disabledoutputofmessages = 0) |
||
2415 | } |
||
2416 | } |