dolibarr 24.0.0-beta
index.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2016-2023 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2020 Nicolas ZABOURI <info@inovea-conseil.com>
4 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
5 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
29// We allow POST of rich content with js and style, but only for this php file and if into some given POST variable
30define('NOSCANPOSTFORINJECTION', array('PAGE_CONTENT', 'WEBSITE_CSS_INLINE', 'WEBSITE_JS_INLINE', 'WEBSITE_HTML_HEADER', 'htmlheader'));
31
32define('USEDOLIBARREDITOR', 1);
33define('FORCE_CKEDITOR', 1); // We need CKEditor, even if module is off.
34if (!defined('DISABLE_JS_GRAHP')) {
35 define('DISABLE_JS_GRAPH', 1);
36}
37
38//header('X-XSS-Protection:0'); // Disable XSS filtering protection of some browsers (note: use of Content-Security-Policy is more efficient). Disabled as deprecated.
39
40// Load Dolibarr environment
41require '../main.inc.php';
51require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
52require_once DOL_DOCUMENT_ROOT.'/website/lib/website.lib.php';
53require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
54require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';
55require_once DOL_DOCUMENT_ROOT.'/core/lib/website2.lib.php';
56require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
57require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
58require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
59require_once DOL_DOCUMENT_ROOT.'/core/class/html.formwebsite.class.php';
60require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
61require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
62require_once DOL_DOCUMENT_ROOT.'/website/class/website.class.php';
63require_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php';
64require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
65require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
66
67// Load translation files required by the page
68$langs->loadLangs(array("admin", "other", "users", "website"));
69
70// Security check
71if (!$user->hasRight('website', 'read')) {
73}
74
75$conf->dol_hide_leftmenu = 1; // Force hide of left menu.
76
77$error = 0;
78$virtualurl = '';
79$dataroot = '';
80$websiteid = GETPOSTINT('websiteid');
81$websitekey = GETPOST('website', 'alpha');
82$page = GETPOST('page', 'alpha');
83$pageid = GETPOSTINT('pageid');
84$pageref = GETPOST('pageref', 'alphanohtml');
85
86$action = GETPOST('action', 'aZ09');
87$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
88$confirm = GETPOST('confirm', 'alpha');
89$cancel = GETPOST('cancel', 'alpha');
90$toselect = GETPOST('toselect', 'array:int'); // Array of ids of elements selected into a list
91$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'websitelist'; // To manage different context of search
92$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
93$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
94$dol_hide_topmenu = GETPOSTINT('dol_hide_topmenu');
95$dol_hide_leftmenu = GETPOSTINT('dol_hide_leftmenu');
96$dol_openinpopup = GETPOST('dol_openinpopup', 'aZ09');
97
98$type_container = GETPOST('WEBSITE_TYPE_CONTAINER', 'alpha');
99$section_dir = GETPOST('section_dir', 'alpha');
100$file_manager = GETPOST('file_manager', 'alpha');
101$replacesite = GETPOST('replacesite', 'alpha');
102$mode = GETPOST('mode', 'alpha');
103
104if (GETPOST('deletesite', 'alpha')) {
105 $action = 'deletesite';
106}
107if (GETPOST('delete', 'alpha')) {
108 $action = 'delete';
109}
110if (GETPOST('preview', 'alpha')) {
111 $action = 'preview';
112}
113if (GETPOST('createsite', 'alpha')) {
114 $action = 'createsite';
115}
116if (GETPOST('createcontainer', 'alpha')) {
117 $action = 'createcontainer';
118}
119if (GETPOST('editcss', 'alpha')) {
120 $action = 'editcss';
121}
122if (GETPOST('editmenu', 'alpha')) {
123 $action = 'editmenu';
124}
125if (GETPOST('setashome', 'alpha')) {
126 $action = 'setashome';
127}
128if (GETPOST('editmeta', 'alpha')) {
129 $action = 'editmeta';
130}
131if (GETPOST('editsource', 'alpha')) {
132 $action = 'editsource';
133}
134if (GETPOST('editcontent', 'alpha')) {
135 $action = 'editcontent';
136}
137if (GETPOST('exportsite', 'alpha')) {
138 $action = 'exportsite';
139}
140if (GETPOST('importsite')) { // Can be a string when clicking on button "Import site"
141 $action = 'importsite';
142}
143if (GETPOST('createfromclone', 'alpha')) {
144 $action = 'createfromclone';
145}
146if (GETPOST('createpagefromclone', 'alpha')) {
147 $action = 'createpagefromclone';
148}
149if (empty($action) && $file_manager) {
150 $action = 'file_manager';
151}
152if ($action == 'replacesite' || (empty($action) && $replacesite)) { // Test on permission not required
153 $mode = 'replacesite';
154}
155if (GETPOST('refreshsite') || GETPOST('refreshsite_x') || GETPOST('refreshsite.x')) {
156 $pageid = 0;
157}
158
159// Load variable for pagination
160$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
161$sortfield = (string) GETPOST('sortfield', 'aZ09comma');
162$sortorder = GETPOST('sortorder', 'aZ09comma');
163$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
164if (empty($page) || $page == -1) {
165 $page = 0;
166} // If $page is not defined, or '' or -1
167$offset = $limit * $page;
168$pageprev = $page - 1;
169$pagenext = $page + 1;
170
171if (empty($action)) {
172 $action = 'preview';
173}
174
175$object = new Website($db);
176$objectpage = new WebsitePage($db);
177
178$listofwebsites = $object->fetchAll('ASC', 'position'); // Init list of websites
179
180// If website not defined, we take first found
181if (!($websiteid > 0) && empty($websitekey) && $action != 'createsite') {
182 foreach ($listofwebsites as $key => $valwebsite) {
183 $websitekey = $valwebsite->ref;
184 break;
185 }
186}
187if ($websiteid > 0 || $websitekey) {
188 $res = $object->fetch($websiteid, $websitekey);
189 $websitekey = $object->ref;
190}
191
192$website = $object;
193
194// Check pageid received as parameter
195if ($pageid < 0) {
196 $pageid = 0;
197}
198if (($pageid > 0 || $pageref) && $action != 'addcontainer') {
199 $res = $objectpage->fetch($pageid, ($object->id > 0 ? $object->id : null), $pageref);
200 // @phan-suppress
201 if ($res == 0) {
202 $res = $objectpage->fetch($pageid, ($object->id > 0 ? $object->id : null), null, $pageref);
203 }
204
205 // Check if pageid is inside the new website, if not we reset param pageid
206 if ($res >= 0 && $object->id > 0) {
207 if ($objectpage->fk_website != $object->id) { // We have a bad page that does not belong to web site
208 if ($object->fk_default_home > 0) {
209 $res = $objectpage->fetch($object->fk_default_home, (string) $object->id, ''); // We search first page of web site
210 if ($res > 0) {
211 $pageid = $object->fk_default_home;
212 }
213 } else {
214 $res = $objectpage->fetch(0, (string) $object->id, ''); // We search first page of web site
215 if ($res == 0) { // Page was not found, we reset it
216 $objectpage = new WebsitePage($db);
217 } else { // We found a page, we set pageid to it.
218 $pageid = $objectpage->id;
219 }
220 }
221 } else { // We have a valid page. We force pageid for the case we got the page with a fetch on ref.
222 $pageid = $objectpage->id;
223 }
224 }
225}
226
227// Define pageid if pageid and pageref not received as parameter or was wrong
228$atleastonepage = false;
229if (empty($pageid) && empty($pageref) && $object->id > 0 && $action != 'createcontainer') {
230 $pageid = $object->fk_default_home;
231 if (empty($pageid)) {
232 $array = $objectpage->fetchAll($object->id, 'ASC,ASC', 'type_container,pageurl');
233 if (!is_array($array) && $array < 0) {
234 dol_print_error(null, $objectpage->error, $objectpage->errors);
235 }
236 $atleastonepage = (is_array($array) && count($array) > 0);
237
238 $firstpageid = 0;
239 $homepageid = 0;
240 foreach ($array as $key => $valpage) {
241 if (empty($firstpageid)) {
242 $firstpageid = $valpage->id;
243 }
244 if ($object->fk_default_home && $key == $object->fk_default_home) {
245 $homepageid = $valpage->id;
246 }
247 }
248 $pageid = ($homepageid ? $homepageid : $firstpageid); // We choose home page and if not defined yet, we take first page
249 }
250}
251
252
253global $dolibarr_main_data_root;
254$pathofwebsite = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$websitekey;
255$filehtmlheader = $pathofwebsite.'/htmlheader.html';
256$filecss = $pathofwebsite.'/styles.css.php';
257$filejs = $pathofwebsite.'/javascript.js.php';
258$filerobot = $pathofwebsite.'/robots.txt';
259$filehtaccess = $pathofwebsite.'/.htaccess';
260$filetpl = $pathofwebsite.'/page'.$pageid.'.tpl.php';
261$fileindex = $pathofwebsite.'/index.php';
262$filewrapper = $pathofwebsite.'/wrapper.php';
263$filemanifestjson = $pathofwebsite.'/manifest.json.php';
264$filereadme = $pathofwebsite.'/README.md';
265$filelicense = $pathofwebsite.'/LICENSE';
266$filemaster = $pathofwebsite.'/master.inc.php';
267
268$forceCSP = getDolGlobalString("WEBSITE_".$object->id."_SECURITY_FORCECSP");
269
270// Define $urlwithroot
271$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
272$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
273//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
274
275
276$permtouploadfile = $user->hasRight('website', 'write');
277$diroutput = $conf->medias->multidir_output[$conf->entity];
278
279$relativepath = $section_dir;
280$upload_dir = preg_replace('/\/$/', '', $diroutput).'/'.preg_replace('/^\//', '', $relativepath);
281
282$htmlheadercontentdefault = '';
283$htmlheadercontentdefault .= '<link rel="stylesheet" id="google-fonts-css" href="//fonts.googleapis.com/css?family=Open+Sans:300,400,700" />'."\n";
284$htmlheadercontentdefault .= '<link rel="stylesheet" id="font-wasesome-css" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />'."\n";
285$htmlheadercontentdefault .= '<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>'."\n";
286$htmlheadercontentdefault .= '<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>'."\n";
287$htmlheadercontentdefault .= '<!--'."\n";
288$htmlheadercontentdefault .= '<script src="/document.php?modulepart=medias&file=css/myfile.css"></script>'."\n";
289$htmlheadercontentdefault .= '<script src="/document.php?modulepart=medias&file=js/myfile.js"></script>'."\n";
290$htmlheadercontentdefault .= '-->'."\n";
291
292$manifestjsoncontentdefault = '';
293$manifestjsoncontentdefault .= '{
294 "name": "MyWebsite",
295 "short_name": "MyWebsite",
296 "start_url": "/",
297 "lang": "en-US",
298 "display": "standalone",
299 "background_color": "#fff",
300 "description": "A simple Web app.",
301 "icons": [{
302 "src": "images/'.urlencode($website->ref).'/homescreen48.png",
303 "sizes": "48x48",
304 "type": "image/png"
305 }, {
306 "src": "image/'.urlencode($website->ref).'/homescreen72.png",
307 "sizes": "72x72",
308 "type": "image/png"
309 }, {
310 "src": "image/'.urlencode($website->ref).'/homescreen96.png",
311 "sizes": "96x96",
312 "type": "image/png"
313 }, {
314 "src": "image/'.urlencode($website->ref).'/homescreen144.png",
315 "sizes": "144x144",
316 "type": "image/png"
317 }, {
318 "src": "image/'.urlencode($website->ref).'/homescreen168.png",
319 "sizes": "168x168",
320 "type": "image/png"
321 }, {
322 "src": "image/'.urlencode($website->ref).'/homescreen192.png",
323 "sizes": "192x192",
324 "type": "image/png"
325 }],
326 "related_applications": [{
327 "platform": "play",
328 "url": "https://play.google.com/store/apps/details?id=com.nltechno.dolidroidpro"
329 }]
330}';
331
332$listofpages = array();
333
334$algo = '';
335if (GETPOST('optionpagecontent')) {
336 $algo .= 'content';
337}
338if (GETPOST('optionmeta')) {
339 $algo .= 'meta';
340}
341if (GETPOST('optionsitefiles')) {
342 $algo .= 'sitefiles';
343}
344
345$searchkey = GETPOST('searchstring', 'restricthtmlallowunvalid'); // or 'none', must be same as $searchstring
346
347if ($sortfield == '') {
348 if ($action == 'file_manager') { // Test on permission not required
349 $sortfield = 'name';
350 $sortorder = 'ASC';
351 } else {
352 $sortfield = 'pageurl';
353 $sortorder = 'ASC';
354 }
355}
356'@phan-var-force string $sortfield';
357
358$langcode = '';
359$containertype = '';
360$otherfilters = array();
361
362if ($action == 'replacesite' || $mode == 'replacesite') { // Test on permission not required
363 $containertype = GETPOST('optioncontainertype', 'aZ09') != '-1' ? GETPOST('optioncontainertype', 'aZ09') : '';
364 $langcode = GETPOST('optionlanguage', 'aZ09');
365 if (GETPOSTINT('optioncategory') > 0) {
366 $otherfilters['category'] = GETPOSTINT('optioncategory');
367 }
368
369 $listofpages = getPagesFromSearchCriterias($containertype, $algo, $searchkey, 1000, $sortfield, $sortorder, $langcode, $otherfilters, -1);
370}
371
372$usercanedit = $user->hasRight('website', 'write');
373$permissiontoadd = $user->hasRight('website', 'write'); // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php
374$permissiontodelete = $user->hasRight('website', 'delete');
375
376
377/*
378 * Actions
379 */
380
381// Protections
382if (GETPOST('refreshsite') || GETPOST('refreshsite_x') || GETPOST('refreshsite.x') || GETPOST('refreshpage') || GETPOST('refreshpage_x') || GETPOST('refreshpage.x')) {
383 $action = 'preview'; // To avoid to make an action on another page or another site when we click on button to select another site or page.
384}
385if (GETPOST('refreshsite', 'alpha') || GETPOST('refreshsite.x', 'alpha') || GETPOST('refreshsite_x', 'alpha')) { // If we change the site, we reset the pageid and cancel addsite action.
386 if ($action == 'addsite') { // Test on permission not required here
387 $action = 'preview';
388 }
389 if ($action == 'updatesource') { // Test on permission not required here
390 $action = 'preview';
391 }
392
393 $pageid = $object->fk_default_home;
394 if (empty($pageid)) {
395 $array = $objectpage->fetchAll($object->id, 'ASC,ASC', 'type_container,pageurl');
396 if (!is_array($array) && $array < 0) {
397 dol_print_error(null, $objectpage->error, $objectpage->errors);
398 }
399 $atleastonepage = (is_array($array) && count($array) > 0);
400
401 $firstpageid = 0;
402 $homepageid = 0;
403 foreach ($array as $key => $valpage) {
404 if (empty($firstpageid)) {
405 $firstpageid = $valpage->id;
406 }
407 if ($object->fk_default_home && $key == $object->fk_default_home) {
408 $homepageid = $valpage->id;
409 }
410 }
411 $pageid = ($homepageid ? $homepageid : $firstpageid); // We choose home page and if not defined yet, we take first page
412 }
413}
414if (GETPOST('refreshpage', 'alpha') && !in_array($action, array('updatecss'))) {
415 $action = 'preview';
416}
417
418if ($cancel && $action == 'renamefile') { // Test on permission not required here
419 $cancel = '';
420}
421
422// Cancel
423if ($cancel) {
424 $action = 'preview';
425 $mode = '';
426 if ($backtopage) {
427 header("Location: ".$backtopage);
428 exit;
429 }
430}
431
432$savbacktopage = $backtopage;
433$backtopage = $_SERVER["PHP_SELF"].'?file_manager=1&website='.urlencode($websitekey).'&pageid='.urlencode((string) $pageid).(GETPOST('section_dir', 'alpha') ? '&section_dir='.urlencode(GETPOST('section_dir', 'alpha')) : ''); // used after a confirm_deletefile into actions_linkedfiles.inc.php
434if ($sortfield) {
435 $backtopage .= '&sortfield='.urlencode($sortfield);
436}
437if ($sortorder) {
438 $backtopage .= '&sortorder='.urlencode($sortorder);
439}
440include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; // This manage 'sendit', 'confirm_deletefile', 'renamefile' action when submitting a new file.
441
442$backtopage = $savbacktopage;
443//var_dump($backtopage);
444//var_dump($action);
445
446if ($action == 'renamefile') { // Test on permission not required here. Must be after include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; If action were renamefile, we set it to 'file_manager'
447 $action = 'file_manager';
448}
449
450if ($action == 'setwebsiteonline' && $usercanedit) {
451 $website->setStatut($website::STATUS_VALIDATED, null, '', 'WEBSITE_MODIFY', 'status');
452
453 header("Location: ".$_SERVER["PHP_SELF"].'?website='.urlencode(GETPOST('website')).'&pageid='.GETPOSTINT('websitepage'));
454 exit;
455}
456if ($action == 'setwebsiteoffline' && $usercanedit) {
457 $result = $website->setStatut($website::STATUS_DRAFT, null, '', 'WEBSITE_MODIFY', 'status');
458
459 header("Location: ".$_SERVER["PHP_SELF"].'?website='.urlencode(GETPOST('website')).'&pageid='.GETPOSTINT('websitepage'));
460 exit;
461}
462if ($action == 'seteditinline') { // Test on permission not required here
463 if (!getDolGlobalString('WEBSITE_EDITINLINE_SAVE_CKEDITOR_EDIT')) {
464 // Show warning for feature not yet ready
465 setEventMessages($langs->trans("FeatureNotYetAvailable"), null, 'warnings');
466 }
467
468 dolibarr_set_const($db, 'WEBSITE_EDITINLINE', 1);
469 //dolibarr_set_const($db, 'WEBSITE_SUBCONTAINERSINLINE', 0); // Force disable of 'Include dynamic content'
470 header("Location: ".$_SERVER["PHP_SELF"].'?website='.urlencode(GETPOST('website')).'&pageid='.GETPOSTINT('pageid'));
471 exit;
472}
473if ($action == 'unseteditinline') { // Test on permission not required here
474 dolibarr_del_const($db, 'WEBSITE_EDITINLINE');
475 header("Location: ".$_SERVER["PHP_SELF"].'?website='.urlencode(GETPOST('website')).'&pageid='.GETPOSTINT('pageid'));
476 exit;
477}
478if ($action == 'setshowsubcontainers') { // Test on permission not required here
479 dolibarr_set_const($db, 'WEBSITE_SUBCONTAINERSINLINE', 1);
480 //dolibarr_set_const($db, 'WEBSITE_EDITINLINE', 0); // Force disable of edit inline
481 header("Location: ".$_SERVER["PHP_SELF"].'?website='.urlencode(GETPOST('website')).'&pageid='.GETPOSTINT('pageid'));
482 exit;
483}
484if ($action == 'unsetshowsubcontainers') { // Test on permission not required here
485 dolibarr_del_const($db, 'WEBSITE_SUBCONTAINERSINLINE');
486 header("Location: ".$_SERVER["PHP_SELF"].'?website='.urlencode(GETPOST('website')).'&pageid='.GETPOSTINT('pageid'));
487 exit;
488}
489
490if ($massaction == 'replace' && GETPOST('confirmmassaction', 'alpha') && !$searchkey && $usercanedit) {
491 $mode = 'replacesite';
492 $action = 'replacesite';
493 $massaction = '';
494}
495
496if ($action == 'deletetemplate' && $usercanedit) {
497 $dirthemes = array('/doctemplates/websites');
498 if (!empty($conf->modules_parts['websitetemplates'])) { // Using this feature slow down application
499 foreach ($conf->modules_parts['websitetemplates'] as $reldir) {
500 $dirthemes = array_merge($dirthemes, (array) ($reldir.'doctemplates/websites'));
501 }
502 }
503 $dirthemes = array_unique($dirthemes);
504
505
506 // Delete template files and dir
507 $mode = 'importsite';
508 $action = 'importsite';
509
510 if (count($dirthemes)) {
511 $i = 0;
512 foreach ($dirthemes as $dir) {
513 //print $dirroot.$dir;exit;
514 $dirtheme = DOL_DATA_ROOT.$dir; // This include loop on $conf->file->dol_document_root
515 if (is_dir($dirtheme)) {
516 $templateuserfile = GETPOST('templateuserfile');
517 $imguserfile = preg_replace('/\.zip$/', '', $templateuserfile).'.jpg';
518 dol_delete_file($dirtheme.'/'.$templateuserfile);
519 dol_delete_file($dirtheme.'/'.$imguserfile);
520 }
521 }
522 }
523}
524
525// Set category
526if ($massaction == 'setcategory' && GETPOST('confirmmassaction', 'alpha') && $usercanedit) {
527 $error = 0;
528 $nbupdate = 0;
529
530 $db->begin();
531
532 $categoryid = GETPOSTINT('setcategory');
533 if ($categoryid > 0) {
534 $tmpwebsitepage = new WebsitePage($db);
535 $category = new Categorie($db);
536 $category->fetch($categoryid);
537
538 foreach ($toselect as $tmpid) {
539 $tmpwebsitepage->id = (int) $tmpid;
540 $result = $category->add_type($tmpwebsitepage, 'website_page');
541 if ($result < 0 && $result != -3) {
542 $error++;
543 setEventMessages($category->error, $category->errors, 'errors');
544 break;
545 } else {
546 $nbupdate++;
547 }
548 }
549 }
550
551 if ($error) {
552 $db->rollback();
553 } else {
554 if ($nbupdate) {
555 setEventMessages($langs->trans("RecordsModified", $nbupdate), null, 'mesgs');
556 }
557
558 $db->commit();
559 }
560 // Now we reload list
561 $listofpages = getPagesFromSearchCriterias($containertype, $algo, $searchkey, 1000, $sortfield, $sortorder, $langcode, $otherfilters, -1);
562}
563
564// Del category
565if ($massaction == 'delcategory' && GETPOST('confirmmassaction', 'alpha') && $usercanedit) {
566 $error = 0;
567 $nbupdate = 0;
568
569 $db->begin();
570
571 $categoryid = GETPOSTINT('setcategory');
572 if ($categoryid > 0) {
573 $tmpwebsitepage = new WebsitePage($db);
574 $category = new Categorie($db);
575 $category->fetch($categoryid);
576
577 foreach ($toselect as $tmpid) {
578 $tmpwebsitepage->id = (int) $tmpid;
579 $result = $category->del_type($tmpwebsitepage, 'website_page');
580 if ($result < 0 && $result != -3) {
581 $error++;
582 setEventMessages($category->error, $category->errors, 'errors');
583 break;
584 } else {
585 $nbupdate++;
586 }
587 }
588 }
589
590 if ($error) {
591 $db->rollback();
592 } else {
593 if ($nbupdate) {
594 setEventMessages($langs->trans("RecordsModified", $nbupdate), null, 'mesgs');
595 }
596
597 $db->commit();
598 }
599 // Now we reload list
600 $listofpages = getPagesFromSearchCriterias($containertype, $algo, $searchkey, 1000, $sortfield, $sortorder, $langcode, $otherfilters, -1);
601}
602
603// Replacement of string into pages
604if ($massaction == 'replace' && GETPOST('confirmmassaction', 'alpha') && $usercanedit) {
605 $replacestring = GETPOST('replacestring', 'restricthtmlallowunvalid'); // or 'none', must be same then $searchstring
606
607 $dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT);
608 $allowimportsite = true;
609 if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) {
610 $allowimportsite = false;
611 }
612
613 if (!$allowimportsite) {
614 // Blocked by installmodules.lock
615 if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) {
616 // Show clean corporate message
617 $message = $langs->trans('InstallModuleFromWebHasBeenDisabledContactUs');
618 } else {
619 // Show technical generic message
620 $message = $langs->trans("InstallModuleFromWebHasBeenDisabledByFile", $dolibarrdataroot.'/installmodules.lock');
621 }
622 setEventMessages($message, null, 'errors');
623 } elseif (!$user->hasRight('website', 'writephp')) {
624 setEventMessages("NotAllowedToAddDynamicContent", null, 'errors');
625 } elseif (!$replacestring) {
626 setEventMessages("ErrorReplaceStringEmpty", null, 'errors');
627 } else {
628 $nbreplacement = 0;
629
630 foreach ($toselect as $keyselected) {
631 $objectpage = $listofpages['list'][$keyselected];
632 if ($objectpage->pageurl) {
633 dol_syslog("Replace string into page ".$objectpage->pageurl);
634
635 if (GETPOST('optionpagecontent', 'aZ09')) {
636 $objectpage->content = str_replace($searchkey, $replacestring, $objectpage->content);
637 }
638 if (GETPOST('optionmeta', 'aZ09')) {
639 $objectpage->title = str_replace($searchkey, $replacestring, $objectpage->title);
640 $objectpage->description = str_replace($searchkey, $replacestring, $objectpage->description);
641 $objectpage->keywords = str_replace($searchkey, $replacestring, $objectpage->keywords);
642 }
643
644 $filealias = $pathofwebsite.'/'.$objectpage->pageurl.'.php';
645 $filetpl = $pathofwebsite.'/page'.$objectpage->id.'.tpl.php';
646
647 // Save page alias
648 $result = dolSavePageAlias($filealias, $object, $objectpage);
649 if (!$result) {
650 setEventMessages('Failed to write file '.basename($filealias), null, 'errors');
651 }
652
653 // Save page of content
654 $result = dolSavePageContent($filetpl, $object, $objectpage, 1);
655 if ($result) {
656 $nbreplacement++;
657 //var_dump($objectpage->content);exit;
658 $objectpage->update($user);
659 } else {
660 $error++;
661 setEventMessages('Failed to write file '.$filetpl, null, 'errors');
662 $action = 'createcontainer';
663 break;
664 }
665 }
666 }
667
668 if ($nbreplacement > 0) {
669 setEventMessages($langs->trans("ReplacementDoneInXPages", $nbreplacement), null, 'mesgs');
670 }
671
672 $containertype = GETPOST('optioncontainertype', 'aZ09') != '-1' ? GETPOST('optioncontainertype', 'aZ09') : '';
673 $langcode = GETPOST('optionlanguage', 'aZ09');
674 $otherfilters = array();
675 if (GETPOSTINT('optioncategory') > 0) {
676 $otherfilters['category'] = GETPOSTINT('optioncategory');
677 }
678
679 // Now we reload list
680 $listofpages = getPagesFromSearchCriterias($containertype, $algo, $searchkey, 1000, $sortfield, $sortorder, $langcode, $otherfilters);
681 }
682}
683
684
685// Add directory
686/*
687if ($action == 'adddir' && $permtouploadfile)
688{
689 $ecmdir->ref = 'NOTUSEDYET';
690 $ecmdir->label = GETPOST("label");
691 $ecmdir->description = GETPOST("desc");
692
693 //$id = $ecmdir->create($user);
694 if ($id > 0)
695 {
696 header("Location: ".$_SERVER["PHP_SELF"]);
697 exit;
698 }
699 else
700 {
701 setEventMessages('Error '.$langs->trans($ecmdir->error), null, 'errors');
702 $action = "createcontainer";
703 }
704
705 clearstatcache();
706}
707*/
708
709// Add a website
710if ($action == 'addsite' && $usercanedit) {
711 $db->begin();
712
713 if (GETPOST('virtualhost', 'alpha') && !preg_match('/^http/', GETPOST('virtualhost', 'alpha'))) {
714 $error++;
715 setEventMessages($langs->trans('ErrorURLMustStartWithHttp', $langs->transnoentitiesnoconv("VirtualHost")), null, 'errors');
716 }
717
718 if (!$error && !GETPOST('WEBSITE_REF', 'alpha')) {
719 $error++;
720 $langs->load("errors");
721 setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities("WebsiteName")), null, 'errors');
722 }
723 if (!$error && !preg_match('/^[a-z0-9_\-\.]+$/i', GETPOST('WEBSITE_REF', 'alpha'))) {
724 $error++;
725 $langs->load("errors");
726 setEventMessages($langs->transnoentities("ErrorFieldCanNotContainSpecialCharacters", $langs->transnoentities("Ref")), null, 'errors');
727 }
728
729 $tmpobject = null;
730 if (!$error) {
731 $arrayotherlang = explode(',', GETPOST('WEBSITE_OTHERLANG', 'alphanohtml'));
732 foreach ($arrayotherlang as $key => $val) {
733 // It possible we have empty val here if postparam WEBSITE_OTHERLANG is empty or set like this : 'en,,sv' or 'en,sv,'
734 if (empty(trim($val))) {
735 continue;
736 }
737 $arrayotherlang[$key] = substr(trim($val), 0, 2); // Kept short language code only
738 }
739
740 $tmpobject = new Website($db);
741 $tmpobject->ref = GETPOST('WEBSITE_REF', 'alpha');
742 $tmpobject->description = GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml');
743 $tmpobject->lang = GETPOST('WEBSITE_LANG', 'aZ09');
744 $tmpobject->otherlang = implode(',', $arrayotherlang);
745 $tmpobject->virtualhost = GETPOST('virtualhost', 'alpha');
746
747 $result = $tmpobject->create($user);
748 if ($result == 0) {
749 $error++;
750 setEventMessages($langs->trans("ErrorLabelAlreadyExists"), null, 'errors');
751 } elseif ($result < 0) {
752 $error++;
753 setEventMessages($tmpobject->error, $tmpobject->errors, 'errors');
754 }
755 }
756
757 if (!$error && $tmpobject !== null) {
758 $db->commit();
759 setEventMessages($langs->trans("SiteAdded", $object->ref), null, 'mesgs');
760 $action = '';
761
762 header("Location: ".$_SERVER["PHP_SELF"].'?website='.$tmpobject->ref);
763 exit;
764 } else {
765 $db->rollback();
766 $action = 'createsite';
767 }
768
769 if (!$error) {
770 $action = 'preview';
771 $id = $object->id;
772 }
773}
774
775'@phan-var-force int $error';
776
777// Add page/container
778if ($action == 'addcontainer' && $usercanedit) {
779 dol_mkdir($pathofwebsite);
780
781 $db->begin();
782
783 $objectpage->fk_website = $object->id;
784 $objectpage->status = $objectpage::STATUS_DRAFT;
785
786 if (GETPOSTISSET('fetchexternalurl')) { // Fetch from external url
787 $urltograb = GETPOST('externalurl', 'alpha');
788 $grabimages = GETPOSTINT('grabimages') ? 1 : 0;
789 $grabimagesinto = GETPOST('grabimagesinto', 'alpha');
790
791 include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
792 // The include seems to break typing on variables
793
794 if (empty($urltograb)) {
795 $error++;
796 $langs->load("errors");
797 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("URL")), null, 'errors');
798 $action = 'createcontainer';
799 } elseif (!preg_match('/^http/', $urltograb)) {
800 $error++;
801 $langs->load("errors");
802 setEventMessages('Error URL must start with http:// or https://', null, 'errors');
803 $action = 'createcontainer';
804 }
805
806 $pageurl = '';
807 $urltograbdirwithoutslash = '';
808 $urltograbdirrootwithoutslash = '';
809 if (!$error) {
810 // Clean url to grab, so url can be
811 // http://www.example.com/ or http://www.example.com/dir1/ or http://www.example.com/dir1/aaa
812 $urltograbwithoutdomainandparam = preg_replace('/^https?:\/\/[^\/]+\/?/i', '', $urltograb);
813 //$urltograbwithoutdomainandparam = preg_replace('/^file:\/\/[^\/]+\/?/i', '', $urltograb);
814 $urltograbwithoutdomainandparam = preg_replace('/\?.*$/', '', $urltograbwithoutdomainandparam);
815 if (empty($urltograbwithoutdomainandparam) && !preg_match('/\/$/', $urltograb)) {
816 $urltograb .= '/';
817 }
818 $pageurl = dol_sanitizeFileName(preg_replace('/[\/\.]/', '-', preg_replace('/\/+$/', '', $urltograbwithoutdomainandparam)));
819
820 $urltograbdirwithoutslash = dirname($urltograb.'.');
821 $urltograbdirrootwithoutslash = getRootURLFromURL($urltograbdirwithoutslash);
822 // Example, now $urltograbdirwithoutslash is https://www.dolimed.com/screenshots
823 // and $urltograbdirrootwithoutslash is https://www.dolimed.com
824 }
825
826 // Check pageurl is not already used
827 if ($pageurl) {
828 $tmpwebsitepage = new WebsitePage($db);
829 $result = $tmpwebsitepage->fetch(0, (string) $object->id, $pageurl);
830 if ($result > 0) {
831 setEventMessages($langs->trans("AliasPageAlreadyExists", $pageurl), null, 'errors');
832 $error++;
833 $action = 'createcontainer';
834 }
835 }
836
837 if (!$error) {
838 // Download URL to grab
839 $tmp = getURLContent($urltograb, 'GET', '', 1, array(), array('http', 'https'), 0);
840
841 // Test charset of result and convert it into UTF-8 if not in this encoding charset
842 if (!empty($tmp['content_type']) && preg_match('/ISO-8859-1/', $tmp['content_type'])) {
843 if (function_exists('mb_check_encoding')) {
844 if (mb_check_encoding($tmp['content'], 'ISO-8859-1')) {
845 // This is a ISO-8829-1 encoding string
846 $tmp['content'] = mb_convert_encoding($tmp['content'], 'ISO-8859-1', 'UTF-8');
847 } else {
848 $error++;
849 setEventMessages('Error getting '.$urltograb.': content seems non valid ISO-8859-1', null, 'errors');
850 $action = 'createcontainer';
851 }
852 } else {
853 $error++;
854 setEventMessages('Error getting '.$urltograb.': content seems ISO-8859-1 but functions to convert into UTF-8 are not available in your PHP', null, 'errors');
855 $action = 'createcontainer';
856 }
857 }
858 if (empty($tmp['content_type']) || (!empty($tmp['content_type']) && preg_match('/UTF-8/', $tmp['content_type']))) {
859 if (function_exists('mb_check_encoding')) {
860 if (mb_check_encoding($tmp['content'], 'UTF-8')) {
861 // This is a UTF8 or ASCII compatible string
862 } else {
863 $error++;
864 setEventMessages('Error getting '.$urltograb.': content seems not a valid UTF-8', null, 'errors');
865 $action = 'createcontainer';
866 }
867 }
868 }
869
870 if (!empty($tmp['curl_error_no'])) {
871 $error++;
872 setEventMessages('Error getting '.$urltograb.': '.$tmp['curl_error_msg'], null, 'errors');
873 $action = 'createcontainer';
874 } elseif ($tmp['http_code'] != 200) {
875 $error++;
876 setEventMessages('Error getting '.$urltograb.': '.$tmp['http_code'], null, 'errors');
877 $action = 'createcontainer';
878 } else {
879 // Remove comments
880 $tmp['content'] = removeHtmlComment($tmp['content']);
881
882 /* disable this, moved into the create() method
883 // Check there is no PHP content into the imported file (must be only HTML + JS)
884 $phpcontent = dolKeepOnlyPhpCode($tmp['content']);
885 if ($phpcontent) {
886 $error++;
887 setEventMessages('Error getting '.$urltograb.': file that include PHP content is not allowed', null, 'errors');
888 $action = 'createcontainer';
889 }
890 */
891 }
892
893 if (!$error) {
894 $regs = array();
895
896 preg_match('/<head>(.*)<\/head>/ims', $tmp['content'], $regs);
897 $head = $regs[1];
898
899 $objectpage->type_container = 'page';
900 $objectpage->pageurl = $pageurl;
901 if (empty($objectpage->pageurl)) {
902 $tmpdomain = getDomainFromURL($urltograb);
903 $objectpage->pageurl = $tmpdomain.'-home';
904 }
905
906 $objectpage->aliasalt = '';
907
908 if (preg_match('/^(\d+)\-/', basename($urltograb), $regs)) {
909 $objectpage->aliasalt = $regs[1];
910 }
911
912 $regtmp = array();
913 if (preg_match('/<title>(.*)<\/title>/ims', $head, $regtmp)) {
914 $objectpage->title = $regtmp[1];
915 }
916 if (preg_match('/<meta name="title"[^"]+content="([^"]+)"/ims', $head, $regtmp)) {
917 if (empty($objectpage->title)) {
918 $objectpage->title = $regtmp[1]; // If title not found into <title>, we get it from <meta title>
919 }
920 }
921 if (preg_match('/<meta name="description"[^"]+content="([^"]+)"/ims', $head, $regtmp)) {
922 $objectpage->description = $regtmp[1];
923 }
924 if (preg_match('/<meta name="keywords"[^"]+content="([^"]+)"/ims', $head, $regtmp)) {
925 $objectpage->keywords = $regtmp[1];
926 }
927 if (preg_match('/<html\s+lang="([^"]+)"/ims', $tmp['content'], $regtmp)) {
928 $tmplang = explode('-', $regtmp[1]);
929 $objectpage->lang = $tmplang[0].(empty($tmplang[1]) ? '' : '_'.strtoupper($tmplang[1]));
930 }
931
932 $tmp['content'] = preg_replace('/\s*<meta name="generator"[^"]+content="([^"]+)"\s*\/?>/ims', '', $tmp['content']);
933
934 $objectpage->content = $tmp['content'];
935 $objectpage->content = preg_replace('/^.*<body(\s[^>]*)*>/ims', '', $objectpage->content);
936 $objectpage->content = preg_replace('/<\/body(\s[^>]*)*>.*$/ims', '', $objectpage->content);
937
938 // TODO Replace 'action="$urltograbdirwithoutslash' into action="/"
939 // TODO Replace 'action="$urltograbdirwithoutslash..."' into action="..."
940 // TODO Replace 'a href="$urltograbdirwithoutslash' into a href="/"
941 // TODO Replace 'a href="$urltograbdirwithoutslash..."' into a href="..."
942
943 // Now loop to fetch all css files. Include them inline into header of page
944 $objectpage->htmlheader = $tmp['content'];
945 $objectpage->htmlheader = preg_replace('/^.*<head(\s[^>]*)*>/ims', '', $objectpage->htmlheader);
946 $objectpage->htmlheader = preg_replace('/<\/head(\s[^>]*)*>.*$/ims', '', $objectpage->htmlheader);
947 $objectpage->htmlheader = preg_replace('/<base(\s[^>]*)*>\n*/ims', '', $objectpage->htmlheader);
948 $objectpage->htmlheader = preg_replace('/<meta http-equiv="content-type"([^>]*)*>\n*/ims', '', $objectpage->htmlheader);
949 $objectpage->htmlheader = preg_replace('/<meta name="robots"([^>]*)*>\n*/ims', '', $objectpage->htmlheader);
950 $objectpage->htmlheader = preg_replace('/<meta name="title"([^>]*)*>\n*/ims', '', $objectpage->htmlheader);
951 $objectpage->htmlheader = preg_replace('/<meta name="description"([^>]*)*>\n*/ims', '', $objectpage->htmlheader);
952 $objectpage->htmlheader = preg_replace('/<meta name="keywords"([^>]*)*>\n*/ims', '', $objectpage->htmlheader);
953 $objectpage->htmlheader = preg_replace('/<meta name="generator"([^>]*)*>\n*/ims', '', $objectpage->htmlheader);
954 //$objectpage->htmlheader = preg_replace('/<meta name="verify-v1[^>]*>\n*/ims', '', $objectpage->htmlheader);
955 //$objectpage->htmlheader = preg_replace('/<meta name="msvalidate.01[^>]*>\n*/ims', '', $objectpage->htmlheader);
956 $objectpage->htmlheader = preg_replace('/<title>[^<]*<\/title>\n*/ims', '', $objectpage->htmlheader);
957 $objectpage->htmlheader = preg_replace('/<link[^>]*rel="shortcut[^>]*>\n/ims', '', $objectpage->htmlheader);
958 $objectpage->htmlheader = preg_replace('/<link[^>]*rel="alternate[^>]*>\n/ims', '', $objectpage->htmlheader);
959 $objectpage->htmlheader = preg_replace('/<link[^>]*rel="canonical[^>]*>\n/ims', '', $objectpage->htmlheader);
960
961 // Now loop to fetch JS
962 $tmp = $objectpage->htmlheader;
963
964 // We grab files found into <script> tags
965 preg_match_all('/<script([^\.>]+)src=["\']([^"\'>]+)["\']([^>]*)><\/script>/i', $objectpage->htmlheader, $regs);
966 $errorforsubresource = 0;
967 foreach ($regs[0] as $key => $val) {
968 dol_syslog("We will grab the script resource found into script tag ".$regs[2][$key]);
969
970 $linkwithoutdomain = $regs[2][$key];
971 if (preg_match('/^\//', $regs[2][$key])) {
972 $urltograbbis = $urltograbdirrootwithoutslash.$regs[2][$key]; // We use dirroot
973 } else {
974 $urltograbbis = $urltograbdirwithoutslash.'/'.$regs[2][$key]; // We use dir of grabbed file
975 }
976
977 //$filetosave = $conf->medias->multidir_output[$conf->entity].'/css/'.$object->ref.'/'.$objectpage->pageurl.(preg_match('/^\//', $regs[2][$key])?'':'/').$regs[2][$key];
978 if (preg_match('/^http/', $regs[2][$key])) {
979 $urltograbbis = $regs[2][$key];
980 $linkwithoutdomain = preg_replace('/^https?:\/\/[^\/]+\//i', '', $regs[2][$key]);
981 //$filetosave = $conf->medias->multidir_output[$conf->entity].'/css/'.$object->ref.'/'.$objectpage->pageurl.(preg_match('/^\//', $linkwithoutdomain)?'':'/').$linkwithoutdomain;
982 }
983
984 //print $domaintograb.' - '.$domaintograbbis.' - '.$urltograbdirwithoutslash.' - ';
985 //print $linkwithoutdomain.' - '.$urltograbbis."<br>\n";
986
987 // Test if this is an external URL of grabbed web site. If yes, we do not load resource
988 $domaintograb = getDomainFromURL($urltograbdirwithoutslash);
989 $domaintograbbis = getDomainFromURL($urltograbbis);
990 if ($domaintograb != $domaintograbbis) {
991 continue;
992 }
993
994 /*
995 $tmpgeturl = getURLContent($urltograbbis, 'GET', '', 1, array(), array('http', 'https'), 0);
996 if (!empty($tmpgeturl['curl_error_no']))
997 {
998 $error++;
999 setEventMessages('Error getting script url '.$urltograbbis.': '.$tmpgeturl['curl_error_msg'], null, 'errors');
1000 $errorforsubresource++;
1001 $action='createcontainer';
1002 }
1003 elseif ($tmpgeturl['http_code'] != 200)
1004 {
1005 $error++;
1006 setEventMessages('Error getting script url '.$urltograbbis.': '.$tmpgeturl['http_code'], null, 'errors');
1007 $errorforsubresource++;
1008 $action='createcontainer';
1009 }
1010 else
1011 {
1012 dol_mkdir(dirname($filetosave));
1013
1014 $fp = fopen($filetosave, "w");
1015 fputs($fp, $tmpgeturl['content']);
1016 fclose($fp);
1017 dolChmod($file);
1018 }
1019 */
1020
1021 //$filename = 'image/'.$object->ref.'/'.$objectpage->pageurl.(preg_match('/^\//', $linkwithoutdomain)?'':'/').$linkwithoutdomain;
1022 $tmp = preg_replace('/'.preg_quote($regs[0][$key], '/').'/i', '', $tmp);
1023 }
1024 $objectpage->htmlheader = trim($tmp)."\n";
1025
1026
1027 // Now we grab CSS found into <link> tags
1028 $pagecsscontent = "\n".'<style>'."\n";
1029
1030 preg_match_all('/<link([^\.>]+)href=["\']([^"\'>]+\.css[^"\'>]*)["\']([^>]*)>/i', $objectpage->htmlheader, $regs);
1031 $errorforsubresource = 0;
1032 foreach ($regs[0] as $key => $val) {
1033 dol_syslog("We will grab the css resources found into link tag ".$regs[2][$key]);
1034
1035 $linkwithoutdomain = $regs[2][$key];
1036 if (preg_match('/^\//', $regs[2][$key])) {
1037 $urltograbbis = $urltograbdirrootwithoutslash.$regs[2][$key]; // We use dirroot
1038 } else {
1039 $urltograbbis = $urltograbdirwithoutslash.'/'.$regs[2][$key]; // We use dir of grabbed file
1040 }
1041
1042 //$filetosave = $conf->medias->multidir_output[$conf->entity].'/css/'.$object->ref.'/'.$objectpage->pageurl.(preg_match('/^\//', $regs[2][$key])?'':'/').$regs[2][$key];
1043 if (preg_match('/^http/', $regs[2][$key])) {
1044 $urltograbbis = $regs[2][$key];
1045 $linkwithoutdomain = preg_replace('/^https?:\/\/[^\/]+\//i', '', $regs[2][$key]);
1046 //$filetosave = $conf->medias->multidir_output[$conf->entity].'/css/'.$object->ref.'/'.$objectpage->pageurl.(preg_match('/^\//', $linkwithoutdomain)?'':'/').$linkwithoutdomain;
1047 }
1048
1049 //print $domaintograb.' - '.$domaintograbbis.' - '.$urltograbdirwithoutslash.' - ';
1050 //print $linkwithoutdomain.' - '.$urltograbbis."<br>\n";
1051
1052 // Test if this is an external URL of grabbed web site. If yes, we do not load resource
1053 $domaintograb = getDomainFromURL($urltograbdirwithoutslash);
1054 $domaintograbbis = getDomainFromURL($urltograbbis);
1055 if ($domaintograb != $domaintograbbis) {
1056 continue;
1057 }
1058
1059 $tmpgeturl = getURLContent($urltograbbis, 'GET', '', 1, array(), array('http', 'https'), 0);
1060 if (!empty($tmpgeturl['curl_error_no'])) {
1061 $errorforsubresource++;
1062 setEventMessages('Error getting link tag url '.$urltograbbis.': '.$tmpgeturl['curl_error_msg'], null, 'errors');
1063 dol_syslog('Error getting '.$urltograbbis.': '.$tmpgeturl['curl_error_msg']);
1064 $action = 'createcontainer';
1065 } elseif ($tmpgeturl['http_code'] != 200) {
1066 $errorforsubresource++;
1067 setEventMessages('Error getting link tag url '.$urltograbbis.': '.$tmpgeturl['http_code'], null, 'errors');
1068 dol_syslog('Error getting '.$urltograbbis.': '.$tmpgeturl['curl_error_msg']);
1069 $action = 'createcontainer';
1070 } else {
1071 // Clean some comment
1072 //$tmpgeturl['content'] = dol_string_is_good_iso($tmpgeturl['content'], 1);
1073 //$tmpgeturl['content'] = mb_convert_encoding($tmpgeturl['content'], 'UTF-8', 'UTF-8');
1074 //$tmpgeturl['content'] = remove_bs($tmpgeturl['content']);
1075 //$tmpgeturl['content'] = str_replace('$screen-md-max', 'auto', $tmpgeturl['content']);
1076
1077 //var_dump($tmpgeturl['content']);exit;
1078 $tmpgeturl['content'] = preg_replace('/\/\*\s+CSS content[a-z\s]*\s+\*\//', '', $tmpgeturl['content']);
1079
1080 //dol_mkdir(dirname($filetosave));
1081
1082 //$fp = fopen($filetosave, "w");
1083 //fputs($fp, $tmpgeturl['content']);
1084 //fclose($fp);
1085 //dolChmod($file);
1086
1087 // $filename = 'image/'.$object->ref.'/'.$objectpage->pageurl.(preg_match('/^\//', $linkwithoutdomain)?'':'/').$linkwithoutdomain;
1088 $pagecsscontent .= "\n".'/* Content of file '.$urltograbbis.' */'."\n";
1089
1090 getAllImages($object, $objectpage, $urltograbbis, $tmpgeturl['content'], $action, 1, $grabimages, $grabimagesinto);
1091
1092 // We try to convert the CSS we got by adding a prefix .bodywebsite with lessc to avoid conflict with CSS of Dolibarr.
1093 include_once DOL_DOCUMENT_ROOT.'/core/class/lessc.class.php';
1094 $lesscobj = new Lessc();
1095 try {
1096 $contentforlessc = ".bodywebsite {\n".$tmpgeturl['content']."\n}\n";
1097 //print '<pre>'.$contentforlessc.'</pre>';
1098 $contentforlessc = $lesscobj->compile($contentforlessc);
1099 //var_dump($contentforlessc); exit;
1100
1101 $pagecsscontent .= $contentforlessc."\n";
1102 //$pagecsscontent.=$tmpgeturl['content']."\n";
1103 } catch (Exception $e) {
1104 //echo "failed to compile lessc";
1105 dol_syslog("Failed to compile the CSS from URL ".$urltograbbis." with lessc: ".$e->getMessage(), LOG_WARNING);
1106 $pagecsscontent .= $tmpgeturl['content']."\n";
1107 }
1108
1109 $objectpage->htmlheader = preg_replace('/'.preg_quote($regs[0][$key], '/').'\n*/ims', '', $objectpage->htmlheader);
1110 }
1111 }
1112
1113 $pagecsscontent .= '</style>';
1114 //var_dump($pagecsscontent);
1115
1116 //print dol_escape_htmltag($tmp);exit;
1117 $objectpage->htmlheader .= trim($pagecsscontent)."\n";
1118
1119
1120 // Now we have to fetch all images into page
1121 $tmp = $objectpage->content;
1122
1123 getAllImages($object, $objectpage, $urltograb, $tmp, $action, 1, $grabimages, $grabimagesinto);
1124
1125 // Normalize links href to Dolibarr internal naming
1126 $tmp = preg_replace('/a href="\/([^\/"]+)\/([^\/"]+)"/', 'a href="/\1-\2.php"', $tmp);
1127 $tmp = preg_replace('/a href="\/([^\/"]+)\/([^\/"]+)\/([^\/"]+)"/', 'a href="/\1-\2-\3.php"', $tmp);
1128 $tmp = preg_replace('/a href="\/([^\/"]+)\/([^\/"]+)\/([^\/"]+)\/([^\/"]+)"/', 'a href="/\1-\2-\3-\4.php"', $tmp);
1129
1130 //print dol_escape_htmltag($tmp);exit;
1131 $objectpage->content = $tmp;
1132
1133 $objectpage->grabbed_from = $urltograb;
1134 }
1135 }
1136 } else { // add website from scratch
1137 $newaliasnames = '';
1138 if (!$error && GETPOST('WEBSITE_ALIASALT', 'alpha')) {
1139 $arrayofaliastotest = explode(',', str_replace(array('<', '>'), '', GETPOST('WEBSITE_ALIASALT', 'alpha')));
1140 $websitepagetemp = new WebsitePage($db);
1141 foreach ($arrayofaliastotest as $aliastotest) {
1142 $aliastotest = trim(preg_replace('/\.php$/i', '', $aliastotest));
1143
1144 // Disallow alias name pageX (already used to save the page with id)
1145 if (preg_match('/^page\d+/i', $aliastotest)) {
1146 $error++;
1147 $langs->load("errors");
1148 setEventMessages("Alias name 'pageX' is not allowed", null, 'errors');
1149 $action = 'createcontainer';
1150 break;
1151 } else {
1152 $result = $websitepagetemp->fetch(0, (string) $object->id, $aliastotest);
1153 if ($result < 0) {
1154 $error++;
1155 $langs->load("errors");
1156 setEventMessages($websitepagetemp->error, $websitepagetemp->errors, 'errors');
1157 $action = 'createcontainer';
1158 break;
1159 }
1160 if ($result > 0) {
1161 $error++;
1162 $langs->load("errors");
1163 setEventMessages($langs->trans("ErrorAPageWithThisNameOrAliasAlreadyExists", $websitepagetemp->pageurl), null, 'errors');
1164 $action = 'createcontainer';
1165 break;
1166 }
1167 $newaliasnames .= ($newaliasnames ? ', ' : '').$aliastotest;
1168 }
1169 }
1170 }
1171
1172 $objectpage->title = str_replace(array('<', '>'), '', GETPOST('WEBSITE_TITLE', 'alphanohtml'));
1173 $objectpage->type_container = GETPOST('WEBSITE_TYPE_CONTAINER', 'aZ09');
1174 $objectpage->pageurl = dol_sanitizeUrl(GETPOST('WEBSITE_PAGENAME', 'alpha'));
1175 $objectpage->ref = $objectpage->pageurl;
1176 $objectpage->aliasalt = $newaliasnames;
1177 $objectpage->description = str_replace(array('<', '>'), '', GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml'));
1178 $objectpage->lang = GETPOST('WEBSITE_LANG', 'aZ09');
1179 $objectpage->otherlang = GETPOST('WEBSITE_OTHERLANG', 'aZ09comma');
1180 $objectpage->image = GETPOST('WEBSITE_IMAGE', 'alpha');
1181 $objectpage->keywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml'));
1182 $objectpage->allowed_in_frames = GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09') ? 1 : 0;
1183 $objectpage->htmlheader = GETPOST('htmlheader', 'restricthtmlallowlinkscript'); // Must accept tags like '<script>' and '<link>'
1184
1185 $objectpage->author_alias = GETPOST('WEBSITE_AUTHORALIAS', 'alphanohtml');
1186 $objectpage->object_type = GETPOST('WEBSITE_OBJECTCLASS');
1187 $objectpage->fk_object = GETPOST('WEBSITE_OBJECTID');
1188 $substitutionarray = array();
1189 $substitutionarray['__WEBSITE_CREATED_BY__'] = $user->getFullName($langs);
1190
1191 // Define id of the page the new page is translation of
1192 /*
1193 if ($objectpage->lang == $object->lang) {
1194 // If
1195 $pageidfortranslation = (GETPOSTINT('pageidfortranslation') > 0 ? GETPOSTINT('pageidfortranslation') : 0);
1196 if ($pageidfortranslation > 0) {
1197 // We must update the page $pageidfortranslation to set fk_page = $object->id.
1198 // But what if page $pageidfortranslation is already linked to another ?
1199 }
1200 } else {
1201 */
1202 $pageidfortranslation = (GETPOSTINT('pageidfortranslation') > 0 ? GETPOSTINT('pageidfortranslation') : 0);
1203 if ($pageidfortranslation > 0) {
1204 // Check if the page we are translation of is already a translation of a source page. if yes, we will use source id instead
1205 $objectpagetmp = new WebsitePage($db);
1206 $objectpagetmp->fetch($pageidfortranslation);
1207 if ($objectpagetmp->fk_page > 0) {
1208 $pageidfortranslation = $objectpagetmp->fk_page;
1209 }
1210 }
1211 $objectpage->fk_page = $pageidfortranslation;
1212 //}
1213
1214 $content = '';
1215 if (GETPOSTISSET('content')) {
1216 //$content = GETPOST('content', 'restricthtmlallowunvalid'); // @TODO Use a restricthtmlallowunvalidwithphp
1217 $content = GETPOST('content', 'none'); // @TODO Use a restricthtmlallowunvalidwithphp
1218
1219 $objectpage->content = make_substitutions($content, $substitutionarray);
1220 } else {
1221 /*$sample = GETPOST('sample', 'alpha');
1222 if (empty($sample)) {
1223 $sample = 'empty';
1224 }
1225
1226 $pathtosample = DOL_DOCUMENT_ROOT.'/website/samples/page-sample-'.dol_sanitizeFileName(strtolower($sample)).'.html';
1227 */
1228 // Init content with content into page-sample-...
1229 //$objectpage->content = make_substitutions(@file_get_contents($pathtosample), $substitutionarray);
1230 }
1231 }
1232
1233 if (!$error) {
1234 if (empty($objectpage->pageurl)) {
1235 $langs->load("errors");
1236 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("WEBSITE_PAGENAME")), null, 'errors');
1237 $error++;
1238 $action = 'createcontainer';
1239 } elseif (!preg_match('/^[a-z0-9\-\_]+$/i', $objectpage->pageurl)) {
1240 $langs->load("errors");
1241 setEventMessages($langs->transnoentities("ErrorFieldCanNotContainSpecialCharacters", $langs->transnoentities('WEBSITE_PAGENAME')), null, 'errors');
1242 $error++;
1243 $action = 'createcontainer';
1244 }
1245 if (empty($objectpage->title)) {
1246 $langs->load("errors");
1247 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("WEBSITE_TITLE")), null, 'errors');
1248 $error++;
1249 $action = 'createcontainer';
1250 }
1251 if ($objectpage->fk_page > 0 && empty($objectpage->lang)) {
1252 $langs->load("errors");
1253 setEventMessages($langs->trans("ErrorLanguageRequiredIfPageIsTranslationOfAnother"), null, 'errors');
1254 $error++;
1255 $action = 'createcontainer';
1256 }
1257 if ($objectpage->fk_page > 0 && !empty($objectpage->lang)) {
1258 if ($objectpage->lang == $website->lang) {
1259 $langs->load("errors");
1260 setEventMessages($langs->trans("ErrorLanguageMustNotBeSourceLanguageIfPageIsTranslationOfAnother"), null, 'errors');
1261 $error++;
1262 $action = 'createcontainer';
1263 }
1264 }
1265 }
1266
1267 $pageid = 0;
1268 if (!$error) {
1269 // Create page. This also check there is no PHP content if user has no pemrissions for that.
1270 $pageid = $objectpage->create($user);
1271 if ($pageid <= 0) {
1272 $error++;
1273 setEventMessages($objectpage->error, $objectpage->errors, 'errors');
1274 $action = 'createcontainer';
1275 }
1276 }
1277
1278 if (!$error) {
1279 // Website categories association
1280 $categoriesarray = GETPOST('categories', 'array:int');
1281 $result = $objectpage->setCategories($categoriesarray);
1282 if ($result < 0) {
1283 $error++;
1284 setEventMessages($object->error, $object->errors, 'errors');
1285 }
1286 }
1287
1288 if (!$error) {
1289 // If there is no home page yet, this new page will be set as the home page
1290 if (empty($object->fk_default_home)) {
1291 $object->fk_default_home = $pageid;
1292 $res = $object->update($user);
1293 if ($res <= 0) {
1294 $error++;
1295 setEventMessages($object->error, $object->errors, 'errors');
1296 } else {
1297 $filetpl = $pathofwebsite.'/page'.$pageid.'.tpl.php';
1298
1299 // Generate the index.php page (to be the home page) and the wrapper.php file
1300 $result = dolSaveIndexPage($pathofwebsite, $fileindex, $filetpl, $filewrapper, $object);
1301
1302 if ($result <= 0) {
1303 setEventMessages('Failed to write file '.$fileindex, null, 'errors');
1304 }
1305 }
1306 }
1307 }
1308
1309 if (!$error) {
1310 if ($pageid > 0) {
1311 $filealias = $pathofwebsite.'/'.$objectpage->pageurl.'.php';
1312 $filetpl = $pathofwebsite.'/page'.$objectpage->id.'.tpl.php';
1313
1314 // Save page alias
1315 $result = dolSavePageAlias($filealias, $object, $objectpage);
1316 if (!$result) {
1317 setEventMessages('Failed to write file '.basename($filealias), null, 'errors');
1318 }
1319
1320 // Save page of content
1321 $result = dolSavePageContent($filetpl, $object, $objectpage, 1);
1322 if ($result) {
1323 setEventMessages($langs->trans("Saved"), null, 'mesgs');
1324 } else {
1325 setEventMessages('Failed to write file '.$filetpl, null, 'errors');
1326 $action = 'createcontainer';
1327 }
1328 }
1329 }
1330
1331 if (!$error) {
1332 $db->commit();
1333 setEventMessages($langs->trans("PageAdded", $objectpage->pageurl), null, 'mesgs');
1334 $action = '';
1335 } else {
1336 $db->rollback();
1337 }
1338
1339 if (!$error) {
1340 $pageid = $objectpage->id;
1341
1342 // To generate the CSS, robot and htmlheader file.
1343
1344 // Check symlink documents/website/mywebsite/medias to point to documents/medias and restore it if ko.
1345 // Recreate also dir of website if not found.
1346 $pathtomedias = DOL_DATA_ROOT.'/medias';
1347 $pathtomediasinwebsite = $pathofwebsite.'/medias';
1348 if (!is_link(dol_osencode($pathtomediasinwebsite))) {
1349 dol_syslog("Create symlink for ".$pathtomedias." into name ".$pathtomediasinwebsite);
1350 dol_mkdir(dirname($pathtomediasinwebsite)); // To be sure that the directory for website exists
1351 $result = symlink($pathtomedias, $pathtomediasinwebsite);
1352 if (!$result) {
1353 $langs->load("errors");
1354 setEventMessages($langs->trans("ErrorFailedToCreateSymLinkToMedias", $pathtomediasinwebsite, $pathtomedias), null, 'errors');
1355 }
1356 }
1357
1358 // Now generate the master.inc.php page if it does not exists yet
1359 if (!dol_is_file($filemaster)) {
1360 $result = dolSaveMasterFile($filemaster);
1361 if (!$result) {
1362 $error++;
1363 setEventMessages('Failed to write file '.$filemaster, null, 'errors');
1364 }
1365 }
1366
1367 if (!dol_is_file($filehtmlheader)) {
1368 $htmlheadercontent = "<html>\n";
1369 $htmlheadercontent .= $htmlheadercontentdefault;
1370 $htmlheadercontent .= "</html>";
1371 $result = dolSaveHtmlHeader($filehtmlheader, $htmlheadercontent);
1372 }
1373
1374 if (!dol_is_file($filecss)) {
1375 $csscontent = "/* CSS content (all pages) */\nbody.bodywebsite { margin: 0; font-family: 'Open Sans', sans-serif; }\n.bodywebsite h1 { margin-top: 0; margin-bottom: 0; padding: 10px;}";
1376 $result = dolSaveCssFile($filecss, $csscontent);
1377 }
1378
1379 if (!dol_is_file($filejs)) {
1380 $jscontent = "/* JS content (all pages) */\n";
1381 $result = dolSaveJsFile($filejs, $jscontent);
1382 }
1383
1384 if (!dol_is_file($filerobot)) {
1385 $robotcontent = "# Robot file. Generated with Dolibarr\nUser-agent: *\nAllow: /public/\nDisallow: /administrator/";
1386 $result = dolSaveRobotFile($filerobot, $robotcontent);
1387 }
1388
1389 if (!dol_is_file($filehtaccess)) {
1390 $htaccesscontent = "# Order allow,deny\n# Deny from all";
1391 $result = dolSaveHtaccessFile($filehtaccess, $htaccesscontent);
1392 }
1393
1394 if (!dol_is_file($filemanifestjson)) {
1395 $manifestjsoncontent = "";
1396 $result = dolSaveManifestJson($filemanifestjson, $manifestjsoncontent);
1397 }
1398
1399 if (!dol_is_file($filereadme)) {
1400 $readmecontent = "Website generated by Dolibarr ERP CRM";
1401 $result = dolSaveReadme($filereadme, $readmecontent);
1402 }
1403
1404 if (!dol_is_file($filelicense)) {
1405 $licensecontent = "LICENSE\n-------\nThis website template content (HTML and PHP code) is published under the license CC-BY-SA - https://creativecommons.org/licenses/by/4.0/";
1406 $result = dolSaveLicense($filelicense, $licensecontent);
1407 }
1408
1409 $action = 'preview';
1410 }
1411}
1412
1413// Delete site
1414if ($action == 'confirm_deletesite' && $confirm == 'yes' && $permissiontodelete) {
1415 $error = 0;
1416
1417 $db->begin();
1418
1419 $res = $object->fetch(GETPOSTINT('id'));
1420 $website = $object;
1421
1422 if ($res > 0) {
1423 $res = $object->delete($user);
1424 if ($res <= 0) {
1425 $error++;
1426 setEventMessages($object->error, $object->errors, 'errors');
1427 }
1428 }
1429 if (!$error) {
1430 if (GETPOST('delete_also_js', 'alpha') == 'on') {
1431 $pathofwebsitejs = DOL_DATA_ROOT.'/medias/js/'.$object->ref;
1432
1433 dol_delete_dir_recursive($pathofwebsitejs);
1434 }
1435 if (GETPOST('delete_also_medias', 'alpha') == 'on') {
1436 $pathofwebsitemedias = DOL_DATA_ROOT.'/medias/image/'.$object->ref;
1437
1438 dol_delete_dir_recursive($pathofwebsitemedias);
1439 }
1440 }
1441
1442 if (!$error) {
1443 $db->commit();
1444 setEventMessages($langs->trans("SiteDeleted", $object->ref), null, 'mesgs');
1445
1446 header("Location: ".$_SERVER["PHP_SELF"].'?id='.$object->id);
1447 exit;
1448 } else {
1449 $db->rollback();
1450 setEventMessages($object->error, $object->errors, 'errors');
1451 }
1452}
1453
1454// Delete page (from website page menu)
1455if (GETPOSTISSET('pageid') && $action == 'delete' && $permissiontodelete && !GETPOST('file_manager')) {
1456 $error = 0;
1457
1458 $db->begin();
1459
1460 $res = $object->fetch(0, $websitekey);
1461 $website = $object;
1462
1463 $res = $objectpage->fetch($pageid, (string) $object->id);
1464
1465 if ($res > 0) {
1466 $res = $objectpage->delete($user);
1467 if ($res <= 0) {
1468 $error++;
1469 setEventMessages($objectpage->error, $objectpage->errors, 'errors');
1470 }
1471 }
1472
1473 if (!$error) {
1474 $db->commit();
1475 setEventMessages($langs->trans("PageDeleted", $objectpage->pageurl, $websitekey), null, 'mesgs');
1476
1477 header("Location: ".$_SERVER["PHP_SELF"].'?website='.$websitekey);
1478 exit;
1479 } else {
1480 $db->rollback();
1482 }
1483}
1484// Delete page (from menu search)
1485if (!GETPOSTISSET('pageid')) {
1486 $objectclass = 'WebsitePage';
1487
1488 // Add part of code from actions_massactions.inc.php
1489 // Delete record from mass action (massaction = 'delete' for direct delete, action/confirm='delete'/'yes' with a confirmation step before)
1490 if (!$error && ($massaction == 'delete' || ($action == 'delete' && $confirm == 'yes')) && $permissiontodelete) {
1491 $db->begin();
1492
1493 $objecttmp = new $objectclass($db);
1494 $nbok = 0;
1495 foreach ($toselect as $toselectid) {
1496 $result = $objecttmp->fetch($toselectid);
1497 if ($result > 0) {
1498 $result = $objecttmp->delete($user);
1499
1500 if ($result <= 0) {
1501 setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
1502 $error++;
1503 break;
1504 } else {
1505 $nbok++;
1506 }
1507 } else {
1508 setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
1509 $error++;
1510 break;
1511 }
1512 }
1513
1514 if (!$error) {
1515 if ($nbok > 1) {
1516 setEventMessages($langs->trans("RecordsDeleted", $nbok), null, 'mesgs');
1517 } else {
1518 setEventMessages($langs->trans("RecordDeleted", $nbok), null, 'mesgs');
1519 }
1520 $db->commit();
1521 } else {
1522 $db->rollback();
1523 }
1524 //var_dump($listofobjectthirdparties);exit;
1525 }
1526
1527 if ($action == 'delete') { // Test on permission not required here
1528 $mode = 'replacesite';
1529 $action = 'replacesite';
1530
1531 $containertype = GETPOST('optioncontainertype', 'aZ09') != '-1' ? GETPOST('optioncontainertype', 'aZ09') : '';
1532 $langcode = GETPOST('optionlanguage', 'aZ09');
1533 $otherfilters = array();
1534 if (GETPOSTINT('optioncategory') > 0) {
1535 $otherfilters['category'] = GETPOSTINT('optioncategory');
1536 }
1537
1538 $listofpages = getPagesFromSearchCriterias($containertype, $algo, $searchkey, 1000, $sortfield, $sortorder, $langcode, $otherfilters);
1539 }
1540}
1541
1542// Update css site properties. Re-generates also the wrapper.
1543if ($action == 'updatecss' && $usercanedit) {
1544 // If we tried to reload another site/page, we stay on editcss mode.
1545 if (GETPOST('refreshsite') || GETPOST('refreshsite_x') || GETPOST('refreshsite.x') || GETPOST('refreshpage') || GETPOST('refreshpage_x') || GETPOST('refreshpage.x')) {
1546 $action = 'editcss';
1547 } else {
1548 $res = $object->fetch(0, $websitekey);
1549 $website = $object;
1550
1551 if (GETPOSTISSET('virtualhost')) {
1552 $tmpvirtualhost = preg_replace('/\/$/', '', GETPOST('virtualhost', 'alpha'));
1553 if ($tmpvirtualhost && !preg_match('/^http/', $tmpvirtualhost)) {
1554 $error++;
1555 setEventMessages($langs->trans('ErrorURLMustStartWithHttp', $langs->transnoentitiesnoconv("VirtualHost")), null, 'errors');
1556 $action = 'editcss';
1557 }
1558
1559 if (!$error) {
1560 $arrayotherlang = explode(',', GETPOST('WEBSITE_OTHERLANG', 'alphanohtml'));
1561 foreach ($arrayotherlang as $key => $val) {
1562 // It possible we have empty val here if postparam WEBSITE_OTHERLANG is empty or set like this : 'en,,sv' or 'en,sv,'
1563 if (empty(trim($val))) {
1564 continue;
1565 }
1566 $arrayotherlang[$key] = substr(trim($val), 0, 2); // Kept short language code only
1567 }
1568
1569 $object->virtualhost = $tmpvirtualhost;
1570 $object->lang = GETPOST('WEBSITE_LANG', 'aZ09');
1571 $object->otherlang = implode(',', $arrayotherlang);
1572 $object->use_manifest = GETPOSTINT('use_manifest');
1573
1574 $result = $object->update($user);
1575 if ($result < 0) {
1576 $error++;
1577 setEventMessages($object->error, $object->errors, 'errors');
1578 $action = 'editcss';
1579 }
1580 }
1581 }
1582
1583 if (!$error) {
1584 if (($_FILES['addedfile']["name"] != '')) {
1585 $uploadfolder = $conf->website->dir_output.'/'.$websitekey;
1586 if ($_FILES['addedfile']['type'] != 'image/png') {
1587 $error++;
1588 setEventMessages($langs->trans('ErrorFaviconType'), array(), 'errors');
1589 }
1590 $filetoread = realpath(dol_osencode($_FILES['addedfile']['tmp_name']));
1591 $filesize = getimagesize($filetoread);
1592 if ($filesize[0] != $filesize[1]) {
1593 $error++;
1594 setEventMessages($langs->trans('ErrorFaviconMustBeASquaredImage'), array(), 'errors');
1595 }
1596 if (! $error && ($filesize[0] != 16 && $filesize[0] != 32 && $filesize[0] != 64)) {
1597 $error++;
1598 setEventMessages($langs->trans('ErrorFaviconSize'), array(), 'errors');
1599 }
1600 if (!$error) {
1601 dol_add_file_process($uploadfolder, 1, 0, 'addedfile', 'favicon.png');
1602 }
1603 }
1604 if ($error) {
1605 if (!GETPOSTISSET('updateandstay')) { // If we click on "Save And Stay", we don not make the redirect
1606 $action = 'preview';
1607 if ($backtopage) {
1608 $backtopage = preg_replace('/searchstring=[^&]*/', '', $backtopage); // Clean backtopage url
1609 header("Location: ".$backtopage);
1610 exit;
1611 }
1612 } else {
1613 $action = 'editcss';
1614 }
1615 }
1616 }
1617
1618 if (!$error) {
1619 // Save master.inc.php file
1620 dol_syslog("Save master file ".$filemaster);
1621
1622 dol_mkdir($pathofwebsite);
1623
1624 // Now generate the master.inc.php page
1625 $result = dolSaveMasterFile($filemaster);
1626 if (!$result) {
1627 $error++;
1628 setEventMessages('Failed to write file '.$filemaster, null, 'errors');
1629 }
1630
1631
1632 $dataposted = trim(GETPOST('WEBSITE_HTML_HEADER', 'restricthtmlallowlinkscript')); // Must accept tags like '<script>' and '<link>'
1633
1634 $dataposted = preg_replace(array('/<html>\n*/ims', '/<\/html>\n*/ims'), array('', ''), $dataposted);
1635 $dataposted = str_replace('<?=', '<?php', $dataposted);
1636
1637 // Html header file
1638 $phpfullcodestringold = '';
1639 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1640
1641 // Security analysis
1642 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1643
1644 if (!$errorphpcheck) {
1645 $htmlheadercontent = '';
1646
1647 /* We disable php code since global htmlheader for all website is never executed as an include but only read by fgets_content.
1648 $htmlheadercontent.= "<?php // BEGIN PHP\n";
1649 $htmlheadercontent.= '$websitekey=basename(__DIR__);'."\n";
1650 $htmlheadercontent.= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) { require_once './master.inc.php'; } // Load env if not already loaded"."\n";
1651 $htmlheadercontent.= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1652 $htmlheadercontent.= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1653 $htmlheadercontent.= "ob_start();\n";
1654 // $htmlheadercontent.= "header('Content-type: text/html');\n"; // Not required. htmlheader.html is never call as a standalone page
1655 $htmlheadercontent.= "// END PHP ?>\n";*/
1656
1657 $htmlheadercontent .= $dataposted."\n";
1658
1659 /*$htmlheadercontent.= "\n".'<?php // BEGIN PHP'."\n";
1660 $htmlheadercontent.= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp);'."\n";
1661 $htmlheadercontent.= "// END PHP"."\n";*/
1662
1663 $result = dolSaveHtmlHeader($filehtmlheader, $htmlheadercontent);
1664 if (!$result) {
1665 $error++;
1666 setEventMessages('Failed to write file '.$filehtmlheader, null, 'errors');
1667 }
1668 } else {
1669 $error++;
1670 }
1671
1672 $dataposted = trim(GETPOST('WEBSITE_CSS_INLINE', 'none'));
1673 $dataposted = str_replace('<?=', '<?php', $dataposted);
1674
1675 // Css file
1676 $phpfullcodestringold = '';
1677 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1678
1679 // Security analysis
1680 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1681
1682 if (!$errorphpcheck) {
1683 $csscontent = '';
1684
1685 $csscontent .= "<?php // BEGIN PHP\n";
1686 $csscontent .= '$websitekey=basename(__DIR__);'."\n";
1687 $csscontent .= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) { require_once __DIR__.'/master.inc.php'; } // Load env if not already loaded\n"; // For the css, we need to set path of master using the dirname of css file.
1688 $csscontent .= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1689 $csscontent .= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1690 $csscontent .= "ob_start();\n";
1691 $csscontent .= "if (! headers_sent()) { /* because file is included inline when in edit mode and we don't want warning */ \n";
1692 $csscontent .= "header('Cache-Control: max-age=3600, public, must-revalidate');\n";
1693 $csscontent .= "header('Content-type: text/css');\n";
1694 $csscontent .= "}\n";
1695 $csscontent .= "// END PHP ?>\n";
1696
1697 $csscontent .= $dataposted."\n";
1698
1699 $csscontent .= '<?php // BEGIN PHP'."\n";
1700 $csscontent .= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "css");'."\n";
1701 $csscontent .= "// END PHP\n";
1702
1703 dol_syslog("Save css content into ".$filecss);
1704
1705 $result = dolSaveCssFile($filecss, $csscontent);
1706 if (!$result) {
1707 $error++;
1708 setEventMessages('Failed to write file '.$filecss, null, 'errors');
1709 }
1710 } else {
1711 $error++;
1712 }
1713
1714
1715 $dataposted = trim(GETPOST('WEBSITE_JS_INLINE', 'none'));
1716 $dataposted = str_replace('<?=', '<?php', $dataposted);
1717
1718 // Js file
1719 $phpfullcodestringold = '';
1720 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1721
1722 // Security analysis
1723 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1724
1725 if (!$errorphpcheck) {
1726 $jscontent = '';
1727
1728 $jscontent .= "<?php // BEGIN PHP\n";
1729 $jscontent .= '$websitekey=basename(__DIR__);'."\n";
1730 $jscontent .= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) { require_once __DIR__.'/master.inc.php'; } // Load env if not already loaded\n"; // For the css, we need to set path of master using the dirname of css file.
1731 $jscontent .= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1732 $jscontent .= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1733 $jscontent .= "ob_start();\n";
1734 $jscontent .= "header('Cache-Control: max-age=3600, public, must-revalidate');\n";
1735 $jscontent .= "header('Content-type: application/javascript');\n";
1736 $jscontent .= "// END PHP ?>\n";
1737
1738 $jscontent .= $dataposted."\n";
1739
1740 $jscontent .= '<?php // BEGIN PHP'."\n";
1741 $jscontent .= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "js");'."\n";
1742 $jscontent .= "// END PHP\n";
1743
1744 $result = dolSaveJsFile($filejs, $jscontent);
1745 if (!$result) {
1746 $error++;
1747 setEventMessages('Failed to write file '.$filejs, null, 'errors');
1748 }
1749 } else {
1750 $error++;
1751 }
1752
1753 $dataposted = trim(GETPOST('WEBSITE_ROBOT', 'nohtml'));
1754 $dataposted = str_replace('<?=', '<?php', $dataposted);
1755
1756 // Robot file
1757 $phpfullcodestringold = '';
1758 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1759
1760 // Security analysis
1761 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1762
1763 if (!$errorphpcheck) {
1764 $robotcontent = '';
1765
1766 /*$robotcontent.= "<?php // BEGIN PHP\n";
1767 $robotcontent.= '$websitekey=basename(__DIR__);'."\n";
1768 $robotcontent.= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) { require_once './master.inc.php'; } // Load env if not already loaded"."\n";
1769 $robotcontent.= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1770 $robotcontent.= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1771 $robotcontent.= "ob_start();\n";
1772 $robotcontent.= "header('Cache-Control: max-age=3600, public, must-revalidate');\n";
1773 $robotcontent.= "header('Content-type: text/css');\n";
1774 $robotcontent.= "// END PHP ?>\n";*/
1775
1776 $robotcontent .= $dataposted."\n";
1777
1778 /*$robotcontent.= "\n".'<?php // BEGIN PHP'."\n";
1779 $robotcontent.= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "robot");'."\n";
1780 $robotcontent.= "// END PHP ?>"."\n";*/
1781
1782 $result = dolSaveRobotFile($filerobot, $robotcontent);
1783 if (!$result) {
1784 $error++;
1785 setEventMessages('Failed to write file '.$filerobot, null, 'errors');
1786 }
1787 } else {
1788 $error++;
1789 }
1790
1791 $dataposted = trim(GETPOST('WEBSITE_HTACCESS', 'nohtml'));
1792 $dataposted = str_replace('<?=', '<?php', $dataposted);
1793
1794 // Htaccess file
1795 $phpfullcodestringold = '';
1796 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1797
1798 // Security analysis
1799 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1800
1801 if (!$errorphpcheck) {
1802 if ($dataposted) {
1803 $htaccesscontent = '';
1804 $htaccesscontent .= $dataposted."\n";
1805
1806 $result = dolSaveHtaccessFile($filehtaccess, $htaccesscontent);
1807 if (!$result) {
1808 $error++;
1809 setEventMessages('Failed to write file '.$filehtaccess, null, 'errors');
1810 }
1811 } else {
1812 dol_delete_file($filehtaccess, 0, 0);
1813 }
1814 } else {
1815 $error++;
1816 }
1817
1818
1819 $dataposted = trim(GETPOST('WEBSITE_MANIFEST_JSON', 'restricthtmlallowunvalid'));
1820 $dataposted = str_replace('<?=', '<?php', $dataposted);
1821
1822 // Manifest.json file
1823 $phpfullcodestringold = '';
1824 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1825
1826 // Security analysis
1827 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1828
1829 if (!$errorphpcheck) {
1830 $manifestjsoncontent = '';
1831
1832 $manifestjsoncontent .= "<?php // BEGIN PHP\n";
1833 $manifestjsoncontent .= '$websitekey=basename(__DIR__);'."\n";
1834 $manifestjsoncontent .= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) { require_once __DIR__.'/master.inc.php'; } // Load env if not already loaded\n"; // For the css, we need to set path of master using the dirname of css file.
1835 $manifestjsoncontent .= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1836 $manifestjsoncontent .= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1837 $manifestjsoncontent .= "ob_start();\n";
1838 $manifestjsoncontent .= "header('Cache-Control: max-age=3600, public, must-revalidate');\n";
1839 $manifestjsoncontent .= "header('Content-type: application/manifest+json');\n";
1840 $manifestjsoncontent .= "// END PHP ?>\n";
1841
1842 $manifestjsoncontent .= $dataposted."\n";
1843
1844 $manifestjsoncontent .= '<?php // BEGIN PHP'."\n";
1845 $manifestjsoncontent .= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "manifest");'."\n";
1846 $manifestjsoncontent .= "// END PHP\n";
1847
1848 $result = dolSaveManifestJson($filemanifestjson, $manifestjsoncontent);
1849 if (!$result) {
1850 $error++;
1851 setEventMessages('Failed to write file '.$filemanifestjson, null, 'errors');
1852 }
1853 } else {
1854 $error++;
1855 }
1856
1857
1858 $dataposted = trim(GETPOST('WEBSITE_README', 'nohtml'));
1859 $dataposted = str_replace('<?=', '<?php', $dataposted);
1860
1861 // README.md file
1862 $phpfullcodestringold = '';
1863 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1864
1865 // Security analysis
1866 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1867
1868 if (!$errorphpcheck) {
1869 $readmecontent = '';
1870
1871 /*$readmecontent.= "<?php // BEGIN PHP\n";
1872 $readmecontent.= '$websitekey=basename(__DIR__);'."\n";
1873 $readmecontent.= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) { require_once __DIR__.'/master.inc.php'; } // Load env if not already loaded"."\n"; // For the css, we need to set path of master using the dirname of css file.
1874 $readmecontent.= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1875 $readmecontent.= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1876 $readmecontent.= "ob_start();\n";
1877 $readmecontent.= "header('Cache-Control: max-age=3600, public, must-revalidate');\n";
1878 $readmecontent.= "header('Content-type: application/manifest+json');\n";
1879 $readmecontent.= "// END PHP ?>\n";*/
1880
1881 $readmecontent .= $dataposted."\n";
1882
1883 /*$readmecontent.= '<?php // BEGIN PHP'."\n";
1884 $readmecontent.= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "manifest");'."\n";
1885 $readmecontent.= "// END PHP ?>"."\n";*/
1886
1887 $result = dolSaveReadme($filereadme, $readmecontent);
1888 if (!$result) {
1889 $error++;
1890 setEventMessages('Failed to write file '.$filereadme, null, 'errors');
1891 }
1892 } else {
1893 $error++;
1894 }
1895
1896
1897 $dataposted = trim(GETPOST('WEBSITE_LICENSE', 'nohtml'));
1898 $dataposted = str_replace('<?=', '<?php', $dataposted);
1899
1900 // LICENSE file
1901 $phpfullcodestringold = '';
1902 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1903
1904 // Security analysis
1905 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1906
1907 if (!$errorphpcheck) {
1908 $licensecontent = '';
1909
1910 /*$readmecontent.= "<?php // BEGIN PHP\n";
1911 $readmecontent.= '$websitekey=basename(__DIR__);'."\n";
1912 $readmecontent.= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) { require_once __DIR__.'/master.inc.php'; } // Load env if not already loaded"."\n"; // For the css, we need to set path of master using the dirname of css file.
1913 $readmecontent.= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1914 $readmecontent.= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1915 $readmecontent.= "ob_start();\n";
1916 $readmecontent.= "header('Cache-Control: max-age=3600, public, must-revalidate');\n";
1917 $readmecontent.= "header('Content-type: application/manifest+json');\n";
1918 $readmecontent.= "// END PHP ?>\n";*/
1919
1920 $licensecontent .= $dataposted."\n";
1921
1922 /*$readmecontent.= '<?php // BEGIN PHP'."\n";
1923 $readmecontent.= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "manifest");'."\n";
1924 $readmecontent.= "// END PHP ?>"."\n";*/
1925
1926 $result = dolSaveLicense($filelicense, $licensecontent);
1927 if (!$result) {
1928 $error++;
1929 setEventMessages('Failed to write file '.$filelicense, null, 'errors');
1930 }
1931 } else {
1932 $error++;
1933 }
1934
1935 // Save wrapper.php
1936 $result = dolSaveIndexPage($pathofwebsite, '', '', $filewrapper, $object);
1937
1938
1939 // Message if no error
1940 if (!$error) {
1941 setEventMessages($langs->trans("Saved"), null, 'mesgs');
1942 }
1943
1944 if (!GETPOSTISSET('updateandstay')) { // If we click on "Save And Stay", we don not make the redirect
1945 $action = 'preview';
1946 if ($backtopage) {
1947 $backtopage = preg_replace('/searchstring=[^&]*/', '', $backtopage); // Clean backtopage url
1948 header("Location: ".$backtopage);
1949 exit;
1950 }
1951 } else {
1952 $action = 'editcss';
1953 }
1954 }
1955 }
1956}
1957
1958$sourcetype = '';
1959if ($action == "updatesecurity" && $usercanedit && GETPOST("btn_WEBSITE_SECURITY_FORCECSP")) {
1960 $directivecsp = GETPOST("select_identifier_WEBSITE_SECURITY_FORCECSP");
1961 $sourcecsp = GETPOST("select_source_WEBSITE_SECURITY_FORCECSP");
1962 $sourcedatacsp = GETPOST("input_data_WEBSITE_SECURITY_FORCECSP");
1963
1964 $forceCSPArr = websiteGetContentPolicyToArray($forceCSP);
1965 $directivesarray = websiteGetContentPolicyDirectives();
1966 $sourcesarray = websiteGetContentPolicySources();
1967 if (empty($directivecsp)) {
1968 $error++;
1969 }
1970 if ($error || (!isset($sourcecsp) && $directivesarray[$directivecsp]["data-directivetype"] != "none")) {
1971 $error++;
1972 }
1973 if (!$error) {
1974 $directivetype = $directivesarray[$directivecsp]["data-directivetype"];
1975 if (isset($sourcecsp)) {
1976 $sourcetype = $sourcesarray[$directivetype][$sourcecsp]["data-sourcetype"];
1977 }
1978 $securityspstring = "";
1979 if (isset($sourcetype) && $sourcetype == "data") {
1980 $forceCSPArr[$directivecsp][] = "data:".$sourcedatacsp;
1981 } elseif (isset($sourcetype) && $sourcetype == "input") {
1982 if (empty($forceCSPArr[$directivecsp])) {
1983 $forceCSPArr[$directivecsp] = array();
1984 }
1985 $forceCSPArr[$directivecsp] = array_merge(explode(" ", $sourcedatacsp), $forceCSPArr[$directivecsp]);
1986 } else {
1987 if (empty($forceCSPArr[$directivecsp])) {
1988 $forceCSPArr[$directivecsp] = array();
1989 }
1990 if (!isset($sourcecsp)) {
1991 $sourcecsp = "";
1992 }
1993 array_unshift($forceCSPArr[$directivecsp], $sourcecsp);
1994 }
1995 foreach ($forceCSPArr as $directive => $sourcekeys) {
1996 if ($securityspstring != "") {
1997 $securityspstring .= "; ";
1998 }
1999 $sourcestring = "";
2000 foreach ($sourcekeys as $key => $source) {
2001 $directivetype = $directivesarray[$directive]["data-directivetype"];
2002 $sourcetype = $sourcesarray[$directivetype][$source]["data-sourcetype"];
2003 if (isset($sourcetype) && $sourcetype == "quoted") {
2004 $sourcestring .= " '".$source."'";
2005 } elseif ($directivetype != "none") {
2006 $sourcestring .= " ".$source;
2007 }
2008 }
2009 $securityspstring .= $directive . $sourcestring;
2010 }
2011 $res = dolibarr_set_const($db, 'WEBSITE_'.$object->id.'_SECURITY_FORCECSP', $securityspstring, 'chaine', 0, '', $conf->entity);
2012 if ($res <= 0) {
2013 $error++;
2014 }
2015 }
2016
2017 if (!$error) {
2018 $db->commit();
2019 setEventMessages($langs->trans("SecurityPolicySucesfullyAdded"), null, 'mesgs');
2020 } else {
2021 $db->rollback();
2022 setEventMessages($langs->trans("ErrorAddingSecurityPolicy"), null, 'errors');
2023 }
2024 header("Location: ".$_SERVER["PHP_SELF"].'?websiteid='.$websiteid."&action=editsecurity");
2025 exit();
2026}
2027
2028if ($action == "updatesecurity" && $usercanedit) {
2029 $db->begin();
2030 $res1 = $res2 = $res3 = $res4 = 0;
2031 $securityrp = GETPOST('WEBSITE_'.$object->id.'_SECURITY_FORCERP', 'alpha');
2032 $securitysts = GETPOST('WEBSITE_'.$object->id.'_SECURITY_FORCESTS', 'alpha');
2033 $securitypp = GETPOST('WEBSITE_'.$object->id.'_SECURITY_FORCEPP', 'alpha');
2034 $securitysp = GETPOST('WEBSITE_'.$object->id.'_SECURITY_FORCECSP', 'alpha');
2035 $securitycspro = GETPOST('WEBSITE_'.$object->id.'_SECURITY_FORCECSPRO', 'alpha');
2036
2037 $res1 = dolibarr_set_const($db, 'WEBSITE_'.$object->id.'_SECURITY_FORCERP', $securityrp, 'chaine', 0, '', $conf->entity);
2038 $res2 = dolibarr_set_const($db, 'WEBSITE_'.$object->id.'_SECURITY_FORCESTS', $securitysts, 'chaine', 0, '', $conf->entity);
2039 $res3 = dolibarr_set_const($db, 'WEBSITE_'.$object->id.'_SECURITY_FORCEPP', $securitypp, 'chaine', 0, '', $conf->entity);
2040 $res4 = dolibarr_set_const($db, 'WEBSITE_'.$object->id.'_SECURITY_FORCECSP', $securitysp, 'chaine', 0, '', $conf->entity);
2041 $res5 = dolibarr_set_const($db, 'WEBSITE_'.$object->id.'_SECURITY_FORCECSPRO', $securitycspro, 'chaine', 0, '', $conf->entity);
2042
2043 if ($res1 >= 0 && $res2 >= 0 && $res3 >= 0 && $res4 >= 0 && $res5 >= 0) {
2044 $db->commit();
2045 setEventMessages($langs->trans("Saved"), null, 'mesgs');
2046 } else {
2047 $db->rollback();
2048 setEventMessages($langs->trans("ErrorSavingChanges"), null, 'errors');
2049 }
2050
2051 if (!GETPOSTISSET('updateandstay')) { // If we click on "Save And Stay", we don not make the redirect
2052 $action = 'preview';
2053 if ($backtopage) {
2054 $backtopage = preg_replace('/searchstring=[^&]*/', '', $backtopage); // Clean backtopage url
2055 header("Location: ".$backtopage);
2056 exit;
2057 }
2058 } else {
2059 $action = 'editsecurity';
2060 $forceCSP = getDolGlobalString("WEBSITE_".$object->id."_SECURITY_FORCECSP");
2061 }
2062}
2063
2064// Update page
2065if ($action == 'setashome' && $usercanedit) {
2066 $db->begin();
2067 $object->fetch(0, $websitekey);
2068 $website = $object;
2069
2070 $object->fk_default_home = $pageid;
2071 $res = $object->update($user);
2072 if (! ($res > 0)) {
2073 $error++;
2074 setEventMessages($object->error, $object->errors, 'errors');
2075 }
2076
2077 if (!$error) {
2078 $db->commit();
2079
2080 $filetpl = $pathofwebsite.'/page'.$pageid.'.tpl.php';
2081
2082 // Generate the index.php page to be the home page
2083 $result = dolSaveIndexPage($pathofwebsite, $fileindex, $filetpl, $filewrapper, $object);
2084
2085 if ($result) {
2086 setEventMessages($langs->trans("Saved"), null, 'mesgs');
2087 } else {
2088 setEventMessages('Failed to write file '.$fileindex, null, 'errors');
2089 }
2090
2091 $action = 'preview';
2092 } else {
2093 $db->rollback();
2094 }
2095}
2096
2097// Update page properties (meta)
2098if ($action == 'updatemeta' && $usercanedit) {
2099 $db->begin();
2100
2101 $result = $object->fetch(0, $websitekey);
2102 $website = $object;
2103
2104 $objectpage->fk_website = $object->id;
2105
2106 // Check parameters
2107 if (!preg_match('/^[a-z0-9\-\_]+$/i', GETPOST('WEBSITE_PAGENAME', 'alpha'))) {
2108 $error++;
2109 $langs->load("errors");
2110 setEventMessages($langs->transnoentities("ErrorFieldCanNotContainSpecialCharacters", $langs->transnoentities('WEBSITE_PAGENAME')), null, 'errors');
2111 $action = 'editmeta';
2112 }
2113
2114 $res = $objectpage->fetch($pageid, (string) $object->id);
2115 if ($res <= 0) {
2116 $error++;
2117 setEventMessages('Page not found '.$objectpage->error, $objectpage->errors, 'errors');
2118 }
2119
2120 // Check alias not exists
2121 if (!$error && GETPOST('WEBSITE_PAGENAME', 'alpha')) {
2122 $websitepagetemp = new WebsitePage($db);
2123 $result = $websitepagetemp->fetch(-1 * $objectpage->id, (string) $object->id, GETPOST('WEBSITE_PAGENAME', 'alpha'));
2124 if ($result < 0) {
2125 $error++;
2126 $langs->load("errors");
2127 setEventMessages($websitepagetemp->error, $websitepagetemp->errors, 'errors');
2128 $action = 'editmeta';
2129 }
2130 if ($result > 0) {
2131 $error++;
2132 $langs->load("errors");
2133 setEventMessages($langs->trans("ErrorAPageWithThisNameOrAliasAlreadyExists", $websitepagetemp->pageurl), null, 'errors');
2134 $action = 'editmeta';
2135 }
2136 }
2137
2138 $newaliasnames = '';
2139 if (!$error && GETPOST('WEBSITE_ALIASALT', 'alpha')) {
2140 $arrayofaliastotest = explode(',', str_replace(array('<', '>'), '', GETPOST('WEBSITE_ALIASALT', 'alpha')));
2141
2142 $websitepagetemp = new WebsitePage($db);
2143 foreach ($arrayofaliastotest as $aliastotest) {
2144 $aliastotest = trim(preg_replace('/\.php$/i', '', $aliastotest));
2145
2146 // Disallow alias name pageX (already used to save the page with id)
2147 if (preg_match('/^page\d+/i', $aliastotest)) {
2148 $error++;
2149 $langs->load("errors");
2150 setEventMessages("Alias name 'pageX' is not allowed", null, 'errors');
2151 $action = 'editmeta';
2152 break;
2153 } else {
2154 $result = $websitepagetemp->fetch(-1 * $objectpage->id, (string) $object->id, $aliastotest);
2155 if ($result < 0) {
2156 $error++;
2157 $langs->load("errors");
2158 setEventMessages($websitepagetemp->error, $websitepagetemp->errors, 'errors');
2159 $action = 'editmeta';
2160 break;
2161 }
2162 if ($result > 0) {
2163 $error++;
2164 $langs->load("errors");
2165 setEventMessages($langs->trans("ErrorAPageWithThisNameOrAliasAlreadyExists", $websitepagetemp->pageurl), null, 'errors');
2166 $action = 'editmeta';
2167 break;
2168 }
2169 $newaliasnames .= ($newaliasnames ? ', ' : '').$aliastotest;
2170 }
2171 }
2172 }
2173
2174 if (!$error) {
2175 $objectpage->old_object = clone $objectpage;
2176
2177 $objectpage->title = str_replace(array('<', '>'), '', GETPOST('WEBSITE_TITLE', 'alphanohtml'));
2178 $objectpage->type_container = GETPOST('WEBSITE_TYPE_CONTAINER', 'aZ09');
2179 $objectpage->pageurl = dol_sanitizeUrl(GETPOST('WEBSITE_PAGENAME', 'alpha'));
2180 $objectpage->aliasalt = $newaliasnames;
2181 $objectpage->lang = GETPOST('WEBSITE_LANG', 'aZ09');
2182 $objectpage->otherlang = GETPOST('WEBSITE_OTHERLANG', 'aZ09comma');
2183 $objectpage->description = str_replace(array('<', '>'), '', GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml'));
2184 $objectpage->image = GETPOST('WEBSITE_IMAGE', 'alpha');
2185 $objectpage->keywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml'));
2186 $objectpage->allowed_in_frames = GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09') ? 1 : 0;
2187 $objectpage->htmlheader = trim(GETPOST('htmlheader', 'restricthtmlallowlinkscript')); // Must accept tags like '<script>' and '<link>'
2188 $objectpage->fk_page = (GETPOSTINT('pageidfortranslation') > 0 ? GETPOSTINT('pageidfortranslation') : 0);
2189 $objectpage->author_alias = trim(GETPOST('WEBSITE_AUTHORALIAS', 'alphanohtml'));
2190 $objectpage->object_type = GETPOST('WEBSITE_OBJECTCLASS', 'alpha');
2191 $objectpage->fk_object = GETPOST('WEBSITE_OBJECTID', 'aZ09');
2192
2193 $newdatecreation = dol_mktime(GETPOSTINT('datecreationhour'), GETPOSTINT('datecreationmin'), GETPOSTINT('datecreationsec'), GETPOSTINT('datecreationmonth'), GETPOSTINT('datecreationday'), GETPOSTINT('datecreationyear'));
2194 if ($newdatecreation) {
2195 $objectpage->date_creation = $newdatecreation;
2196 }
2197
2198 $res = $objectpage->update($user);
2199 if (!($res > 0)) {
2200 $langs->load("errors");
2201 if ($db->lasterrno == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
2202 $error++;
2203 setEventMessages($langs->trans("ErrorAPageWithThisNameOrAliasAlreadyExists"), null, 'errors');
2204 $action = 'editmeta';
2205 } else {
2206 $error++;
2207 setEventMessages($objectpage->error, $objectpage->errors, 'errors');
2208 $action = 'editmeta';
2209 }
2210 }
2211 }
2212
2213 if (!$error) {
2214 // Website categories association
2215 $categoriesarray = GETPOST('categories', 'array:int');
2216 $result = $objectpage->setCategories($categoriesarray);
2217 if ($result < 0) {
2218 $error++;
2219 setEventMessages($object->error, $object->errors, 'errors');
2220 }
2221 }
2222
2223 if (!$error) {
2224 $db->commit();
2225 } else {
2226 $db->rollback();
2227 }
2228
2229 if (!$error) {
2230 $filemaster = $pathofwebsite.'/master.inc.php';
2231 $fileoldalias = $pathofwebsite.'/'.$objectpage->old_object->pageurl.'.php';
2232 $filealias = $pathofwebsite.'/'.$objectpage->pageurl.'.php';
2233
2234 dol_mkdir($pathofwebsite);
2235
2236 // Now generate the master.inc.php page
2237 $result = dolSaveMasterFile($filemaster);
2238 if (!$result) {
2239 setEventMessages('Failed to write file '.$filemaster, null, 'errors');
2240 }
2241
2242 // Now delete the alias.php page
2243 if (!empty($fileoldalias)) {
2244 dol_syslog("We delete old alias page name=".$fileoldalias." to build a new alias page=".$filealias);
2245 dol_delete_file($fileoldalias);
2246
2247 // Delete also pages into language subdirectories
2248 if (empty($objectpage->lang) || !in_array($objectpage->lang, explode(',', $object->otherlang))) {
2249 $dirname = dirname($fileoldalias);
2250 $filename = basename($fileoldalias);
2251 $sublangs = explode(',', $object->otherlang);
2252 foreach ($sublangs as $sublang) {
2253 // Under certain conditions $sublang can be an empty string
2254 // ($object->otherlang with empty string or with string like this 'en,,sv')
2255 // if is the case we try to re-delete the main alias file. Avoid it.
2256 if (empty(trim($sublang))) {
2257 continue;
2258 }
2259 $fileoldaliassub = $dirname.'/'.$sublang.'/'.$filename;
2260 dol_delete_file($fileoldaliassub);
2261 }
2262 }
2263 }
2264 // Now delete the alternative alias.php pages
2265 if (!empty($objectpage->old_object->aliasalt)) {
2266 $tmpaltaliases = explode(',', $objectpage->old_object->aliasalt);
2267 if (is_array($tmpaltaliases)) {
2268 foreach ($tmpaltaliases as $tmpaliasalt) {
2269 dol_syslog("We delete old alt alias pages name=".trim($tmpaliasalt));
2270 dol_delete_file($pathofwebsite.'/'.trim($tmpaliasalt).'.php');
2271
2272 // Delete also pages into language subdirectories
2273 if (empty($objectpage->lang) || !in_array($objectpage->lang, explode(',', $object->otherlang))) {
2274 $dirname = dirname($pathofwebsite.'/'.trim($tmpaliasalt).'.php');
2275 $filename = basename($pathofwebsite.'/'.trim($tmpaliasalt).'.php');
2276 $sublangs = explode(',', $object->otherlang);
2277 foreach ($sublangs as $sublang) {
2278 // Under certain conditions $ sublang can be an empty string
2279 // ($object->otherlang with empty string or with string like this 'en,,sv')
2280 // if is the case we try to re-delete the main alias file. Avoid it.
2281 if (empty(trim($sublang))) {
2282 continue;
2283 }
2284 $fileoldaliassub = $dirname.'/'.$sublang.'/'.$filename;
2285 dol_delete_file($fileoldaliassub);
2286 }
2287 }
2288 }
2289 }
2290 }
2291
2292 // Save page main alias
2293 $result = dolSavePageAlias($filealias, $object, $objectpage);
2294 if (!$result) {
2295 setEventMessages('Failed to write file '.$filealias, null, 'errors');
2296 }
2297 // Save alt aliases
2298 if (!empty($objectpage->aliasalt)) {
2299 $tmpaltaliases = explode(',', $objectpage->aliasalt);
2300 if (is_array($tmpaltaliases)) {
2301 foreach ($tmpaltaliases as $tmpaliasalt) {
2302 if (trim($tmpaliasalt)) {
2303 $filealias = $pathofwebsite.'/'.trim($tmpaliasalt).'.php';
2304 $result = dolSavePageAlias($filealias, $object, $objectpage);
2305 if (!$result) {
2306 setEventMessages('Failed to write file '.basename($filealias), null, 'errors');
2307 }
2308 }
2309 }
2310 }
2311 }
2312
2313
2314 // Save page of content
2315 $result = dolSavePageContent($filetpl, $object, $objectpage, 1);
2316 if ($result) {
2317 setEventMessages($langs->trans("Saved"), null, 'mesgs');
2318
2319 if (!GETPOSTISSET('updateandstay')) { // If we click on "Save And Stay", we do not make the redirect
2320 //header("Location: ".$_SERVER["PHP_SELF"].'?website='.$websitekey.'&pageid='.$pageid);
2321 //exit;
2322 $action = 'preview';
2323 } else {
2324 $action = 'editmeta';
2325 }
2326 } else {
2327 setEventMessages('Failed to write file '.$filetpl, null, 'errors');
2328 //header("Location: ".$_SERVER["PHP_SELF"].'?website='.$websitekey.'&pageid='.$pageid);
2329 //exit;
2330 $action = 'preview';
2331 }
2332 }
2333}
2334
2335// Update page
2336if ((($action == 'updatesource' || $action == 'updatecontent' || $action == 'confirm_createfromclone' || $action == 'confirm_createpagefromclone') || ($action == 'preview' && (GETPOST('refreshsite') || GETPOST('refreshpage') || GETPOST('preview')))) && $usercanedit) {
2337 $object->fetch(0, $websitekey);
2338 $website = $object;
2339
2340 if ($action == 'confirm_createfromclone') { // Test on permissions already done
2341 $db->begin();
2342
2343 $objectnew = new Website($db);
2344 $result = $objectnew->createFromClone($user, GETPOSTINT('id'), GETPOST('siteref'), (GETPOSTINT('newlang') ? GETPOSTINT('newlang') : ''));
2345
2346 if ($result < 0) {
2347 $error++;
2348 setEventMessages($objectnew->error, $objectnew->errors, 'errors');
2349 $action = 'preview';
2350
2351 $db->rollback();
2352 } else {
2353 setEventMessages("ObjectClonedSuccessfuly", null, 'mesgs');
2354 $object = $objectnew;
2355 $id = $object->id;
2356 $pageid = $object->fk_default_home;
2357 $websitekey = GETPOST('siteref', 'aZ09');
2358
2359 $db->commit();
2360 }
2361 }
2362
2363 if ($action == 'confirm_createpagefromclone') { // Test on permissions already done
2364 $istranslation = (GETPOST('is_a_translation', 'aZ09') == 'on' ? 1 : 0);
2365 // Protection if it is a translation page
2366 if ($istranslation) {
2367 if (GETPOST('newlang', 'aZ09') == $objectpage->lang || !GETPOST('newlang', 'aZ09')) {
2368 $error++;
2369 setEventMessages($langs->trans("LanguageMustNotBeSameThanClonedPage"), null, 'errors');
2370 $action = 'preview';
2371 }
2372 if (GETPOSTINT('newwebsite') != $object->id) {
2373 $error++;
2374 setEventMessages($langs->trans("WebsiteMustBeSameThanClonedPageIfTranslation"), null, 'errors');
2375 $action = 'preview';
2376 }
2377 }
2378
2379 if (!$error) {
2380 $db->begin();
2381
2382 $newwebsiteid = GETPOSTINT('newwebsite');
2383 $pathofwebsitenew = $pathofwebsite;
2384
2385 $tmpwebsite = new Website($db);
2386 if ($newwebsiteid > 0 && $newwebsiteid != $object->id) {
2387 $tmpwebsite->fetch($newwebsiteid);
2388 $pathofwebsitenew = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$tmpwebsite->ref;
2389 } else {
2390 $tmpwebsite = $object;
2391 }
2392
2393 $objectpage = new WebsitePage($db);
2394 $resultpage = $objectpage->createFromClone($user, $pageid, GETPOST('newpageurl', 'aZ09'), (GETPOST('newlang', 'aZ09') ? GETPOST('newlang', 'aZ09') : ''), $istranslation, $newwebsiteid, GETPOST('newtitle', 'alphanohtml'), $tmpwebsite);
2395 if ($resultpage < 0) {
2396 $error++;
2397 setEventMessages($objectpage->error, $objectpage->errors, 'errors');
2398 $action = 'createpagefromclone';
2399
2400 $db->rollback();
2401 } else {
2402 $filetpl = $pathofwebsitenew.'/page'.$resultpage->id.'.tpl.php';
2403 $fileindex = $pathofwebsitenew.'/index.php';
2404 $filewrapper = $pathofwebsitenew.'/wrapper.php';
2405
2406 //var_dump($pathofwebsitenew);
2407 //var_dump($filetpl);
2408 //exit;
2409
2410 dolSavePageContent($filetpl, $tmpwebsite, $resultpage, 1);
2411
2412 // Switch on the new page if web site of new page/container is same
2413 if (empty($newwebsiteid) || $newwebsiteid == $object->id) {
2414 $pageid = $resultpage->id;
2415 }
2416
2417 $db->commit();
2418 }
2419 }
2420 }
2421
2422 $res = 0;
2423
2424 if (!$error) {
2425 // Check symlink documents/website/mywebsite/medias to point to documents/medias and restore it if ko.
2426 // Recreate also dir of website if not found.
2427 $pathtomedias = DOL_DATA_ROOT.'/medias';
2428 $pathtomediasinwebsite = $pathofwebsite.'/medias';
2429 if (!is_link(dol_osencode($pathtomediasinwebsite))) {
2430 dol_syslog("Create symlink for ".$pathtomedias." into name ".$pathtomediasinwebsite);
2431 dol_mkdir(dirname($pathtomediasinwebsite)); // To be sure that the directory for website exists
2432 $result = symlink($pathtomedias, $pathtomediasinwebsite);
2433 if (!$result) {
2434 $langs->load("errors");
2435 setEventMessages($langs->trans("ErrorFailedToCreateSymLinkToMedias", $pathtomediasinwebsite, $pathtomedias), null, 'errors');
2436 }
2437 }
2438
2439 /*if (GETPOST('savevirtualhost') && $object->virtualhost != GETPOST('previewsite'))
2440 {
2441 $object->virtualhost = GETPOST('previewsite', 'alpha');
2442 $object->update($user);
2443 }*/
2444
2445 $objectpage->fk_website = $object->id;
2446
2447 if ($pageid > 0) {
2448 $res = $objectpage->fetch($pageid);
2449 } else {
2450 $res = 0;
2451 if ($object->fk_default_home > 0) {
2452 $res = $objectpage->fetch($object->fk_default_home);
2453 }
2454 if (!($res > 0)) {
2455 $res = $objectpage->fetch(0, (string) $object->id);
2456 }
2457 }
2458 }
2459
2460 if (!$error && $res > 0) {
2461 if ($action == 'updatesource' || $action == 'updatecontent') { // Test on permissions already done
2462 $db->begin();
2463
2464 $phpfullcodestringold = dolKeepOnlyPhpCode($objectpage->content);
2465
2466 $objectpage->content = GETPOST('PAGE_CONTENT', 'none'); // any HTML content allowed
2467
2468 $phpfullcodestring = dolKeepOnlyPhpCode($objectpage->content);
2469
2470 // Security analysis (check PHP content and check permission website->writephp if php content is modified)
2471 $error = checkPHPCode($phpfullcodestringold, $phpfullcodestring);
2472
2473 if ($error) {
2474 if ($action == 'updatesource') { // Test on permissions already done
2475 $action = 'editsource';
2476 }
2477 if ($action == 'updatecontent') { // Test on permissions already done
2478 $action = 'editcontent';
2479 }
2480 }
2481
2482 // Clean data. We remove all the head section.
2483 $objectpage->content = preg_replace('/<head>.*<\/head>/ims', '', $objectpage->content);
2484 /* $objectpage->content = preg_replace('/<base\s+href=[\'"][^\'"]+[\'"]\s/?>/s', '', $objectpage->content); */
2485
2486
2487 $res = $objectpage->update($user);
2488 if ($res < 0) {
2489 $error++;
2490 setEventMessages($objectpage->error, $objectpage->errors, 'errors');
2491 if ($action == 'updatesource') { // Test on permissions already done
2492 $action = 'editsource';
2493 }
2494 if ($action == 'updatecontent') { // Test on permissions already done
2495 $action = 'editcontent';
2496 }
2497 }
2498
2499 if (!$error) {
2500 $db->commit();
2501
2502 $filemaster = $pathofwebsite.'/master.inc.php';
2503 //$fileoldalias=$pathofwebsite.'/'.$objectpage->old_object->pageurl.'.php';
2504 $filealias = $pathofwebsite.'/'.$objectpage->pageurl.'.php';
2505
2506 dol_mkdir($pathofwebsite);
2507
2508 // Now generate the master.inc.php page
2509 $result = dolSaveMasterFile($filemaster);
2510
2511 if (!$result) {
2512 setEventMessages('Failed to write the master file file '.$filemaster, null, 'errors');
2513 }
2514
2515 // Now delete the old alias.php page if we removed one
2516 /*if (!empty($fileoldalias))
2517 {
2518 dol_syslog("We regenerate alias page new name=".$filealias.", old name=".$fileoldalias);
2519 dol_delete_file($fileoldalias);
2520
2521 // Delete also pages into language subdirectories
2522 if (empty($objectpage->lang) || !in_array($objectpage->lang, explode(',', $object->otherlang))) {
2523 $dirname = dirname($fileoldalias);
2524 $filename = basename($fileoldalias);
2525 $sublangs = explode(',', $object->otherlang);
2526 foreach ($sublangs as $sublang) {
2527 $fileoldaliassub = $dirname.'/'.$sublang.'/'.$filename;
2528 dol_delete_file($fileoldaliassub);
2529 }
2530 }
2531 }*/
2532
2533 // Save page alias
2534 $result = dolSavePageAlias($filealias, $object, $objectpage);
2535 if (!$result) {
2536 setEventMessages('Failed to write the alias file '.basename($filealias), null, 'errors');
2537 }
2538
2539 // Save page content
2540 $result = dolSavePageContent($filetpl, $object, $objectpage, 1);
2541 if ($result) {
2542 setEventMessages($langs->trans("Saved"), null, 'mesgs');
2543
2544 if (!GETPOSTISSET('updateandstay')) { // If we click on "Save And Stay", we do not make the redirect
2545 if ($backtopage) {
2546 header("Location: ".$backtopage);
2547 exit;
2548 } else {
2549 header("Location: ".$_SERVER["PHP_SELF"].'?website='.$websitekey.'&pageid='.$pageid);
2550 exit;
2551 }
2552 } else {
2553 if ($action == 'updatesource') { // Test on permissions already done
2554 $action = 'editsource';
2555 }
2556 if ($action == 'updatecontent') { // Test on permissions already done
2557 $action = 'editcontent';
2558 }
2559 }
2560 } else {
2561 setEventMessages('Failed to write file '.$filetpl, null, 'errors');
2562 header("Location: ".$_SERVER["PHP_SELF"].'?website='.$websitekey.'&pageid='.$pageid);
2563 exit;
2564 }
2565 } else {
2566 $db->rollback();
2567 }
2568 } else {
2569 header("Location: ".$_SERVER["PHP_SELF"].'?website='.$websitekey.'&pageid='.$pageid);
2570 exit;
2571 }
2572 } else {
2573 if (!$error) {
2574 if (empty($websitekey) || $websitekey == '-1') {
2575 setEventMessages($langs->trans("NoWebSiteCreateOneFirst"), null, 'warnings');
2576 } else {
2577 setEventMessages($langs->trans("NoPageYet"), null, 'warnings');
2578 setEventMessages($langs->trans("YouCanCreatePageOrImportTemplate"), null, 'warnings');
2579 }
2580 }
2581 }
2582}
2583
2584if ($action == 'deletelang' && $usercanedit) {
2585 $sql = "UPDATE ".MAIN_DB_PREFIX."website_page SET fk_page = NULL";
2586 $sql .= " WHERE rowid = ".GETPOSTINT('deletelangforid');
2587 //$sql .= " AND fk_page = ".((int) $objectpage->id);
2588
2589 $resql = $db->query($sql);
2590 if (!$resql) {
2591 setEventMessages($db->lasterror(), null, 'errors');
2592 } else {
2593 $objectpage->fk_page = null;
2594 }
2595
2596 $action = 'editmeta';
2597}
2598
2599
2600// Export site
2601if ($action == 'exportsite' && $user->hasRight('website', 'export')) {
2602 $fileofzip = $object->exportWebSite();
2603
2604 if ($fileofzip) {
2605 $file_name = basename($fileofzip);
2606 header("Content-Type: application/zip");
2607 header("Content-Disposition: attachment; filename=".$file_name);
2608 header("Content-Length: ".filesize($fileofzip));
2609
2610 readfile($fileofzip);
2611 exit;
2612 } else {
2613 setEventMessages($object->error, $object->errors, 'errors');
2614 $action = 'preview';
2615 }
2616}
2617
2618// Overwrite site
2619if ($action == 'overwritesite' && $user->hasRight('website', 'export')) {
2620 if (getDolGlobalString('WEBSITE_ALLOW_OVERWRITE_GIT_SOURCE')) {
2621 // Generate a zip of the website
2622 $fileofzip = $object->exportWebSite();
2623 $pathToExport = GETPOST('export_path');
2624 if ($fileofzip) {
2625 // Uncompress the exported web site into a destination directory
2626 $result = $object->overwriteTemplate($fileofzip, $pathToExport);
2627 if ($result < 0) {
2628 $action = 'preview';
2629 }
2630 } else {
2631 setEventMessages($object->error, $object->errors, 'errors');
2632 $action = 'preview';
2633 }
2634 }
2635}
2636// Regenerate site
2637if ($action == 'regeneratesite' && $usercanedit) {
2638 // Check symlink documents/website/mywebsite/medias to point to documents/medias and restore it if ko.
2639 // Recreate also dir of website if not found.
2640 $pathtomedias = DOL_DATA_ROOT.'/medias';
2641 $pathtomediasinwebsite = $pathofwebsite.'/medias';
2642 if (!is_link(dol_osencode($pathtomediasinwebsite))) {
2643 dol_syslog("Create symlink for ".$pathtomedias." into name ".$pathtomediasinwebsite);
2644 dol_mkdir(dirname($pathtomediasinwebsite)); // To be sure that the directory for website exists
2645 $result = symlink($pathtomedias, $pathtomediasinwebsite);
2646 if (!$result) {
2647 $langs->load("errors");
2648 setEventMessages($langs->trans("ErrorFailedToCreateSymLinkToMedias", $pathtomediasinwebsite, $pathtomedias), null, 'errors');
2649 $action = 'preview';
2650 }
2651 }
2652
2653 $result = $object->rebuildWebSiteFiles();
2654 if ($result > 0) {
2655 setEventMessages($langs->trans("PagesRegenerated", $result), null, 'mesgs');
2656 $action = 'preview';
2657 } else {
2658 setEventMessages($object->error, $object->errors, 'errors');
2659 $action = 'preview';
2660 }
2661}
2662
2663// Import site
2664if ($action == 'importsiteconfirm' && $usercanedit) {
2665 $dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT);
2666 $allowimportsite = true;
2667 if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) {
2668 $allowimportsite = false;
2669 }
2670
2671 if ($allowimportsite) {
2672 if (empty($_FILES) && !GETPOSTISSET('templateuserfile')) {
2673 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("File")), null, 'errors');
2674 $action = 'importsite';
2675 } else {
2676 if (!empty($_FILES) || GETPOSTISSET('templateuserfile')) {
2677 // Check symlink documents/website/mywebsite/medias to point to documents/medias and restore it if ko.
2678 // Recreate also dir of website if not found.
2679 $pathtomedias = DOL_DATA_ROOT.'/medias';
2680 $pathtomediasinwebsite = $pathofwebsite.'/medias';
2681 if (!is_link(dol_osencode($pathtomediasinwebsite))) {
2682 dol_syslog("Create symlink for ".$pathtomedias." into name ".$pathtomediasinwebsite);
2683 dol_mkdir(dirname($pathtomediasinwebsite)); // To be sure dir for website exists
2684 $result = symlink($pathtomedias, $pathtomediasinwebsite);
2685 if (!$result) {
2686 $langs->load("errors");
2687 setEventMessages($langs->trans("ErrorFailedToCreateSymLinkToMedias", $pathtomediasinwebsite, $pathtomedias), null, 'errors');
2688 $action = 'importsite';
2689 }
2690 }
2691
2692 $fileofzip = '';
2693 if (GETPOSTISSET('templateuserfile')) {
2694 // Case we selected one template
2695 $fileofzip = DOL_DATA_ROOT.'/doctemplates/websites/'.GETPOST('templateuserfile', 'alpha'); // $fileofzip will be sanitized later into the importWebSite()
2696 } elseif (!empty($_FILES) && is_array($_FILES['userfile'])) {
2697 // Case we upload a new template
2698 if (is_array($_FILES['userfile']['tmp_name'])) {
2699 $userfiles = $_FILES['userfile']['tmp_name'];
2700 } else {
2701 $userfiles = array($_FILES['userfile']['tmp_name']);
2702 }
2703
2704 // Check if $_FILES is ok
2705 foreach ($userfiles as $key => $userfile) {
2706 if (empty($_FILES['userfile']['tmp_name'][$key])) {
2707 $error++;
2708 if ($_FILES['userfile']['error'][$key] == 1 || $_FILES['userfile']['error'][$key] == 2) {
2709 setEventMessages($langs->trans('ErrorFileSizeTooLarge'), null, 'errors');
2710 $action = 'importsite';
2711 } else {
2712 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("File")), null, 'errors');
2713 $action = 'importsite';
2714 }
2715 }
2716 }
2717
2718 if (!$error) {
2719 //$upload_dir = $conf->website->dir_temp;
2720 $upload_dir = DOL_DATA_ROOT.'/doctemplates/websites/';
2721 $result = dol_add_file_process($upload_dir, 1, -1, 'userfile', '');
2722 }
2723
2724 // Get name of file (take last one if several name provided)
2725 /*
2726 $fileofzip = $upload_dir.'/unknown';
2727 foreach ($_FILES as $key => $ifile) {
2728 foreach ($ifile['name'] as $key2 => $ifile2) {
2729 $fileofzip = $upload_dir.'/'.$ifile2;
2730 }
2731 }
2732 */
2733
2734 $action = 'importsite';
2735 }
2736
2737 if (!$error && GETPOSTISSET('templateuserfile')) {
2738 $templatewithoutzip = preg_replace('/\.zip$/i', '', GETPOST('templateuserfile'));
2739 $object->setTemplateName($templatewithoutzip);
2740
2741 $result = $object->importWebSite($fileofzip);
2742
2743 if ($result < 0) {
2744 setEventMessages($object->error, $object->errors, 'errors');
2745 $action = 'importsite';
2746 } else {
2747 // Force mode dynamic on
2748 dolibarr_set_const($db, 'WEBSITE_SUBCONTAINERSINLINE', 1, 'chaine', 0, '', $conf->entity);
2749
2750 header("Location: ".$_SERVER["PHP_SELF"].'?website='.$object->ref);
2751 exit();
2752 }
2753 }
2754 }
2755 }
2756 } else {
2757 if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) {
2758 // Show clean corporate message
2759 $message = $langs->trans('InstallModuleFromWebHasBeenDisabledContactUs');
2760 } else {
2761 // Show technical generic message
2762 $message = $langs->trans("InstallModuleFromWebHasBeenDisabledByFile", $dolibarrdataroot.'/installmodules.lock');
2763 }
2764 setEventMessages($message, null, 'errors');
2765 }
2766}
2767
2768$domainname = '0.0.0.0:8080';
2769$tempdir = $conf->website->dir_output.'/'.$websitekey.'/';
2770
2771// Generate web site sitemaps
2772if ($action == 'generatesitemaps' && $usercanedit) {
2773 // Define $domainname
2774 if ($website->virtualhost) {
2775 $domainname = $website->virtualhost;
2776 }
2777 if (! preg_match('/^http/i', $domainname)) {
2778 $domainname = 'https://'.$domainname;
2779 }
2780
2781 $domtree = new DOMDocument('1.0', 'UTF-8');
2782
2783 $root = $domtree->createElementNS('http://www.sitemaps.org/schemas/sitemap/0.9', 'urlset');
2784 $root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xhtml', 'http://www.w3.org/1999/xhtml');
2785
2786 $domtree->formatOutput = true;
2787
2788 $addrsswrapper = 0;
2789 $xmlname = 'sitemap.xml';
2790
2791 $sql = "SELECT wp.rowid, wp.type_container , wp.pageurl, wp.lang, wp.fk_page, wp.tms as tms,";
2792 $sql .= " w.virtualhost, w.fk_default_home";
2793 $sql .= " FROM ".MAIN_DB_PREFIX."website_page as wp, ".MAIN_DB_PREFIX."website as w";
2794 $sql .= " WHERE wp.type_container IN ('page', 'blogpost')";
2795 $sql .= " AND wp.fk_website = w.rowid";
2796 $sql .= " AND wp.status = ".WebsitePage::STATUS_VALIDATED;
2797 $sql .= " AND wp.pageurl NOT IN ('404', '500', '501', '503')";
2798 $sql .= " AND w.ref = '".dol_escape_json($websitekey)."'";
2799 $sql .= " ORDER BY wp.tms DESC, wp.rowid DESC";
2800 $resql = $db->query($sql);
2801 if ($resql) {
2802 $num_rows = $db->num_rows($resql);
2803 if ($num_rows > 0) {
2804 $i = 0;
2805 while ($i < $num_rows) {
2806 $objp = $db->fetch_object($resql);
2807 $url = $domtree->createElement('url');
2808
2809 $shortlangcode = '';
2810 if ($objp->lang) {
2811 $shortlangcode = substr($objp->lang, 0, 2); // en_US or en-US -> en
2812 }
2813 if (empty($shortlangcode)) {
2814 $shortlangcode = substr($object->lang, 0, 2); // Use short lang code of website
2815 }
2816
2817 // Is it a blog post for the RSS wrapper ?
2818 if ($objp->type_container == 'blogpost') {
2819 $addrsswrapper = 1;
2820 }
2821
2822 // Forge $pageurl, adding language prefix if it is an alternative language
2823 $pageurl = $objp->pageurl.'.php';
2824 if ($objp->fk_default_home == $objp->rowid) {
2825 $pageurl = '';
2826 } else {
2827 if ($shortlangcode != substr($object->lang, 0, 2)) {
2828 $pageurl = $shortlangcode.'/'.$pageurl;
2829 }
2830 }
2831
2832 //$pathofpage = $dolibarr_main_url_root.'/'.$pageurl.'.php';
2833
2834 // URL of sitemaps must end with trailing slash if page is ''
2835 $loc = $domtree->createElement('loc', $domainname.'/'.$pageurl);
2836 $lastmod = $domtree->createElement('lastmod', dol_print_date($db->jdate($objp->tms), 'dayrfc', 'gmt'));
2837 $priority = $domtree->createElement('priority', '1');
2838
2839 $url->appendChild($loc);
2840 $url->appendChild($lastmod);
2841 // Add suggested frequency for refresh
2842 if (getDolGlobalString('WEBSITE_SITEMAPS_ADD_WEEKLY_FREQ')) {
2843 $changefreq = $domtree->createElement('changefreq', 'weekly'); // TODO Manage other values
2844 $url->appendChild($changefreq);
2845 }
2846 // Add higher priority for home page
2847 if ($objp->fk_default_home == $objp->rowid) {
2848 $url->appendChild($priority);
2849 }
2850
2851 // Now add alternate language entries
2852 if ($object->isMultiLang()) {
2853 $alternatefound = 0;
2854
2855 // Add page "translation of"
2856 $translationof = $objp->fk_page;
2857 if ($translationof) {
2858 $tmppage = new WebsitePage($db);
2859 $tmppage->fetch($translationof);
2860 if ($tmppage->id > 0) {
2861 $tmpshortlangcode = '';
2862 if ($tmppage->lang) {
2863 $tmpshortlangcode = preg_replace('/[_-].*$/', '', $tmppage->lang); // en_US or en-US -> en
2864 }
2865 if (empty($tmpshortlangcode)) {
2866 $tmpshortlangcode = preg_replace('/[_-].*$/', '', $object->lang); // en_US or en-US -> en
2867 }
2868 if ($tmpshortlangcode != $shortlangcode) {
2869 $xhtmllink = $domtree->createElement('xhtml:link', '');
2870 $xhtmllink->setAttribute("rel", "alternate");
2871 $xhtmllink->setAttribute("hreflang", $tmpshortlangcode);
2872 $xhtmllink->setAttribute("href", $domainname.($objp->fk_default_home == $tmppage->id ? '/' : (($tmpshortlangcode != substr($object->lang, 0, 2)) ? '/'.$tmpshortlangcode : '').'/'.$tmppage->pageurl.'.php'));
2873 $url->appendChild($xhtmllink);
2874
2875 $alternatefound++;
2876 }
2877 }
2878 }
2879
2880 // Add "has translation pages"
2881 $sql = 'SELECT rowid as id, lang, pageurl from '.MAIN_DB_PREFIX.'website_page';
2882 $sql .= " WHERE status = ".((int) WebsitePage::STATUS_VALIDATED).' AND fk_page IN ('.$db->sanitize($objp->rowid.($translationof ? ", ".$translationof : "")).")";
2883 $resqlhastrans = $db->query($sql);
2884 if ($resqlhastrans) {
2885 $num_rows_hastrans = $db->num_rows($resqlhastrans);
2886 if ($num_rows_hastrans > 0) {
2887 while ($objhastrans = $db->fetch_object($resqlhastrans)) {
2888 $tmpshortlangcode = '';
2889 if ($objhastrans->lang) {
2890 $tmpshortlangcode = preg_replace('/[_-].*$/', '', $objhastrans->lang); // en_US or en-US -> en
2891 }
2892 if ($tmpshortlangcode != $shortlangcode) {
2893 $xhtmllink = $domtree->createElement('xhtml:link', '');
2894 $xhtmllink->setAttribute("rel", "alternate");
2895 $xhtmllink->setAttribute("hreflang", $tmpshortlangcode);
2896 $xhtmllink->setAttribute("href", $domainname.($objp->fk_default_home == $objhastrans->id ? '/' : (($tmpshortlangcode != substr($object->lang, 0, 2) ? '/'.$tmpshortlangcode : '')).'/'.$objhastrans->pageurl.'.php'));
2897 $url->appendChild($xhtmllink);
2898
2899 $alternatefound++;
2900 }
2901 }
2902 }
2903 } else {
2905 }
2906
2907 if ($alternatefound) {
2908 // Add myself
2909 $xhtmllink = $domtree->createElement('xhtml:link', '');
2910 $xhtmllink->setAttribute("rel", "alternate");
2911 $xhtmllink->setAttribute("hreflang", $shortlangcode);
2912 $xhtmllink->setAttribute("href", $domainname.'/'.$pageurl);
2913 $url->appendChild($xhtmllink);
2914 }
2915 }
2916
2917 // Now add sitempas extension for news
2918 // TODO When adding and when not ?
2919 /*<news:news>
2920 <news:publication>
2921 <news:name>The Example Times</news:name>
2922 <news:language>en</news:language>
2923 </news:publication>
2924 <news:publication_date>2008-12-23</news:publication_date>
2925 <news:title>Companies A, B in Merger Talks</news:title>
2926 </news:news>
2927 */
2928
2929 $root->appendChild($url);
2930 $i++;
2931 }
2932
2933 // Adding a RSS feed into a sitemap should not be required. The RSS contains pages that are already included into
2934 // the sitemap and RSS feeds are not shown into index.
2935 if ($addrsswrapper && getDolGlobalInt('WEBSITE_ADD_RSS_FEED_INTO_SITEMAP')) {
2936 $url = $domtree->createElement('url');
2937
2938 $pageurl = 'wrapper.php?rss=1';
2939
2940 // URL of sitemaps must end with trailing slash if page is ''
2941 $loc = $domtree->createElement('loc', $domainname.'/'.$pageurl);
2942 $lastmod = $domtree->createElement('lastmod', dol_print_date(dol_now(), 'dayrfc', 'gmt'));
2943
2944 $url->appendChild($loc);
2945 $url->appendChild($lastmod);
2946 // Add suggested frequency for refresh
2947 if (getDolGlobalString('WEBSITE_SITEMAPS_ADD_WEEKLY_FREQ')) {
2948 $changefreq = $domtree->createElement('changefreq', 'weekly'); // TODO Manage other values
2949 $url->appendChild($changefreq);
2950 }
2951
2952 $root->appendChild($url);
2953 }
2954
2955 $domtree->appendChild($root);
2956
2957 if ($domtree->save($tempdir.$xmlname)) {
2958 dolChmod($tempdir.$xmlname);
2959 setEventMessages($langs->trans("SitemapGenerated", $xmlname), null, 'mesgs');
2960 } else {
2961 setEventMessages($object->error, $object->errors, 'errors');
2962 }
2963 }
2964 } else {
2966 }
2967
2968 // Add the entry Sitemap: into the robot.txt file.
2969 $robotcontent = @file_get_contents($filerobot);
2970 $result = preg_replace('/<?php \/\/ BEGIN PHP[^?]END PHP ?>\n/ims', '', $robotcontent);
2971 if ($result) {
2972 $robotcontent = $result;
2973 }
2974 $robotsitemap = "Sitemap: ".$domainname."/".$xmlname;
2975 $result = strpos($robotcontent, 'Sitemap: ');
2976 if ($result) {
2977 $result = preg_replace('/Sitemap:.*/', $robotsitemap, $robotcontent);
2978 $robotcontent = $result ? $result : $robotcontent;
2979 } else {
2980 $robotcontent .= $robotsitemap."\n";
2981 }
2982 $result = dolSaveRobotFile($filerobot, $robotcontent);
2983 if (!$result) {
2984 $error++;
2985 setEventMessages('Failed to write file '.$filerobot, null, 'errors');
2986 }
2987 $action = 'preview';
2988}
2989
2990if ($action == 'removecspsource' && $usercanedit) {
2991 $db->begin();
2992 $sourcetype = "";
2993 $sourcecsp = explode("_", GETPOST("sourcecsp"));
2994 $directive = $sourcecsp[0];
2995 $sourcekey = isset($sourcecsp[1]) ? $sourcecsp[1] : null;
2996 $sourcedata = isset($sourcecsp[2]) ? $sourcecsp[2] : null;
2997 $forceCSPArr = websiteGetContentPolicyToArray($forceCSP);
2998 $directivesarray = websiteGetContentPolicyDirectives();
2999 $sourcesarray = websiteGetContentPolicySources();
3000 if (empty($directive)) {
3001 $error++;
3002 }
3003
3004 if (!empty($directivesarray[$directive])) {
3005 $directivetype = (string) $directivesarray[$directive]["data-directivetype"];
3006 if (isset($sourcekey)) {
3007 $sourcetype = $sourcesarray[$directivetype][$sourcekey]["data-sourcetype"];
3008 }
3009 }
3010
3011 $securityspstring = "";
3012 if (!$error && !empty($forceCSPArr)) {
3013 if (isset($sourcekey) && !empty($forceCSPArr[$directive][$sourcekey])) {
3014 unset($forceCSPArr[$directive][$sourcekey]);
3015 }
3016 if (count($forceCSPArr[$directive]) == 0) {
3017 unset($forceCSPArr[$directive]);
3018 }
3019 foreach ($forceCSPArr as $directive => $sourcekeys) {
3020 if ($securityspstring != "") {
3021 $securityspstring .= "; ";
3022 }
3023 $sourcestring = "";
3024 foreach ($sourcekeys as $key => $source) {
3025 $directivetype = $directivesarray[$directive]["data-directivetype"];
3026 $sourcetype = $sourcesarray[$directivetype][$source]["data-sourcetype"];
3027 if ($sourcetype == "quoted") {
3028 $sourcestring .= " '".$source."'";
3029 } else {
3030 $sourcestring .= " ".$source;
3031 }
3032 }
3033 $securityspstring .= $directive . $sourcestring;
3034 }
3035 $res = dolibarr_set_const($db, 'WEBSITE_'.$object->id.'_SECURITY_FORCECSP', $securityspstring, 'chaine', 0, '', $conf->entity);
3036 if ($res <= 0) {
3037 $error++;
3038 }
3039 }
3040
3041 if (!$error) {
3042 $db->commit();
3043 setEventMessages($langs->trans("SecurityPolicySucesfullyRemoved"), null, 'mesgs');
3044 } else {
3045 $db->rollback();
3046 setEventMessages($langs->trans("ErrorRemovingSecurityPolicy"), null, 'errors');
3047 }
3048
3049 header("Location: ".$_SERVER["PHP_SELF"].'?websiteid='.$websiteid."&action=editsecurity");
3050 exit();
3051}
3052
3053
3054/*
3055 * View
3056 */
3057
3058$form = new Form($db);
3059$formadmin = new FormAdmin($db);
3060$formwebsite = new FormWebsite($db);
3061$formother = new FormOther($db);
3062$formconfirm = "";
3063
3064// Confirm generation of website sitemaps
3065if ($action == 'confirmgeneratesitemaps') {
3066 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?website='.urlencode($website->ref), $langs->trans('ConfirmSitemapsCreation'), $langs->trans('ConfirmGenerateSitemaps', $object->ref), 'generatesitemaps', '', "yes", 1);
3067 $action = 'preview';
3068}
3069$helpurl = 'EN:Module_Website|FR:Module_Website_FR|ES:M&oacute;dulo_Website';
3070
3071$arrayofjs = array(
3072 '/includes/ace/src/ace.js',
3073 '/includes/ace/src/ext-statusbar.js',
3074 '/includes/ace/src/ext-language_tools.js',
3075 //'/includes/ace/src/ext-chromevox.js'
3076);
3077$arrayofcss = array();
3078
3079if (!getDolGlobalString('MAIN_ECM_DISABLE_JS')) {
3080 $arrayofjs[] = "public/includes/jquery/plugins/jqueryFileTree/jqueryFileTree.js";
3081}
3082
3083llxHeader('', $langs->trans("Website").(empty($website->ref) ? '' : ' - '.$website->ref), $helpurl, '', 0, 0, $arrayofjs, $arrayofcss, '', 'mod-website page-index', '<!-- Begin div class="fiche" -->'."\n".'<div class="fichebutwithotherclass">');
3084
3085print "\n";
3086print '<!-- Open form common to all pages generated by website/index.php -->'."\n";
3087print '<form action="'.$_SERVER["PHP_SELF"].($action == 'file_manager' ? '?uploadform=1' : '').'" method="POST" enctype="multipart/form-data" class="websiteformtoolbar">'."\n";
3088print '<input type="hidden" name="token" value="'.newToken().'">';
3089print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
3090print '<input type="hidden" name="dol_openinpopup" value="'.$dol_openinpopup.'">';
3091
3092if ($action == 'createsite') {
3093 print '<input type="hidden" name="action" value="addsite">';
3094}
3095if ($action == 'createcontainer') {
3096 print '<input type="hidden" name="action" value="addcontainer">';
3097}
3098if ($action == 'editcss') {
3099 print '<input type="hidden" name="action" value="updatecss">';
3100}
3101if ($action == 'editmenu') {
3102 print '<input type="hidden" name="action" value="updatemenu">';
3103}
3104if ($action == 'setashome') {
3105 print '<input type="hidden" name="action" value="updateashome">';
3106}
3107if ($action == 'editmeta') {
3108 print '<input type="hidden" name="action" value="updatemeta">';
3109}
3110if ($action == 'editsource') {
3111 print '<input type="hidden" name="action" value="updatesource">';
3112}
3113if ($action == 'editcontent') {
3114 print '<input type="hidden" name="action" value="updatecontent">';
3115}
3116if ($action == 'edit') {
3117 print '<input type="hidden" name="action" value="update">';
3118}
3119if ($action == 'importsite') {
3120 print '<input type="hidden" name="action" value="importsiteconfirm">';
3121}
3122if ($action == 'file_manager') {
3123 print '<input type="hidden" name="action" value="file_manager">';
3124}
3125if ($mode) {
3126 print '<input type="hidden" name="mode" value="'.$mode.'">';
3127}
3128if ($action == 'editsecurity') {
3129 print '<input type="hidden" name="action" value="updatesecurity">';
3130}
3131
3132print '<div>'."\n";
3133
3134// Add a margin under toolbar ?
3135$style = '';
3136if ($action != 'preview' && $action != 'editcontent' && $action != 'editsource' && !GETPOST('createpagefromclone', 'alphanohtml')) {
3137 $style = ' margin-bottom: 5px;';
3138}
3139
3140
3141$disabled = '';
3142if (!GETPOST('hide_websitemenu')) {
3143 if (!$user->hasRight('website', 'write')) {
3144 $disabled = ' disabled="disabled"';
3145 }
3146 $disabledexport = '';
3147 if (!$user->hasRight('website', 'export')) {
3148 $disabledexport = ' disabled="disabled"';
3149 }
3150
3151 if ($websitekey) {
3152 $virtualurl = '';
3153 $dataroot = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$websitekey;
3154 if (!empty($object->virtualhost)) {
3155 $virtualurl = $object->virtualhost;
3156 }
3157 }
3158
3159 $array = array();
3160 if ($object->id > 0) {
3161 $array = $objectpage->fetchAll($object->id, 'ASC,ASC', 'type_container,pageurl');
3162 $object->lines = $array;
3163 }
3164 if (!is_array($array) && $array < 0) {
3165 dol_print_error(null, $objectpage->error, $objectpage->errors);
3166 }
3167 $atleastonepage = (is_array($array) && count($array) > 0);
3168
3169 $websitepage = new WebsitePage($db);
3170 if ($pageid > 0) {
3171 $websitepage->fetch($pageid);
3172 }
3173
3174
3175 $disabled = '';
3176 $morecss = '';
3177 if (!$user->hasRight('website', 'write')) {
3178 $disabled = ' disabled="disabled"';
3179 $morecss = 'opacitymedium cursordefault';
3180 }
3181
3182 //var_dump($objectpage);exit;
3183 print '<div class="centpercent websitebar'.(GETPOST('dol_openinpopup', 'aZ09') ? ' hiddenforpopup' : '').'">'."\n";
3184
3185 //
3186 // Toolbar for websites
3187 //
3188
3189 print '<!-- Toolbar for website -->';
3190 if ($action != 'file_manager') {
3191 print '<div class="websiteselection hideonsmartphoneimp minwidth75 tdoverflowmax100 inline-block">';
3192 print $langs->trans("Website").': ';
3193 print '</div>';
3194
3195 // Button Add new website
3196 $urltocreatenewwebsite = $_SERVER["PHP_SELF"].'?action=createsite';
3197 if ($user->hasRight('website', 'write')) {
3198 print '<span class="websiteselection paddingrightonly">';
3199 print '<a href="'.$urltocreatenewwebsite.'" class=""'.$disabled.' title="'.dol_escape_htmltag($langs->trans("AddWebsite")).'"><span class="fa fa-plus-circle valignmiddle btnTitle-icon"><span></a>';
3200 print '</span>';
3201 }
3202
3203 // List of website
3204 print '<span class="websiteselection nopaddingrightimp">';
3205
3206 $out = '';
3207 $out .= '<select name="website" class="minwidth100 width200 maxwidth150onsmartphone" id="website">';
3208 if (empty($listofwebsites)) {
3209 $out .= '<option value="-1">&nbsp;</option>';
3210 }
3211
3212 // Loop on each sites
3213 $i = 0;
3214 foreach ($listofwebsites as $key => $valwebsite) {
3215 if (empty($websitekey)) {
3216 if ($action != 'createsite') {
3217 $websitekey = $valwebsite->ref;
3218 }
3219 }
3220
3221 $out .= '<option value="'.$valwebsite->ref.'"';
3222 if ($websitekey == $valwebsite->ref) {
3223 $out .= ' selected'; // To preselect a value
3224 }
3225 //$outoption = $valwebsite->getLibStatut(3).' '.$valwebsite->ref.' ';
3226 $outoption = (($valwebsite->status == $valwebsite::STATUS_DRAFT) ? '<span class="opacitymedium">' : '').$valwebsite->ref.(($valwebsite->status == $valwebsite::STATUS_DRAFT) ? '</span>' : '');
3227 $out .= ' data-html="'.dol_escape_htmltag($outoption).'"';
3228 $out .= '>';
3229 $out .= $valwebsite->ref;
3230 $out .= '</option>';
3231 $i++;
3232 }
3233 $out .= '</select>';
3234 $out .= ajax_combobox('website');
3235
3236 if (!empty($conf->use_javascript_ajax)) {
3237 $out .= '<script type="text/javascript">';
3238 $out .= 'jQuery(document).ready(function () {';
3239 $out .= ' jQuery("#website").change(function () {';
3240 $out .= ' console.log("We select "+jQuery("#website option:selected").val());';
3241 $out .= ' if (jQuery("#website option:selected").val() == \'-2\') {';
3242 $out .= ' window.location.href = "'.dol_escape_js($urltocreatenewwebsite).'";';
3243 $out .= ' } else {';
3244 $out .= ' window.location.href = "'.$_SERVER["PHP_SELF"].'?website="+jQuery("#website option:selected").val();';
3245 $out .= ' }';
3246 $out .= ' });';
3247 $out .= '});';
3248 $out .= '</script>';
3249 }
3250 print $out;
3251
3252 print '</span>';
3253
3254 // Switch offline/onine
3255 if (!empty($conf->use_javascript_ajax)) {
3256 print '<span class="websiteselection">';
3257 // Do not use ajax, we need a refresh of full page when we change status of a website
3258 //print '<div class="inline-block marginrightonly">';
3259 //print ajax_object_onoff($object, 'status', 'status', 'Online', 'Offline', array(), 'valignmiddle inline-block', 'statuswebsite');
3260 //print '</div>';
3261 if ($website->status == $website::STATUS_DRAFT) {
3262 $text_off = 'Offline';
3263 print '<a href="'.$_SERVER["PHP_SELF"].'?action=setwebsiteonline&token='.newToken().'&website='.urlencode($website->ref).'&websitepage='.((int) $websitepage->id).'"'.$disabled.'>'.img_picto($langs->trans($text_off), 'switch_off', '', 0, 0, 0, '', $morecss).'</a>';
3264 } else {
3265 $text_off = 'Online';
3266 print '<a href="'.$_SERVER["PHP_SELF"].'?action=setwebsiteoffline&token='.newToken().'&website='.urlencode($website->ref).'&websitepage='.((int) $websitepage->id).'"'.$disabled.'>'.img_picto($langs->trans($text_off), 'switch_on', '', 0, 0, 0, '', $morecss).'</a>';
3267 }
3268 print '</span>';
3269 }
3270
3271 // Refresh / Reload web site (for non javascript browsers)
3272 if (empty($conf->use_javascript_ajax)) {
3273 print '<span class="websiteselection">';
3274 print '<input type="image" class="valignmiddle" src="'.img_picto('', 'refresh', '', 0, 1).'" name="refreshsite" value="'.$langs->trans("Load").'"'.$disabled.'>';
3275 print '</span>';
3276 }
3277
3278
3279 print '<span class="websiteselection">';
3280
3281 if ($websitekey && $websitekey != '-1' && ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone' || $action == 'deletesite')) {
3282 // Edit website properties
3283 print '<a href="'.$_SERVER["PHP_SELF"].'?website='.urlencode($object->ref).'&pageid='.((int) $pageid).'&action=editcss&token='.newToken().'" class="button bordertransp valignmiddle" title="'.dol_escape_htmltag($langs->trans("EditCss")).'"'.$disabled.'>';
3284 print img_picto('', 'setup');
3285 print '<span class="hideonsmartphone paddingleft">'.dol_escape_htmltag($langs->trans("EditCss")).'</span>';
3286 print '</a>';
3287
3288 // Import web site
3289 $importlabel = $langs->trans("ImportSite");
3290 $exportlabel = $langs->trans("ExportSite");
3291 if (!empty($conf->dol_optimize_smallscreen)) {
3292 $importlabel = $langs->trans("Import");
3293 $exportlabel = $langs->trans("Export");
3294 }
3295
3296 if ($atleastonepage) {
3297 print '<input type="submit" class="button bordertransp" disabled="disabled" value="'.dol_escape_htmltag($importlabel).'" name="importsite">';
3298 } else {
3299 print '<input type="submit" class="button bordertransp"'.$disabled.' value="'.dol_escape_htmltag($importlabel).'" name="importsite">';
3300 }
3301
3302 // // Export web site
3303 $extraCssClass = getDolGlobalString('WEBSITE_ALLOW_OVERWRITE_GIT_SOURCE') ? 'hideobject' : '';
3304 print '<input type="submit" class="button bordertransp ' . $extraCssClass . '" ' . $disabledexport . ' value="' . dol_escape_htmltag($exportlabel) . '" name="exportsite">';
3305
3306 if (getDolGlobalString('WEBSITE_ALLOW_OVERWRITE_GIT_SOURCE')) {
3307 // Overwrite template in sources
3308 $overwriteGitUrl = $_SERVER["PHP_SELF"] . '?action=overwritesite&website=' . urlencode($website->ref);
3309 print dolButtonToOpenExportDialog('exportpopup', $langs->trans('ExportOptions'), $langs->trans('ExportSite'), 'exportsite', $overwriteGitUrl, $website);
3310 //print '<a href="'.$_SERVER["PHP_SELF"].'?action=overwritesite&website='.urlencode($website->ref).'" class="button bordertransp hideobject" title="'.dol_escape_htmltag($langs->trans("ExportIntoGIT").". Directory ".getDolGlobalString('WEBSITE_ALLOW_OVERWRITE_GIT_SOURCE')).'">'.dol_escape_htmltag($langs->trans("ExportIntoGIT")).'</a>';
3311 }
3312
3313 // Clone web site
3314 print '<input type="submit" class="button bordertransp"'.$disabled.' value="'.dol_escape_htmltag($langs->trans("CloneSite")).'" name="createfromclone">';
3315
3316 // Delete website
3317 if (!$permissiontodelete) {
3318 $disabled = ' disabled="disabled"';
3319 $title = $langs->trans("NotEnoughPermissions");
3320 $url = '#';
3321 } else {
3322 if ($website->status == $website::STATUS_VALIDATED) {
3323 $disabled = ' disabled="disabled"';
3324 $title = $langs->trans("WebsiteMustBeDisabled", $langs->transnoentitiesnoconv($website->LibStatut(0, 0)));
3325 $url = '#';
3326 } else {
3327 $disabled = '';
3328 $title = $langs->trans("Delete");
3329 $url = $_SERVER["PHP_SELF"].'?action=deletesite&token='.newToken().'&website='.urlencode($website->ref);
3330 }
3331 }
3332 print '<a href="'.$url.'" class="button buttonDelete bordertransp'.($disabled ? ' disabled' : '').'"'.$disabled.' title="'.dol_escape_htmltag($title).'">'.img_picto('', 'delete', 'class=""').'<span class="hideonsmartphone paddingleft">'.$langs->trans("Delete").'</span></a>';
3333
3334 // Regenerate all pages
3335 print '<a href="'.$_SERVER["PHP_SELF"].'?action=regeneratesite&token='.newToken().'&website='.urlencode($website->ref).'" class="button bordertransp"'.$disabled.' title="'.dol_escape_htmltag($langs->trans("RegenerateWebsiteContent")).'"><span class="far fa-hdd"></span></a>';
3336
3337 // Generate site map
3338 print '<a href="'.$_SERVER["PHP_SELF"].'?action=confirmgeneratesitemaps&token='.newToken().'&website='.urlencode($website->ref).'" class="button bordertransp"'.$disabled.' title="'.dol_escape_htmltag($langs->trans("GenerateSitemaps")).'"><span class="fa fa-sitemap"></span></a>';
3339
3340 // Find / replace tool
3341 print '<a href="'.$_SERVER["PHP_SELF"].'?action=replacesite&token='.newToken().'&website='.urlencode($website->ref).'" class="button bordertransp"'.$disabled.' title="'.dol_escape_htmltag($langs->trans("ReplaceWebsiteContent")).'"><span class="fa fa-search"></span></a>';
3342 }
3343
3344 print '</span>';
3345
3346 if ($websitekey && $websitekey != '-1' && ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone' || $action == 'deletesite')) {
3347 print '<span class="websiteselection">';
3348
3349 print dolButtonToOpenUrlInDialogPopup('file_manager', $langs->transnoentitiesnoconv("MediaFiles"), '<span class="fa fa-image"></span>', '/website/index.php?action=file_manager&website='.urlencode($website->ref).'&section_dir='.urlencode('image/'.$website->ref.'/'), $disabled);
3350
3351 if (isModEnabled('category')) {
3352 //print '<a href="'.DOL_URL_ROOT.'/categories/categorie_list.php?leftmenu=website&dol_hide_leftmenu=1&nosearch=1&type=website_page&website='.$website->ref.'" class="button bordertransp"'.$disabled.' title="'.dol_escape_htmltag($langs->trans("Categories")).'"><span class="fa fa-tags"></span></a>';
3353 print dolButtonToOpenUrlInDialogPopup('categories', $langs->transnoentitiesnoconv("Categories"), '<span class="fa fa-tags"></span>', '/categories/categorie_list.php?leftmenu=website&nosearch=1&type='.urlencode(Categorie::TYPE_WEBSITE_PAGE).'&website='.urlencode($website->ref), $disabled);
3354 }
3355
3356 print '</span>';
3357 }
3358 } else {
3359 print '<input type="hidden" name="website" id="website" value="'.$websitekey.'">';
3360 }
3361
3362
3363 print '<span class="websitetools">';
3364
3365 if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone' || $action == 'deletesite') {
3366 $urlext = $virtualurl;
3367 $urlint = $urlwithroot.'/public/website/index.php?website='.$websitekey;
3368
3369 print '<span class="websiteinputurl valignmiddle" id="websiteinputurl">';
3370 $linktotestonwebserver = '<a href="'.($virtualurl ? $virtualurl : '#').'" class="valignmiddle">';
3371 $linktotestonwebserver .= '<span class="hideonsmartphone paddingrightonly">'.$langs->trans("TestDeployOnWeb", $virtualurl).'</span>'.img_picto('', 'globe');
3372 $linktotestonwebserver .= '</a>';
3373
3374 $htmltext = '';
3375 if (empty($object->fk_default_home)) {
3376 $htmltext .= '<br><span class="error">'.$langs->trans("YouMustDefineTheHomePage").'</span><br><br>';
3377 } elseif (empty($virtualurl)) {
3378 //$htmltext .= '<br><span class="error">'.$langs->trans("VirtualHostUrlNotDefined").'</span><br><br>';
3379 } else {
3380 $htmltext .= '<br><center>'.$langs->trans("GoTo").' <a href="'.$virtualurl.'" target="_website">'.$virtualurl.' '.img_picto('', 'url').'</a></center><br>';
3381 }
3382 if (getDolGlobalString('WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER')) {
3383 $htmltext .= '<!-- Message defined translate key set into WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER -->';
3384 $htmltext .= '<br>'.$langs->trans(getDolGlobalString('WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER'));
3385 } else {
3386 $htmltext .= $langs->trans("ToDeployYourWebsiteOnLiveYouHave3Solutions").'<br><br>';
3387 $htmltext .= '<div class="titre inline-block">1</div> - '.$langs->trans("SetHereVirtualHost", $dataroot);
3388 $htmltext .= '<br>';
3389 $htmltext .= '<br>'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("ReadPerm"), DOL_DOCUMENT_ROOT);
3390 $htmltext .= '<br>'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("WritePerm"), '{s1}');
3391 $htmltext = str_replace('{s1}', DOL_DATA_ROOT.'/website<br>'.DOL_DATA_ROOT.'/medias', $htmltext);
3392
3393 $examplewithapache = "<VirtualHost *:80>\n";
3394 $examplewithapache .= '#php_admin_value open_basedir /tmp/:'.DOL_DOCUMENT_ROOT.':'.DOL_DATA_ROOT.':/dev/urandom'."\n";
3395 //$examplewithapache .= '#php_admin_value disable_functions "exec,passthru,shell_exec,system,popen,proc_open"'."\n"; This is not effective if not in php.ini
3396 $examplewithapache .= "\n";
3397 $examplewithapache .= 'DocumentRoot "'.DOL_DOCUMENT_ROOT.'"'."\n";
3398 $examplewithapache .= "\n";
3399 $examplewithapache .= '<Directory "'.DOL_DOCUMENT_ROOT.'">'."\n";
3400 $examplewithapache .= 'AllowOverride FileInfo Options
3401 Options -Indexes -MultiViews -FollowSymLinks -ExecCGI
3402 Require all granted
3403 </Directory>'."\n".'
3404 <Directory "'.DOL_DATA_ROOT.'/website">
3405 AllowOverride FileInfo Options
3406 Options -Indexes -MultiViews +FollowSymLinks -ExecCGI
3407 Require all granted
3408 </Directory>'."\n".'
3409 <Directory "'.DOL_DATA_ROOT.'/medias">
3410 AllowOverride FileInfo Options
3411 Options -Indexes -MultiViews -FollowSymLinks -ExecCGI
3412 Require all granted
3413 </Directory>'."\n";
3414
3415 $examplewithapache .= "\n";
3416 $examplewithapache .= "#ErrorLog /var/log/apache2/".$websitekey."_error_log\n";
3417 $examplewithapache .= "#TransferLog /var/log/apache2/".$websitekey."_access_log\n";
3418
3419 $examplewithapache .= "\n";
3420 $examplewithapache .= "# If you need include the payment page into a frame of the website,\n";
3421 $examplewithapache .= "# you need to make a proxy redirection of URLs required for the payment to your backoffice pages\n";
3422 $examplewithapache .= "#SSLProxyEngine On\n";
3423 $examplewithapache .= "#SSLProxyVerify none\n";
3424 $examplewithapache .= "#SSLProxyCheckPeerCN off\n";
3425 $examplewithapache .= "#SSLProxyCheckPeerName off\n";
3426 $examplewithapache .= "#ProxyPreserveHost Off\n";
3427 $examplewithapache .= '#ProxyPass "/public/payment/" "'.$urlwithroot.'/public/payment/'."\n";
3428 $examplewithapache .= '#ProxyPassReverse "/public/payment/" "'.$urlwithroot.'/public/payment/'."\n";
3429 $examplewithapache .= '#ProxyPass "/includes/" "'.$urlwithroot.'/includes/'."\n";
3430 $examplewithapache .= '#ProxyPassReverse "/includes/" "'.$urlwithroot.'/includes/'."\n";
3431 $examplewithapache .= '#ProxyPass "/theme/" "'.$urlwithroot.'/theme/'."\n";
3432 $examplewithapache .= '#ProxyPassReverse "/theme/" "'.$urlwithroot.'/theme/'."\n";
3433 $examplewithapache .= '#ProxyPass "/core/js/" "'.$urlwithroot.'/core/js/'."\n";
3434 $examplewithapache .= '#ProxyPassReverse "/core/js/" "'.$urlwithroot.'/core/js/'."\n";
3435 $examplewithapache .= "\n";
3436
3437 $examplewithapache .= "</VirtualHost>\n";
3438
3439 $htmltext .= '<br>'.$langs->trans("ExampleToUseInApacheVirtualHostConfig").':<br>';
3440 $htmltext .= '<div class="quatrevingtpercent exampleapachesetup wordbreak" spellcheck="false">'.dol_nl2br(dol_escape_htmltag($examplewithapache, 1, 1)).'</div>';
3441
3442 $htmltext .= '<br>';
3443 $htmltext .= '<div class="titre inline-block">2</div> - '.$langs->trans("YouCanAlsoTestWithPHPS");
3444 $htmltext .= '<br><div class="urllink"><input type="text" id="cliphpserver" spellcheck="false" class="quatrevingtpercent" value="php -S 0.0.0.0:8080 -t '.$dataroot.'"></div>';
3445 $htmltext .= ajax_autoselect("cliphpserver");
3446 $htmltext .= '<br>';
3447 $htmltext .= '<div class="titre inline-block">3</div> - '.$langs->trans("YouCanAlsoDeployToAnotherWHP");
3448 }
3449 print $form->textwithpicto($linktotestonwebserver, $htmltext, 1, 'none', 'valignmiddle', 0, 3, 'helpvirtualhost');
3450 print '</span>';
3451 }
3452
3453 if (in_array($action, array('editcss', 'editmenu', 'file_manager', 'replacesiteconfirm', 'editsecurity')) || in_array($mode, array('replacesite'))) {
3454 if (!$user->hasRight('website', 'write')) {
3455 $disabled = ' disabled';
3456 }
3457 if ($action == 'editcss' || $action == 'editsecurity') {
3458 print '<input type="submit" accesskey="s" title="'.dol_escape_htmltag($conf->browser->stringforfirstkey.' s').'" id="savefileandstay" class="button buttonforacesave hideonsmartphone small'.$disabled.'" value="'.dol_escape_htmltag($langs->trans("SaveAndStay")).'" name="updateandstay">';
3459 }
3460 if (preg_match('/^create/', $action) && $action != 'file_manager' && $action != 'replacesite' && $action != 'replacesiteconfirm') {
3461 print '<input type="submit" id="savefile" class="button buttonforacesave button-save small'.$disabled.'" value="'.dol_escape_htmltag($langs->trans("Save")).'" name="update">';
3462 }
3463 if (preg_match('/^edit/', $action) && $action != 'file_manager' && $action != 'replacesite' && $action != 'replacesiteconfirm') {
3464 print '<input type="submit" id="savefile" class="button buttonforacesave button-save small'.$disabled.'" value="'.dol_escape_htmltag($langs->trans("Save")).'" name="update">';
3465 }
3466 if ($action != 'preview') {
3467 print '<input type="submit" class="button button-cancel small" value="'.dol_escape_htmltag($langs->trans("Cancel")).'" name="cancel">';
3468 }
3469 }
3470
3471 print '</span>';
3472
3473 //
3474 // Toolbar for pages
3475 //
3476
3477 if ($websitekey && $websitekey != '-1' && (!in_array($action, array('editcss', 'editmenu', 'importsite', 'file_manager', 'replacesite', 'replacesiteconfirm', 'editsecurity'))) && (!in_array($mode, array('replacesite'))) && !$file_manager) {
3478 print '</div>'; // Close current websitebar to open a new one
3479
3480 print '<!-- Toolbar for websitepage -->';
3481 print '<div class="centpercent websitebar"'.($style ? ' style="'.$style.'"' : '').'>'."\n";
3482
3483 print '<div class="websiteselection hideonsmartphoneimp minwidth75 tdoverflowmax100 inline-block">';
3484 print $langs->trans("PageContainer").': ';
3485 print '</div>';
3486
3487 // Button Add new web page
3488 if ($user->hasRight('website', 'write')) {
3489 print '<span class="websiteselection paddingrightonly">';
3490 print '<a href="'.$_SERVER["PHP_SELF"].'?action=createcontainer&token='.newToken().'&website='.urlencode($website->ref).'" class=""'.$disabled.' title="'.dol_escape_htmltag($langs->trans("AddPage")).'"><span class="fa fa-plus-circle valignmiddle btnTitle-icon"></span></a>';
3491 print '</span>';
3492 }
3493
3494 $out = '';
3495
3496 $s = $formwebsite->selectContainer($website, 'pageid', $pageid, 0, $action, 'minwidth100 maxwidth200onsmartphone');
3497
3498 $out .= '<span class="websiteselection nopaddingrightimp">';
3499 $out .= $s;
3500 $out .= '</span>';
3501
3502 $urltocreatenewpage = $_SERVER["PHP_SELF"].'?action=createcontainer&token='.newToken().'&website='.urlencode($website->ref);
3503
3504 if (!empty($conf->use_javascript_ajax)) {
3505 $out .= '<script type="text/javascript">';
3506 $out .= 'jQuery(document).ready(function () {';
3507 $out .= ' jQuery("#pageid").change(function () {';
3508 $out .= ' console.log("We select "+jQuery("#pageid option:selected").val());';
3509 $out .= ' if (jQuery("#pageid option:selected").val() == \'-2\') {';
3510 $out .= ' window.location.href = "'.$urltocreatenewpage.'";';
3511 $out .= ' } else {';
3512 $out .= ' window.location.href = "'.$_SERVER["PHP_SELF"].'?website='.urlencode($website->ref).'&pageid="+jQuery("#pageid option:selected").val();';
3513 $out .= ' }';
3514 $out .= ' });';
3515 $out .= '});';
3516 $out .= '</script>';
3517 }
3518
3519 print $out;
3520
3521 // Button to switch status
3522 if (!empty($conf->use_javascript_ajax)) {
3523 print '<span class="websiteselection">';
3524 //print '<div class="inline-block marginrightonly">';
3525 if ($object->status == $object::STATUS_DRAFT) { // website is off, we do not allow to change status of page
3526 $text_off = 'SetWebsiteOnlineBefore';
3527 if ($websitepage->status == $websitepage::STATUS_DRAFT) { // page is off
3528 print '<span class="valignmiddle disabled opacitymedium">'.img_picto($langs->trans($text_off), 'switch_off', '', 0, 0, 0, '', $morecss).'</span>';
3529 } else {
3530 print '<span class="valignmiddle disabled opacitymedium">'.img_picto($langs->trans($text_off), 'switch_on', '', 0, 0, 0, '', $morecss).'</span>';
3531 }
3532 } else {
3533 if ($objectpage->type_container != 'setup') { // we do not allow to change status of setup pages
3534 print ajax_object_onoff($websitepage, 'status', 'status', 'Online', 'Offline', array(), 'valignmiddle inline-block'.((empty($websitepage->id) || !$user->hasRight('website', 'write')) ? ' opacitymedium disabled' : ''), 'statuswebsitepage', 1, 'website='.urlencode($website->ref).'&pageid='.((int) $websitepage->id), $user->hasRight('website', 'write') ? 0 : 1);
3535 }
3536 }
3537 //print '</div>';
3538 print '</span>';
3539 }
3540
3541 print '<span class="websiteselection">';
3542
3543 print '<input type="image" class="valignmiddle buttonwebsite hideonsmartphone" src="'.img_picto('', 'refresh', '', 0, 1).'" name="refreshpage" value="'.$langs->trans("Load").'"'.(($action != 'editsource') ? '' : ' disabled="disabled"').'>';
3544
3545 // Print nav arrows
3546 $pagepreviousid = 0;
3547 $pagenextid = 0;
3548 if ($pageid) {
3549 $sql = "SELECT MAX(rowid) as pagepreviousid FROM ".MAIN_DB_PREFIX."website_page WHERE rowid < ".((int) $pageid)." AND fk_website = ".((int) $object->id);
3550 $resql = $db->query($sql);
3551 if ($resql) {
3552 $obj = $db->fetch_object($resql);
3553 if ($obj) {
3554 $pagepreviousid = $obj->pagepreviousid;
3555 }
3556 } else {
3558 }
3559 $sql = "SELECT MIN(rowid) as pagenextid FROM ".MAIN_DB_PREFIX."website_page WHERE rowid > ".((int) $pageid)." AND fk_website = ".((int) $object->id);
3560 $resql = $db->query($sql);
3561 if ($resql) {
3562 $obj = $db->fetch_object($resql);
3563 if ($obj) {
3564 $pagenextid = $obj->pagenextid;
3565 }
3566 } else {
3568 }
3569 }
3570
3571 if ($pagepreviousid) {
3572 print '<a class="valignmiddle" href="'.$_SERVER['PHP_SELF'].'?website='.urlencode($object->ref).'&pageid='.((int) $pagepreviousid).'&action='.urlencode($action).'&token='.newToken().'">'.img_previous($langs->trans("PreviousContainer")).'</a>';
3573 } else {
3574 print '<span class="valignmiddle opacitymedium">'.img_previous($langs->trans("PreviousContainer")).'</span>';
3575 }
3576 if ($pagenextid) {
3577 print '<a class="valignmiddle" href="'.$_SERVER['PHP_SELF'].'?website='.urlencode($object->ref).'&pageid='.((int) $pagenextid).'&action='.urlencode($action).'&token='.newToken().'">'.img_next($langs->trans("NextContainer")).'</a>';
3578 } else {
3579 print '<span class="valignmiddle opacitymedium">'.img_next($langs->trans("NextContainer")).'</span>';
3580 }
3581
3582 print '</span>';
3583
3584 if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone' || $action == 'deletesite') {
3585 $disabled = '';
3586 if (!$user->hasRight('website', 'write')) {
3587 $disabled = ' disabled="disabled"';
3588 }
3589
3590 // Confirmation delete site
3591 if ($action == 'deletesite') {
3592 // Create an array for form
3593 $formquestion = array(
3594 array('type' => 'checkbox', 'name' => 'delete_also_js', 'label' => $langs->trans("DeleteAlsoJs"), 'value' => 0),
3595 array('type' => 'checkbox', 'name' => 'delete_also_medias', 'label' => $langs->trans("DeleteAlsoMedias"), 'value' => 0),
3596 //array('type' => 'other','name' => 'newlang','label' => $langs->trans("Language"), 'value' => $formadmin->select_language(GETPOST('newlang', 'aZ09')?GETPOST('newlang', 'aZ09'):$langs->defaultlang, 'newlang', 0, null, '', 0, 0, 'minwidth200')),
3597 //array('type' => 'other','name' => 'newwebsite','label' => $langs->trans("WebSite"), 'value' => $formwebsite->selectWebsite($object->id, 'newwebsite', 0))
3598 );
3599
3600 if ($atleastonepage) {
3601 $langs->load("errors");
3602 $formquestion[] = array('type' => 'onecolumn', 'value' => '<div class="warning">'.$langs->trans("WarningPagesWillBeDeleted").'</div>');
3603 }
3604
3605 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteWebsite'), '', 'confirm_deletesite', $formquestion, 0, 1, 210 + ($atleastonepage ? 70 : 0), 580);
3606
3607 print $formconfirm;
3608 }
3609
3610 // Confirmation to clone
3611 if ($action == 'createfromclone') {
3612 // Create an array for form
3613 $formquestion = array(
3614 array('type' => 'text', 'name' => 'siteref', 'label' => $langs->trans("WebSite"), 'value' => 'copy_of_'.$object->ref)
3615 );
3616
3617 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('CloneSite'), '', 'confirm_createfromclone', $formquestion, 0, 1, 200);
3618
3619 print $formconfirm;
3620 }
3621
3622 if ($pageid > 0 && $atleastonepage) { // pageid can be set without pages, if homepage of site is set and all pages were removed
3623 // Confirmation to clone
3624 if ($action == 'createpagefromclone') {
3625 // Create an array for form
3626 $preselectedlanguage = GETPOST('newlang', 'aZ09') ? GETPOST('newlang', 'aZ09') : ''; // Dy default, we do not force any language on pages
3627 $onlylang = array();
3628 if ($website->otherlang) {
3629 if (!empty($website->lang)) {
3630 $onlylang[$website->lang] = $website->lang.' ('.$langs->trans("Default").')';
3631 }
3632 foreach (explode(',', $website->otherlang) as $langkey) {
3633 if (empty(trim($langkey))) {
3634 continue;
3635 }
3636 $onlylang[$langkey] = $langkey;
3637 }
3638 $textifempty = $langs->trans("Default");
3639 } else {
3640 $onlylang['none'] = 'none';
3641 $textifempty = $langs->trans("Default");
3642 }
3643
3644 $formheight = 300;
3645
3646 $formquestion = array(
3647 array('type' => 'hidden', 'name' => 'sourcepageurl', 'value' => $objectpage->pageurl),
3648 array('type' => 'other', 'tdclass' => 'fieldrequired', 'name' => 'newwebsite', 'label' => $langs->trans("WebSite"), 'value' => $formwebsite->selectWebsite((string) $object->id, 'newwebsite', 0)),
3649 array('type' => 'text', 'tdclass' => 'maxwidth200 fieldrequired', 'moreattr' => 'autofocus="autofocus"', 'name' => 'newtitle', 'label' => $langs->trans("WEBSITE_TITLE"), 'value' => $langs->trans("CopyOf").' '.$objectpage->title),
3650 array('type' => 'text', 'tdclass' => 'maxwidth200', 'name' => 'newpageurl', 'label' => $langs->trans("WEBSITE_PAGENAME"), 'value' => '')
3651 );
3652 if (count($onlylang) > 1) {
3653 $formquestion[] = array('type' => 'checkbox', 'tdclass' => 'maxwidth200', 'name' => 'is_a_translation', 'label' => $langs->trans("PageIsANewTranslation"), 'value' => 0, 'morecss' => 'margintoponly');
3654 $formheight += 50;
3655 }
3656
3657 $value = $formadmin->select_language($preselectedlanguage, 'newlang', 0, array(), $textifempty, 0, 0, 'minwidth200', 1, 0, 0, $onlylang, 1);
3658 $formquestion[] = array('type' => 'other', 'name' => 'newlang', 'label' => $form->textwithpicto($langs->trans("Language"), $langs->trans("DefineListOfAltLanguagesInWebsiteProperties")), 'value' => $value);
3659
3660 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?website='.$object->ref.'&pageid='.$pageid, $langs->trans('ClonePage'), '', 'confirm_createpagefromclone', $formquestion, 0, 1, $formheight, 550);
3661
3662 print $formconfirm;
3663 }
3664
3665 print '<span class="websiteselection">';
3666
3667 // Edit web page properties
3668 print '<a href="'.$_SERVER["PHP_SELF"].'?website='.$object->ref.'&pageid='.$pageid.'&action=editmeta&token='.newToken().'" class="button bordertransp valignmiddle" title="'.dol_escape_htmltag($langs->trans("EditPageMeta")).'"'.$disabled.'>';
3669 print img_picto('', 'setup');
3670 print '<span class="hideonsmartphone paddingleft">'.dol_escape_htmltag($langs->trans("EditPageMeta")).'</span>';
3671 print '</a>';
3672
3673 // Edit HTML content
3674 print '<a href="'.$_SERVER["PHP_SELF"].'?website='.$object->ref.'&pageid='.$pageid.'&action=editsource&token='.newToken().'" class="button bordertransp"'.$disabled.'>';
3675 print img_picto('', 'code');
3676 print '<span class="hideonsmartphone paddingleft">'.dol_escape_htmltag($langs->trans($conf->dol_optimize_smallscreen ? "HTML" : "EditHTMLSource")).'</span>';
3677 print '</a>';
3678
3679 // Edit CKEditor
3680 if (getDolGlobalInt('WEBSITE_ALLOW_CKEDITOR')) {
3681 print '<a href="'.$_SERVER["PHP_SELF"].'?website='.$object->ref.'&pageid='.$pageid.'&action=editcontent&token='.newToken().'" class="button bordertransp"'.$disabled.'>'.dol_escape_htmltag("CKEditor").'</a>';
3682 } else {
3683 print '<!-- Add option WEBSITE_ALLOW_CKEDITOR to allow ckeditor -->';
3684 }
3685
3686 print '</span>';
3687
3688
3689 // Switch include dynamic content / edit inline
3690 print '<!-- button EditInLine and ShowSubcontainers -->'."\n";
3691 print '<div class="websiteselectionsection inline-block">';
3692
3693 // Force to show subcontainers if we are in setup mode
3694 if ($objectpage->type_container == 'setup') {
3695 dolibarr_set_const($db, 'WEBSITE_SUBCONTAINERSINLINE', 1);
3696 }
3697
3698 if ($objectpage->type_container != 'setup') {
3699 print '<div class="inline-block marginrightonly">'; // Button includes dynamic content
3700 print $langs->trans("ShowSubcontainers");
3701 if (!getDolGlobalString('WEBSITE_SUBCONTAINERSINLINE')) {
3702 print '<a class="nobordertransp nohoverborder marginleftonlyshort valignmiddle"'.$disabled.' href="'.$_SERVER["PHP_SELF"].'?website='.$object->ref.'&pageid='.$websitepage->id.'&action=setshowsubcontainers&token='.newToken().'">'.img_picto($langs->trans("ShowSubContainersOnOff", $langs->transnoentitiesnoconv("Off")), 'switch_off', '', 0, 0, 0, '', 'nomarginleft').'</a>';
3703 } else {
3704 print '<a class="nobordertransp nohoverborder marginleftonlyshort valignmiddle"'.$disabled.' href="'.$_SERVER["PHP_SELF"].'?website='.$object->ref.'&pageid='.$websitepage->id.'&action=unsetshowsubcontainers&token='.newToken().'">'.img_picto($langs->trans("ShowSubContainersOnOff", $langs->transnoentitiesnoconv("On")), 'switch_on', '', 0, 0, 0, '', 'nomarginleft').'</a>';
3705 }
3706 print '</div>';
3707 }
3708
3709 print '<div class="inline-block marginrightonly">'; // Button edit inline
3710
3711 print '<span id="switchckeditorinline">'."\n";
3712 // Enable CKEditor inline with js on section and div with conteneditable=true
3713 print '<!-- Code to enabled edit inline ckeditor -->'."\n";
3714 print '<script type="text/javascript">
3715 $(document).ready(function() {
3716 var isEditingEnabled = '.(getDolGlobalString("WEBSITE_EDITINLINE") ? 'true' : 'false').';
3717 if (isEditingEnabled)
3718 {
3719 switchEditorOnline(true);
3720 }
3721
3722 $( "#switchckeditorinline" ).click(function() {
3723 switchEditorOnline();
3724 });
3725
3726 function switchEditorOnline(forceenable)
3727 {
3728 if (! isEditingEnabled || forceenable)
3729 {
3730 console.log("Enable inline edit for some html tags with contenteditable=true attribute");
3731
3732 jQuery(\'section[contenteditable="true"],div[contenteditable="true"],header[contenteditable="true"],main[contenteditable="true"],footer[contenteditable="true"]\').each(function(idx){
3733 var idtouse = $(this).attr(\'id\');
3734 console.log("Enable inline edit for "+idtouse);
3735 if (idtouse !== undefined) {
3736 var inlineditor = CKEDITOR.inline(idtouse, {
3737 // Allow some non-standard markup that we used in the introduction.
3738 // + a[target];div{float,display} ?
3739 extraAllowedContent: \'span(*);cite(*);q(*);dl(*);dt(*);dd(*);ul(*);li(*);header(*);main(*);footer(*);button(*);h1(*);h2(*);h3(*);\',
3740 //extraPlugins: \'sourcedialog\',
3741 removePlugins: \'flash,stylescombo,exportpdf,scayt,wsc,pagebreak,iframe,smiley\',
3742 // Show toolbar on startup (optional).
3743 // startupFocus: true
3744 });
3745
3746 // Custom bar tool
3747 // Note the Source tool does not work on inline
3748 inlineditor.config.toolbar = [
3749 [\'Templates\',\'NewPage\'],
3750 [\'Save\'],
3751 [\'Maximize\',\'Preview\'],
3752 [\'PasteText\'],
3753 [\'Undo\',\'Redo\',\'-\',\'Find\',\'Replace\',\'-\',\'SelectAll\',\'RemoveFormat\'],
3754 [\'CreateDiv\',\'ShowBlocks\'],
3755 [\'Form\', \'Checkbox\', \'Radio\', \'TextField\', \'Textarea\', \'Select\', \'Button\', \'ImageButton\', \'HiddenField\'],
3756 [\'Bold\',\'Italic\',\'Underline\',\'Strike\',\'Superscript\'],
3757 [\'NumberedList\',\'BulletedList\',\'-\',\'Outdent\',\'Indent\',\'Blockquote\'],
3758 [\'JustifyLeft\',\'JustifyCenter\',\'JustifyRight\',\'JustifyBlock\'],
3759 [\'Link\',\'Unlink\'],
3760 [\'Image\',\'Table\',\'HorizontalRule\'],
3761 [\'Styles\',\'Format\',\'Font\',\'FontSize\'],
3762 [\'TextColor\',\'BGColor\']
3763 ];
3764
3765 // Start editor
3766 //inlineditor.on(\'instanceReady\', function () {
3767 // ...
3768 //});
3769
3770 CKEDITOR.instances[idtouse].on(\'change\', function() {
3771 $(this.element.$).addClass(\'modified\');
3772 })
3773 } else {
3774 console.warn("A html section has the contenteditable=true attribute but has no id attribute");
3775 }
3776 })
3777
3778 isEditingEnabled = true;
3779
3780 // Trigger the function when clicking outside the elements with contenteditable=true attribute
3781 // so we can save the change.
3782 $(document).on(\'click\', function(e) {
3783 var target = $(e.target);
3784
3785 // Check if the click is outside the elements with contenteditable=true attribute
3786 if (!target.closest(\'[contenteditable="true"]\').length) {
3787 // Repeat through the elements with contenteditable="true" attribute
3788 $(\'[contenteditable="true"]\').each(function() {
3789 var idToUse = $(this).attr(\'id\');
3790 var elementType = $(this).prop("tagName").toLowerCase(); // Get the tag name (div, section, footer...)
3791 var instance = CKEDITOR.instances[idToUse];
3792
3793 // Check if the element has been modified
3794 if ($(this).hasClass(\'modified\')) {
3795 var content = instance.getData();
3796 content = "\\n" + content;
3797
3798 // Retrieving the content and ID of the element
3799 var elementId = $(this).attr(\'id\');
3800
3801 ';
3802 if (getDolGlobalString('WEBSITE_EDITINLINE_SAVE_CKEDITOR_EDIT')) {
3803 print '
3804 console.log("A change has been detected, we send new content for update with ajax");
3805
3806 // Sending data via AJAX to update section
3807 $.ajax({
3808 type: \'POST\',
3809 url: \'' . DOL_URL_ROOT . '/core/ajax/editinline.php\',
3810 data: {
3811 website_ref: \''.dol_escape_js($website->ref).'\',
3812 page_id: \'' . ((int) $websitepage->id) . '\',
3813 content: content,
3814 element_id: elementId,
3815 element_type: elementType,
3816 action: \'updatedElementContent\',
3817 token: \'' . newToken() . '\'
3818 },
3819 success: function(response) {
3820 console.log(response);
3821 var $lastWebsitebar = $(".websitebar").last();
3822 var $span = $("<span></span>").html("'.$langs->trans("Saved").'").css({
3823 \'display\': \'block\',
3824 \'position\': \'absolute\',
3825 \'margin-top\': \'6px\',
3826 \'right\': \'5px\',
3827 \'background-color\': \'#e3f0db\',
3828 \'color\': \'#446548\',
3829 \'font-size\': \'14px\',
3830 \'padding\': \'0px 5px\',
3831 \'z-index\': 1000
3832 });
3833 $lastWebsitebar.after($span);
3834
3835 // Close message after 2 seconds
3836 setTimeout(function() {
3837 $span.fadeOut(500, function() {
3838 $(this).remove();
3839 });
3840 }, 2000);
3841 }
3842 });
3843 ';
3844 } else {
3845 print 'console.log("A change has been detected, but saving is not enabled by option WEBSITE_EDITINLINE_SAVE_CKEDITOR_EDIT, so no ajax update is done");';
3846 }
3847 print '
3848
3849 $(this).removeClass(\'modified\');
3850 }
3851 });
3852 }
3853 });
3854
3855 } else {
3856 console.log("Disable inline edit");
3857 for(name in CKEDITOR.instances) {
3858 CKEDITOR.instances[name].destroy(true);
3859 }
3860 isEditingEnabled = false;
3861 }
3862 }
3863 });
3864 </script>';
3865 print $langs->trans("EditInLine");
3866 print '</span>';
3867
3868 //$disableeditinline = $websitepage->grabbed_from;
3869 $disableeditinline = 0;
3870 if ($disableeditinline) {
3871 //print '<input type="submit" class="button bordertransp" disabled="disabled" title="'.dol_escape_htmltag($langs->trans("OnlyEditionOfSourceForGrabbedContent")).'" value="'.dol_escape_htmltag($langs->trans("EditWithEditor")).'" name="editcontent">';
3872 print '<a class="nobordertransp opacitymedium nohoverborder marginleftonlyshort"'.$disabled.' href="#" disabled="disabled" title="'.dol_escape_htmltag($langs->trans("OnlyEditionOfSourceForGrabbedContent")).'">'.img_picto($langs->trans("OnlyEditionOfSourceForGrabbedContent"), 'switch_off', '', 0, 0, 0, '', 'nomarginleft').'</a>';
3873 } else {
3874 //print '<input type="submit" class="button nobordertransp"'.$disabled.' value="'.dol_escape_htmltag($langs->trans("EditWithEditor")).'" name="editcontent">';
3875 if (!getDolGlobalString('WEBSITE_EDITINLINE')) {
3876 print '<a class="nobordertransp nohoverborder marginleftonlyshort valignmiddle"'.$disabled.' href="'.$_SERVER["PHP_SELF"].'?website='.$object->ref.'&pageid='.$websitepage->id.'&action=seteditinline&token='.newToken().'">'.img_picto($langs->trans("EditInLineOnOff", $langs->transnoentitiesnoconv("Off")), 'switch_off', '', 0, 0, 0, '', 'nomarginleft').'</a>';
3877 } else {
3878 print '<a class="nobordertransp nohoverborder marginleftonlyshort valignmiddle"'.$disabled.' href="'.$_SERVER["PHP_SELF"].'?website='.$object->ref.'&pageid='.$websitepage->id.'&action=unseteditinline&token='.newToken().'">'.img_picto($langs->trans("EditInLineOnOff", $langs->transnoentitiesnoconv("On")), 'switch_on', '', 0, 0, 0, '', 'nomarginleft').'</a>';
3879 }
3880 }
3881
3882 print '</div>';
3883
3884 print '</div>';
3885
3886 // Set page as homepage
3887 print '<span class="websiteselection">';
3888 if ($object->fk_default_home > 0 && $pageid == $object->fk_default_home) {
3889 //$disabled=' disabled="disabled"';
3890 //print '<span class="button bordertransp disabled"'.$disabled.' title="'.dol_escape_htmltag($langs->trans("SetAsHomePage")).'"><span class="fas fa-home"></span></span>';
3891 //print '<input type="submit" class="button bordertransp" disabled="disabled" value="'.dol_escape_htmltag($langs->trans("SetAsHomePage")).'" name="setashome">';
3892 print '<a href="#" class="button bordertransp disabled" disabled="disabled" title="'.dol_escape_htmltag($langs->trans("SetAsHomePage")).'"><span class="fas fa-home valignmiddle btnTitle-icon"></span></a>';
3893 } else {
3894 //$disabled='';
3895 //print '<input type="submit" class="button bordertransp"'.$disabled.' value="'.dol_escape_htmltag($langs->trans("SetAsHomePage")).'" name="setashome">';
3896 print '<a href="'.$_SERVER["PHP_SELF"].'?action=setashome&token='.newToken().'&website='.urlencode($website->ref).'&pageid='.((int) $pageid).'" class="button bordertransp"'.$disabled.' title="'.dol_escape_htmltag($langs->trans("SetAsHomePage")).'"><span class="fas fa-home valignmiddle btnTitle-icon"></span></a>';
3897 }
3898 print '<input type="submit" class="button bordertransp"'.$disabled.' value="'.dol_escape_htmltag($langs->trans("ClonePage")).'" name="createpagefromclone">';
3899
3900 // Delete
3901 if ($websitepage->status != $websitepage::STATUS_DRAFT) {
3902 $disabled = ' disabled="disabled"';
3903 $title = $langs->trans("WebpageMustBeDisabled", $langs->transnoentitiesnoconv($websitepage->LibStatut(0, 0)));
3904 $url = '#';
3905 } else {
3906 $disabled = '';
3907 $title = '';
3908 $url = $_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&pageid='.((int) $websitepage->id).'&website='.urlencode($website->ref); // action=delete for webpage, deletesite for website
3909 }
3910 print '<a href="'.$url.'" class="button buttonDelete bordertransp'.($disabled ? ' disabled' : '').'"'.$disabled.' title="'.dol_escape_htmltag($title).'">'.img_picto('', 'delete', 'class=""').'<span class="hideonsmartphone paddingleft">'.$langs->trans("Delete").'</span></a>';
3911 print '</span>';
3912 }
3913 }
3914
3915 //print '</span>'; // end website selection
3916
3917 print '<span class="websitetools">';
3918
3919 if (($pageid > 0 && $atleastonepage) && ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone' || $action == 'deletesite')) {
3920 $realpage = $urlwithroot.'/public/website/index.php?website='.$websitekey.'&pageref='.$websitepage->pageurl;
3921 $pagealias = $websitepage->pageurl;
3922
3923 $htmltext = $langs->trans("PreviewSiteServedByDolibarr", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $realpage, $langs->transnoentitiesnoconv("TestDeployOnWeb"));
3924 //$htmltext .= '<br>'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("ReadPerm"), '{s1}');
3925 //$htmltext = str_replace('{s1}', $dataroot.'<br>'.DOL_DATA_ROOT.'/medias<br>'.DOL_DOCUMENT_ROOT, $htmltext);
3926 //$htmltext .= '<br>'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("WritePerm"), '{s1}');
3927 //$htmltext = str_replace('{s1}', DOL_DATA_ROOT.'/medias', $htmltext);
3928
3929 print '<div class="websiteinputurl inline-block paddingright">';
3930 print '<a class="websitebuttonsitepreview inline-block" id="previewpage" href="'.$realpage.'&nocache='.dol_now().'" class="button" target="tab'.$websitekey.'" alt="'.dol_escape_htmltag($htmltext).'">';
3931 print $form->textwithpicto('', $htmltext, 1, 'preview');
3932 print '</a>'; // View page in new Tab
3933 print '</div>';
3934
3935 /*print '<div class="websiteinputurl inline-block" id="websiteinputpage">';
3936 print '<input type="text" id="previewpageurl" class="minwidth200imp" name="previewsite" value="'.$pagealias.'" disabled="disabled">';
3937 $htmltext = $langs->trans("PageNameAliasHelp", $langs->transnoentitiesnoconv("EditPageMeta"));
3938 print $form->textwithpicto('', $htmltext, 1, 'help', '', 0, 2, 'helppagealias');
3939 print '</div>';*/
3940
3941 /*
3942 $urlext = $virtualurl.'/'.$pagealias.'.php';
3943 $urlint = $urlwithroot.'/public/website/index.php?website='.$websitekey;
3944
3945 $htmltext = $langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $dataroot, $virtualurl ? $urlext : '<span class="error">'.$langs->trans("VirtualHostUrlNotDefined").'</span>');
3946
3947 print '<a class="websitebuttonsitepreview'.($virtualurl ? '' : ' websitebuttonsitepreviewdisabled cursornotallowed').'" id="previewpageext" href="'.$urlext.'" target="tab'.$websitekey.'ext" alt="'.dol_escape_htmltag($htmltext).'">';
3948 print $form->textwithpicto('', $htmltext, 1, 'preview_ext');
3949 print '</a>';
3950 */
3951 //print '<input type="submit" class="button" name="previewpage" target="tab'.$websitekey.'"value="'.$langs->trans("ViewPageInNewTab").'">';
3952
3953 // TODO Add js to save alias like we save virtual host name and use dynamic virtual host for url of id=previewpageext
3954 }
3955 if (!in_array($mode, array('replacesite')) && !in_array($action, array('editcss', 'editmenu', 'file_manager', 'replacesiteconfirm', 'createsite', 'createcontainer', 'createfromclone', 'createpagefromclone', 'deletesite', 'editsecurity'))) {
3956 if (!$user->hasRight('website', 'write')) {
3957 $disabled = ' disabled';
3958 }
3959 if ($action == 'editsource' || $action == 'editmeta') {
3960 print '<input type="submit" accesskey="s" title="'.dol_escape_htmltag($conf->browser->stringforfirstkey.' s').'" id="savefileandstay" class="button buttonforacesave hideonsmartphone small'.$disabled.'" value="'.dol_escape_htmltag($langs->trans("SaveAndStay")).'" name="updateandstay">';
3961 }
3962 if (preg_match('/^create/', $action)) {
3963 print '<input type="submit" id="savefile" class="button buttonforacesave button-save small'.$disabled.'" value="'.dol_escape_htmltag($langs->trans("Save")).'" name="update">';
3964 }
3965 if (preg_match('/^edit/', $action)) {
3966 print '<input type="submit" id="savefile" class="button buttonforacesave button-save small'.$disabled.'" value="'.dol_escape_htmltag($langs->trans("Save")).'" name="update">';
3967 }
3968 if ($action != 'preview') {
3969 print '<input type="submit" class="button button-cancel small" value="'.dol_escape_htmltag($langs->trans("Cancel")).'" name="cancel">';
3970 }
3971 }
3972
3973 print '</span>'; // end websitetools
3974
3975 print '<span class="websitehelp">';
3976 if ($action == 'editsource' || $action == 'editcontent' || GETPOST('editsource', 'alpha') || GETPOST('editcontent', 'alpha')) {
3977 $url = 'https://wiki.dolibarr.org/index.php/Module_Website';
3978
3979 $htmltext = '<small>';
3980 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource", $url);
3981 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSourceb", $url);
3982 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSourcec", $url);
3983 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSourced", $url);
3984 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource1", $url);
3985 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource2", $url);
3986 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource3", $url);
3987 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource4", $url);
3988 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSourceMore", $url);
3989 $htmltext .= '<br>';
3990 $htmltext .= '</small>';
3991 if ($conf->browser->layout == 'phone') {
3992 print $form->textwithpicto('', $htmltext, 1, 'help', 'inline-block', 1, 2, 'tooltipsubstitution');
3993 } else {
3994 //img_help(($tooltiptrigger != '' ? 2 : 1), $alt)
3995 print $form->textwithpicto($langs->trans("SyntaxHelp").' '.img_help(2, $langs->trans("SyntaxHelp")), $htmltext, 1, 'none', 'inline-block', 1, 2, 'tooltipsubstitution');
3996 }
3997 }
3998 print '</span>'; // end websitehelp
3999
4000
4001 if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone') {
4002 // Adding jquery code to change on the fly url of preview ext
4003 if (!empty($conf->use_javascript_ajax)) {
4004 print '<script type="text/javascript">
4005 jQuery(document).ready(function() {
4006 jQuery("#websiteinputurl").keyup(function() {
4007 console.log("Website external url modified "+jQuery("#previewsiteurl").val());
4008 if (jQuery("#previewsiteurl").val() != "" && jQuery("#previewsiteurl").val().startsWith("http"))
4009 {
4010 jQuery("a.websitebuttonsitepreviewdisabled img").css({ opacity: 1 });
4011 }
4012 else jQuery("a.websitebuttonsitepreviewdisabled img").css({ opacity: 0.2 });
4013 ';
4014 print '
4015 });
4016 jQuery("#previewsiteext,#previewpageext").click(function() {
4017
4018 newurl=jQuery("#previewsiteurl").val();
4019 if (! newurl.startsWith("http"))
4020 {
4021 alert(\''.dol_escape_js($langs->trans("ErrorURLMustStartWithHttp")).'\');
4022 return false;
4023 }
4024
4025 newpage=jQuery("#previewsiteurl").val() + "/" + jQuery("#previewpageurl").val() + ".php";
4026 console.log("Open url "+newurl);
4027 /* Save url */
4028 jQuery.ajax({
4029 method: "POST",
4030 url: "'.DOL_URL_ROOT.'/core/ajax/saveinplace.php",
4031 data: {
4032 field: \'editval_virtualhost\',
4033 element: \'website\',
4034 table_element: \'website\',
4035 fk_element: '.((int) $object->id).',
4036 value: newurl,
4037 },
4038 context: document.body
4039 });
4040
4041 jQuery("#previewsiteext").attr("href",newurl);
4042 jQuery("#previewpageext").attr("href",newpage);
4043 });
4044 });
4045 </script>';
4046 }
4047 }
4048 }
4049
4050 print '</div>'."\n"; // end current websitebar
4051}
4052
4053
4054$head = array();
4055
4056
4057/*
4058 * Edit Site HTML header and CSS
4059 */
4060
4061if ($action == 'editcss') {
4062 print '<div class="fiche">';
4063
4064 print '<br>';
4065
4066 if (!GETPOSTISSET('WEBSITE_CSS_INLINE')) {
4067 $csscontent = @file_get_contents($filecss);
4068 // Clean the php css file to remove php code and get only css part
4069 $csscontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $csscontent);
4070 } else {
4071 $csscontent = GETPOST('WEBSITE_CSS_INLINE', 'none');
4072 }
4073 if (!trim($csscontent)) {
4074 $csscontent = '/* CSS content (all pages) */'."\nbody.bodywebsite { margin: 0; font-family: 'Open Sans', sans-serif; }\n.bodywebsite h1 { margin-top: 0; margin-bottom: 0; padding: 10px;}";
4075 }
4076
4077 if (!GETPOSTISSET('WEBSITE_JS_INLINE')) {
4078 $jscontent = @file_get_contents($filejs);
4079 // Clean the php js file to remove php code and get only js part
4080 $jscontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $jscontent);
4081 } else {
4082 $jscontent = GETPOST('WEBSITE_JS_INLINE', 'none');
4083 }
4084 if (!trim($jscontent)) {
4085 $jscontent = '/* JS content (all pages) */'."\n";
4086 }
4087
4088 if (!GETPOSTISSET('WEBSITE_HTML_HEADER')) {
4089 $htmlheadercontent = @file_get_contents($filehtmlheader);
4090 // Clean the php htmlheader file to remove php code and get only html part
4091 $htmlheadercontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $htmlheadercontent);
4092 } else {
4093 $htmlheadercontent = GETPOST('WEBSITE_HTML_HEADER', 'none'); // Must accept tags like '<script>' and '<link>'
4094 }
4095 if (!trim($htmlheadercontent)) {
4096 $htmlheadercontent = "<html>\n";
4097 $htmlheadercontent .= $htmlheadercontentdefault;
4098 $htmlheadercontent .= "</html>";
4099 } else {
4100 $htmlheadercontent = preg_replace('/^\s*<html>/ims', '', $htmlheadercontent);
4101 $htmlheadercontent = preg_replace('/<\/html>\s*$/ims', '', $htmlheadercontent);
4102 $htmlheadercontent = '<html>'."\n".trim($htmlheadercontent)."\n".'</html>';
4103 }
4104
4105 if (!GETPOSTISSET('WEBSITE_ROBOT')) {
4106 $robotcontent = @file_get_contents($filerobot);
4107 // Clean the php htmlheader file to remove php code and get only html part
4108 $robotcontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $robotcontent);
4109 } else {
4110 $robotcontent = GETPOST('WEBSITE_ROBOT', 'nohtml');
4111 }
4112 if (!trim($robotcontent)) {
4113 $robotcontent .= "# Robot file. Generated with ".DOL_APPLICATION_TITLE."\n";
4114 $robotcontent .= "User-agent: *\n";
4115 $robotcontent .= "Allow: /public/\n";
4116 $robotcontent .= "Disallow: /administrator/\n";
4117 }
4118
4119 if (!GETPOSTISSET('WEBSITE_HTACCESS')) {
4120 $htaccesscontent = @file_get_contents($filehtaccess);
4121 // Clean the php htaccesscontent file to remove php code and get only html part
4122 $htaccesscontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $htaccesscontent);
4123 } else {
4124 $htaccesscontent = GETPOST('WEBSITE_HTACCESS', 'nohtml'); // We must use 'nohtml' and not 'alphanohtml' because we must accept "
4125 }
4126
4127 if (!GETPOSTISSET('WEBSITE_MANIFEST_JSON')) {
4128 $manifestjsoncontent = @file_get_contents($filemanifestjson);
4129 // Clean the manifestjson file to remove php code and get only html part
4130 $manifestjsoncontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $manifestjsoncontent);
4131 } else {
4132 $manifestjsoncontent = trim(GETPOST('WEBSITE_MANIFEST_JSON', 'restricthtmlallowunvalid'));
4133 $manifestjsoncontent = str_replace('<?=', '<?php', $manifestjsoncontent);
4134 }
4135
4136 //if (!trim($manifestjsoncontent)) {
4137 //$manifestjsoncontent.="";
4138 //}
4139
4140 if (!GETPOSTISSET('WEBSITE_README')) {
4141 $readmecontent = @file_get_contents($filereadme);
4142 // Clean the readme file to remove php code and get only html part
4143 $readmecontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $readmecontent);
4144 } else {
4145 $readmecontent = GETPOST('WEBSITE_README', 'restricthtmlallowunvalid');
4146 }
4147 //if (!trim($readmecontent)) {
4148 //$readmecontent.="";
4149 //}
4150
4151 if (!GETPOSTISSET('WEBSITE_LICENSE')) {
4152 $licensecontent = @file_get_contents($filelicense);
4153 // Clean the readme file to remove php code and get only html part
4154 $licensecontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $licensecontent);
4155 } else {
4156 $licensecontent = GETPOST('WEBSITE_LICENSE', 'restricthtmlallowunvalid');
4157 }
4158 //if (!trim($licensecontent)) {
4159 //$readmecontent.="";
4160 //}
4161
4162 $head = websiteconfigPrepareHead($object);
4163 print dol_get_fiche_head($head, 'general', $langs->trans("General"), 0, 'website');
4164
4165 print '<!-- Edit Website properties (CSS, Language, ...) -->'."\n";
4166 print '<table class="border centpercent">';
4167
4168 // Website
4169 print '<tr><td class="titlefieldcreate fieldrequired">';
4170 print $langs->trans('WebSite');
4171 print '</td><td>';
4172 print $websitekey;
4173 print '</td></tr>';
4174
4175 // Status of web site
4176 if ($action != 'createcontainer') {
4177 if (empty($conf->use_javascript_ajax)) {
4178 print '<!-- Status of web site page -->'."\n";
4179 print '<tr><td class="fieldrequired">';
4180 print $langs->trans('Status');
4181 print '</td><td>';
4182 print $form->selectyesno('status', $object->status);
4183 print '</td></tr>';
4184 }
4185 }
4186
4187 // Main language
4188 print '<tr><td class="tdtop fieldrequired">';
4189 $htmltext = '';
4190 print $form->textwithpicto($langs->trans('MainLanguage'), $htmltext, 1, 'help', '', 0, 2, 'WEBSITE_LANG');
4191 print '</td><td>';
4192 print img_picto('', 'language', 'class="pictofixedwidth"');
4193 print $formadmin->select_language((GETPOSTISSET('WEBSITE_LANG') ? GETPOST('WEBSITE_LANG', 'aZ09comma') : ($object->lang ? $object->lang : '0')), 'WEBSITE_LANG', 0, array(), 1, 0, 0, 'minwidth300', 2, 0, 0, array(), 1);
4194 print '</td>';
4195 print '</tr>';
4196
4197 // Other languages
4198 print '<tr><td class="tdtop">';
4199 $htmltext = $langs->trans("Example").': fr,de,sv,it,pt';
4200 print $form->textwithpicto($langs->trans('OtherLanguages'), $htmltext, 1, 'help', '', 0, 2);
4201 print '</td><td>';
4202 print img_picto('', 'language', 'class="pictofixedwidth"');
4203 print '<input type="text" class="flat maxwidth200" value="'.(GETPOSTISSET('WEBSITE_OTHERLANG') ? GETPOST('WEBSITE_OTHERLANG', 'alpha') : $object->otherlang).'" name="WEBSITE_OTHERLANG">';
4204 print '</td>';
4205 print '</tr>';
4206
4207 // VirtualHost
4208 print '<tr><td class="tdtop">';
4209
4210 $htmltext = $langs->trans("VirtualhostDesc");
4211 print $form->textwithpicto($langs->trans('Virtualhost'), $htmltext, 1, 'help', '', 0, 2, 'virtualhosttooltip');
4212 print '</td><td>';
4213 print '<input type="text" class="flat minwidth300" value="'.(GETPOSTISSET('virtualhost') ? GETPOST('virtualhost', 'alpha') : $virtualurl).'" name="virtualhost">';
4214 print '</td>';
4215 print '</tr>';
4216
4217 // Favicon
4218 print '<tr><td>';
4219 print $form->textwithpicto($langs->trans('ImportFavicon'), $langs->trans('FaviconTooltip'));
4220 print '</td><td>';
4221 $maxfilesizearray = getMaxFileSizeArray();
4222 $maxmin = $maxfilesizearray['maxmin'];
4223 if ($maxmin > 0) {
4224 print '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
4225 }
4226 print '<input type="file" class="flat minwidth300" name="addedfile" id="addedfile"/>';
4227
4228 $uploadfolder = $conf->website->dir_output.'/'.$websitekey;
4229 if (dol_is_file($uploadfolder.'/favicon.png')) {
4230 print '<div class="inline-block valignmiddle marginrightonly">';
4231 print '<img style="max-height: 80px" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=website&file='.$websitekey.'/favicon.png">';
4232 print '</div>';
4233 }
4234 print '</tr></td>';
4235
4236 // CSS file
4237 print '<tr><td class="tdtop">';
4238 $htmlhelp = $langs->trans("CSSContentTooltipHelp");
4239 print $form->textwithpicto($langs->trans('WEBSITE_CSS_INLINE'), $htmlhelp, 1, 'help', '', 0, 2, 'csstooltip');
4240 print '</td><td>';
4241
4242 $poscursor = array('x' => GETPOST('WEBSITE_CSS_INLINE_x'), 'y' => GETPOST('WEBSITE_CSS_INLINE_y'));
4243 $doleditor = new DolEditor('WEBSITE_CSS_INLINE', $csscontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4244 print $doleditor->Create(1, '', true, 'CSS', 'css');
4245
4246 print '</td></tr>';
4247
4248 // JS file
4249 print '<tr><td class="tdtop">';
4250 $textwithhelp = $langs->trans('WEBSITE_JS_INLINE');
4251 $htmlhelp2 = $langs->trans("LinkAndScriptsHereAreNotLoadedInEditor").'<br>';
4252 print $form->textwithpicto($textwithhelp, $htmlhelp2, 1, 'warning', '', 0, 2, 'htmljstooltip2');
4253
4254 print '</td><td>';
4255
4256 $poscursor = array('x' => GETPOST('WEBSITE_JS_INLINE_x'), 'y' => GETPOST('WEBSITE_JS_INLINE_y'));
4257 $doleditor = new DolEditor('WEBSITE_JS_INLINE', $jscontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4258 print $doleditor->Create(1, '', true, 'JS', 'javascript');
4259
4260 print '</td></tr>';
4261
4262 // Common HTML header
4263 print '<tr><td class="tdtop">';
4264 print $langs->trans('WEBSITE_HTML_HEADER');
4265 $htmlhelp = $langs->trans("Example").' :<br>';
4266 $htmlhelp .= dol_nl2br(dol_htmlentities($htmlheadercontentdefault)); // do not use dol_htmlentitiesbr here, $htmlheadercontentdefault is HTML with content like <link> and <script> that we want to be html encode as they must be show as doc content not executable instruction.
4267 $textwithhelp = $form->textwithpicto('', $htmlhelp, 1, 'help', '', 0, 2, 'htmlheadertooltip');
4268 $htmlhelp2 = $langs->trans("LinkAndScriptsHereAreNotLoadedInEditor").'<br>';
4269 print $form->textwithpicto($textwithhelp, $htmlhelp2, 1, 'warning', '', 0, 2, 'htmlheadertooltip2');
4270 print '</td><td>';
4271
4272 $poscursor = array('x' => GETPOST('WEBSITE_HTML_HEADER_x'), 'y' => GETPOST('WEBSITE_HTML_HEADER_y'));
4273 $doleditor = new DolEditor('WEBSITE_HTML_HEADER', $htmlheadercontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4274 print $doleditor->Create(1, '', true, 'HTML Header', 'html');
4275
4276 print '</td></tr>';
4277
4278 // Robot file
4279 print '<tr><td class="tdtop">';
4280 print $langs->trans('WEBSITE_ROBOT');
4281 print '</td><td>';
4282
4283 $poscursor = array('x' => GETPOST('WEBSITE_ROBOT_x'), 'y' => GETPOST('WEBSITE_ROBOT_y'));
4284 $doleditor = new DolEditor('WEBSITE_ROBOT', $robotcontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4285 print $doleditor->Create(1, '', true, 'Robot file', 'text');
4286
4287 print '</td></tr>';
4288
4289 // .htaccess
4290 print '<tr><td class="tdtop">';
4291
4292 $textwithhelp3 = $langs->trans("Example").' :';
4293 $textwithhelp3 .= "<br># Order allow,deny\n";
4294 $textwithhelp3 .= "<br># Deny from all\n";
4295 $textwithhelp3 .= "<br># Require all granted\n";
4296
4297 print $form->textwithpicto($langs->trans('WEBSITE_HTACCESS'), $textwithhelp3, 1, 'help', '', 0, 2, 'htmlheadertooltip3');
4298 print '</td><td>';
4299
4300 $poscursor = array('x' => GETPOST('WEBSITE_HTACCESS_x'), 'y' => GETPOST('WEBSITE_HTACCESS_y'));
4301 $doleditor = new DolEditor('WEBSITE_HTACCESS', $htaccesscontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4302 print $doleditor->Create(1, '', true, $langs->trans("File").' .htaccess', 'text');
4303
4304 print '</td></tr>';
4305
4306 // Manifest.json
4307 print '<tr><td class="tdtop">';
4308 $htmlhelp = $langs->trans("Example").' :<br>';
4309 $htmlhelp .= '<small>'.dol_htmlentitiesbr($manifestjsoncontentdefault).'</small>';
4310 print $form->textwithpicto($langs->trans('WEBSITE_MANIFEST_JSON'), $htmlhelp, 1, 'help', '', 0, 2, 'manifestjsontooltip');
4311 print '</td><td>';
4312 print $langs->trans("UseManifest").': '.$form->selectyesno('use_manifest', $website->use_manifest, 1).'<br>';
4313
4314 $poscursor = array('x' => GETPOST('WEBSITE_MANIFEST_JSON_x'), 'y' => GETPOST('WEBSITE_MANIFEST_JSON_y'));
4315 $doleditor = new DolEditor('WEBSITE_MANIFEST_JSON', $manifestjsoncontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4316 print $doleditor->Create(1, '', true, $langs->trans("File").' manifest.json', 'text');
4317 print '</td></tr>';
4318
4319 // README.md
4320 print '<tr><td class="tdtop">';
4321 $htmlhelp = $langs->trans("EnterHereReadmeInformation");
4322 print $form->textwithpicto($langs->trans("File").' README.md', $htmlhelp, 1, 'help', '', 0, 2, 'readmetooltip');
4323 print '</td><td>';
4324
4325 $poscursor = array('x' => GETPOST('WEBSITE_README_x'), 'y' => GETPOST('WEBSITE_README_y'));
4326 $doleditor = new DolEditor('WEBSITE_README', $readmecontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4327 print $doleditor->Create(1, '', true, $langs->trans("File").' README.md', 'text');
4328
4329 print '</td></tr>';
4330
4331 // LICENSE
4332 print '<tr><td class="tdtop">';
4333 $htmlhelp = $langs->trans("EnterHereLicenseInformation");
4334 print $form->textwithpicto($langs->trans("File").' LICENSE', $htmlhelp, 1, 'help', '', 0, 2, 'licensetooltip');
4335 print '</td><td>';
4336
4337 $poscursor = array('x' => GETPOST('WEBSITE_LICENSE_x'), 'y' => GETPOST('WEBSITE_LICENSE_y'));
4338 $doleditor = new DolEditor('WEBSITE_LICENSE', $licensecontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4339 print $doleditor->Create(1, '', true, $langs->trans("File").' LICENSE', 'text');
4340
4341 print '</td></tr>';
4342
4343 // RSS
4344 print '<tr><td class="tdtop">';
4345 $htmlhelp = $langs->trans('RSSFeedDesc');
4346 print $form->textwithpicto($langs->trans('RSSFeed'), $htmlhelp, 1, 'help', '', 0, 2, '');
4347 print '</td><td>';
4348 print '/wrapper.php?rss=1[&l=XX][&limit=99][&cachedelay=99]';
4349 print '</td></tr>';
4350
4351 print '</table>';
4352
4353 print dol_get_fiche_end();
4354
4355 print '</div>';
4356
4357 print '<br>';
4358}
4359
4360if ($action == 'editsecurity') {
4361 $selectarrayCSPDirectives = websiteGetContentPolicyDirectives();
4362 $selectarrayCSPSources = websiteGetContentPolicySources();
4363 $forceCSPArr = websiteGetContentPolicyToArray($forceCSP);
4364 print '<div class="fiche">';
4365 print '<br>';
4366
4367 $head = websiteconfigPrepareHead($object);
4368 print dol_get_fiche_head($head, 'security', $langs->trans("General"), -1, 'website');
4369
4370 print '<span class="opacitymedium">'.$langs->trans("HTTPHeaderEditor").'. '.$langs->trans("ReservedToAdvancedUsers").'.</span><br><br>';
4371
4372 print '<div class="div-table-responsive-no-min">';
4373 print '<table class="noborder centpercent">';
4374 print '<tr class="liste_titre">';
4375 print '<td>'.$langs->trans("HTTPHeader").'</td>';
4376 print '<td></td>'."\n";
4377 print '</tr>';
4378
4379 // Force RP
4380 print '<tr class="oddeven">';
4381 print '<td>'.$form->textwithpicto($langs->trans('WebsiteSecurityForceRP'), 'HTTP Header Referer-Policy<br><br>'.$langs->trans("Recommended").':<br>strict-origin-when-cross-origin <span class="opacitymedium">'.$langs->trans("or").'</span> same-origin"=more secured', 1, 'help', 'valignmiddle', 0, 3, 'WEBSITE_'.$object->id.'_SECURITY_FORCERP').'</td>';
4382 print '<td><input class="minwidth500" name="WEBSITE_'.$object->id.'_SECURITY_FORCERP" id="WEBSITE_'.$object->id.'_SECURITY_FORCERP" value="'.getDolGlobalString("WEBSITE_".$object->id."_SECURITY_FORCERP").'"></td>';
4383 print '</tr>';
4384 // Force STS
4385 print '<tr class="oddeven">';
4386 print '<td>'.$form->textwithpicto($langs->trans('WebsiteSecurityForceSTS'), 'HTTP Header Strict-Transport-Security<br><br>'.$langs->trans("Example").':<br>max-age=31536000; includeSubDomains', 1, 'help', 'valignmiddle', 0, 3, 'WEBSITE_'.$object->id.'_SECURITY_FORCESTS').'</td>';
4387 print '<td><input class="minwidth500" name="WEBSITE_'.$object->id.'_SECURITY_FORCESTS" id="WEBSITE_'.$object->id.'_SECURITY_FORCESTS" value="'.getDolGlobalString("WEBSITE_".$object->id."_SECURITY_FORCESTS").'"></td>';
4388 print '</tr>';
4389 // Force PP
4390 print '<tr class="oddeven">';
4391 print '<td>'.$form->textwithpicto($langs->trans('WebsiteSecurityForcePP'), 'HTTP Header Permissions-Policy<br><br>'.$langs->trans("Example").':<br>camera=*, microphone=(), geolocation=*', 1, 'help', 'valignmiddle', 0, 3, 'WEBSITE_'.$object->id.'_SECURITY_FORCEPP').'</td>';
4392 print '<td><input class="minwidth500" name="WEBSITE_'.$object->id.'_SECURITY_FORCEPP" id="WEBSITE_'.$object->id.'_SECURITY_FORCEPP" value="'.getDolGlobalString("WEBSITE_".$object->id."_SECURITY_FORCEPP").'"></td>';
4393 print '</tr>';
4394
4395 $examplecsprule = "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;";
4396
4397 // Force CSP - Content Security Policy
4398 print '<tr class="oddeven nohover">';
4399 print '<td class="tdtop">'.$form->textwithpicto($langs->trans('ContentSecurityPolicy'), 'HTTP Header Content-Security-Policy<br><br>'.$langs->trans("Example").":<br>".$examplecsprule, 1, 'help', 'valignmiddle', 0, 3, 'WEBSITE_'.$object->id.'_SECURITY_FORCECSP').'</td>';
4400 print '<td>';
4401
4402 print '<div class="div-table-responsive-no-min">';
4403
4404 print '<input class="minwidth500 quatrevingtpercent" name="WEBSITE_'.$object->id.'_SECURITY_FORCECSP" id="WEBSITE_'.$object->id.'_SECURITY_FORCECSP" value="'.$forceCSP.'"> <a href="#" id="btnaddcontentsecuritypolicy">'.img_picto('', 'add').'</a><br>';
4405
4406 print '<br class="selectaddcontentsecuritypolicy hidden">';
4407
4408 print '<div id="selectaddcontentsecuritypolicy" class="hidden selectaddcontentsecuritypolicy">';
4409 print $form->selectarray("select_identifier_WEBSITE_SECURITY_FORCECSP", $selectarrayCSPDirectives, "select_identifier_WEBSITE_SECURITY_FORCECSP", $langs->trans("FillCSPDirective"), 0, 0, '', 0, 0, 0, '', 'minwidth200 maxwidth350 inline-block');
4410 print ' ';
4411 print '<input type="hidden" id="select_source_WEBSITE_SECURITY_FORCECSP" name="select_source_WEBSITE_SECURITY_FORCECSP">';
4412 foreach ($selectarrayCSPSources as $key => $values) {
4413 print '<div class="div_WEBSITE_SECURITY_FORCECSP hidden inline-block maxwidth350" id="div_'.$key.'_WEBSITE_SECURITY_FORCECSP">';
4414 print $form->selectarray("select_".$key."_WEBSITE_SECURITY_FORCECSP", $values, "select_".$key."_WEBSITE_SECURITY_FORCECSP", $langs->trans("FillCSPSource"), 0, 0, '', 0, 0, 0, '', 'minwidth200 maxwidth300 inline-block select_WEBSITE_SECURITY_FORCECSP');
4415 print '</div>';
4416 }
4417 print ' ';
4418 print '<div class="div_input_data_WEBSITE_SECURITY_FORCECSP hidden inline-block maxwidth200"><input id="input_data_WEBSITE_SECURITY_FORCECSP" name="input_data_WEBSITE_SECURITY_FORCECSP"></div>';
4419 print ' ';
4420 print '<div class="div_btn_class_WEBSITE_SECURITY_FORCECSP inline-block maxwidth200"><input type="submit" id="btn_WEBSITE_SECURITY_FORCECSP" name="btn_WEBSITE_SECURITY_FORCECSP" class="butAction small smallpaddingimp" value="'.$langs->trans("Add").'" disabled></div>';
4421 print '<br><br>';
4422 print '</div>';
4423
4424 if (!empty($forceCSP)) {
4425 // Content Security Policy list of selected rules
4426 print '<br>';
4427 print '<div class="div-table-responsive-no-min">';
4428 print img_picto('', 'graph', 'class="pictofixedwidth"').$langs->trans("HierarchicView").'<br>';
4429 print '<ul>';
4430 foreach ($forceCSPArr as $directive => $sources) {
4431 print '<li>';
4432 if (in_array($directive, array_keys($selectarrayCSPDirectives))) {
4433 print '<span>'.$directive.'</span>';
4434 } else {
4435 print $form->textwithpicto($directive, $langs->trans("UnknowContentSecurityPolicyDirective"), 1, 'warning');
4436 }
4437 if (!empty($sources)) {
4438 print '<ul>';
4439 foreach ($sources as $key => $source) {
4440 print '<li><span>'.$source.'</span>&nbsp;<a href="'.$_SERVER["PHP_SELF"].'?websiteid='.$websiteid.'&action=removecspsource&sourcecsp='.$directive.'_'.$key.'&token='.newToken().'">'.img_delete().'</a></li>';
4441 }
4442 print '</ul>';
4443 } else {
4444 print '&nbsp;<a href="'.$_SERVER["PHP_SELF"].'?websiteid='.$websiteid.'&action=removecspsource&sourcecsp='.$directive.'&token='.newToken().'">'.img_delete().'</a>';
4445 }
4446 print '</li>';
4447 }
4448 print '</ul>';
4449 print '</div>';
4450 }
4451 print '</div>';
4452
4453 print '</td>';
4454 print '</tr>';
4455
4456 // Force CSPRO
4457 if (getDolGlobalString("WEBSITE_".$object->id."_SECURITY_FORCECSPRO")) {
4458 print '<tr class="oddeven">';
4459 print '<td>'.$form->textwithpicto($langs->trans('WebsiteSecurityForceCSPRO'), 'HTTP Header Content-Security-Policy-Report-Only<br><br>'.$langs->trans("Example").":<br>".$examplecsprule, 1, 'help', 'valignmiddle', 0, 3, 'WEBSITE_'.$object->id.'_SECURITY_FORCECSPRO').'</td>';
4460 print '<td><input class="minwidth500" name="WEBSITE_'.$object->id.'_SECURITY_FORCECSPRO" id="WEBSITE_'.$object->id.'_SECURITY_FORCECSPRO" value="'.getDolGlobalString("WEBSITE_".$object->id."_SECURITY_FORCECSPRO").'"></td>';
4461 print '</tr>';
4462 }
4463
4464 print '</table>';
4465 print '</div>';
4466
4467
4468 print '<div class="center">';
4469
4470 print '<input type="submit" class="button small" name="updateandstay" value="'.$langs->trans("Save").'">';
4471 print '<input class="button button-cancel small" type="submit" name="preview" value="'.$langs->trans("Cancel").'">';
4472
4473 print '</div>';
4474
4475
4476 print '<script>
4477 $(document).ready(function() {
4478 $("#btnaddcontentsecuritypolicy").on("click", function(){
4479 if($("#selectaddcontentsecuritypolicy").is(":visible")){
4480 console.log("We hide select to add Content Security Policy");
4481 $(".selectaddcontentsecuritypolicy").hide();
4482 } else {
4483 console.log("We show select to add Content Security Policy");
4484 $(".selectaddcontentsecuritypolicy").show();
4485 }
4486 });
4487
4488 $("#select_identifier_WEBSITE_SECURITY_FORCECSP").on("change", function() {
4489 key = $(this).find(":selected").data("directivetype");
4490 console.log("We hide all select div");
4491 $(".div_WEBSITE_SECURITY_FORCECSP").hide();
4492 $(".select_WEBSITE_SECURITY_FORCECSP").val(null).trigger("change");
4493 $(".div_input_data_WEBSITE_SECURITY_FORCECSP").hide();
4494 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",true);
4495 if (key == "none"){
4496 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",false);
4497 } else {
4498 console.log("We show div select with key "+key);
4499 $("#div_"+key+"_WEBSITE_SECURITY_FORCECSP").css("display", "inline-block");
4500 }
4501 });
4502
4503 $(".select_WEBSITE_SECURITY_FORCECSP").on("change", function() {
4504 keysource = $(this).find(":selected").data("sourcetype");
4505 $("#select_source_WEBSITE_SECURITY_FORCECSP").val($(this).val());
4506 console.log("We hide and show fields");
4507 if (keysource == "data" || keysource == "input") {
4508 $(".div_input_data_WEBSITE_SECURITY_FORCECSP").css("display", "inline-block");
4509 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",true);
4510 } else {
4511 $("#input_data_WEBSITE_SECURITY_FORCECSP").val("");
4512 $(".div_input_data_WEBSITE_SECURITY_FORCECSP").hide();
4513 if (keysource != undefined) {
4514 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",false);
4515 } else {
4516 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",true);
4517 }
4518 }
4519 });
4520
4521 $("#input_data_WEBSITE_SECURITY_FORCECSP").on("change keyup", function(){
4522 if ($(this).val() != "") {
4523 console.log("We show add button");
4524 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",false);
4525 } else {
4526 console.log("We hide add button");
4527 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",true);
4528 }
4529 });
4530 });
4531 </script>';
4532
4533 print dol_get_fiche_end();
4534 print '</div>';
4535}
4536
4537
4538if ($action == 'createsite') {
4539 print '<div class="fiche">';
4540
4541 print '<br>';
4542
4543 /*$h = 0;
4544 $head = array();
4545
4546 $head[$h][0] = dol_buildpath('/website/index.php',1).'?id='.$object->id;
4547 $head[$h][1] = $langs->trans("AddWebsite");
4548 $head[$h][2] = 'card';
4549 $h++;
4550
4551 print dol_get_fiche_head($head, 'card', '', -1, 'website');
4552 */
4553 if ($action == 'createcontainer') {
4554 print load_fiche_titre($langs->trans("AddWebsite"));
4555 }
4556
4557 print '<!-- Add site -->'."\n";
4558 print '<div class="tabBar tabBarWithBottom">';
4559
4560 print '<table class="border centpercent">';
4561
4562 $siteref = $sitedesc = $sitelang = $siteotherlang = '';
4563 if (GETPOST('WEBSITE_REF')) {
4564 $siteref = GETPOST('WEBSITE_REF', 'aZ09');
4565 }
4566 if (GETPOST('WEBSITE_DESCRIPTION')) {
4567 $sitedesc = GETPOST('WEBSITE_DESCRIPTION', 'alpha');
4568 }
4569 if (GETPOST('WEBSITE_LANG')) {
4570 $sitelang = GETPOST('WEBSITE_LANG', 'aZ09');
4571 }
4572 if (GETPOST('WEBSITE_OTHERLANG')) {
4573 $siteotherlang = GETPOST('WEBSITE_OTHERLANG', 'aZ09comma');
4574 }
4575
4576 print '<tr><td class="titlefieldcreate fieldrequired">';
4577 print $form->textwithpicto($langs->trans('WebsiteName'), $langs->trans("Example").': MyPortal, www.mywebsite.com, ...');
4578 print '</td><td>';
4579 print '<input type="text" class="flat maxwidth300" name="WEBSITE_REF" value="'.dol_escape_htmltag($siteref).'" autofocus>';
4580 print '</td></tr>';
4581
4582 print '<tr><td class="fieldrequired">';
4583 print $langs->trans('MainLanguage');
4584 print '</td><td>';
4585 $shortlangcode = preg_replace('/[_-].*$/', '', trim($langs->defaultlang));
4586 print img_picto('', 'language', 'class="pictofixedwidth"');
4587 print $formadmin->select_language((GETPOSTISSET('WEBSITE_LANG') ? GETPOST('WEBSITE_LANG', 'aZ09comma') : $shortlangcode), 'WEBSITE_LANG', 0, array(), 1, 0, 0, 'minwidth300', 2, 0, 0, array(), 1);
4588 print '</td></tr>';
4589
4590 print '<tr><td>';
4591 $htmltext = $langs->trans("Example").': fr,de,sv,it,pt';
4592 print $form->textwithpicto($langs->trans('OtherLanguages'), $htmltext, 1, 'help', '', 0, 2);
4593 print '</td><td>';
4594 print img_picto('', 'language', 'class="pictofixedwidth"');
4595 print '<input type="text" class="flat minwidth300" name="WEBSITE_OTHERLANG" value="'.dol_escape_htmltag($siteotherlang).'">';
4596 print '</td></tr>';
4597
4598 print '<tr><td>';
4599 print $langs->trans('Description');
4600 print '</td><td>';
4601 print '<input type="text" class="flat minwidth500" name="WEBSITE_DESCRIPTION" value="'.dol_escape_htmltag($sitedesc).'">';
4602 print '</td></tr>';
4603
4604 print '<tr><td>';
4605
4606 $htmltext = $langs->trans("VirtualhostDesc");
4607 /*$htmltext = str_replace('{s1}', DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/<i>websiteref</i>', $htmltext);
4608 $htmltext .= '<br>';
4609 $htmltext .= '<br>'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("ReadPerm"), DOL_DOCUMENT_ROOT);
4610 $htmltext .= '<br>'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("WritePerm"), '{s1}');
4611 $htmltext = str_replace('{s1}', DOL_DATA_ROOT.'/website<br>'.DOL_DATA_ROOT.'/medias', $htmltext);*/
4612
4613
4614 print $form->textwithpicto($langs->trans('Virtualhost'), $htmltext, 1, 'help', '', 0, 2, '');
4615 print '</td><td>';
4616 print '<input type="text" class="flat minwidth300" name="virtualhost" value="'.dol_escape_htmltag(GETPOST('virtualhost', 'alpha')).'">';
4617 print '</td></tr>';
4618
4619 print '</table>';
4620 print '</div>';
4621
4622 if ($action == 'createsite') {
4623 print '<div class="center">';
4624
4625 print '<input type="submit" class="button small" name="addcontainer" value="'.$langs->trans("Create").'">';
4626 print '<input class="button button-cancel small" type="submit" name="preview" value="'.$langs->trans("Cancel").'">';
4627
4628 print '</div>';
4629 }
4630
4631
4632 //print '</div>';
4633
4634 //print dol_get_fiche_end();
4635
4636 print '</div>';
4637
4638 print '<br>';
4639}
4640
4641// Page view to import a website template
4642if ($action == 'importsite') {
4643 print '<!-- action=importsite -->';
4644 print '<div class="fiche">';
4645
4646 print '<br>';
4647
4648 print load_fiche_titre($langs->trans("ImportSite"));
4649
4650 print dol_get_fiche_head(array(), '0', '', -1);
4651
4652 print '<span class="opacitymedium">'.$langs->trans("ZipOfWebsitePackageToImport").'</span><br><br>';
4653
4654
4655 $dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT);
4656 $allowimportsite = true;
4657 if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) {
4658 $allowimportsite = false;
4659 }
4660
4661 if ($allowimportsite) {
4662 $maxfilesizearray = getMaxFileSizeArray();
4663 $maxmin = $maxfilesizearray['maxmin'];
4664 if ($maxmin > 0) {
4665 print '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
4666 }
4667 print '<input class="flat minwidth400" type="file" name="userfile[]" accept=".zip">';
4668 print '<input type="submit" class="button small" name="buttonsubmitimportfile" value="'.dol_escape_htmltag($langs->trans("Upload")).'">';
4669 print '<input type="submit" class="button button-cancel small" name="preview" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
4670 print '<br><br><br>';
4671 } else {
4672 if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) {
4673 // Show clean corporate message
4674 $message = $langs->trans('InstallModuleFromWebHasBeenDisabledContactUs');
4675 } else {
4676 // Show technical generic message
4677 $message = $langs->trans("InstallModuleFromWebHasBeenDisabledByFile", $dolibarrdataroot.'/installmodules.lock');
4678 }
4679 print info_admin($message).'<br><br>';
4680 }
4681
4682
4683 print '<span class="opacitymedium">'.$langs->trans("ZipOfWebsitePackageToLoad").'</span><br><br>';
4684
4685 // This will scan the dir /doctemplates/websites and show all templates.
4686 showWebsiteTemplates($website, GETPOSTINT('importsite') == 2 ? 1 : 0);
4687
4688 print dol_get_fiche_end();
4689
4690 print '</div>';
4691
4692 print '<br>';
4693}
4694
4695if ($action == 'editmeta' || $action == 'createcontainer') { // Edit properties of a web site OR properties of a web page
4696 print '<div class="fiche">';
4697
4698 print '<br>';
4699
4700 /*$h = 0;
4701 $head = array();
4702
4703 $head[$h][0] = dol_buildpath('/website/index.php',1).'?id='.$object->id;
4704 $head[$h][1] = $langs->trans("AddPage");
4705 $head[$h][2] = 'card';
4706 $h++;
4707
4708 print dol_get_fiche_head($head, 'card', '', -1, 'website');
4709 */
4710 if ($action == 'createcontainer') {
4711 print load_fiche_titre($langs->trans("AddPage"));
4712 }
4713
4714 print '<!-- Edit or create page/container -->'."\n";
4715 //print '<div class="fichecenter">';
4716
4717 $hiddenfromfetchingafterload = ' hideobject';
4718 $hiddenmanuallyafterload = ' hideobject';
4719 if (GETPOST('radiocreatefrom') == 'checkboxcreatefromfetching') {
4720 $hiddenfromfetchingafterload = '';
4721 }
4722 if (GETPOST('radiocreatefrom') == 'checkboxcreatemanually') {
4723 $hiddenmanuallyafterload = '';
4724 }
4725
4726 if ($action == 'editmeta' || empty($conf->use_javascript_ajax)) { // No autohide/show in such case
4727 $hiddenfromfetchingafterload = '';
4728 $hiddenmanuallyafterload = '';
4729 }
4730
4731 if ($action == 'createcontainer') {
4732 print '<br>';
4733
4734 if (!empty($conf->use_javascript_ajax)) {
4735 print '<input type="radio" name="radiocreatefrom" id="checkboxcreatemanually" value="checkboxcreatemanually"'.(GETPOST('radiocreatefrom') == 'checkboxcreatemanually' ? ' checked' : '').'> ';
4736 }
4737 print '<label for="checkboxcreatemanually"><span class="opacitymediumxx">'.$langs->trans("OrEnterPageInfoManually").'</span></label><br>';
4738 print '<hr class="tablecheckboxcreatemanually'.$hiddenmanuallyafterload.'">';
4739 }
4740
4741
4742
4743 print '<table class="border tableforfield nobackground centpercent tablecheckboxcreatemanually'.$hiddenmanuallyafterload.'">';
4744
4745 if ($action != 'createcontainer') {
4746 print '<tr><td class="titlefield fieldrequired">';
4747 print $langs->trans('IDOfPage').' - '.$langs->trans('InternalURLOfPage');
4748 print '</td><td>';
4749 print $pageid;
4750 //print '</td></tr>';
4751
4752 //print '<tr><td class="titlefield fieldrequired">';
4753 //print $langs->trans('InternalURLOfPage');
4754 //print '</td><td>';
4755 print ' &nbsp; - &nbsp; ';
4756 print '/public/website/index.php?website='.urlencode($websitekey).'&pageid='.urlencode((string) $pageid);
4757 //if ($objectpage->grabbed_from) print ' - <span class="opacitymedium">'.$langs->trans('InitiallyGrabbedFrom').' '.$objectpage->grabbed_from.'</span>';
4758 print '</td></tr>';
4759
4760 $type_container = $objectpage->type_container;
4761 $pageurl = $objectpage->pageurl;
4762 $pagealiasalt = $objectpage->aliasalt;
4763 $pagetitle = $objectpage->title;
4764 $pagedescription = $objectpage->description;
4765 $pageimage = $objectpage->image;
4766 $pagekeywords = $objectpage->keywords;
4767 $pagelang = $objectpage->lang;
4768 $pageallowedinframes = $objectpage->allowed_in_frames;
4769 $pagehtmlheader = $objectpage->htmlheader;
4770 $pagedatecreation = (string) $objectpage->date_creation;
4771 $pagedatemodification = $objectpage->date_modification;
4772 $pageauthorid = $objectpage->fk_user_creat;
4773 $pageusermodifid = $objectpage->fk_user_modif;
4774 $pageauthoralias = $objectpage->author_alias;
4775 $pagestatus = $objectpage->status;
4776 } else { // $action = 'createcontainer'
4777 $type_container = 'page';
4778 $pageurl = '';
4779 $pagealiasalt = '';
4780 $pagetitle = '';
4781 $pagedescription = '';
4782 $pageimage = '';
4783 $pagekeywords = '';
4784 $pagelang = '';
4785 $pageallowedinframes = 0;
4786 $pagehtmlheader = '';
4787 $pagedatecreation = dol_now();
4788 $pagedatemodification = '';
4789 $pageauthorid = $user->id;
4790 $pageusermodifid = 0;
4791 $pageauthoralias = '';
4792 $pagestatus = 1;
4793 }
4794 if (GETPOST('WEBSITE_TITLE', 'alpha')) {
4795 $pagetitle = str_replace(array('<', '>'), '', GETPOST('WEBSITE_TITLE', 'alphanohtml'));
4796 }
4797 if (GETPOST('WEBSITE_PAGENAME', 'alpha')) {
4798 $pageurl = GETPOST('WEBSITE_PAGENAME', 'alpha');
4799 }
4800 if (GETPOST('WEBSITE_ALIASALT', 'alpha')) {
4801 $pagealiasalt = str_replace(array('<', '>'), '', GETPOST('WEBSITE_ALIASALT', 'alphanohtml'));
4802 }
4803 if (GETPOST('WEBSITE_DESCRIPTION', 'alpha')) {
4804 $pagedescription = str_replace(array('<', '>'), '', GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml'));
4805 }
4806 if (GETPOST('WEBSITE_IMAGE', 'alpha')) {
4807 $pageimage = GETPOST('WEBSITE_IMAGE', 'alpha');
4808 }
4809 if (GETPOST('WEBSITE_KEYWORDS', 'alpha')) {
4810 $pagekeywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml'));
4811 }
4812 if (GETPOST('WEBSITE_LANG', 'aZ09')) {
4813 $pagelang = GETPOST('WEBSITE_LANG', 'aZ09');
4814 }
4815 if (GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09')) {
4816 $pageallowedinframes = 1;
4817 }
4818 if (GETPOST('htmlheader', 'restricthtmlallowlinkscript')) { // Must accept tags like '<script>' and '<link>'
4819 $pagehtmlheader = GETPOST('htmlheader', 'none');
4820 }
4821
4822 if ($action != 'createcontainer') {
4823 if (empty($conf->use_javascript_ajax)) {
4824 print '<!-- Status of web site page -->'."\n";
4825 print '<tr><td class="fieldrequired">';
4826 print $langs->trans('Status');
4827 print '</td><td>';
4828 print $form->selectyesno('status', $objectpage->status);
4829 print '</td></tr>';
4830 }
4831 }
4832
4833 // Type of container
4834 print '<tr><td class="titlefield fieldrequired">';
4835 print $langs->trans('WEBSITE_TYPE_CONTAINER');
4836 print '</td><td>';
4837 print img_picto('', 'object_technic', 'class="paddingrightonly"').' ';
4838 print $formwebsite->selectTypeOfContainer('WEBSITE_TYPE_CONTAINER', (GETPOST('WEBSITE_TYPE_CONTAINER', 'alpha') ? GETPOST('WEBSITE_TYPE_CONTAINER', 'alpha') : $type_container), 0, '', 1, 'minwidth300');
4839 print '</td></tr>';
4840
4841 print '<script type="text/javascript">
4842 jQuery(document).ready(function() {
4843 jQuery("#selectWEBSITE_TYPE_CONTAINER").change(function() {
4844 console.log("We change type of page : "+jQuery("#selectWEBSITE_TYPE_CONTAINER").val());
4845 if (jQuery("#selectWEBSITE_TYPE_CONTAINER").val() == \'blogpost\') {
4846 jQuery(".trpublicauthor").show();
4847 } else {
4848 jQuery(".trpublicauthor").hide();
4849 }
4850 if (jQuery("#selectWEBSITE_TYPE_CONTAINER").val() == \'service\' || jQuery("#selectWEBSITE_TYPE_CONTAINER").val() == \'library\') {
4851 $(".spanprefix").html("_" + $("#selectWEBSITE_TYPE_CONTAINER").val() + "_");
4852 jQuery(".spanprefix").show();
4853 } else {
4854 jQuery(".spanprefix").hide();
4855 }
4856 });
4857
4858 // Force at init execution a first time of the handler change
4859 jQuery("#selectWEBSITE_TYPE_CONTAINER").trigger(\'change\');
4860 });
4861 </script>
4862 ';
4863
4864 // Title
4865 print '<tr><td class="fieldrequired">';
4866 print $langs->trans('WEBSITE_TITLE');
4867 print '</td><td>';
4868 print '<input type="text" class="flat quatrevingtpercent" name="WEBSITE_TITLE" id="WEBSITE_TITLE" value="'.dol_escape_htmltag($pagetitle).'" autofocus>';
4869 print '</td></tr>';
4870
4871 // Alias page
4872 print '<tr><td class="titlefieldcreate fieldrequired">';
4873 print $langs->trans('WEBSITE_PAGENAME');
4874 print '</td><td>';
4875 print '<span class="opacitymedium spanprefix hidden"></span> ';
4876 print '<input type="text" class="flat minwidth300" name="WEBSITE_PAGENAME" id="WEBSITE_PAGENAME" value="'.dol_escape_htmltag((string) preg_replace('/^_[a-z]+_/', '', (string) $pageurl)).'">';
4877 print '</td></tr>';
4878
4879 print '<script type="text/javascript">
4880 $(document).ready(function() {
4881 console.log("Manage prefix for service or library");
4882 if ($("#selectWEBSITE_TYPE_CONTAINER").val() == "service" || $("#selectWEBSITE_TYPE_CONTAINER").val() == "library") {
4883 $(".spanprefix").html("_" + $("#selectWEBSITE_TYPE_CONTAINER").val() + "_");
4884 $(".spanprefix").show();
4885 }
4886 $(".websiteformtoolbar").on("submit", function(event) {
4887 if ($("#selectWEBSITE_TYPE_CONTAINER").val() == "service" || $("#selectWEBSITE_TYPE_CONTAINER").val() == "library") {
4888 var prefix = "_" + $("#selectWEBSITE_TYPE_CONTAINER").val() + "_";
4889 var userInput = $("#WEBSITE_PAGENAME").val();
4890 var $inputField = $("#WEBSITE_PAGENAME");
4891 if (userInput.indexOf(prefix) !== 0) {
4892 $inputField.val(prefix + userInput);
4893 }
4894 }
4895 });
4896 });
4897 </script>
4898 ';
4899
4900 print '<tr><td class="titlefieldcreate">';
4901 $htmlhelp = $langs->trans("WEBSITE_ALIASALTDesc");
4902 print $form->textwithpicto($langs->trans('WEBSITE_ALIASALT'), $htmlhelp, 1, 'help', '', 0, 2, 'aliastooltip');
4903 print '</td><td>';
4904 print '<input type="text" class="flat minwidth500" name="WEBSITE_ALIASALT" value="'.dol_escape_htmltag($pagealiasalt).'">';
4905 print '</td></tr>';
4906
4907 print '<tr><td>';
4908 print $langs->trans('WEBSITE_DESCRIPTION');
4909 print '</td><td>';
4910 print '<input type="text" class="flat quatrevingtpercent" name="WEBSITE_DESCRIPTION" value="'.dol_escape_htmltag($pagedescription).'">';
4911 print '</td></tr>';
4912
4913 // Deprecated. Image for RSS or Thumbs are now taken from the content.
4914 if (getDolGlobalInt('WEBSITE_MANAGE_IMAGE_FOR_PAGES')) {
4915 print '<tr class="trimageforpage hidden"><td>';
4916 $htmlhelp = $langs->trans("WEBSITE_IMAGEDesc");
4917 print $form->textwithpicto($langs->trans('WEBSITE_IMAGE'), $htmlhelp, 1, 'help', '', 0, 2, 'imagetooltip');
4918 print '</td><td>';
4919 print '<input type="text" class="flat quatrevingtpercent" name="WEBSITE_IMAGE" value="'.dol_escape_htmltag($pageimage).'">';
4920 print '</td></tr>';
4921
4922 print '<script type="text/javascript">
4923 jQuery(document).ready(function() {
4924 jQuery("#selectWEBSITE_TYPE_CONTAINER").change(function() {
4925 console.log("We change type of page : "+jQuery("#selectWEBSITE_TYPE_CONTAINER").val());
4926 if (jQuery("#selectWEBSITE_TYPE_CONTAINER").val() == \'blogpost\') {
4927 jQuery(".trimageforpage").show();
4928 } else {
4929 jQuery(".trimageforpage").hide();
4930 }
4931 });
4932 });
4933 </script>
4934 ';
4935 }
4936
4937 // Keywords
4938 print '<tr><td>';
4939 $htmlhelp = $langs->trans("WEBSITE_KEYWORDSDesc");
4940 print $form->textwithpicto($langs->trans('WEBSITE_KEYWORDS'), $htmlhelp, 1, 'help', '', 0, 2, 'keywordtooltip');
4941 print '</td><td>';
4942 print '<input type="text" class="flat quatrevingtpercent" name="WEBSITE_KEYWORDS" value="'.dol_escape_htmltag($pagekeywords).'">';
4943 print '</td></tr>';
4944
4945 print '<tr><td>';
4946 print $langs->trans('Language');
4947 print '</td><td>';
4948 $onlykeys = array();
4949 if ($object->lang) {
4950 $onlykeys[$object->lang] = $object->lang;
4951 } else {
4952 $onlykeys[$langs->defaultlang] = $langs->defaultlang;
4953 }
4954 if ($object->otherlang) {
4955 $tmparray = explode(',', $object->otherlang);
4956 foreach ($tmparray as $key) {
4957 $tmpkey = trim($key);
4958 if (strlen($key) == 2) {
4959 $tmpkey = strtolower($key);
4960 }
4961 $onlykeys[$tmpkey] = $tmpkey;
4962 }
4963 }
4964 if (empty($object->lang) && empty($object->otherlang)) {
4965 $onlykeys = array(); // We keep full list of languages
4966 }
4967 print img_picto('', 'language', 'class="pictofixedwidth"').$formadmin->select_language($pagelang ? $pagelang : '', 'WEBSITE_LANG', 0, array(), '1', 0, 0, 'minwidth200', 0, 0, 0, $onlykeys, 1);
4968 $htmltext = $langs->trans("AvailableLanguagesAreDefinedIntoWebsiteProperties");
4969 print $form->textwithpicto('', $htmltext);
4970 print '</td></tr>';
4971
4972 // Translation of
4973 $translationof = 0;
4974 $translatedby = 0;
4975 print '<!-- Translation of --><tr><td>';
4976 print $langs->trans('TranslationLinks');
4977 print '</td><td>';
4978 if ($action != 'createcontainer') {
4979 // Has translation pages
4980 $sql = "SELECT rowid, lang from ".MAIN_DB_PREFIX."website_page where fk_page = ".((int) $objectpage->id);
4981 $resql = $db->query($sql);
4982 if ($resql) {
4983 $num_rows = $db->num_rows($resql);
4984 if ($num_rows > 0) {
4985 print '<span class="opacitymedium">'.$langs->trans('ThisPageHasTranslationPages').':</span>';
4986 $i = 0;
4987 $tmppage = new WebsitePage($db);
4988 $tmpstring = '';
4989 while ($obj = $db->fetch_object($resql)) {
4990 $result = $tmppage->fetch($obj->rowid);
4991 if ($result > 0) {
4992 if ($i > 0) {
4993 $tmpstring .= '<br>';
4994 }
4995 $tmpstring .= $tmppage->getNomUrl(1).' '.picto_from_langcode($tmppage->lang).' '.$tmppage->lang;
4996 // Button unlink
4997 $tmpstring .= ' <a class="paddingleft" href="'.$_SERVER["PHP_SELF"].'?website='.urlencode($object->ref).'&pageid='.((int) $objectpage->id).'&action=deletelang&token='.newToken().'&deletelangforid='.((int) $tmppage->id).'">'.img_picto($langs->trans("Remove"), 'unlink').'</a>';
4998 $translatedby++;
4999 $i++;
5000 }
5001 }
5002 if ($i > 1) {
5003 print '<br>';
5004 } else {
5005 print ' ';
5006 }
5007 print $tmpstring;
5008 }
5009 } else {
5011 }
5012 }
5013 if ((empty($translatedby) || ($objectpage->lang != $object->lang)) && ($action == 'editmeta' || $action == 'createcontainer' || $objectpage->fk_page > 0)) {
5014 $sourcepage = new WebsitePage($db);
5015 $result = 1;
5016 if ($objectpage->fk_page > 0) {
5017 $result = $sourcepage->fetch($objectpage->fk_page);
5018 if ($result == 0) {
5019 // not found, we can reset value to clean database
5020 // TODO
5021 }
5022 }
5023 if ($result >= 0) {
5024 if ($translatedby) {
5025 print '<br>';
5026 }
5027 $translationof = $objectpage->fk_page;
5028 print '<span class="opacitymedium">'.$langs->trans('ThisPageIsTranslationOf').'</span> ';
5029 print $sourcepage->getNomUrl(2).' '.$formwebsite->selectContainer($website, 'pageidfortranslation', ($translationof ? $translationof : -1), 1, $action, 'minwidth300', array($objectpage->id));
5030 if ($translationof > 0 && $sourcepage->lang) {
5031 print picto_from_langcode($sourcepage->lang).' '.$sourcepage->lang;
5032 // Button unlink
5033 print ' <a class="paddingleft" href="'.$_SERVER["PHP_SELF"].'?website='.urlencode($object->ref).'&pageid='.((int) $objectpage->id).'&action=deletelang&token='.newToken().'&deletelangforid='.((int) $objectpage->id).'">'.img_picto($langs->trans("Remove"), 'unlink').'</a>';
5034 }
5035 }
5036 }
5037 print '</td></tr>';
5038
5039 // Categories
5040 if (isModEnabled('category') && $user->hasRight('categorie', 'lire')) {
5041 $disabled = '';
5042 $langs->load('categories');
5043
5044 print '<tr><td class="toptd">'.$form->editfieldkey('Categories', 'categories', '', $objectpage, 0).'</td><td>';
5045 print $form->selectCategories(Categorie::TYPE_WEBSITE_PAGE, 'categories', $objectpage);
5046 //print dolButtonToOpenUrlInDialogPopup('categories', $langs->transnoentitiesnoconv("Categories"), img_picto('', 'add'), '/categories/categorie_list.php?leftmenu=website&nosearch=1&type='.urlencode(Categorie::TYPE_WEBSITE_PAGE).'&website='.urlencode($website->ref), $disabled);
5047 print "</td></tr>";
5048 }
5049
5050 if (getDolGlobalString('WEBSITE_PAGE_SHOW_INTERNAL_LINKS_TO_OBJECT')) { // TODO Replace this with link into element_element ?
5051 print '<tr><td class="titlefieldcreate">';
5052 print 'ObjectClass';
5053 print '</td><td>';
5054 print '<input type="text" class="flat minwidth300" name="WEBSITE_OBJECTCLASS" placeholder="ClassName::/path/class/ObjectClass.class.php" >';
5055 print '</td></tr>';
5056
5057 print '<tr><td class="titlefieldcreate">';
5058 print 'ObjectID';
5059 print '</td><td>';
5060 print '<input type="text" class="flat minwidth300" name="WEBSITE_OBJECTID" >';
5061 print '</td></tr>';
5062 }
5063
5064 $fuser = new User($db);
5065
5066 // Date last modification
5067 if ($action != 'createcontainer') {
5068 print '<tr><td>';
5069 print $langs->trans('DateLastModification');
5070 print '</td><td>';
5071 print dol_print_date($pagedatemodification, 'dayhour', 'tzuser');
5072 print '</td></tr>';
5073
5074 print '<tr><td>';
5075 print $langs->trans('UserModification');
5076 print '</td><td>';
5077 if ($pageusermodifid > 0) {
5078 $fuser->fetch($pageusermodifid);
5079 print $fuser->getNomUrl(-1);
5080 } else {
5081 print '<span class="opacitymedium">'.$langs->trans("Unknown").'</span>';
5082 }
5083 print '</td></tr>';
5084 }
5085
5086 // Content - Example/templates of page
5087 $url = 'https://wiki.dolibarr.org/index.php/Module_Website';
5088 $htmltext = '<small>';
5089 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource", $url);
5090 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource1", $url);
5091 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource2", $url);
5092 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource3", $url);
5093 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource4", $url);
5094 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSourceMore", $url);
5095 $htmltext .= '<br>';
5096 $htmltext .= '</small>';
5097
5098 $formmail = new FormMail($db);
5099 $formmail->withaiprompt = 'html';
5100 $formmail->withlayout = 'websitepage';
5101 $showlinktolayout = $formmail->withlayout;
5102 $showlinktoai = ($formmail->withaiprompt && isModEnabled('ai')) ? 'textgenerationwebpage' : '';
5103 if (($action == 'createcontainer' && $showlinktolayout) || ($action == 'createcontainer' && $showlinktoai)) {
5104 print '<tr><td class="titlefield tdtop">';
5105 if ($conf->browser->layout == 'phone') {
5106 print $form->textwithpicto('', $htmltext, 1, 'help', 'inline-block', 1, 2, 'tooltipsubstitution');
5107 } else {
5108 //img_help(($tooltiptrigger != '' ? 2 : 1), $alt)
5109 print $form->textwithpicto($langs->trans("PreviewPageContent").' '.img_help(2, $langs->trans("PreviewPageContent")), $htmltext, 1, 'none', 'inline-block', 1, 2, 'tooltipsubstitution');
5110 }
5111 print '</td><td class="tdtop">';
5112
5113 $out = '';
5114
5115 $showlinktolayoutlabel = $langs->trans("FillPageWithALayout");
5116 $showlinktoailabel = $langs->trans("FillPageWithAIContent");
5117 $htmlname = 'content';
5118 // Fill $out
5119 include DOL_DOCUMENT_ROOT.'/core/tpl/formlayoutai.tpl.php';
5120
5121 print $out;
5122 print '</td></tr>';
5123 }
5124
5125 if ($action == 'createcontainer') {
5126 print '<tr id="pageContent"><td class="tdtop">';
5127 if (!$showlinktolayout || !$showlinktoai) {
5128 if ($conf->browser->layout == 'phone') {
5129 print $form->textwithpicto('', $htmltext, 1, 'help', 'inline-block', 1, 2, 'tooltipsubstitution');
5130 } else {
5131 //img_help(($tooltiptrigger != '' ? 2 : 1), $alt)
5132 print $form->textwithpicto($showlinktolayout ? '' : ($langs->trans("PreviewPageContent").' '.img_help(2, $langs->trans("PreviewPageContent"))), $htmltext, 1, 'none', 'inline-block', 1, 2, 'tooltipsubstitution');
5133 }
5134 }
5135 print '</td><td>';
5136 //$doleditor = new DolEditor('content', GETPOST('content', 'restricthtmlallowunvalid'), '', 200, 'dolibarr_mailings', 'In', true, true, true, 40, '90%');
5137 $doleditor = new DolEditor('content', GETPOST('content', 'none'), '', 200, 'dolibarr_mailings', 'In', true, true, true, 40, '90%');
5138 $doleditor->Create();
5139 print '</div>';
5140 print '</td></tr>';
5141 }
5142
5143 // Date creation
5144 print '<tr><td>';
5145 print $langs->trans('DateCreation');
5146 print '</td><td>';
5147 print $form->selectDate($pagedatecreation, 'datecreation', 1, 1, 0, '', 1, 1);
5148 //print dol_print_date($pagedatecreation, 'dayhour');
5149 print '</td></tr>';
5150
5151 // Author
5152 print '<tr><td>';
5153 print $langs->trans('Author');
5154 print '</td><td>';
5155 if ($pageauthorid > 0) {
5156 $fuser->fetch($pageauthorid);
5157 print $fuser->getNomUrl(-1);
5158 } else {
5159 print '<span class="opacitymedium">'.$langs->trans("Unknown").'</span>';
5160 }
5161 print '</td></tr>';
5162
5163 // Author - public alias
5164 print '<tr class="trpublicauthor hidden"><td>';
5165 print $langs->trans('PublicAuthorAlias');
5166 print '</td><td>';
5167 print '<input type="text" class="flat minwidth300" name="WEBSITE_AUTHORALIAS" value="'.dol_escape_htmltag($pageauthoralias).'" placeholder="'.dol_escape_htmltag($langs->trans("Anonymous")).'">';
5168 print '</td></tr>';
5169
5170 // Web page header
5171 print '<tr><td class="tdhtmlheader tdtop">';
5172 $htmlhelp = $langs->trans("EditTheWebSiteForACommonHeader").'<br><br>';
5173 $htmlhelp .= $langs->trans("Examples").' :<br>';
5174 $htmlhelp .= '<span class="small">';
5175 $htmlhelp .= dol_nl2br(dol_htmlentities($htmlheadercontentdefault)); // do not use dol_htmlentitiesbr here, $htmlheadercontentdefault is HTML with content like <link> and <script> that we want to be html encode as they must be show as doc content not executable instruction.
5176 $htmlhelp .= '</span>';
5177 print $form->textwithpicto($langs->transnoentitiesnoconv('HtmlHeaderPage'), $htmlhelp, 1, 'help', '', 0, 2, 'htmlheadertooltip');
5178 print '</td><td>';
5179 $poscursor = array('x' => GETPOST('htmlheader_x'), 'y' => GETPOST('htmlheader_y'));
5180 $doleditor = new DolEditor('htmlheader', $pagehtmlheader, '', 160, 'ace', 'In', true, false, 'ace', ROWS_4, '100%', 0, $poscursor);
5181 print $doleditor->Create(1, '', true, 'HTML Header', 'html');
5182 print '</td></tr>';
5183
5184 // Allowed in frames
5185 print '<tr><td>';
5186 print $langs->trans('AllowedInFrames');
5187 //$htmlhelp = $langs->trans("AllowedInFramesDesc");
5188 //print $form->textwithpicto($langs->trans('AllowedInFrames'), $htmlhelp, 1, 'help', '', 0, 2, 'allowedinframestooltip');
5189 print '</td><td>';
5190 print '<input type="checkbox" class="flat" name="WEBSITE_ALLOWED_IN_FRAMES" value="1"'.($pageallowedinframes ? 'checked="checked"' : '').'>';
5191 print '</td></tr>';
5192
5193 print '</table>';
5194
5195
5196 if ($action == 'createcontainer') {
5197 $langs->load("website");
5198
5199 print '<div class="center tablecheckboxcreatemanually'.$hiddenmanuallyafterload.'">';
5200
5201 print '<input type="submit" class="button small buttonforacesave" name="addcontainer" value="'.$langs->trans("Create").'">';
5202 print '<input class="button button-cancel small" type="submit" name="preview" value="'.$langs->trans("Cancel").'">';
5203
5204 print '</div>';
5205
5206 print '<br>';
5207
5208 if (!empty($conf->use_javascript_ajax)) {
5209 print '<input type="radio" name="radiocreatefrom" id="checkboxcreatefromfetching" value="checkboxcreatefromfetching"'.(GETPOST('radiocreatefrom') == 'checkboxcreatefromfetching' ? ' checked' : '').'> ';
5210 }
5211 print '<label for="checkboxcreatefromfetching"><span class="opacitymediumxx">'.$langs->trans("CreateByFetchingExternalPage").'</span> <span class="small opacitymedium">('.$langs->trans("ForAdvancedWebmastersOnly").')</small></label><br>';
5212 print '<hr class="tablecheckboxcreatefromfetching'.$hiddenfromfetchingafterload.'">';
5213
5214 print info_admin($langs->trans("OnlyEditionOfSourceForGrabbedContentFuture"), 0, 0, 'warning tablecheckboxcreatefromfetching'.$hiddenfromfetchingafterload);
5215 print '<br>';
5216
5217 print '<table class="tableforfield centpercent tablecheckboxcreatefromfetching'.$hiddenfromfetchingafterload.'">';
5218 print '<tr><td class="titlefield tdtop">';
5219 print $langs->trans("URL");
5220 print '</td><td>';
5221 print '<input class="flat minwidth500 marginbottomonly" type="text" name="externalurl" value="'.dol_escape_htmltag(GETPOST('externalurl', 'alpha')).'" placeholder="https://externalsite/pagetofetch"> ';
5222 print '<br>';
5223 print '<div class="paddingtop">';
5224 print '<input class="flat paddingtop paddingright" type="checkbox" name="grabimages" value="1" checked="checked">';
5225 print '<span class="valignmiddle">'.$langs->trans("GrabImagesInto");
5226 print ' ';
5227 print $langs->trans("ImagesShouldBeSavedInto").' ';
5228 print '</span>';
5229 $arraygrabimagesinto = array('root' => $langs->trans("WebsiteRootOfImages"), 'subpage' => $langs->trans("SubdirOfPage"));
5230 print $form->selectarray('grabimagesinto', $arraygrabimagesinto, GETPOSTISSET('grabimagesinto') ? GETPOST('grabimagesinto') : 'root', 0, 0, 0, '', 0, 0, 0, '', 'minwidth75 valignmiddle', 1);
5231 print '</div>';
5232
5233 print '<input class="button small" style="margin-top: 5px" type="submit" name="fetchexternalurl" value="'.dol_escape_htmltag($langs->trans("FetchAndCreate")).'">';
5234 print '<input class="button button-cancel small" type="submit" name="preview" value="'.$langs->trans("Cancel").'">';
5235
5236 print '</td></tr>';
5237 print '</table>';
5238 }
5239
5240 if ($action == 'createcontainer') {
5241 print '<script type="text/javascript">
5242 jQuery(document).ready(function() {
5243 var disableautofillofalias = 0;
5244 var selectedm = \'\';
5245 var selectedf = \'\';
5246
5247 jQuery("#WEBSITE_TITLE").keyup(function() {
5248 if (disableautofillofalias == 0) {
5249 var valnospecial = jQuery("#WEBSITE_TITLE").val();
5250 valnospecial = valnospecial.replace(/[éèê]/g, \'e\').replace(/[à]/g, \'a\').replace(/[ù]/g, \'u\').replace(/[î]/g, \'i\');
5251 valnospecial = valnospecial.replace(/[ç]/g, \'c\').replace(/[ö]/g, \'o\');
5252 valnospecial = valnospecial.replace(/[^\w]/gi, \'-\').toLowerCase();
5253 valnospecial = valnospecial.replace(/\-+/g, \'-\').replace(/\-$/, \'\');
5254 console.log("disableautofillofalias=0 so we replace WEBSITE_TITLE with "+valnospecial);
5255 jQuery("#WEBSITE_PAGENAME").val(valnospecial);
5256 }
5257 });
5258 jQuery("#WEBSITE_PAGENAME").keyup(function() {
5259 if (jQuery("#WEBSITE_PAGENAME").val() == \'\') {
5260 disableautofillofalias = 0;
5261 } else {
5262 disableautofillofalias = 1;
5263 }
5264 });
5265 jQuery("#WEBSITE_PAGENAME").blur(function() {
5266 if (jQuery("#WEBSITE_PAGENAME").val() == \'\') {
5267 disableautofillofalias = 0;
5268 jQuery("#WEBSITE_TITLE").trigger(\'keyup\');
5269 }
5270 });
5271
5272 jQuery("#checkboxcreatefromfetching,#checkboxcreatemanually").click(function() {
5273 console.log("we select a method to create a new container "+jQuery("#checkboxcreatefromfetching:checked").val())
5274 jQuery(".tablecheckboxcreatefromfetching").hide();
5275 jQuery(".tablecheckboxcreatemanually").hide();
5276 if (typeof(jQuery("#checkboxcreatefromfetching:checked").val()) != \'undefined\') {
5277 console.log("show create from spider form");
5278 if (selectedf != \'createfromfetching\') {
5279 jQuery(".tablecheckboxcreatefromfetching").show();
5280 selectedf = \'createfromfetching\';
5281 selectedm = \'\';
5282 } else {
5283 jQuery(".tablecheckboxcreatefromfetching").hide();
5284 selectedf = \'\';
5285 }
5286 }
5287 if (typeof(jQuery("#checkboxcreatemanually:checked").val()) != \'undefined\') {
5288 console.log("show create from scratch or template form");
5289 if (selectedm != \'createmanually\') {
5290 jQuery(".tablecheckboxcreatemanually").show();
5291 selectedm = \'createmanually\';
5292 selectedf = \'\';
5293 } else {
5294 jQuery(".tablecheckboxcreatemanually").hide();
5295 selectedm = \'\';
5296 }
5297 }
5298 });
5299 });
5300 </script>';
5301 }
5302
5303 print '</div>';
5304
5305 print '<br>';
5306}
5307
5308
5309// Print formconfirm
5310if ($action == 'preview') {
5311 print $formconfirm;
5312}
5313
5314if ($action == 'editfile' || $action == 'file_manager' || $action == 'convertimgwebp' || $action == 'confirmconvertimgwebp') {
5315 print '<!-- Edit Media -->'."\n";
5316 print '<div class="fichenopadding" style="padding-right: 20px"><br>';
5317
5318 $module = 'medias';
5319 $formalreadyopen = 2; // So the form to submit a new file will not be open another time inside the core/tpl/filemanager.tpl.php
5320 if (empty($url)) {
5321 $url = DOL_URL_ROOT.'/website/index.php'; // Must be an url without param
5322 }
5323 include DOL_DOCUMENT_ROOT.'/core/tpl/filemanager.tpl.php';
5324
5325 print '</div>';
5326}
5327
5328if ($action == 'editmenu') {
5329 print '<!-- Edit Menu -->'."\n";
5330 print '<div class="center">'.$langs->trans("FeatureNotYetAvailable").'</center>';
5331}
5332
5333if ($action == 'editsource') {
5334 // Editing with source editor
5335
5336 $contentforedit = '';
5337 //$contentforedit.='<style scoped>'."\n"; // "scoped" means "apply to parent element only". Not yet supported by browsers
5338 //$contentforedit.=$csscontent;
5339 //$contentforedit.='</style>'."\n";
5340 $contentforedit .= $objectpage->content;
5341
5342 // We set maxheightwin in px. We take the height of screen in px and we remove a part for the top banner and more
5343 $maxheightwin = 480;
5344 if (isset($_SESSION["dol_screenheight"])) {
5345 if ($_SESSION["dol_screenheight"] > 680) {
5346 $maxheightwin = (int) $_SESSION["dol_screenheight"] - 300; // We remove a height for header
5347 }
5348 if ($_SESSION["dol_screenheight"] > 800) {
5349 $maxheightwin = (int) $_SESSION["dol_screenheight"] - 250; // We remove a height for header (on large width, risk to have header on 2 lines is lower)
5350 }
5351 }
5352
5353 $poscursor = array('x' => GETPOST('PAGE_CONTENT_x'), 'y' => GETPOST('PAGE_CONTENT_y'));
5354 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
5355 $doleditor = new DolEditor('PAGE_CONTENT', $contentforedit, '', $maxheightwin, 'Full', '', true, true, 'ace', ROWS_5, '40%', 0, $poscursor);
5356 $doleditor->Create(0, '', false, 'HTML Source', 'php');
5357}
5358
5359if ($action == 'editcontent') {
5360 // Editing with default ckeditor
5361
5362 $contentforedit = '';
5363 //$contentforedit.='<style scoped>'."\n"; // "scoped" means "apply to parent element only". Not yet supported by browsers
5364 //$contentforedit.=$csscontent;
5365 //$contentforedit.='</style>'."\n";
5366 $contentforedit .= $objectpage->content;
5367
5368 $nbrep = array();
5369 // If contentforedit has a string <img src="xxx", we replace the xxx with /viewimage.php?modulepart=medias&file=xxx except if xxx starts
5370 // with http, /viewimage.php or DOL_URL_ROOT./viewimage.phps
5371 $contentforedit = preg_replace('/(<img.*\ssrc=")(?!http|\/viewimage\.php|'.preg_quote(DOL_URL_ROOT, '/').'\/viewimage\.php)/', '\1'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $contentforedit, -1, $nbrep);
5372
5373 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
5374 $poscursor = array('x' => GETPOST('PAGE_CONTENT_x'), 'y' => GETPOST('PAGE_CONTENT_y'));
5375 $doleditor = new DolEditor('PAGE_CONTENT', $contentforedit, '', 500, 'Full', '', true, true, true, ROWS_5, '90%', 0, $poscursor);
5376 $doleditor->Create(0, '', false);
5377}
5378
5379print "</div>\n";
5380print "</form>\n";
5381
5382
5383if ($mode == 'replacesite' || $massaction == 'replace') {
5384 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5385 print '<input type="hidden" name="token" value="'.newToken().'">';
5386 print '<input type="hidden" name="action" value="replacesiteconfirm">';
5387 print '<input type="hidden" name="mode" value="replacesite">';
5388 print '<input type="hidden" name="website" value="'.$website->ref.'">';
5389
5390
5391 print '<!-- Search page and replace string -->'."\n";
5392 print '<div class="fiche"><br>';
5393
5394 print load_fiche_titre($langs->trans("ReplaceWebsiteContent"), '', 'search');
5395
5396 print '<div class="neutral">';
5397
5398 print '<div class="display-flex"><div class="flex-item">';
5399
5400 print '<div class="tagtable">';
5401
5402 print '<div class="tagtr">';
5403 print '<div class="tagtd paddingrightonly opacitymedium">';
5404 print $langs->trans("SearchReplaceInto");
5405 print '</div>';
5406 print '<div class="tagtd">';
5407 print '<input type="checkbox" class="marginleftonly" id="checkboxoptionpagecontent" name="optionpagecontent" value="content"'.((!GETPOSTISSET('buttonreplacesitesearch') || GETPOST('optionpagecontent', 'aZ09')) ? ' checked' : '').'> <label for="checkboxoptionpagecontent" class="tdoverflowmax150onsmartphone inline-block valignmiddle">'.$langs->trans("Content").'</label><br>';
5408 print '<input type="checkbox" class="marginleftonly" id="checkboxoptionmeta" name="optionmeta" value="meta"'.(GETPOST('optionmeta', 'aZ09') ? ' checked' : '').'> <label for="checkboxoptionmeta" class="tdoverflowmax150onsmartphone inline-block valignmiddle">'.$langs->trans("WEBSITE_PAGENAME").' | '.$langs->trans("Title").' | '.$langs->trans("Description").' | '.$langs->trans("Keywords").'</label><br>';
5409 print '<input type="checkbox" class="marginleftonly" id="checkboxoptionsitefiles" name="optionsitefiles" value="sitefiles"'.(GETPOST('optionsitefiles', 'aZ09') ? ' checked' : '').'> <label for="checkboxoptionsitefiles" class="tdoverflowmax150onsmartphone inline-block valignmiddle">'.$langs->trans("GlobalCSSorJS").'</label><br>';
5410 print '</div>';
5411 print '</div>';
5412
5413 print '<div class="tagtr">';
5414 print '<div class="tagtd paddingrightonly opacitymedium" style="padding-right: 10px !important">';
5415 print $langs->trans("SearchString");
5416 print '</div>';
5417 print '<div class="tagtd">';
5418 print '<input type="text" name="searchstring" value="'.dol_escape_htmltag($searchkey, 0, 0, '', 1).'" autofocus>';
5419 print '</div>';
5420 print '</div>';
5421
5422 print '</div>';
5423
5424 print '</div><div class="flex-item">';
5425
5426 print '<div class="tagtable">';
5427
5428 print '<div class="tagtr">';
5429 print '<div class="tagtd paddingrightonly opacitymedium tdoverflowmax100onsmartphone" style="padding-right: 10px !important">';
5430 print $langs->trans("WEBSITE_TYPE_CONTAINER");
5431 print '</div>';
5432 print '<div class="tagtd">';
5433 print img_picto('', 'object_technic', 'class="pictofixedwidth"').' ';
5434 print $formwebsite->selectTypeOfContainer('optioncontainertype', (GETPOST('optioncontainertype', 'alpha') ? GETPOST('optioncontainertype', 'alpha') : ''), 1, '', 1, 'minwidth125 maxwidth400 widthcentpercentminusx');
5435 print '</div>';
5436 print '</div>';
5437
5438 print '<div class="tagtr">';
5439 print '<div class="tagtd paddingrightonly opacitymedium tdoverflowmax100onsmartphone" style="padding-right: 10px !important">';
5440 print $langs->trans("Language");
5441 print '</div>';
5442 print '<div class="tagtd">';
5443 print img_picto('', 'language', 'class="pictofixedwidth"').' '.$formadmin->select_language(GETPOSTISSET('optionlanguage') ? GETPOST('optionlanguage') : '', 'optionlanguage', 0, array(), '1', 0, 0, 'minwidth125 maxwidth400 widthcentpercentminusx', 2, 0, 0, array(), 1);
5444 print '</div>';
5445 print '</div>';
5446
5447 // Categories
5448 if (isModEnabled('category') && $user->hasRight('categorie', 'lire')) {
5449 print '<div class="tagtr">';
5450 print '<div class="tagtd paddingrightonly marginrightonly opacitymedium tdoverflowmax100onsmartphone" style="padding-right: 10px !important">';
5451 print $langs->trans("Category");
5452 print '</div>';
5453 print '<div class="tagtd">';
5454 //print $form->selectCategories(Categorie::TYPE_WEBSITE_PAGE, 'optioncategory', $object);
5455 print img_picto('', 'category', 'class="pictofixedwidth"').' '.$form->select_all_categories(Categorie::TYPE_WEBSITE_PAGE, GETPOSTISSET('optioncategory') ? GETPOST('optioncategory') : '', 'optioncategory', 0, 0, 0, 0, 'minwidth125 maxwidth400 widthcentpercentminusx');
5456 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
5457 print ajax_combobox('optioncategory');
5458 print '</div>';
5459 print '</div>';
5460 }
5461
5462 print '</div>';
5463
5464 print '</div></div>';
5465
5466 print '<center>';
5467 print '<input type="submit" class="button margintoponly" name="buttonreplacesitesearch" value="'.dol_escape_htmltag($langs->trans("Search")).'">';
5468 print '</center>';
5469
5470 print '</div>';
5471
5472
5473 if ($mode == 'replacesite') {
5474 print '<!-- List of search result -->'."\n";
5475 print '<div class="rowsearchresult clearboth">';
5476
5477 print '<br>';
5478 print '<br>';
5479
5480 if ($listofpages['code'] == 'OK') {
5481 $arrayofselected = is_array($toselect) ? $toselect : array();
5482 $param = '';
5483 $nbtotalofrecords = count($listofpages['list']);
5484 $num = $limit;
5485 $permissiontodelete = $user->hasRight('website', 'delete');
5486
5487 // List of mass actions available
5488 $arrayofmassactions = array();
5489 if ($user->hasRight('website', 'writephp') && $searchkey) {
5490 $arrayofmassactions['replace'] = img_picto('', 'replacement', 'class="pictofixedwidth"').$langs->trans("Replace");
5491 }
5492 if ($user->hasRight('website', 'write')) {
5493 $langs->load("categories");
5494 $arrayofmassactions['setcategory'] = img_picto('', 'category', 'class="pictofixedwidth"').$langs->trans("ClassifyInCategory");
5495 }
5496 if ($user->hasRight('website', 'write')) {
5497 $langs->load("categories");
5498 $arrayofmassactions['delcategory'] = img_picto('', 'category', 'class="pictofixedwidth"').$langs->trans("RemoveCategory");
5499 }
5500 if ($permissiontodelete) {
5501 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
5502 }
5503 if (GETPOSTINT('nomassaction') || in_array($massaction, array('presend', 'predelete'))) {
5504 $arrayofmassactions = array();
5505 }
5506
5507 $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
5508 $massactionbutton .= '<div class="massactionother massactionreplace hidden">';
5509 $massactionbutton .= $langs->trans("ReplaceString");
5510 $massactionbutton .= ' <input type="text" name="replacestring" value="'.dol_escape_htmltag(GETPOST('replacestring', 'none')).'">';
5511 $massactionbutton .= '</div>';
5512 $massactionbutton .= '<div class="massactionother massactionsetcategory massactiondelcategory hidden">';
5513 $massactionbutton .= img_picto('', 'category', 'class="pictofixedwidth"');
5514 $massactionbutton .= $form->select_all_categories(Categorie::TYPE_WEBSITE_PAGE, GETPOSTISSET('setcategory') ? GETPOST('setcategory') : '', 'setcategory', 64, 0, 0, 0, 'minwidth300 alignstart');
5515 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
5516 $massactionbutton .= ajax_combobox('setcategory');
5517 $massactionbutton .= '</div>';
5518
5519 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
5520
5521 //$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, $conf->main_checkbox_left_column); // This also change content of $arrayfields
5522 $selectedfields = '';
5523 $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
5524
5525 print_barre_liste($langs->trans("Results"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'generic', 0, '', '', $limit, 1, 1, 1);
5526
5527 $topicmail = "WebsitePageRef";
5528 $modelmail = "websitepage_send";
5529 $objecttmp = new WebsitePage($db);
5530 $trackid = 'wsp'.$object->id;
5531 include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
5532
5533 $param = 'mode=replacesite&website='.urlencode($website->ref);
5534 $param .= '&searchstring='.urlencode($searchkey);
5535 if (GETPOST('optionpagecontent')) {
5536 $param .= '&optionpagecontent=content';
5537 }
5538 if (GETPOST('optionmeta')) {
5539 $param .= '&optionmeta=meta';
5540 }
5541 if (GETPOST('optionsitefiles')) {
5542 $param .= '&optionsitefiles=optionsitefiles';
5543 }
5544 if (GETPOST('optioncontainertype')) {
5545 $param .= '&optioncontainertype='.GETPOST('optioncontainertype', 'aZ09');
5546 }
5547 if (GETPOST('optionlanguage')) {
5548 $param .= '&optionlanguage='.GETPOST('optionlanguage', 'aZ09');
5549 }
5550 if (GETPOST('optioncategory')) {
5551 $param .= '&optioncategory='.GETPOST('optioncategory', 'aZ09');
5552 }
5553
5554 print '<div class="div-table-responsive-no-min">';
5555 print '<table class="noborder centpercent">';
5556 print '<tr class="liste_titre">';
5557 // Action column
5558 if ($conf->main_checkbox_left_column) {
5559 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
5560 }
5561 print getTitleFieldOfList("Type", 0, $_SERVER['PHP_SELF'], 'type_container', '', $param, '', $sortfield, $sortorder, '')."\n";
5562 print getTitleFieldOfList("Page", 0, $_SERVER['PHP_SELF'], 'pageurl', '', $param, '', $sortfield, $sortorder, '')."\n";
5563 print getTitleFieldOfList("Language", 0, $_SERVER['PHP_SELF'], 'lang', '', $param, '', $sortfield, $sortorder, 'center ')."\n";
5564 print getTitleFieldOfList("Categories", 0, $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'center ')."\n";
5565 print getTitleFieldOfList("", 0, $_SERVER['PHP_SELF']);
5566 print getTitleFieldOfList("UserCreation", 0, $_SERVER['PHP_SELF'], 'fk_user_creat', '', $param, '', $sortfield, $sortorder, '')."\n";
5567 print getTitleFieldOfList("DateCreation", 0, $_SERVER['PHP_SELF'], 'date_creation', '', $param, '', $sortfield, $sortorder, 'center ')."\n"; // Date creation
5568 print getTitleFieldOfList("DateLastModification", 0, $_SERVER['PHP_SELF'], 'tms', '', $param, '', $sortfield, $sortorder, 'center ')."\n"; // Date last modif
5569 print getTitleFieldOfList("", 0, $_SERVER['PHP_SELF']);
5570 // Action column
5571 if (!$conf->main_checkbox_left_column) {
5572 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
5573 }
5574 print '</tr>';
5575
5576 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
5577 $c = new Categorie($db);
5578
5579 $totalnbwords = 0;
5580
5581 foreach ($listofpages['list'] as $answerrecord) {
5582 if (is_object($answerrecord) && get_class($answerrecord) == 'WebsitePage') {
5583 $param = '?mode=replacesite';
5584 $param .= '&websiteid='.$website->id;
5585 $param .= '&optionpagecontent='.GETPOST('optionpagecontent', 'aZ09');
5586 $param .= '&optionmeta='.GETPOST('optionmeta', 'aZ09');
5587 $param .= '&optionsitefiles='.GETPOST('optionsitefiles', 'aZ09');
5588 $param .= '&optioncontainertype='.GETPOST('optioncontainertype', 'aZ09');
5589 $param .= '&optionlanguage='.GETPOST('optionlanguage', 'aZ09');
5590 $param .= '&optioncategory='.GETPOST('optioncategory', 'aZ09');
5591 $param .= '&searchstring='.urlencode($searchkey);
5592
5593 print '<tr>';
5594
5595 // Action column
5596 if ($conf->main_checkbox_left_column) {
5597 print '<td class="nowrap center">';
5598
5599 print '<!-- Status of page -->'."\n";
5600 if ($massactionbutton || $massaction) {
5601 $selected = 0;
5602 if (in_array($answerrecord->id, $arrayofselected)) {
5603 $selected = 1;
5604 }
5605 print '<input id="'.$answerrecord->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$answerrecord->id.'"'.($selected ? ' checked="checked"' : '').'>';
5606 }
5607 print '</td>';
5608 }
5609
5610 // Type of container
5611 print '<td class="nowraponall">';
5612 //print $langs->trans("Container").'<br>';
5613 if (!empty($conf->cache['type_of_container'][$answerrecord->type_container])) {
5614 print $langs->trans($conf->cache['type_of_container'][$answerrecord->type_container]);
5615 } else {
5616 print $langs->trans($answerrecord->type_container);
5617 }
5618 print '</td>';
5619
5620 // Container url and label
5621 $titleofpage = ($answerrecord->title ? $answerrecord->title : $langs->trans("NoTitle"));
5622 print '<td class="tdoverflowmax300" title="'.dol_escape_htmltag($titleofpage).'">';
5623 print $answerrecord->getNomUrl(1);
5624 print ' <span class="opacitymedium">('.dol_escape_htmltag($titleofpage).')</span>';
5625 //print '</td>';
5626 //print '<td class="tdoverflow100">';
5627 print '<br>';
5628 print '<span class="opacitymedium">'.dol_escape_htmltag($answerrecord->description ? $answerrecord->description : $langs->trans("NoDescription")).'</span>';
5629 print '</td>';
5630
5631 // Language
5632 print '<td class="center">';
5633 print picto_from_langcode($answerrecord->lang, $answerrecord->lang);
5634 print '</td>';
5635
5636 // Categories - Tags
5637 print '<td class="center">';
5638 if (isModEnabled('category') && $user->hasRight('categorie', 'lire')) {
5639 // Get current categories
5640 $existing = $c->containing($answerrecord->id, Categorie::TYPE_WEBSITE_PAGE, 'object');
5641 if (is_array($existing)) {
5642 foreach ($existing as $tmpcategory) {
5643 //var_dump($tmpcategory);
5644 print img_object($langs->trans("Category").' : '.$tmpcategory->label, 'category', 'style="padding-left: 2px; padding-right: 2px; color: #'.($tmpcategory->color != '' ? $tmpcategory->color : '888').'"');
5645 }
5646 }
5647 }
5648 //var_dump($existing);
5649 print '</td>';
5650
5651 // Number of words
5652 print '<td class="center nowraponall">';
5653 $textwithouthtml = dol_string_nohtmltag(dolStripPhpCode($answerrecord->content));
5654 $characterMap = 'áàéèëíóúüñùç0123456789';
5655 $nbofwords = str_word_count($textwithouthtml, 0, $characterMap);
5656 if ($nbofwords) {
5657 print $nbofwords.' '.$langs->trans("words");
5658 $totalnbwords += $nbofwords;
5659 }
5660 print '</td>';
5661
5662 // Author
5663 print '<td class="tdoverflowmax125">';
5664 if (!empty($answerrecord->fk_user_creat)) {
5665 if (empty($conf->cache['user'][$answerrecord->fk_user_creat])) {
5666 $tmpuser = new User($db);
5667 $tmpuser->fetch($answerrecord->fk_user_creat);
5668 $conf->cache['user'][$answerrecord->fk_user_creat] = $tmpuser;
5669 } else {
5670 $tmpuser = $conf->cache['user'][$answerrecord->fk_user_creat];
5671 }
5672 print $tmpuser->getNomUrl(-1, '', 0, 0, 0, 0, 'login');
5673 }
5674 print '</td>';
5675
5676 // Date creation
5677 print '<td class="center nowraponall">';
5678 print dol_print_date($answerrecord->date_creation, 'dayhour');
5679 print '</td>';
5680
5681 // Date last modification
5682 print '<td class="center nowraponall">';
5683 print dol_print_date($answerrecord->date_modification, 'dayhour');
5684 print '</td>';
5685
5686 // Edit properties, HTML sources, status
5687 print '<td class="tdwebsitesearchresult right nowraponall">';
5688 $disabled = '';
5689 $urltoedithtmlsource = $_SERVER["PHP_SELF"].'?action=editmeta&token='.newToken().'&websiteid='.$website->id.'&pageid='.$answerrecord->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"].$param);
5690 if (!$user->hasRight('website', 'write')) {
5691 $disabled = ' disabled';
5692 $urltoedithtmlsource = '';
5693 }
5694 print '<a class="editfielda marginleftonly marginrightonly '.$disabled.'" href="'.$urltoedithtmlsource.'" title="'.$langs->trans("EditPageMeta").'">'.img_picto($langs->trans("EditPageMeta"), 'pencil-ruler').'</a>';
5695
5696 $disabled = '';
5697 $urltoedithtmlsource = $_SERVER["PHP_SELF"].'?action=editsource&token='.newToken().'&websiteid='.$website->id.'&pageid='.$answerrecord->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"].$param);
5698 if (!$user->hasRight('website', 'write')) {
5699 $disabled = ' disabled';
5700 $urltoedithtmlsource = '';
5701 }
5702 print '<a class="editfielda marginleftonly marginrightonly '.$disabled.'" href="'.$urltoedithtmlsource.'" title="'.$langs->trans("EditHTMLSource").'">'.img_picto($langs->trans("EditHTMLSource"), 'edit').'</a>';
5703
5704 print '<span class="marginleftonly marginrightonly"></span>';
5705 print ajax_object_onoff($answerrecord, 'status', 'status', 'Enabled', 'Disabled', array(), 'valignmiddle inline-block');
5706
5707 print '</td>';
5708
5709 // Action column
5710 if (!$conf->main_checkbox_left_column) {
5711 print '<td class="nowrap center">';
5712
5713 print '<!-- Status of page -->'."\n";
5714 if ($massactionbutton || $massaction) {
5715 $selected = 0;
5716 if (in_array($answerrecord->id, $arrayofselected)) {
5717 $selected = 1;
5718 }
5719 print '<input id="'.$answerrecord->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$answerrecord->id.'"'.($selected ? ' checked="checked"' : '').'>';
5720 }
5721 print '</td>';
5722 }
5723
5724 print '</tr>';
5725 } else {
5726 // $answerrecord is not list of WebsitePage
5727 '@phan-var-force array{type:string} $answerrecord';
5728 $param = '?mode=replacesite';
5729 $param .= '&websiteid='.$website->id;
5730 $param .= '&optionpagecontent='.GETPOST('optionpagecontent', 'aZ09');
5731 $param .= '&optionmeta='.GETPOST('optionmeta', 'aZ09');
5732 $param .= '&optionsitefiles='.GETPOST('optionsitefiles', 'aZ09');
5733 $param .= '&optioncontainertype='.GETPOST('optioncontainertype', 'aZ09');
5734 $param .= '&optionlanguage='.GETPOST('optionlanguage', 'aZ09');
5735 $param .= '&optioncategory='.GETPOST('optioncategory', 'aZ09');
5736 $param .= '&searchstring='.urlencode($searchkey);
5737
5738 print '<tr>';
5739
5740 // Action column
5741 if ($conf->main_checkbox_left_column) {
5742 print '<td class="nowrap center">';
5743 print '</td>';
5744 }
5745
5746 // Type of container
5747 print '<td>';
5748 $translateofrecordtype = array(
5749 'website_csscontent' => 'WEBSITE_CSS_INLINE',
5750 'website_jscontent' => 'WEBSITE_JS_INLINE',
5751 'website_robotcontent' => 'WEBSITE_ROBOT',
5752 'website_htmlheadercontent' => 'WEBSITE_HTML_HEADER',
5753 'website_htaccess' => 'WEBSITE_HTACCESS',
5754 'website_readme' => 'WEBSITE_README',
5755 'website_manifestjson' => 'WEBSITE_MANIFEST_JSON'
5756 );
5757 print '<span class="opacitymedium">';
5758 if (!empty($translateofrecordtype[$answerrecord['type']])) {
5759 print $langs->trans($translateofrecordtype[$answerrecord['type']]);
5760 } else {
5761 print $answerrecord['type'];
5762 }
5763 print '</span>';
5764 print '</td>';
5765
5766 // Container url and label
5767 print '<td>';
5768 $backtopageurl = $_SERVER["PHP_SELF"].$param;
5769 print '<a href="'.$_SERVER["PHP_SELF"].'?action=editcss&token='.newToken().'&website='.urlencode($website->ref).'&backtopage='.urlencode($backtopageurl).'">'.$langs->trans("EditCss").'</a>';
5770 print '</td>';
5771
5772 // Language
5773 print '<td>';
5774 print '</td>';
5775
5776 // Categories - Tags
5777 print '<td>';
5778 print '</td>';
5779
5780 // Nb of words
5781 print '<td>';
5782 print '</td>';
5783
5784 print '<td>';
5785 print '</td>';
5786
5787 print '<td>';
5788 print '</td>';
5789
5790 // Date last modification
5791 print '<td class="center nowraponall">';
5792 //print dol_print_date(filemtime());
5793 print '</td>';
5794
5795 // Edit properties, HTML sources, status
5796 print '<td>';
5797 print '</td>';
5798
5799 // Action column
5800 if (!$conf->main_checkbox_left_column) {
5801 print '<td class="nowrap center">';
5802 print '</td>';
5803 }
5804
5805 print '</tr>';
5806 }
5807 }
5808
5809 if (count($listofpages['list']) >= 2) {
5810 // Total
5811 print '<tr class="lite_titre">';
5812
5813 // Action column
5814 if ($conf->main_checkbox_left_column) {
5815 print '<td class="nowrap center">';
5816 print '</td>';
5817 }
5818
5819 // Type of container
5820 print '<td>';
5821 print $langs->trans("Total");
5822 print '</td>';
5823
5824 // Container url and label
5825 print '<td>';
5826 print '</td>';
5827
5828 // Language
5829 print '<td>';
5830 print '</td>';
5831
5832 // Categories - Tags
5833 print '<td>';
5834 print '</td>';
5835
5836 // Nb of words
5837 print '<td class="center nowraponall">';
5838 print $totalnbwords.' '.$langs->trans("words");
5839 print '</td>';
5840
5841 print '<td>';
5842 print '</td>';
5843
5844 print '<td>';
5845 print '</td>';
5846
5847 // Date last modification
5848 print '<td>';
5849 print '</td>';
5850
5851 // Edit properties, HTML sources, status
5852 print '<td>';
5853 print '</td>';
5854
5855 // Action column
5856 if (!$conf->main_checkbox_left_column) {
5857 print '<td class="nowrap center">';
5858 print '</td>';
5859 }
5860
5861 print '</tr>';
5862 }
5863
5864 print '</table>';
5865 print '</div>';
5866 print '<br>';
5867 } else {
5868 print '<div class="warning">'.$listofpages['message'].'</div>';
5869 }
5870
5871 print '</div>';
5872 }
5873
5874 print '</form>';
5875}
5876
5877if ((empty($action) || $action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone') && !in_array($mode, array('replacesite'))) {
5878 if ($pageid > 0 && $atleastonepage) {
5879 // $filejs
5880 // $filecss
5881 // $filephp
5882
5883 // Output page under the Dolibarr top menu
5884 $objectpage->fetch($pageid);
5885
5886 $jscontent = @file_get_contents($filejs);
5887
5888 $out = '<!-- Page content '.$filetpl.' : Div with (Htmlheader/Style of page from database + CSS Of website from file + Page content from database or by include if WEBSITE_SUBCONTAINERSINLINE is on) -->'."\n";
5889
5890 // Include a html so we can benefit of the header of page.
5891 // Note: We can't use iframe as it can be used to include another external html file
5892 // Note: We can't use frame as it is deprecated.
5893 /*if ($includepageintoaframeoradiv == 'iframe')
5894 {
5895 $out .= "<iframe><body></html>";
5896 }*/
5897 $out .= "\n<html><head>\n";
5898 $out .= "<!-- htmlheader/style of page from database -->\n";
5899 $out .= dolWebsiteReplacementOfLinks($object, $objectpage->htmlheader, 1, 'htmlheader');
5900
5901 $out .= "<!-- htmlheader/style of website from files -->\n";
5902 // TODO Keep only the <link> or the <script> tags
5903 /*
5904 $htmlheadercontent = @file_get_contents($filehtmlheader);
5905 $dom = new DOMDocument;
5906 @$dom->loadHTML($htmlheadercontent);
5907 $styles = $dom->getElementsByTagName('link');
5908 $scripts = $dom->getElementsByTagName('script');
5909 foreach($styles as $stylescursor)
5910 {
5911 $out.=$stylescursor;
5912 }
5913 foreach($scripts as $scriptscursor)
5914 {
5915 $out.=$scriptscursor;
5916 }
5917 */
5918
5919 $out .= "</head>\n";
5920 $out .= "\n";
5921 $out .= "<body>\n";
5922
5923
5924 $out .= '<div id="websitecontentundertopmenu" class="websitecontentundertopmenu boostrap-iso">'."\n";
5925
5926 // REPLACEMENT OF LINKS When page called by website editor
5927
5928 $out .= '<!-- style of website from file -->'."\n";
5929 $out .= '<style scoped>'."\n"; // "scoped" means "apply to parent element only and not grand parent". No more supported by browsers, snif !
5930 $tmpout = '';
5931 $tmpout .= '/* Include website CSS file */'."\n";
5932 //$csscontent = @file_get_contents($filecss);
5933 if (dol_is_file($filecss)) {
5934 ob_start();
5935 include $filecss;
5936 $csscontent = ob_get_contents();
5937 ob_end_clean();
5938 } else {
5939 $csscontent = '';
5940 }
5941 $tmpout .= dolWebsiteReplacementOfLinks($object, $csscontent, 1, 'css');
5942 $tmpout .= '/* Include style from the HTML header of page */'."\n";
5943 // Clean the html header of page to get only <style> content
5944 $tmp = preg_split('(<style[^>]*>|</style>)', $objectpage->htmlheader);
5945 $tmpstyleinheader = '';
5946 $i = 0;
5947 foreach ($tmp as $valtmp) {
5948 $i++;
5949 if ($i % 2 == 0) {
5950 $tmpstyleinheader .= $valtmp."\n";
5951 }
5952 }
5953 $tmpout .= $tmpstyleinheader."\n";
5954 // Clean style that may affect global style of Dolibarr
5955 $tmpout = preg_replace('/}[\s\n]*body\s*{[^}]+}/ims', '}', $tmpout);
5956 $out .= $tmpout;
5957 $out .= '</style>'."\n";
5958
5959 // Note: <div>, <section>, ... with contenteditable="true" inside this can be edited with inline ckeditor
5960
5961 // Do not enable the contenteditable when page was grabbed, ckeditor is removing span and adding borders,
5962 // so editable will be available only from container created from scratch
5963 //$out.='<div id="bodywebsite" class="bodywebsite"'.($objectpage->grabbed_from ? ' contenteditable="true"' : '').'>'."\n";
5964 $out .= '<div id="divbodywebsite" class="bodywebsite bodywebpage-'.$objectpage->ref.'">'."\n";
5965
5966 $newcontent = $objectpage->content;
5967
5968 // If mode WEBSITE_SUBCONTAINERSINLINE is on
5969 if (getDolGlobalString('WEBSITE_SUBCONTAINERSINLINE')) {
5970 // TODO Check file $filephp exists, if not create it.
5971
5972 //var_dump($filetpl);
5973 $filephp = $filetpl;
5974
5975 // Get session info and obfuscate session cookie
5976 $savsessionname = session_name();
5977 $savsessionid = $_COOKIE[$savsessionname];
5978 $_COOKIE[$savsessionname] = 'obfuscatedcookie';
5979
5980 ob_start();
5981 try {
5982 $res = include $filephp;
5983 if (empty($res)) {
5984 print "ERROR: Failed to include file '".$filephp."'. Try to edit and re-save page with this ID.";
5985 }
5986 } catch (Exception $e) {
5987 print $e->getMessage();
5988 }
5989 $newcontent = ob_get_contents();
5990 ob_end_clean();
5991
5992 // Restore data
5993 $_COOKIE[$savsessionname] = $savsessionid;
5994 }
5995
5996 // Change the contenteditable to "true" or "false" when mode Edit Inline is on or off
5997 if (!getDolGlobalString('WEBSITE_EDITINLINE')) {
5998 // Remove the contenteditable="true"
5999 $newcontent = preg_replace('/(div|section|header|main|footer)(\s[^>]*)contenteditable="true"/', '\1\2', $newcontent);
6000 } else {
6001 // Keep the contenteditable="true" when mode Edit Inline is on
6002 }
6003 $out .= dolWebsiteReplacementOfLinks($object, $newcontent, 0, 'html', $objectpage->id)."\n";
6004 //$out.=$newcontent;
6005
6006 $out .= '</div>'."\n";
6007
6008 $out .= '</div> <!-- End div id=websitecontentundertopmenu -->'."\n";
6009
6010 /*if ($includepageintoaframeoradiv == 'iframe')
6011 {
6012 $out .= "</body></html></iframe>";
6013 }*/
6014 $out .= "\n</body></html>\n";
6015
6016 $out .= "\n".'<!-- End page content '.$filetpl.' -->'."\n\n";
6017
6018 print $out;
6019
6020 /*
6021 file_put_contents($filetpl, $out);
6022 dolChmod($filetpl);
6023
6024 // Output file on browser
6025 dol_syslog("index.php include $filetpl $filename content-type=$type");
6026 $original_file_osencoded=dol_osencode($filetpl); // New file name encoded in OS encoding charset
6027
6028 // This test if file exists should be useless. We keep it to find bug more easily
6029 if (! file_exists($original_file_osencoded))
6030 {
6031 dol_print_error(0,$langs->trans("ErrorFileDoesNotExists",$original_file));
6032 exit;
6033 }
6034
6035 //include_once $original_file_osencoded;
6036 */
6037
6038 /*print '<iframe class="websiteiframenoborder centpercent" src="'.DOL_URL_ROOT.'/public/website/index.php?website='.$websitekey.'&pageid='.$pageid.'"/>';
6039 print '</iframe>';*/
6040 } else {
6041 if (empty($websitekey) || $websitekey == '-1') {
6042 print '<br><br><div class="center previewnotyetavailable"><span class="">'.$langs->trans("NoWebSiteCreateOneFirst").'</span></div><br><br><br>';
6043 print '<div class="center"><div class="logo_setup"></div></div>';
6044 } else {
6045 print '<br><br><div class="center previewnotyetavailable"><span class="">'.$langs->trans("PreviewOfSiteNotYetAvailable", $object->ref).'</span></div><br><br><br>';
6046 print '<div class="center"><div class="logo_setup"></div></div>';
6047 }
6048 }
6049}
6050
6051// End of page
6052llxFooter();
6053$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
global $dolibarr_main_url_root
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
dolibarr_del_const($db, $name, $entity=1)
Delete a constant.
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:476
ajax_object_onoff($object, $code, $field, $text_on, $text_off, $input=array(), $morecss='', $htmlname='', $forcenojs=0, $moreparam='', $readonly=0)
On/off button to change a property status of an object This uses the ajax service objectonoff....
Definition ajax.lib.php:799
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
$c
Definition line.php:334
$object ref
Definition info.php:90
Class to manage categories.
Class to manage a WYSIWYG editor.
Class to generate html code for admin pages.
Class to manage generation of HTML components Only common components must be here.
Class to manage a HTML form to send a unitary email Usage: $formail = new FormMail($db) $formmail->pr...
Class to help generate other html components Only common components are here.
Class to manage component html for module website.
The LESS compiler and parser.
Class to manage Dolibarr users.
Class Website.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:168
getAllImages($object, $objectpage, $urltograb, &$tmp, &$action, $modifylinks=0, $grabimages=1, $grabimagesinto='subpage')
Download all images found into an external URL.
dolStripPhpCode($str, $replacewith='')
Remove PHP code part from a string.
dolWebsiteReplacementOfLinks($website, $content, $removephppart=0, $contenttype='html', $containerid=0)
Convert a page content to have correct links (based on DOL_URL_ROOT) into an html content.
dolKeepOnlyPhpCode($str)
Keep only PHP code part from a HTML string page.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_add_file_process($upload_dir, $allowoverwrite=0, $updatesessionordb=0, $keyforsourcefile='addedfile', $savingdocmask='', $link=null, $trackid='', $generatethumbs=1, $object=null, $forceFullTextIndexation='', $mode=0)
Get and save an upload file (for example after submitting a new file in a mail form).
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0, $level=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
dol_is_file($pathoffile)
Return if path is a file.
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
picto_from_langcode($codelang, $moreatt='', $notitlealt=0)
Return img flag of country for a language code or country code.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $selectlimitsuffix=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
img_help($usehelpcursor=1, $usealttitle=1)
Show help logo with cursor "?".
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='')
Show information in HTML for admin users or standard users.
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled='', $morecss='classlink button bordertransp', $jsonopen='', $jsonclose='', $accesskey='')
Return HTML code to output a button to open a dialog popup box.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dolButtonToOpenExportDialog($name, $label, $buttonstring, $exportSiteName, $overwriteGitUrl, $website)
Create a dialog with two buttons for export and overwrite of a website.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
img_previous($titlealt='default', $moreatt='')
Show previous logo.
dol_htmlentities($string, $flags=ENT_QUOTES|ENT_SUBSTITUTE, $encoding='UTF-8', $double_encode=false)
Replace htmlentities functions.
dol_sanitizeUrl($stringtoclean, $type=1)
Clean a string to use it as an URL (into a href or src attribute)
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get title line of an array.
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_next($titlealt='default', $moreatt='')
Show next logo.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
getDomainFromURL($url, $mode=0)
Function get second level domain name.
getRootURLFromURL($url)
Function root url from a long url For example: https://www.abc.mydomain.com/dir/page....
removeHtmlComment($content)
Function to remove comments into HTML content.
getURLContent($url, $postorget='GET', $param='', $followlocation=1, $addheaders=array(), $allowedschemes=array('http', 'https'), $localurl=0, $ssl_verifypeer=-1, $timeoutconnect=0, $timeoutresponse=0, $otherCurlOptions=array(), $morelogsuffix='')
Function to get a content from an URL (use proxy if proxy defined).
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
getMaxFileSizeArray()
Return the max allowed for file upload.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
dolSaveMasterFile($filemaster)
Save content of a page on disk.
dolSaveLicense($file, $content)
Save content of a page on disk.
checkPHPCode(&$phpfullcodestringold, &$phpfullcodestring)
Check that the new string $phpfullcodestring contains only php code (including <php tag)
dolSaveHtmlHeader($filehtmlheader, $htmlheadercontent)
Save content of a page on disk.
dolSaveReadme($file, $content)
Save content of a page on disk.
dolSaveManifestJson($file, $content)
Save content of a page on disk.
dolSaveIndexPage($pathofwebsite, $fileindex, $filetpl, $filewrapper, $object=null)
Save content of the index.php and/or the wrapper.php page.
dolSavePageAlias($filealias, $object, $objectpage)
Save an alias page on disk (A page that include the reference page).
dolSaveHtaccessFile($filehtaccess, $htaccess)
Save content of a page on disk.
dolSaveJsFile($filejs, $jscontent)
Save content of a page on disk.
dolSavePageContent($filetpl, Website $object, WebsitePage $objectpage, $backupold=0)
Save content of a page on disk (page name is generally ID_of_page.php).
showWebsiteTemplates(Website $website, int $refresh)
Show list of themes.
dolSaveCssFile($filecss, $csscontent)
Save content of a page on disk.
dolSaveRobotFile($filerobot, $robotcontent)
Save content of a page on disk.
websiteGetContentPolicyDirectives()
Prepare array of directives for Website.
websiteGetContentPolicySources()
Prepare array of sources for Website.
websiteGetContentPolicyToArray($forceCSP)
Transform a Content Security Policy to an array.
websiteconfigPrepareHead($object)
Prepare array of tabs for Website.