dolibarr 23.0.3
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-2025 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';
42require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
43require_once DOL_DOCUMENT_ROOT.'/website/lib/website.lib.php';
44require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
45require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';
46require_once DOL_DOCUMENT_ROOT.'/core/lib/website2.lib.php';
47require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
48require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
49require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
50require_once DOL_DOCUMENT_ROOT.'/core/class/html.formwebsite.class.php';
51require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
52require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
53require_once DOL_DOCUMENT_ROOT.'/website/class/website.class.php';
54require_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php';
55require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
56require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
57
58
69// Load translation files required by the page
70$langs->loadLangs(array("admin", "other", "users", "website"));
71
72// Security check
73if (!$user->hasRight('website', 'read')) {
75}
76
77$conf->dol_hide_leftmenu = 1; // Force hide of left menu.
78
79$error = 0;
80$virtualurl = '';
81$dataroot = '';
82$websiteid = GETPOSTINT('websiteid');
83$websitekey = GETPOST('website', 'alpha');
84$page = GETPOST('page', 'alpha');
85$pageid = GETPOSTINT('pageid');
86$pageref = GETPOST('pageref', 'alphanohtml');
87
88$action = GETPOST('action', 'aZ09');
89$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
90$confirm = GETPOST('confirm', 'alpha');
91$cancel = GETPOST('cancel', 'alpha');
92$toselect = GETPOST('toselect', 'array:int'); // Array of ids of elements selected into a list
93$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'websitelist'; // To manage different context of search
94$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
95$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
96$dol_hide_topmenu = GETPOSTINT('dol_hide_topmenu');
97$dol_hide_leftmenu = GETPOSTINT('dol_hide_leftmenu');
98$dol_openinpopup = GETPOST('dol_openinpopup', 'aZ09');
99
100$type_container = GETPOST('WEBSITE_TYPE_CONTAINER', 'alpha');
101$section_dir = GETPOST('section_dir', 'alpha');
102$file_manager = GETPOST('file_manager', 'alpha');
103$replacesite = GETPOST('replacesite', 'alpha');
104$mode = GETPOST('mode', 'alpha');
105
106if (GETPOST('deletesite', 'alpha')) {
107 $action = 'deletesite';
108}
109if (GETPOST('delete', 'alpha')) {
110 $action = 'delete';
111}
112if (GETPOST('preview', 'alpha')) {
113 $action = 'preview';
114}
115if (GETPOST('createsite', 'alpha')) {
116 $action = 'createsite';
117}
118if (GETPOST('createcontainer', 'alpha')) {
119 $action = 'createcontainer';
120}
121if (GETPOST('editcss', 'alpha')) {
122 $action = 'editcss';
123}
124if (GETPOST('editmenu', 'alpha')) {
125 $action = 'editmenu';
126}
127if (GETPOST('setashome', 'alpha')) {
128 $action = 'setashome';
129}
130if (GETPOST('editmeta', 'alpha')) {
131 $action = 'editmeta';
132}
133if (GETPOST('editsource', 'alpha')) {
134 $action = 'editsource';
135}
136if (GETPOST('editcontent', 'alpha')) {
137 $action = 'editcontent';
138}
139if (GETPOST('exportsite', 'alpha')) {
140 $action = 'exportsite';
141}
142if (GETPOST('importsite')) { // Can be a string when clicking on button "Import site"
143 $action = 'importsite';
144}
145if (GETPOST('createfromclone', 'alpha')) {
146 $action = 'createfromclone';
147}
148if (GETPOST('createpagefromclone', 'alpha')) {
149 $action = 'createpagefromclone';
150}
151if (empty($action) && $file_manager) {
152 $action = 'file_manager';
153}
154if ($action == 'replacesite' || (empty($action) && $replacesite)) { // Test on permission not required
155 $mode = 'replacesite';
156}
157if (GETPOST('refreshsite') || GETPOST('refreshsite_x') || GETPOST('refreshsite.x')) {
158 $pageid = 0;
159}
160
161// Load variable for pagination
162$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
163$sortfield = (string) GETPOST('sortfield', 'aZ09comma');
164$sortorder = GETPOST('sortorder', 'aZ09comma');
165$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
166if (empty($page) || $page == -1) {
167 $page = 0;
168} // If $page is not defined, or '' or -1
169$offset = $limit * $page;
170$pageprev = $page - 1;
171$pagenext = $page + 1;
172
173if (empty($action)) {
174 $action = 'preview';
175}
176
177$object = new Website($db);
178$objectpage = new WebsitePage($db);
179
180$listofwebsites = $object->fetchAll('ASC', 'position'); // Init list of websites
181
182// If website not defined, we take first found
183if (!($websiteid > 0) && empty($websitekey) && $action != 'createsite') {
184 foreach ($listofwebsites as $key => $valwebsite) {
185 $websitekey = $valwebsite->ref;
186 break;
187 }
188}
189if ($websiteid > 0 || $websitekey) {
190 $res = $object->fetch($websiteid, $websitekey);
191 $websitekey = $object->ref;
192}
193
194$website = $object;
195
196// Check pageid received as parameter
197if ($pageid < 0) {
198 $pageid = 0;
199}
200if (($pageid > 0 || $pageref) && $action != 'addcontainer') {
201 $res = $objectpage->fetch($pageid, ($object->id > 0 ? $object->id : null), $pageref);
202 // @phan-suppress
203 if ($res == 0) {
204 $res = $objectpage->fetch($pageid, ($object->id > 0 ? $object->id : null), null, $pageref);
205 }
206
207 // Check if pageid is inside the new website, if not we reset param pageid
208 if ($res >= 0 && $object->id > 0) {
209 if ($objectpage->fk_website != $object->id) { // We have a bad page that does not belong to web site
210 if ($object->fk_default_home > 0) {
211 $res = $objectpage->fetch($object->fk_default_home, (string) $object->id, ''); // We search first page of web site
212 if ($res > 0) {
213 $pageid = $object->fk_default_home;
214 }
215 } else {
216 $res = $objectpage->fetch(0, (string) $object->id, ''); // We search first page of web site
217 if ($res == 0) { // Page was not found, we reset it
218 $objectpage = new WebsitePage($db);
219 } else { // We found a page, we set pageid to it.
220 $pageid = $objectpage->id;
221 }
222 }
223 } else { // We have a valid page. We force pageid for the case we got the page with a fetch on ref.
224 $pageid = $objectpage->id;
225 }
226 }
227}
228
229// Define pageid if pageid and pageref not received as parameter or was wrong
230if (empty($pageid) && empty($pageref) && $object->id > 0 && $action != 'createcontainer') {
231 $pageid = $object->fk_default_home;
232 if (empty($pageid)) {
233 $array = $objectpage->fetchAll($object->id, 'ASC,ASC', 'type_container,pageurl');
234 if (!is_array($array) && $array < 0) {
235 dol_print_error(null, $objectpage->error, $objectpage->errors);
236 }
237 $atleastonepage = (is_array($array) && count($array) > 0);
238
239 $firstpageid = 0;
240 $homepageid = 0;
241 foreach ($array as $key => $valpage) {
242 if (empty($firstpageid)) {
243 $firstpageid = $valpage->id;
244 }
245 if ($object->fk_default_home && $key == $object->fk_default_home) {
246 $homepageid = $valpage->id;
247 }
248 }
249 $pageid = ($homepageid ? $homepageid : $firstpageid); // We choose home page and if not defined yet, we take first page
250 }
251}
252
253
254global $dolibarr_main_data_root;
255$pathofwebsite = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$websitekey;
256$filehtmlheader = $pathofwebsite.'/htmlheader.html';
257$filecss = $pathofwebsite.'/styles.css.php';
258$filejs = $pathofwebsite.'/javascript.js.php';
259$filerobot = $pathofwebsite.'/robots.txt';
260$filehtaccess = $pathofwebsite.'/.htaccess';
261$filetpl = $pathofwebsite.'/page'.$pageid.'.tpl.php';
262$fileindex = $pathofwebsite.'/index.php';
263$filewrapper = $pathofwebsite.'/wrapper.php';
264$filemanifestjson = $pathofwebsite.'/manifest.json.php';
265$filereadme = $pathofwebsite.'/README.md';
266$filelicense = $pathofwebsite.'/LICENSE';
267$filemaster = $pathofwebsite.'/master.inc.php';
268
269$forceCSP = getDolGlobalString("WEBSITE_".$object->id."_SECURITY_FORCECSP");
270
271// Define $urlwithroot
272$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
273$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
274//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
275
276
277$permtouploadfile = $user->hasRight('website', 'write');
278$diroutput = $conf->medias->multidir_output[$conf->entity];
279
280$relativepath = $section_dir;
281$upload_dir = preg_replace('/\/$/', '', $diroutput).'/'.preg_replace('/^\//', '', $relativepath);
282
283$htmlheadercontentdefault = '';
284$htmlheadercontentdefault .= '<link rel="stylesheet" id="google-fonts-css" href="//fonts.googleapis.com/css?family=Open+Sans:300,400,700" />'."\n";
285$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";
286$htmlheadercontentdefault .= '<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>'."\n";
287$htmlheadercontentdefault .= '<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>'."\n";
288$htmlheadercontentdefault .= '<!--'."\n";
289$htmlheadercontentdefault .= '<script src="/document.php?modulepart=medias&file=css/myfile.css"></script>'."\n";
290$htmlheadercontentdefault .= '<script src="/document.php?modulepart=medias&file=js/myfile.js"></script>'."\n";
291$htmlheadercontentdefault .= '-->'."\n";
292
293$manifestjsoncontentdefault = '';
294$manifestjsoncontentdefault .= '{
295 "name": "MyWebsite",
296 "short_name": "MyWebsite",
297 "start_url": "/",
298 "lang": "en-US",
299 "display": "standalone",
300 "background_color": "#fff",
301 "description": "A simple Web app.",
302 "icons": [{
303 "src": "images/'.urlencode($website->ref).'/homescreen48.png",
304 "sizes": "48x48",
305 "type": "image/png"
306 }, {
307 "src": "image/'.urlencode($website->ref).'/homescreen72.png",
308 "sizes": "72x72",
309 "type": "image/png"
310 }, {
311 "src": "image/'.urlencode($website->ref).'/homescreen96.png",
312 "sizes": "96x96",
313 "type": "image/png"
314 }, {
315 "src": "image/'.urlencode($website->ref).'/homescreen144.png",
316 "sizes": "144x144",
317 "type": "image/png"
318 }, {
319 "src": "image/'.urlencode($website->ref).'/homescreen168.png",
320 "sizes": "168x168",
321 "type": "image/png"
322 }, {
323 "src": "image/'.urlencode($website->ref).'/homescreen192.png",
324 "sizes": "192x192",
325 "type": "image/png"
326 }],
327 "related_applications": [{
328 "platform": "play",
329 "url": "https://play.google.com/store/apps/details?id=com.nltechno.dolidroidpro"
330 }]
331}';
332
333$listofpages = array();
334
335$algo = '';
336if (GETPOST('optionpagecontent')) {
337 $algo .= 'content';
338}
339if (GETPOST('optionmeta')) {
340 $algo .= 'meta';
341}
342if (GETPOST('optionsitefiles')) {
343 $algo .= 'sitefiles';
344}
345
346$searchkey = GETPOST('searchstring', 'restricthtmlallowunvalid'); // or 'none', must be same as $searchstring
347
348if ($sortfield == '') {
349 if ($action == 'file_manager') { // Test on permission not required
350 $sortfield = 'name';
351 $sortorder = 'ASC';
352 } else {
353 $sortfield = 'pageurl';
354 $sortorder = 'ASC';
355 }
356}
357'@phan-var-force string $sortfield';
358
359$langcode = '';
360$containertype = '';
361$otherfilters = array();
362
363if ($action == 'replacesite' || $mode == 'replacesite') { // Test on permission not required
364 $containertype = GETPOST('optioncontainertype', 'aZ09') != '-1' ? GETPOST('optioncontainertype', 'aZ09') : '';
365 $langcode = GETPOST('optionlanguage', 'aZ09');
366 if (GETPOSTINT('optioncategory') > 0) {
367 $otherfilters['category'] = GETPOSTINT('optioncategory');
368 }
369
370 $listofpages = getPagesFromSearchCriterias($containertype, $algo, $searchkey, 1000, $sortfield, $sortorder, $langcode, $otherfilters, -1);
371}
372
373$usercanedit = $user->hasRight('website', 'write');
374$permissiontoadd = $user->hasRight('website', 'write'); // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles
375$permissiontodelete = $user->hasRight('website', 'delete');
376
377
378/*
379 * Actions
380 */
381
382// Protections
383if (GETPOST('refreshsite') || GETPOST('refreshsite_x') || GETPOST('refreshsite.x') || GETPOST('refreshpage') || GETPOST('refreshpage_x') || GETPOST('refreshpage.x')) {
384 $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.
385}
386if (GETPOST('refreshsite', 'alpha') || GETPOST('refreshsite.x', 'alpha') || GETPOST('refreshsite_x', 'alpha')) { // If we change the site, we reset the pageid and cancel addsite action.
387 if ($action == 'addsite') { // Test on permission not required here
388 $action = 'preview';
389 }
390 if ($action == 'updatesource') { // Test on permission not required here
391 $action = 'preview';
392 }
393
394 $pageid = $object->fk_default_home;
395 if (empty($pageid)) {
396 $array = $objectpage->fetchAll($object->id, 'ASC,ASC', 'type_container,pageurl');
397 if (!is_array($array) && $array < 0) {
398 dol_print_error(null, $objectpage->error, $objectpage->errors);
399 }
400 $atleastonepage = (is_array($array) && count($array) > 0);
401
402 $firstpageid = 0;
403 $homepageid = 0;
404 foreach ($array as $key => $valpage) {
405 if (empty($firstpageid)) {
406 $firstpageid = $valpage->id;
407 }
408 if ($object->fk_default_home && $key == $object->fk_default_home) {
409 $homepageid = $valpage->id;
410 }
411 }
412 $pageid = ($homepageid ? $homepageid : $firstpageid); // We choose home page and if not defined yet, we take first page
413 }
414}
415if (GETPOST('refreshpage', 'alpha') && !in_array($action, array('updatecss'))) {
416 $action = 'preview';
417}
418
419if ($cancel && $action == 'renamefile') { // Test on permission not required here
420 $cancel = '';
421}
422
423// Cancel
424if ($cancel) {
425 $action = 'preview';
426 $mode = '';
427 if ($backtopage) {
428 header("Location: ".$backtopage);
429 exit;
430 }
431}
432
433$savbacktopage = $backtopage;
434$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
435if ($sortfield) {
436 $backtopage .= '&sortfield='.urlencode($sortfield);
437}
438if ($sortorder) {
439 $backtopage .= '&sortorder='.urlencode($sortorder);
440}
441include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; // This manage 'sendit', 'confirm_deletefile', 'renamefile' action when submitting new file.
442
443$backtopage = $savbacktopage;
444//var_dump($backtopage);
445//var_dump($action);
446
447if ($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'
448 $action = 'file_manager';
449}
450
451if ($action == 'setwebsiteonline' && $usercanedit) {
452 $website->setStatut($website::STATUS_VALIDATED, null, '', 'WEBSITE_MODIFY', 'status');
453
454 header("Location: ".$_SERVER["PHP_SELF"].'?website='.urlencode(GETPOST('website')).'&pageid='.GETPOSTINT('websitepage'));
455 exit;
456}
457if ($action == 'setwebsiteoffline' && $usercanedit) {
458 $result = $website->setStatut($website::STATUS_DRAFT, null, '', 'WEBSITE_MODIFY', 'status');
459
460 header("Location: ".$_SERVER["PHP_SELF"].'?website='.urlencode(GETPOST('website')).'&pageid='.GETPOSTINT('websitepage'));
461 exit;
462}
463if ($action == 'seteditinline') { // Test on permission not required here
464 if (!getDolGlobalString('WEBSITE_EDITINLINE_SAVE_CKEDITOR_EDIT')) {
465 // Show warning for feature not yet ready
466 setEventMessages($langs->trans("FeatureNotYetAvailable"), null, 'warnings');
467 }
468
469 dolibarr_set_const($db, 'WEBSITE_EDITINLINE', 1);
470 //dolibarr_set_const($db, 'WEBSITE_SUBCONTAINERSINLINE', 0); // Force disable of 'Include dynamic content'
471 header("Location: ".$_SERVER["PHP_SELF"].'?website='.urlencode(GETPOST('website')).'&pageid='.GETPOSTINT('pageid'));
472 exit;
473}
474if ($action == 'unseteditinline') { // Test on permission not required here
475 dolibarr_del_const($db, 'WEBSITE_EDITINLINE');
476 header("Location: ".$_SERVER["PHP_SELF"].'?website='.urlencode(GETPOST('website')).'&pageid='.GETPOSTINT('pageid'));
477 exit;
478}
479if ($action == 'setshowsubcontainers') { // Test on permission not required here
480 dolibarr_set_const($db, 'WEBSITE_SUBCONTAINERSINLINE', 1);
481 //dolibarr_set_const($db, 'WEBSITE_EDITINLINE', 0); // Force disable of edit inline
482 header("Location: ".$_SERVER["PHP_SELF"].'?website='.urlencode(GETPOST('website')).'&pageid='.GETPOSTINT('pageid'));
483 exit;
484}
485if ($action == 'unsetshowsubcontainers') { // Test on permission not required here
486 dolibarr_del_const($db, 'WEBSITE_SUBCONTAINERSINLINE');
487 header("Location: ".$_SERVER["PHP_SELF"].'?website='.urlencode(GETPOST('website')).'&pageid='.GETPOSTINT('pageid'));
488 exit;
489}
490
491if ($massaction == 'replace' && GETPOST('confirmmassaction', 'alpha') && !$searchkey && $usercanedit) {
492 $mode = 'replacesite';
493 $action = 'replacesite';
494 $massaction = '';
495}
496
497if ($action == 'deletetemplate' && $usercanedit) {
498 $dirthemes = array('/doctemplates/websites');
499 if (!empty($conf->modules_parts['websitetemplates'])) { // Using this feature slow down application
500 foreach ($conf->modules_parts['websitetemplates'] as $reldir) {
501 $dirthemes = array_merge($dirthemes, (array) ($reldir.'doctemplates/websites'));
502 }
503 }
504 $dirthemes = array_unique($dirthemes);
505
506
507 // Delete template files and dir
508 $mode = 'importsite';
509 $action = 'importsite';
510
511 if (count($dirthemes)) {
512 $i = 0;
513 foreach ($dirthemes as $dir) {
514 //print $dirroot.$dir;exit;
515 $dirtheme = DOL_DATA_ROOT.$dir; // This include loop on $conf->file->dol_document_root
516 if (is_dir($dirtheme)) {
517 $templateuserfile = GETPOST('templateuserfile');
518 $imguserfile = preg_replace('/\.zip$/', '', $templateuserfile).'.jpg';
519 dol_delete_file($dirtheme.'/'.$templateuserfile);
520 dol_delete_file($dirtheme.'/'.$imguserfile);
521 }
522 }
523 }
524}
525
526// Set category
527if ($massaction == 'setcategory' && GETPOST('confirmmassaction', 'alpha') && $usercanedit) {
528 $error = 0;
529 $nbupdate = 0;
530
531 $db->begin();
532
533 $categoryid = GETPOSTINT('setcategory');
534 if ($categoryid > 0) {
535 $tmpwebsitepage = new WebsitePage($db);
536 $category = new Categorie($db);
537 $category->fetch($categoryid);
538
539 foreach ($toselect as $tmpid) {
540 $tmpwebsitepage->id = (int) $tmpid;
541 $result = $category->add_type($tmpwebsitepage, 'website_page');
542 if ($result < 0 && $result != -3) {
543 $error++;
544 setEventMessages($category->error, $category->errors, 'errors');
545 break;
546 } else {
547 $nbupdate++;
548 }
549 }
550 }
551
552 if ($error) {
553 $db->rollback();
554 } else {
555 if ($nbupdate) {
556 setEventMessages($langs->trans("RecordsModified", $nbupdate), null, 'mesgs');
557 }
558
559 $db->commit();
560 }
561 // Now we reload list
562 $listofpages = getPagesFromSearchCriterias($containertype, $algo, $searchkey, 1000, $sortfield, $sortorder, $langcode, $otherfilters, -1);
563}
564
565// Del category
566if ($massaction == 'delcategory' && GETPOST('confirmmassaction', 'alpha') && $usercanedit) {
567 $error = 0;
568 $nbupdate = 0;
569
570 $db->begin();
571
572 $categoryid = GETPOSTINT('setcategory');
573 if ($categoryid > 0) {
574 $tmpwebsitepage = new WebsitePage($db);
575 $category = new Categorie($db);
576 $category->fetch($categoryid);
577
578 foreach ($toselect as $tmpid) {
579 $tmpwebsitepage->id = (int) $tmpid;
580 $result = $category->del_type($tmpwebsitepage, 'website_page');
581 if ($result < 0 && $result != -3) {
582 $error++;
583 setEventMessages($category->error, $category->errors, 'errors');
584 break;
585 } else {
586 $nbupdate++;
587 }
588 }
589 }
590
591 if ($error) {
592 $db->rollback();
593 } else {
594 if ($nbupdate) {
595 setEventMessages($langs->trans("RecordsModified", $nbupdate), null, 'mesgs');
596 }
597
598 $db->commit();
599 }
600 // Now we reload list
601 $listofpages = getPagesFromSearchCriterias($containertype, $algo, $searchkey, 1000, $sortfield, $sortorder, $langcode, $otherfilters, -1);
602}
603
604// Replacement of string into pages
605if ($massaction == 'replace' && GETPOST('confirmmassaction', 'alpha') && $usercanedit) {
606 $replacestring = GETPOST('replacestring', 'restricthtmlallowunvalid'); // or 'none', must be same then $searchstring
607
608 $dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT);
609 $allowimportsite = true;
610 if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) {
611 $allowimportsite = false;
612 }
613
614 if (!$allowimportsite) {
615 // Blocked by installmodules.lock
616 if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) {
617 // Show clean corporate message
618 $message = $langs->trans('InstallModuleFromWebHasBeenDisabledContactUs');
619 } else {
620 // Show technical generic message
621 $message = $langs->trans("InstallModuleFromWebHasBeenDisabledByFile", $dolibarrdataroot.'/installmodules.lock');
622 }
623 setEventMessages($message, null, 'errors');
624 } elseif (!$user->hasRight('website', 'writephp')) {
625 setEventMessages("NotAllowedToAddDynamicContent", null, 'errors');
626 } elseif (!$replacestring) {
627 setEventMessages("ErrorReplaceStringEmpty", null, 'errors');
628 } else {
629 $nbreplacement = 0;
630
631 foreach ($toselect as $keyselected) {
632 $objectpage = $listofpages['list'][$keyselected];
633 if ($objectpage->pageurl) {
634 dol_syslog("Replace string into page ".$objectpage->pageurl);
635
636 if (GETPOST('optionpagecontent', 'aZ09')) {
637 $objectpage->content = str_replace($searchkey, $replacestring, $objectpage->content);
638 }
639 if (GETPOST('optionmeta', 'aZ09')) {
640 $objectpage->title = str_replace($searchkey, $replacestring, $objectpage->title);
641 $objectpage->description = str_replace($searchkey, $replacestring, $objectpage->description);
642 $objectpage->keywords = str_replace($searchkey, $replacestring, $objectpage->keywords);
643 }
644
645 $filealias = $pathofwebsite.'/'.$objectpage->pageurl.'.php';
646 $filetpl = $pathofwebsite.'/page'.$objectpage->id.'.tpl.php';
647
648 // Save page alias
649 $result = dolSavePageAlias($filealias, $object, $objectpage);
650 if (!$result) {
651 setEventMessages('Failed to write file '.basename($filealias), null, 'errors');
652 }
653
654 // Save page of content
655 $result = dolSavePageContent($filetpl, $object, $objectpage, 1);
656 if ($result) {
657 $nbreplacement++;
658 //var_dump($objectpage->content);exit;
659 $objectpage->update($user);
660 } else {
661 $error++;
662 setEventMessages('Failed to write file '.$filetpl, null, 'errors');
663 $action = 'createcontainer';
664 break;
665 }
666 }
667 }
668
669 if ($nbreplacement > 0) {
670 setEventMessages($langs->trans("ReplacementDoneInXPages", $nbreplacement), null, 'mesgs');
671 }
672
673 $containertype = GETPOST('optioncontainertype', 'aZ09') != '-1' ? GETPOST('optioncontainertype', 'aZ09') : '';
674 $langcode = GETPOST('optionlanguage', 'aZ09');
675 $otherfilters = array();
676 if (GETPOSTINT('optioncategory') > 0) {
677 $otherfilters['category'] = GETPOSTINT('optioncategory');
678 }
679
680 // Now we reload list
681 $listofpages = getPagesFromSearchCriterias($containertype, $algo, $searchkey, 1000, $sortfield, $sortorder, $langcode, $otherfilters);
682 }
683}
684
685
686// Add directory
687/*
688if ($action == 'adddir' && $permtouploadfile)
689{
690 $ecmdir->ref = 'NOTUSEDYET';
691 $ecmdir->label = GETPOST("label");
692 $ecmdir->description = GETPOST("desc");
693
694 //$id = $ecmdir->create($user);
695 if ($id > 0)
696 {
697 header("Location: ".$_SERVER["PHP_SELF"]);
698 exit;
699 }
700 else
701 {
702 setEventMessages('Error '.$langs->trans($ecmdir->error), null, 'errors');
703 $action = "createcontainer";
704 }
705
706 clearstatcache();
707}
708*/
709
710// Add a website
711if ($action == 'addsite' && $usercanedit) {
712 $db->begin();
713
714 if (GETPOST('virtualhost', 'alpha') && !preg_match('/^http/', GETPOST('virtualhost', 'alpha'))) {
715 $error++;
716 setEventMessages($langs->trans('ErrorURLMustStartWithHttp', $langs->transnoentitiesnoconv("VirtualHost")), null, 'errors');
717 }
718
719 if (!$error && !GETPOST('WEBSITE_REF', 'alpha')) {
720 $error++;
721 $langs->load("errors");
722 setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities("WebsiteName")), null, 'errors');
723 }
724 if (!$error && !preg_match('/^[a-z0-9_\-\.]+$/i', GETPOST('WEBSITE_REF', 'alpha'))) {
725 $error++;
726 $langs->load("errors");
727 setEventMessages($langs->transnoentities("ErrorFieldCanNotContainSpecialCharacters", $langs->transnoentities("Ref")), null, 'errors');
728 }
729
730 $tmpobject = null;
731 if (!$error) {
732 $arrayotherlang = explode(',', GETPOST('WEBSITE_OTHERLANG', 'alphanohtml'));
733 foreach ($arrayotherlang as $key => $val) {
734 // It possible we have empty val here if postparam WEBSITE_OTHERLANG is empty or set like this : 'en,,sv' or 'en,sv,'
735 if (empty(trim($val))) {
736 continue;
737 }
738 $arrayotherlang[$key] = substr(trim($val), 0, 2); // Kept short language code only
739 }
740
741 $tmpobject = new Website($db);
742 $tmpobject->ref = GETPOST('WEBSITE_REF', 'alpha');
743 $tmpobject->description = GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml');
744 $tmpobject->lang = GETPOST('WEBSITE_LANG', 'aZ09');
745 $tmpobject->otherlang = implode(',', $arrayotherlang);
746 $tmpobject->virtualhost = GETPOST('virtualhost', 'alpha');
747
748 $result = $tmpobject->create($user);
749 if ($result == 0) {
750 $error++;
751 setEventMessages($langs->trans("ErrorLabelAlreadyExists"), null, 'errors');
752 } elseif ($result < 0) {
753 $error++;
754 setEventMessages($tmpobject->error, $tmpobject->errors, 'errors');
755 }
756 }
757
758 if (!$error && $tmpobject !== null) {
759 $db->commit();
760 setEventMessages($langs->trans("SiteAdded", $object->ref), null, 'mesgs');
761 $action = '';
762
763 header("Location: ".$_SERVER["PHP_SELF"].'?website='.$tmpobject->ref);
764 exit;
765 } else {
766 $db->rollback();
767 $action = 'createsite';
768 }
769
770 if (!$error) {
771 $action = 'preview';
772 $id = $object->id;
773 }
774}
775
776'@phan-var-force int $error';
777
778// Add page/container
779if ($action == 'addcontainer' && $usercanedit) {
780 dol_mkdir($pathofwebsite);
781
782 $db->begin();
783
784 $objectpage->fk_website = $object->id;
785 $objectpage->status = $objectpage::STATUS_DRAFT;
786
787 if (GETPOSTISSET('fetchexternalurl')) { // Fetch from external url
788 $urltograb = GETPOST('externalurl', 'alpha');
789 $grabimages = GETPOSTINT('grabimages') ? 1 : 0;
790 $grabimagesinto = GETPOST('grabimagesinto', 'alpha');
791
792 include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
793 // The include seems to break typing on variables
794
795 if (empty($urltograb)) {
796 $error++;
797 $langs->load("errors");
798 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("URL")), null, 'errors');
799 $action = 'createcontainer';
800 } elseif (!preg_match('/^http/', $urltograb)) {
801 $error++;
802 $langs->load("errors");
803 setEventMessages('Error URL must start with http:// or https://', null, 'errors');
804 $action = 'createcontainer';
805 }
806
807 $pageurl = '';
808 $urltograbdirwithoutslash = '';
809 $urltograbdirrootwithoutslash = '';
810 if (!$error) {
811 // Clean url to grab, so url can be
812 // http://www.example.com/ or http://www.example.com/dir1/ or http://www.example.com/dir1/aaa
813 $urltograbwithoutdomainandparam = preg_replace('/^https?:\/\/[^\/]+\/?/i', '', $urltograb);
814 //$urltograbwithoutdomainandparam = preg_replace('/^file:\/\/[^\/]+\/?/i', '', $urltograb);
815 $urltograbwithoutdomainandparam = preg_replace('/\?.*$/', '', $urltograbwithoutdomainandparam);
816 if (empty($urltograbwithoutdomainandparam) && !preg_match('/\/$/', $urltograb)) {
817 $urltograb .= '/';
818 }
819 $pageurl = dol_sanitizeFileName(preg_replace('/[\/\.]/', '-', preg_replace('/\/+$/', '', $urltograbwithoutdomainandparam)));
820
821 $urltograbdirwithoutslash = dirname($urltograb.'.');
822 $urltograbdirrootwithoutslash = getRootURLFromURL($urltograbdirwithoutslash);
823 // Example, now $urltograbdirwithoutslash is https://www.dolimed.com/screenshots
824 // and $urltograbdirrootwithoutslash is https://www.dolimed.com
825 }
826
827 // Check pageurl is not already used
828 if ($pageurl) {
829 $tmpwebsitepage = new WebsitePage($db);
830 $result = $tmpwebsitepage->fetch(0, (string) $object->id, $pageurl);
831 if ($result > 0) {
832 setEventMessages($langs->trans("AliasPageAlreadyExists", $pageurl), null, 'errors');
833 $error++;
834 $action = 'createcontainer';
835 }
836 }
837
838 if (!$error) {
839 // Download URL to grab
840 $tmp = getURLContent($urltograb, 'GET', '', 1, array(), array('http', 'https'), 0);
841
842 // Test charset of result and convert it into UTF-8 if not in this encoding charset
843 if (!empty($tmp['content_type']) && preg_match('/ISO-8859-1/', $tmp['content_type'])) {
844 if (function_exists('mb_check_encoding')) {
845 if (mb_check_encoding($tmp['content'], 'ISO-8859-1')) {
846 // This is a ISO-8829-1 encoding string
847 $tmp['content'] = mb_convert_encoding($tmp['content'], 'ISO-8859-1', 'UTF-8');
848 } else {
849 $error++;
850 setEventMessages('Error getting '.$urltograb.': content seems non valid ISO-8859-1', null, 'errors');
851 $action = 'createcontainer';
852 }
853 } else {
854 $error++;
855 setEventMessages('Error getting '.$urltograb.': content seems ISO-8859-1 but functions to convert into UTF-8 are not available in your PHP', null, 'errors');
856 $action = 'createcontainer';
857 }
858 }
859 if (empty($tmp['content_type']) || (!empty($tmp['content_type']) && preg_match('/UTF-8/', $tmp['content_type']))) {
860 if (function_exists('mb_check_encoding')) {
861 if (mb_check_encoding($tmp['content'], 'UTF-8')) {
862 // This is a UTF8 or ASCII compatible string
863 } else {
864 $error++;
865 setEventMessages('Error getting '.$urltograb.': content seems not a valid UTF-8', null, 'errors');
866 $action = 'createcontainer';
867 }
868 }
869 }
870
871 if (!empty($tmp['curl_error_no'])) {
872 $error++;
873 setEventMessages('Error getting '.$urltograb.': '.$tmp['curl_error_msg'], null, 'errors');
874 $action = 'createcontainer';
875 } elseif ($tmp['http_code'] != 200) {
876 $error++;
877 setEventMessages('Error getting '.$urltograb.': '.$tmp['http_code'], null, 'errors');
878 $action = 'createcontainer';
879 } else {
880 // Remove comments
881 $tmp['content'] = removeHtmlComment($tmp['content']);
882
883 /* disable this, moved into the create() method
884 // Check there is no PHP content into the imported file (must be only HTML + JS)
885 $phpcontent = dolKeepOnlyPhpCode($tmp['content']);
886 if ($phpcontent) {
887 $error++;
888 setEventMessages('Error getting '.$urltograb.': file that include PHP content is not allowed', null, 'errors');
889 $action = 'createcontainer';
890 }
891 */
892 }
893
894 if (!$error) {
895 $regs = array();
896
897 preg_match('/<head>(.*)<\/head>/ims', $tmp['content'], $regs);
898 $head = $regs[1];
899
900 $objectpage->type_container = 'page';
901 $objectpage->pageurl = $pageurl;
902 if (empty($objectpage->pageurl)) {
903 $tmpdomain = getDomainFromURL($urltograb);
904 $objectpage->pageurl = $tmpdomain.'-home';
905 }
906
907 $objectpage->aliasalt = '';
908
909 if (preg_match('/^(\d+)\-/', basename($urltograb), $regs)) {
910 $objectpage->aliasalt = $regs[1];
911 }
912
913 $regtmp = array();
914 if (preg_match('/<title>(.*)<\/title>/ims', $head, $regtmp)) {
915 $objectpage->title = $regtmp[1];
916 }
917 if (preg_match('/<meta name="title"[^"]+content="([^"]+)"/ims', $head, $regtmp)) {
918 if (empty($objectpage->title)) {
919 $objectpage->title = $regtmp[1]; // If title not found into <title>, we get it from <meta title>
920 }
921 }
922 if (preg_match('/<meta name="description"[^"]+content="([^"]+)"/ims', $head, $regtmp)) {
923 $objectpage->description = $regtmp[1];
924 }
925 if (preg_match('/<meta name="keywords"[^"]+content="([^"]+)"/ims', $head, $regtmp)) {
926 $objectpage->keywords = $regtmp[1];
927 }
928 if (preg_match('/<html\s+lang="([^"]+)"/ims', $tmp['content'], $regtmp)) {
929 $tmplang = explode('-', $regtmp[1]);
930 $objectpage->lang = $tmplang[0].(empty($tmplang[1]) ? '' : '_'.strtoupper($tmplang[1]));
931 }
932
933 $tmp['content'] = preg_replace('/\s*<meta name="generator"[^"]+content="([^"]+)"\s*\/?>/ims', '', $tmp['content']);
934
935 $objectpage->content = $tmp['content'];
936 $objectpage->content = preg_replace('/^.*<body(\s[^>]*)*>/ims', '', $objectpage->content);
937 $objectpage->content = preg_replace('/<\/body(\s[^>]*)*>.*$/ims', '', $objectpage->content);
938
939 // TODO Replace 'action="$urltograbdirwithoutslash' into action="/"
940 // TODO Replace 'action="$urltograbdirwithoutslash..."' into action="..."
941 // TODO Replace 'a href="$urltograbdirwithoutslash' into a href="/"
942 // TODO Replace 'a href="$urltograbdirwithoutslash..."' into a href="..."
943
944 // Now loop to fetch all css files. Include them inline into header of page
945 $objectpage->htmlheader = $tmp['content'];
946 $objectpage->htmlheader = preg_replace('/^.*<head(\s[^>]*)*>/ims', '', $objectpage->htmlheader);
947 $objectpage->htmlheader = preg_replace('/<\/head(\s[^>]*)*>.*$/ims', '', $objectpage->htmlheader);
948 $objectpage->htmlheader = preg_replace('/<base(\s[^>]*)*>\n*/ims', '', $objectpage->htmlheader);
949 $objectpage->htmlheader = preg_replace('/<meta http-equiv="content-type"([^>]*)*>\n*/ims', '', $objectpage->htmlheader);
950 $objectpage->htmlheader = preg_replace('/<meta name="robots"([^>]*)*>\n*/ims', '', $objectpage->htmlheader);
951 $objectpage->htmlheader = preg_replace('/<meta name="title"([^>]*)*>\n*/ims', '', $objectpage->htmlheader);
952 $objectpage->htmlheader = preg_replace('/<meta name="description"([^>]*)*>\n*/ims', '', $objectpage->htmlheader);
953 $objectpage->htmlheader = preg_replace('/<meta name="keywords"([^>]*)*>\n*/ims', '', $objectpage->htmlheader);
954 $objectpage->htmlheader = preg_replace('/<meta name="generator"([^>]*)*>\n*/ims', '', $objectpage->htmlheader);
955 //$objectpage->htmlheader = preg_replace('/<meta name="verify-v1[^>]*>\n*/ims', '', $objectpage->htmlheader);
956 //$objectpage->htmlheader = preg_replace('/<meta name="msvalidate.01[^>]*>\n*/ims', '', $objectpage->htmlheader);
957 $objectpage->htmlheader = preg_replace('/<title>[^<]*<\/title>\n*/ims', '', $objectpage->htmlheader);
958 $objectpage->htmlheader = preg_replace('/<link[^>]*rel="shortcut[^>]*>\n/ims', '', $objectpage->htmlheader);
959 $objectpage->htmlheader = preg_replace('/<link[^>]*rel="alternate[^>]*>\n/ims', '', $objectpage->htmlheader);
960 $objectpage->htmlheader = preg_replace('/<link[^>]*rel="canonical[^>]*>\n/ims', '', $objectpage->htmlheader);
961
962 // Now loop to fetch JS
963 $tmp = $objectpage->htmlheader;
964
965 // We grab files found into <script> tags
966 preg_match_all('/<script([^\.>]+)src=["\']([^"\'>]+)["\']([^>]*)><\/script>/i', $objectpage->htmlheader, $regs);
967 $errorforsubresource = 0;
968 foreach ($regs[0] as $key => $val) {
969 dol_syslog("We will grab the script resource found into script tag ".$regs[2][$key]);
970
971 $linkwithoutdomain = $regs[2][$key];
972 if (preg_match('/^\//', $regs[2][$key])) {
973 $urltograbbis = $urltograbdirrootwithoutslash.$regs[2][$key]; // We use dirroot
974 } else {
975 $urltograbbis = $urltograbdirwithoutslash.'/'.$regs[2][$key]; // We use dir of grabbed file
976 }
977
978 //$filetosave = $conf->medias->multidir_output[$conf->entity].'/css/'.$object->ref.'/'.$objectpage->pageurl.(preg_match('/^\//', $regs[2][$key])?'':'/').$regs[2][$key];
979 if (preg_match('/^http/', $regs[2][$key])) {
980 $urltograbbis = $regs[2][$key];
981 $linkwithoutdomain = preg_replace('/^https?:\/\/[^\/]+\//i', '', $regs[2][$key]);
982 //$filetosave = $conf->medias->multidir_output[$conf->entity].'/css/'.$object->ref.'/'.$objectpage->pageurl.(preg_match('/^\//', $linkwithoutdomain)?'':'/').$linkwithoutdomain;
983 }
984
985 //print $domaintograb.' - '.$domaintograbbis.' - '.$urltograbdirwithoutslash.' - ';
986 //print $linkwithoutdomain.' - '.$urltograbbis."<br>\n";
987
988 // Test if this is an external URL of grabbed web site. If yes, we do not load resource
989 $domaintograb = getDomainFromURL($urltograbdirwithoutslash);
990 $domaintograbbis = getDomainFromURL($urltograbbis);
991 if ($domaintograb != $domaintograbbis) {
992 continue;
993 }
994
995 /*
996 $tmpgeturl = getURLContent($urltograbbis, 'GET', '', 1, array(), array('http', 'https'), 0);
997 if (!empty($tmpgeturl['curl_error_no']))
998 {
999 $error++;
1000 setEventMessages('Error getting script url '.$urltograbbis.': '.$tmpgeturl['curl_error_msg'], null, 'errors');
1001 $errorforsubresource++;
1002 $action='createcontainer';
1003 }
1004 elseif ($tmpgeturl['http_code'] != 200)
1005 {
1006 $error++;
1007 setEventMessages('Error getting script url '.$urltograbbis.': '.$tmpgeturl['http_code'], null, 'errors');
1008 $errorforsubresource++;
1009 $action='createcontainer';
1010 }
1011 else
1012 {
1013 dol_mkdir(dirname($filetosave));
1014
1015 $fp = fopen($filetosave, "w");
1016 fputs($fp, $tmpgeturl['content']);
1017 fclose($fp);
1018 dolChmod($file);
1019 }
1020 */
1021
1022 //$filename = 'image/'.$object->ref.'/'.$objectpage->pageurl.(preg_match('/^\//', $linkwithoutdomain)?'':'/').$linkwithoutdomain;
1023 $tmp = preg_replace('/'.preg_quote($regs[0][$key], '/').'/i', '', $tmp);
1024 }
1025 $objectpage->htmlheader = trim($tmp)."\n";
1026
1027
1028 // Now we grab CSS found into <link> tags
1029 $pagecsscontent = "\n".'<style>'."\n";
1030
1031 preg_match_all('/<link([^\.>]+)href=["\']([^"\'>]+\.css[^"\'>]*)["\']([^>]*)>/i', $objectpage->htmlheader, $regs);
1032 $errorforsubresource = 0;
1033 foreach ($regs[0] as $key => $val) {
1034 dol_syslog("We will grab the css resources found into link tag ".$regs[2][$key]);
1035
1036 $linkwithoutdomain = $regs[2][$key];
1037 if (preg_match('/^\//', $regs[2][$key])) {
1038 $urltograbbis = $urltograbdirrootwithoutslash.$regs[2][$key]; // We use dirroot
1039 } else {
1040 $urltograbbis = $urltograbdirwithoutslash.'/'.$regs[2][$key]; // We use dir of grabbed file
1041 }
1042
1043 //$filetosave = $conf->medias->multidir_output[$conf->entity].'/css/'.$object->ref.'/'.$objectpage->pageurl.(preg_match('/^\//', $regs[2][$key])?'':'/').$regs[2][$key];
1044 if (preg_match('/^http/', $regs[2][$key])) {
1045 $urltograbbis = $regs[2][$key];
1046 $linkwithoutdomain = preg_replace('/^https?:\/\/[^\/]+\//i', '', $regs[2][$key]);
1047 //$filetosave = $conf->medias->multidir_output[$conf->entity].'/css/'.$object->ref.'/'.$objectpage->pageurl.(preg_match('/^\//', $linkwithoutdomain)?'':'/').$linkwithoutdomain;
1048 }
1049
1050 //print $domaintograb.' - '.$domaintograbbis.' - '.$urltograbdirwithoutslash.' - ';
1051 //print $linkwithoutdomain.' - '.$urltograbbis."<br>\n";
1052
1053 // Test if this is an external URL of grabbed web site. If yes, we do not load resource
1054 $domaintograb = getDomainFromURL($urltograbdirwithoutslash);
1055 $domaintograbbis = getDomainFromURL($urltograbbis);
1056 if ($domaintograb != $domaintograbbis) {
1057 continue;
1058 }
1059
1060 $tmpgeturl = getURLContent($urltograbbis, 'GET', '', 1, array(), array('http', 'https'), 0);
1061 if (!empty($tmpgeturl['curl_error_no'])) {
1062 $errorforsubresource++;
1063 setEventMessages('Error getting link tag url '.$urltograbbis.': '.$tmpgeturl['curl_error_msg'], null, 'errors');
1064 dol_syslog('Error getting '.$urltograbbis.': '.$tmpgeturl['curl_error_msg']);
1065 $action = 'createcontainer';
1066 } elseif ($tmpgeturl['http_code'] != 200) {
1067 $errorforsubresource++;
1068 setEventMessages('Error getting link tag url '.$urltograbbis.': '.$tmpgeturl['http_code'], null, 'errors');
1069 dol_syslog('Error getting '.$urltograbbis.': '.$tmpgeturl['curl_error_msg']);
1070 $action = 'createcontainer';
1071 } else {
1072 // Clean some comment
1073 //$tmpgeturl['content'] = dol_string_is_good_iso($tmpgeturl['content'], 1);
1074 //$tmpgeturl['content'] = mb_convert_encoding($tmpgeturl['content'], 'UTF-8', 'UTF-8');
1075 //$tmpgeturl['content'] = remove_bs($tmpgeturl['content']);
1076 //$tmpgeturl['content'] = str_replace('$screen-md-max', 'auto', $tmpgeturl['content']);
1077
1078 //var_dump($tmpgeturl['content']);exit;
1079 $tmpgeturl['content'] = preg_replace('/\/\*\s+CSS content[a-z\s]*\s+\*\//', '', $tmpgeturl['content']);
1080
1081 //dol_mkdir(dirname($filetosave));
1082
1083 //$fp = fopen($filetosave, "w");
1084 //fputs($fp, $tmpgeturl['content']);
1085 //fclose($fp);
1086 //dolChmod($file);
1087
1088 // $filename = 'image/'.$object->ref.'/'.$objectpage->pageurl.(preg_match('/^\//', $linkwithoutdomain)?'':'/').$linkwithoutdomain;
1089 $pagecsscontent .= "\n".'/* Content of file '.$urltograbbis.' */'."\n";
1090
1091 getAllImages($object, $objectpage, $urltograbbis, $tmpgeturl['content'], $action, 1, $grabimages, $grabimagesinto);
1092
1093 // We try to convert the CSS we got by adding a prefix .bodywebsite with lessc to avoid conflict with CSS of Dolibarr.
1094 include_once DOL_DOCUMENT_ROOT.'/core/class/lessc.class.php';
1095 $lesscobj = new Lessc();
1096 try {
1097 $contentforlessc = ".bodywebsite {\n".$tmpgeturl['content']."\n}\n";
1098 //print '<pre>'.$contentforlessc.'</pre>';
1099 $contentforlessc = $lesscobj->compile($contentforlessc);
1100 //var_dump($contentforlessc); exit;
1101
1102 $pagecsscontent .= $contentforlessc."\n";
1103 //$pagecsscontent.=$tmpgeturl['content']."\n";
1104 } catch (Exception $e) {
1105 //echo "failed to compile lessc";
1106 dol_syslog("Failed to compile the CSS from URL ".$urltograbbis." with lessc: ".$e->getMessage(), LOG_WARNING);
1107 $pagecsscontent .= $tmpgeturl['content']."\n";
1108 }
1109
1110 $objectpage->htmlheader = preg_replace('/'.preg_quote($regs[0][$key], '/').'\n*/ims', '', $objectpage->htmlheader);
1111 }
1112 }
1113
1114 $pagecsscontent .= '</style>';
1115 //var_dump($pagecsscontent);
1116
1117 //print dol_escape_htmltag($tmp);exit;
1118 $objectpage->htmlheader .= trim($pagecsscontent)."\n";
1119
1120
1121 // Now we have to fetch all images into page
1122 $tmp = $objectpage->content;
1123
1124 getAllImages($object, $objectpage, $urltograb, $tmp, $action, 1, $grabimages, $grabimagesinto);
1125
1126 // Normalize links href to Dolibarr internal naming
1127 $tmp = preg_replace('/a href="\/([^\/"]+)\/([^\/"]+)"/', 'a href="/\1-\2.php"', $tmp);
1128 $tmp = preg_replace('/a href="\/([^\/"]+)\/([^\/"]+)\/([^\/"]+)"/', 'a href="/\1-\2-\3.php"', $tmp);
1129 $tmp = preg_replace('/a href="\/([^\/"]+)\/([^\/"]+)\/([^\/"]+)\/([^\/"]+)"/', 'a href="/\1-\2-\3-\4.php"', $tmp);
1130
1131 //print dol_escape_htmltag($tmp);exit;
1132 $objectpage->content = $tmp;
1133
1134 $objectpage->grabbed_from = $urltograb;
1135 }
1136 }
1137 } else { // add website from scratch
1138 $newaliasnames = '';
1139 if (!$error && GETPOST('WEBSITE_ALIASALT', 'alpha')) {
1140 $arrayofaliastotest = explode(',', str_replace(array('<', '>'), '', GETPOST('WEBSITE_ALIASALT', 'alpha')));
1141 $websitepagetemp = new WebsitePage($db);
1142 foreach ($arrayofaliastotest as $aliastotest) {
1143 $aliastotest = trim(preg_replace('/\.php$/i', '', $aliastotest));
1144
1145 // Disallow alias name pageX (already used to save the page with id)
1146 if (preg_match('/^page\d+/i', $aliastotest)) {
1147 $error++;
1148 $langs->load("errors");
1149 setEventMessages("Alias name 'pageX' is not allowed", null, 'errors');
1150 $action = 'createcontainer';
1151 break;
1152 } else {
1153 $result = $websitepagetemp->fetch(0, (string) $object->id, $aliastotest);
1154 if ($result < 0) {
1155 $error++;
1156 $langs->load("errors");
1157 setEventMessages($websitepagetemp->error, $websitepagetemp->errors, 'errors');
1158 $action = 'createcontainer';
1159 break;
1160 }
1161 if ($result > 0) {
1162 $error++;
1163 $langs->load("errors");
1164 setEventMessages($langs->trans("ErrorAPageWithThisNameOrAliasAlreadyExists", $websitepagetemp->pageurl), null, 'errors');
1165 $action = 'createcontainer';
1166 break;
1167 }
1168 $newaliasnames .= ($newaliasnames ? ', ' : '').$aliastotest;
1169 }
1170 }
1171 }
1172
1173 $objectpage->title = str_replace(array('<', '>'), '', GETPOST('WEBSITE_TITLE', 'alphanohtml'));
1174 $objectpage->type_container = GETPOST('WEBSITE_TYPE_CONTAINER', 'aZ09');
1175 $objectpage->pageurl = dol_sanitizeUrl(GETPOST('WEBSITE_PAGENAME', 'alpha'));
1176 $objectpage->ref = $objectpage->pageurl;
1177 $objectpage->aliasalt = $newaliasnames;
1178 $objectpage->description = str_replace(array('<', '>'), '', GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml'));
1179 $objectpage->lang = GETPOST('WEBSITE_LANG', 'aZ09');
1180 $objectpage->otherlang = GETPOST('WEBSITE_OTHERLANG', 'aZ09comma');
1181 $objectpage->image = GETPOST('WEBSITE_IMAGE', 'alpha');
1182 $objectpage->keywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml'));
1183 $objectpage->allowed_in_frames = GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09') ? 1 : 0;
1184 $objectpage->htmlheader = GETPOST('htmlheader', 'restricthtmlallowlinkscript'); // Must accept tags like '<script>' and '<link>'
1185
1186 $objectpage->author_alias = GETPOST('WEBSITE_AUTHORALIAS', 'alphanohtml');
1187 $objectpage->object_type = GETPOST('WEBSITE_OBJECTCLASS');
1188 $objectpage->fk_object = GETPOST('WEBSITE_OBJECTID');
1189 $substitutionarray = array();
1190 $substitutionarray['__WEBSITE_CREATED_BY__'] = $user->getFullName($langs);
1191
1192 // Define id of the page the new page is translation of
1193 /*
1194 if ($objectpage->lang == $object->lang) {
1195 // If
1196 $pageidfortranslation = (GETPOSTINT('pageidfortranslation') > 0 ? GETPOSTINT('pageidfortranslation') : 0);
1197 if ($pageidfortranslation > 0) {
1198 // We must update the page $pageidfortranslation to set fk_page = $object->id.
1199 // But what if page $pageidfortranslation is already linked to another ?
1200 }
1201 } else {
1202 */
1203 $pageidfortranslation = (GETPOSTINT('pageidfortranslation') > 0 ? GETPOSTINT('pageidfortranslation') : 0);
1204 if ($pageidfortranslation > 0) {
1205 // Check if the page we are translation of is already a translation of a source page. if yes, we will use source id instead
1206 $objectpagetmp = new WebsitePage($db);
1207 $objectpagetmp->fetch($pageidfortranslation);
1208 if ($objectpagetmp->fk_page > 0) {
1209 $pageidfortranslation = $objectpagetmp->fk_page;
1210 }
1211 }
1212 $objectpage->fk_page = $pageidfortranslation;
1213 //}
1214
1215 $content = '';
1216 if (GETPOSTISSET('content')) {
1217 //$content = GETPOST('content', 'restricthtmlallowunvalid'); // @TODO Use a restricthtmlallowunvalidwithphp
1218 $content = GETPOST('content', 'none'); // @TODO Use a restricthtmlallowunvalidwithphp
1219
1220 $objectpage->content = make_substitutions($content, $substitutionarray);
1221 } else {
1222 /*$sample = GETPOST('sample', 'alpha');
1223 if (empty($sample)) {
1224 $sample = 'empty';
1225 }
1226
1227 $pathtosample = DOL_DOCUMENT_ROOT.'/website/samples/page-sample-'.dol_sanitizeFileName(strtolower($sample)).'.html';
1228 */
1229 // Init content with content into page-sample-...
1230 //$objectpage->content = make_substitutions(@file_get_contents($pathtosample), $substitutionarray);
1231 }
1232 }
1233
1234 if (!$error) {
1235 if (empty($objectpage->pageurl)) {
1236 $langs->load("errors");
1237 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("WEBSITE_PAGENAME")), null, 'errors');
1238 $error++;
1239 $action = 'createcontainer';
1240 } elseif (!preg_match('/^[a-z0-9\-\_]+$/i', $objectpage->pageurl)) {
1241 $langs->load("errors");
1242 setEventMessages($langs->transnoentities("ErrorFieldCanNotContainSpecialCharacters", $langs->transnoentities('WEBSITE_PAGENAME')), null, 'errors');
1243 $error++;
1244 $action = 'createcontainer';
1245 }
1246 if (empty($objectpage->title)) {
1247 $langs->load("errors");
1248 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("WEBSITE_TITLE")), null, 'errors');
1249 $error++;
1250 $action = 'createcontainer';
1251 }
1252 if ($objectpage->fk_page > 0 && empty($objectpage->lang)) {
1253 $langs->load("errors");
1254 setEventMessages($langs->trans("ErrorLanguageRequiredIfPageIsTranslationOfAnother"), null, 'errors');
1255 $error++;
1256 $action = 'createcontainer';
1257 }
1258 if ($objectpage->fk_page > 0 && !empty($objectpage->lang)) {
1259 if ($objectpage->lang == $website->lang) {
1260 $langs->load("errors");
1261 setEventMessages($langs->trans("ErrorLanguageMustNotBeSourceLanguageIfPageIsTranslationOfAnother"), null, 'errors');
1262 $error++;
1263 $action = 'createcontainer';
1264 }
1265 }
1266 }
1267
1268 $pageid = 0;
1269 if (!$error) {
1270 // Create page. This also check there is no PHP content if user has no pemrissions for that.
1271 $pageid = $objectpage->create($user);
1272 if ($pageid <= 0) {
1273 $error++;
1274 setEventMessages($objectpage->error, $objectpage->errors, 'errors');
1275 $action = 'createcontainer';
1276 }
1277 }
1278
1279 if (!$error) {
1280 // Website categories association
1281 $categoriesarray = GETPOST('categories', 'array:int');
1282 $result = $objectpage->setCategories($categoriesarray);
1283 if ($result < 0) {
1284 $error++;
1285 setEventMessages($object->error, $object->errors, 'errors');
1286 }
1287 }
1288
1289 if (!$error) {
1290 // If there is no home page yet, this new page will be set as the home page
1291 if (empty($object->fk_default_home)) {
1292 $object->fk_default_home = $pageid;
1293 $res = $object->update($user);
1294 if ($res <= 0) {
1295 $error++;
1296 setEventMessages($object->error, $object->errors, 'errors');
1297 } else {
1298 $filetpl = $pathofwebsite.'/page'.$pageid.'.tpl.php';
1299
1300 // Generate the index.php page (to be the home page) and the wrapper.php file
1301 $result = dolSaveIndexPage($pathofwebsite, $fileindex, $filetpl, $filewrapper, $object);
1302
1303 if ($result <= 0) {
1304 setEventMessages('Failed to write file '.$fileindex, null, 'errors');
1305 }
1306 }
1307 }
1308 }
1309
1310 if (!$error) {
1311 if ($pageid > 0) {
1312 $filealias = $pathofwebsite.'/'.$objectpage->pageurl.'.php';
1313 $filetpl = $pathofwebsite.'/page'.$objectpage->id.'.tpl.php';
1314
1315 // Save page alias
1316 $result = dolSavePageAlias($filealias, $object, $objectpage);
1317 if (!$result) {
1318 setEventMessages('Failed to write file '.basename($filealias), null, 'errors');
1319 }
1320
1321 // Save page of content
1322 $result = dolSavePageContent($filetpl, $object, $objectpage, 1);
1323 if ($result) {
1324 setEventMessages($langs->trans("Saved"), null, 'mesgs');
1325 } else {
1326 setEventMessages('Failed to write file '.$filetpl, null, 'errors');
1327 $action = 'createcontainer';
1328 }
1329 }
1330 }
1331
1332 if (!$error) {
1333 $db->commit();
1334 setEventMessages($langs->trans("PageAdded", $objectpage->pageurl), null, 'mesgs');
1335 $action = '';
1336 } else {
1337 $db->rollback();
1338 }
1339
1340 if (!$error) {
1341 $pageid = $objectpage->id;
1342
1343 // To generate the CSS, robot and htmlheader file.
1344
1345 // Check symlink documents/website/mywebsite/medias to point to documents/medias and restore it if ko.
1346 // Recreate also dir of website if not found.
1347 $pathtomedias = DOL_DATA_ROOT.'/medias';
1348 $pathtomediasinwebsite = $pathofwebsite.'/medias';
1349 if (!is_link(dol_osencode($pathtomediasinwebsite))) {
1350 dol_syslog("Create symlink for ".$pathtomedias." into name ".$pathtomediasinwebsite);
1351 dol_mkdir(dirname($pathtomediasinwebsite)); // To be sure that the directory for website exists
1352 $result = symlink($pathtomedias, $pathtomediasinwebsite);
1353 if (!$result) {
1354 $langs->load("errors");
1355 setEventMessages($langs->trans("ErrorFailedToCreateSymLinkToMedias", $pathtomediasinwebsite, $pathtomedias), null, 'errors');
1356 }
1357 }
1358
1359 // Now generate the master.inc.php page if it does not exists yet
1360 if (!dol_is_file($filemaster)) {
1361 $result = dolSaveMasterFile($filemaster);
1362 if (!$result) {
1363 $error++;
1364 setEventMessages('Failed to write file '.$filemaster, null, 'errors');
1365 }
1366 }
1367
1368 if (!dol_is_file($filehtmlheader)) {
1369 $htmlheadercontent = "<html>\n";
1370 $htmlheadercontent .= $htmlheadercontentdefault;
1371 $htmlheadercontent .= "</html>";
1372 $result = dolSaveHtmlHeader($filehtmlheader, $htmlheadercontent);
1373 }
1374
1375 if (!dol_is_file($filecss)) {
1376 $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;}";
1377 $result = dolSaveCssFile($filecss, $csscontent);
1378 }
1379
1380 if (!dol_is_file($filejs)) {
1381 $jscontent = "/* JS content (all pages) */\n";
1382 $result = dolSaveJsFile($filejs, $jscontent);
1383 }
1384
1385 if (!dol_is_file($filerobot)) {
1386 $robotcontent = "# Robot file. Generated with Dolibarr\nUser-agent: *\nAllow: /public/\nDisallow: /administrator/";
1387 $result = dolSaveRobotFile($filerobot, $robotcontent);
1388 }
1389
1390 if (!dol_is_file($filehtaccess)) {
1391 $htaccesscontent = "# Order allow,deny\n# Deny from all";
1392 $result = dolSaveHtaccessFile($filehtaccess, $htaccesscontent);
1393 }
1394
1395 if (!dol_is_file($filemanifestjson)) {
1396 $manifestjsoncontent = "";
1397 $result = dolSaveManifestJson($filemanifestjson, $manifestjsoncontent);
1398 }
1399
1400 if (!dol_is_file($filereadme)) {
1401 $readmecontent = "Website generated by Dolibarr ERP CRM";
1402 $result = dolSaveReadme($filereadme, $readmecontent);
1403 }
1404
1405 if (!dol_is_file($filelicense)) {
1406 $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/";
1407 $result = dolSaveLicense($filelicense, $licensecontent);
1408 }
1409
1410 $action = 'preview';
1411 }
1412}
1413
1414// Delete site
1415if ($action == 'confirm_deletesite' && $confirm == 'yes' && $permissiontodelete) {
1416 $error = 0;
1417
1418 $db->begin();
1419
1420 $res = $object->fetch(GETPOSTINT('id'));
1421 $website = $object;
1422
1423 if ($res > 0) {
1424 $res = $object->delete($user);
1425 if ($res <= 0) {
1426 $error++;
1427 setEventMessages($object->error, $object->errors, 'errors');
1428 }
1429 }
1430 if (!$error) {
1431 if (GETPOST('delete_also_js', 'alpha') == 'on') {
1432 $pathofwebsitejs = DOL_DATA_ROOT.'/medias/js/'.$object->ref;
1433
1434 dol_delete_dir_recursive($pathofwebsitejs);
1435 }
1436 if (GETPOST('delete_also_medias', 'alpha') == 'on') {
1437 $pathofwebsitemedias = DOL_DATA_ROOT.'/medias/image/'.$object->ref;
1438
1439 dol_delete_dir_recursive($pathofwebsitemedias);
1440 }
1441 }
1442
1443 if (!$error) {
1444 $db->commit();
1445 setEventMessages($langs->trans("SiteDeleted", $object->ref), null, 'mesgs');
1446
1447 header("Location: ".$_SERVER["PHP_SELF"].'?id='.$object->id);
1448 exit;
1449 } else {
1450 $db->rollback();
1451 setEventMessages($object->error, $object->errors, 'errors');
1452 }
1453}
1454
1455// Delete page (from website page menu)
1456if (GETPOSTISSET('pageid') && $action == 'delete' && $permissiontodelete && !GETPOST('file_manager')) {
1457 $error = 0;
1458
1459 $db->begin();
1460
1461 $res = $object->fetch(0, $websitekey);
1462 $website = $object;
1463
1464 $res = $objectpage->fetch($pageid, (string) $object->id);
1465
1466 if ($res > 0) {
1467 $res = $objectpage->delete($user);
1468 if ($res <= 0) {
1469 $error++;
1470 setEventMessages($objectpage->error, $objectpage->errors, 'errors');
1471 }
1472 }
1473
1474 if (!$error) {
1475 $db->commit();
1476 setEventMessages($langs->trans("PageDeleted", $objectpage->pageurl, $websitekey), null, 'mesgs');
1477
1478 header("Location: ".$_SERVER["PHP_SELF"].'?website='.$websitekey);
1479 exit;
1480 } else {
1481 $db->rollback();
1482 dol_print_error($db);
1483 }
1484}
1485// Delete page (from menu search)
1486if (!GETPOSTISSET('pageid')) {
1487 $objectclass = 'WebsitePage';
1488
1489 // Add part of code from actions_massactions.inc.php
1490 // Delete record from mass action (massaction = 'delete' for direct delete, action/confirm='delete'/'yes' with a confirmation step before)
1491 if (!$error && ($massaction == 'delete' || ($action == 'delete' && $confirm == 'yes')) && $permissiontodelete) {
1492 $db->begin();
1493
1494 $objecttmp = new $objectclass($db);
1495 $nbok = 0;
1496 foreach ($toselect as $toselectid) {
1497 $result = $objecttmp->fetch($toselectid);
1498 if ($result > 0) {
1499 $result = $objecttmp->delete($user);
1500
1501 if ($result <= 0) {
1502 setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
1503 $error++;
1504 break;
1505 } else {
1506 $nbok++;
1507 }
1508 } else {
1509 setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
1510 $error++;
1511 break;
1512 }
1513 }
1514
1515 if (!$error) {
1516 if ($nbok > 1) {
1517 setEventMessages($langs->trans("RecordsDeleted", $nbok), null, 'mesgs');
1518 } else {
1519 setEventMessages($langs->trans("RecordDeleted", $nbok), null, 'mesgs');
1520 }
1521 $db->commit();
1522 } else {
1523 $db->rollback();
1524 }
1525 //var_dump($listofobjectthirdparties);exit;
1526 }
1527
1528 if ($action == 'delete') { // Test on permission not required here
1529 $mode = 'replacesite';
1530 $action = 'replacesite';
1531
1532 $containertype = GETPOST('optioncontainertype', 'aZ09') != '-1' ? GETPOST('optioncontainertype', 'aZ09') : '';
1533 $langcode = GETPOST('optionlanguage', 'aZ09');
1534 $otherfilters = array();
1535 if (GETPOSTINT('optioncategory') > 0) {
1536 $otherfilters['category'] = GETPOSTINT('optioncategory');
1537 }
1538
1539 $listofpages = getPagesFromSearchCriterias($containertype, $algo, $searchkey, 1000, $sortfield, $sortorder, $langcode, $otherfilters);
1540 }
1541}
1542
1543// Update css site properties. Re-generates also the wrapper.
1544if ($action == 'updatecss' && $usercanedit) {
1545 // If we tried to reload another site/page, we stay on editcss mode.
1546 if (GETPOST('refreshsite') || GETPOST('refreshsite_x') || GETPOST('refreshsite.x') || GETPOST('refreshpage') || GETPOST('refreshpage_x') || GETPOST('refreshpage.x')) {
1547 $action = 'editcss';
1548 } else {
1549 $res = $object->fetch(0, $websitekey);
1550 $website = $object;
1551
1552 if (GETPOSTISSET('virtualhost')) {
1553 $tmpvirtualhost = preg_replace('/\/$/', '', GETPOST('virtualhost', 'alpha'));
1554 if ($tmpvirtualhost && !preg_match('/^http/', $tmpvirtualhost)) {
1555 $error++;
1556 setEventMessages($langs->trans('ErrorURLMustStartWithHttp', $langs->transnoentitiesnoconv("VirtualHost")), null, 'errors');
1557 $action = 'editcss';
1558 }
1559
1560 if (!$error) {
1561 $arrayotherlang = explode(',', GETPOST('WEBSITE_OTHERLANG', 'alphanohtml'));
1562 foreach ($arrayotherlang as $key => $val) {
1563 // It possible we have empty val here if postparam WEBSITE_OTHERLANG is empty or set like this : 'en,,sv' or 'en,sv,'
1564 if (empty(trim($val))) {
1565 continue;
1566 }
1567 $arrayotherlang[$key] = substr(trim($val), 0, 2); // Kept short language code only
1568 }
1569
1570 $object->virtualhost = $tmpvirtualhost;
1571 $object->lang = GETPOST('WEBSITE_LANG', 'aZ09');
1572 $object->otherlang = implode(',', $arrayotherlang);
1573 $object->use_manifest = GETPOSTINT('use_manifest');
1574
1575 $result = $object->update($user);
1576 if ($result < 0) {
1577 $error++;
1578 setEventMessages($object->error, $object->errors, 'errors');
1579 $action = 'editcss';
1580 }
1581 }
1582 }
1583
1584 if (!$error) {
1585 if (($_FILES['addedfile']["name"] != '')) {
1586 $uploadfolder = $conf->website->dir_output.'/'.$websitekey;
1587 if ($_FILES['addedfile']['type'] != 'image/png') {
1588 $error++;
1589 setEventMessages($langs->trans('ErrorFaviconType'), array(), 'errors');
1590 }
1591 $filetoread = realpath(dol_osencode($_FILES['addedfile']['tmp_name']));
1592 $filesize = getimagesize($filetoread);
1593 if ($filesize[0] != $filesize[1]) {
1594 $error++;
1595 setEventMessages($langs->trans('ErrorFaviconMustBeASquaredImage'), array(), 'errors');
1596 }
1597 if (! $error && ($filesize[0] != 16 && $filesize[0] != 32 && $filesize[0] != 64)) {
1598 $error++;
1599 setEventMessages($langs->trans('ErrorFaviconSize'), array(), 'errors');
1600 }
1601 if (!$error) {
1602 dol_add_file_process($uploadfolder, 1, 0, 'addedfile', 'favicon.png');
1603 }
1604 }
1605 if ($error) {
1606 if (!GETPOSTISSET('updateandstay')) { // If we click on "Save And Stay", we don not make the redirect
1607 $action = 'preview';
1608 if ($backtopage) {
1609 $backtopage = preg_replace('/searchstring=[^&]*/', '', $backtopage); // Clean backtopage url
1610 header("Location: ".$backtopage);
1611 exit;
1612 }
1613 } else {
1614 $action = 'editcss';
1615 }
1616 }
1617 }
1618
1619 if (!$error) {
1620 // Save master.inc.php file
1621 dol_syslog("Save master file ".$filemaster);
1622
1623 dol_mkdir($pathofwebsite);
1624
1625 // Now generate the master.inc.php page
1626 $result = dolSaveMasterFile($filemaster);
1627 if (!$result) {
1628 $error++;
1629 setEventMessages('Failed to write file '.$filemaster, null, 'errors');
1630 }
1631
1632
1633 $dataposted = trim(GETPOST('WEBSITE_HTML_HEADER', 'restricthtmlallowlinkscript')); // Must accept tags like '<script>' and '<link>'
1634
1635 $dataposted = preg_replace(array('/<html>\n*/ims', '/<\/html>\n*/ims'), array('', ''), $dataposted);
1636 $dataposted = str_replace('<?=', '<?php', $dataposted);
1637
1638 // Html header file
1639 $phpfullcodestringold = '';
1640 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1641
1642 // Security analysis
1643 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1644
1645 if (!$errorphpcheck) {
1646 $htmlheadercontent = '';
1647
1648 /* We disable php code since global htmlheader for all website is never executed as an include but only read by fgets_content.
1649 $htmlheadercontent.= "<?php // BEGIN PHP\n";
1650 $htmlheadercontent.= '$websitekey=basename(__DIR__);'."\n";
1651 $htmlheadercontent.= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) { require_once './master.inc.php'; } // Load env if not already loaded"."\n";
1652 $htmlheadercontent.= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1653 $htmlheadercontent.= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1654 $htmlheadercontent.= "ob_start();\n";
1655 // $htmlheadercontent.= "header('Content-type: text/html');\n"; // Not required. htmlheader.html is never call as a standalone page
1656 $htmlheadercontent.= "// END PHP ?>\n";*/
1657
1658 $htmlheadercontent .= $dataposted."\n";
1659
1660 /*$htmlheadercontent.= "\n".'<?php // BEGIN PHP'."\n";
1661 $htmlheadercontent.= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp);'."\n";
1662 $htmlheadercontent.= "// END PHP"."\n";*/
1663
1664 $result = dolSaveHtmlHeader($filehtmlheader, $htmlheadercontent);
1665 if (!$result) {
1666 $error++;
1667 setEventMessages('Failed to write file '.$filehtmlheader, null, 'errors');
1668 }
1669 } else {
1670 $error++;
1671 }
1672
1673 $dataposted = trim(GETPOST('WEBSITE_CSS_INLINE', 'none'));
1674 $dataposted = str_replace('<?=', '<?php', $dataposted);
1675
1676 // Css file
1677 $phpfullcodestringold = '';
1678 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1679
1680 // Security analysis
1681 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1682
1683 if (!$errorphpcheck) {
1684 $csscontent = '';
1685
1686 $csscontent .= "<?php // BEGIN PHP\n";
1687 $csscontent .= '$websitekey=basename(__DIR__);'."\n";
1688 $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.
1689 $csscontent .= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1690 $csscontent .= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1691 $csscontent .= "ob_start();\n";
1692 $csscontent .= "if (! headers_sent()) { /* because file is included inline when in edit mode and we don't want warning */ \n";
1693 $csscontent .= "header('Cache-Control: max-age=3600, public, must-revalidate');\n";
1694 $csscontent .= "header('Content-type: text/css');\n";
1695 $csscontent .= "}\n";
1696 $csscontent .= "// END PHP ?>\n";
1697
1698 $csscontent .= $dataposted."\n";
1699
1700 $csscontent .= '<?php // BEGIN PHP'."\n";
1701 $csscontent .= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "css");'."\n";
1702 $csscontent .= "// END PHP\n";
1703
1704 dol_syslog("Save css content into ".$filecss);
1705
1706 $result = dolSaveCssFile($filecss, $csscontent);
1707 if (!$result) {
1708 $error++;
1709 setEventMessages('Failed to write file '.$filecss, null, 'errors');
1710 }
1711 } else {
1712 $error++;
1713 }
1714
1715
1716 $dataposted = trim(GETPOST('WEBSITE_JS_INLINE', 'none'));
1717 $dataposted = str_replace('<?=', '<?php', $dataposted);
1718
1719 // Js file
1720 $phpfullcodestringold = '';
1721 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1722
1723 // Security analysis
1724 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1725
1726 if (!$errorphpcheck) {
1727 $jscontent = '';
1728
1729 $jscontent .= "<?php // BEGIN PHP\n";
1730 $jscontent .= '$websitekey=basename(__DIR__);'."\n";
1731 $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.
1732 $jscontent .= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1733 $jscontent .= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1734 $jscontent .= "ob_start();\n";
1735 $jscontent .= "header('Cache-Control: max-age=3600, public, must-revalidate');\n";
1736 $jscontent .= "header('Content-type: application/javascript');\n";
1737 $jscontent .= "// END PHP ?>\n";
1738
1739 $jscontent .= $dataposted."\n";
1740
1741 $jscontent .= '<?php // BEGIN PHP'."\n";
1742 $jscontent .= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "js");'."\n";
1743 $jscontent .= "// END PHP\n";
1744
1745 $result = dolSaveJsFile($filejs, $jscontent);
1746 if (!$result) {
1747 $error++;
1748 setEventMessages('Failed to write file '.$filejs, null, 'errors');
1749 }
1750 } else {
1751 $error++;
1752 }
1753
1754 $dataposted = trim(GETPOST('WEBSITE_ROBOT', 'nohtml'));
1755 $dataposted = str_replace('<?=', '<?php', $dataposted);
1756
1757 // Robot file
1758 $phpfullcodestringold = '';
1759 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1760
1761 // Security analysis
1762 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1763
1764 if (!$errorphpcheck) {
1765 $robotcontent = '';
1766
1767 /*$robotcontent.= "<?php // BEGIN PHP\n";
1768 $robotcontent.= '$websitekey=basename(__DIR__);'."\n";
1769 $robotcontent.= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) { require_once './master.inc.php'; } // Load env if not already loaded"."\n";
1770 $robotcontent.= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1771 $robotcontent.= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1772 $robotcontent.= "ob_start();\n";
1773 $robotcontent.= "header('Cache-Control: max-age=3600, public, must-revalidate');\n";
1774 $robotcontent.= "header('Content-type: text/css');\n";
1775 $robotcontent.= "// END PHP ?>\n";*/
1776
1777 $robotcontent .= $dataposted."\n";
1778
1779 /*$robotcontent.= "\n".'<?php // BEGIN PHP'."\n";
1780 $robotcontent.= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "robot");'."\n";
1781 $robotcontent.= "// END PHP ?>"."\n";*/
1782
1783 $result = dolSaveRobotFile($filerobot, $robotcontent);
1784 if (!$result) {
1785 $error++;
1786 setEventMessages('Failed to write file '.$filerobot, null, 'errors');
1787 }
1788 } else {
1789 $error++;
1790 }
1791
1792 $dataposted = trim(GETPOST('WEBSITE_HTACCESS', 'nohtml'));
1793 $dataposted = str_replace('<?=', '<?php', $dataposted);
1794
1795 // Htaccess file
1796 $phpfullcodestringold = '';
1797 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1798
1799 // Security analysis
1800 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1801
1802 if (!$errorphpcheck) {
1803 if ($dataposted) {
1804 $htaccesscontent = '';
1805 $htaccesscontent .= $dataposted."\n";
1806
1807 $result = dolSaveHtaccessFile($filehtaccess, $htaccesscontent);
1808 if (!$result) {
1809 $error++;
1810 setEventMessages('Failed to write file '.$filehtaccess, null, 'errors');
1811 }
1812 } else {
1813 dol_delete_file($filehtaccess, 0, 0);
1814 }
1815 } else {
1816 $error++;
1817 }
1818
1819
1820 $dataposted = trim(GETPOST('WEBSITE_MANIFEST_JSON', 'restricthtmlallowunvalid'));
1821 $dataposted = str_replace('<?=', '<?php', $dataposted);
1822
1823 // Manifest.json file
1824 $phpfullcodestringold = '';
1825 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1826
1827 // Security analysis
1828 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1829
1830 if (!$errorphpcheck) {
1831 $manifestjsoncontent = '';
1832
1833 $manifestjsoncontent .= "<?php // BEGIN PHP\n";
1834 $manifestjsoncontent .= '$websitekey=basename(__DIR__);'."\n";
1835 $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.
1836 $manifestjsoncontent .= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1837 $manifestjsoncontent .= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1838 $manifestjsoncontent .= "ob_start();\n";
1839 $manifestjsoncontent .= "header('Cache-Control: max-age=3600, public, must-revalidate');\n";
1840 $manifestjsoncontent .= "header('Content-type: application/manifest+json');\n";
1841 $manifestjsoncontent .= "// END PHP ?>\n";
1842
1843 $manifestjsoncontent .= $dataposted."\n";
1844
1845 $manifestjsoncontent .= '<?php // BEGIN PHP'."\n";
1846 $manifestjsoncontent .= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "manifest");'."\n";
1847 $manifestjsoncontent .= "// END PHP\n";
1848
1849 $result = dolSaveManifestJson($filemanifestjson, $manifestjsoncontent);
1850 if (!$result) {
1851 $error++;
1852 setEventMessages('Failed to write file '.$filemanifestjson, null, 'errors');
1853 }
1854 } else {
1855 $error++;
1856 }
1857
1858
1859 $dataposted = trim(GETPOST('WEBSITE_README', 'nohtml'));
1860 $dataposted = str_replace('<?=', '<?php', $dataposted);
1861
1862 // README.md file
1863 $phpfullcodestringold = '';
1864 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1865
1866 // Security analysis
1867 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1868
1869 if (!$errorphpcheck) {
1870 $readmecontent = '';
1871
1872 /*$readmecontent.= "<?php // BEGIN PHP\n";
1873 $readmecontent.= '$websitekey=basename(__DIR__);'."\n";
1874 $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.
1875 $readmecontent.= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1876 $readmecontent.= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1877 $readmecontent.= "ob_start();\n";
1878 $readmecontent.= "header('Cache-Control: max-age=3600, public, must-revalidate');\n";
1879 $readmecontent.= "header('Content-type: application/manifest+json');\n";
1880 $readmecontent.= "// END PHP ?>\n";*/
1881
1882 $readmecontent .= $dataposted."\n";
1883
1884 /*$readmecontent.= '<?php // BEGIN PHP'."\n";
1885 $readmecontent.= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "manifest");'."\n";
1886 $readmecontent.= "// END PHP ?>"."\n";*/
1887
1888 $result = dolSaveReadme($filereadme, $readmecontent);
1889 if (!$result) {
1890 $error++;
1891 setEventMessages('Failed to write file '.$filereadme, null, 'errors');
1892 }
1893 } else {
1894 $error++;
1895 }
1896
1897
1898 $dataposted = trim(GETPOST('WEBSITE_LICENSE', 'nohtml'));
1899 $dataposted = str_replace('<?=', '<?php', $dataposted);
1900
1901 // LICENSE file
1902 $phpfullcodestringold = '';
1903 $phpfullcodestring = dolKeepOnlyPhpCode($dataposted);
1904
1905 // Security analysis
1906 $errorphpcheck = checkPHPCode($phpfullcodestringold, $phpfullcodestring); // Contains the setEventMessages
1907
1908 if (!$errorphpcheck) {
1909 $licensecontent = '';
1910
1911 /*$readmecontent.= "<?php // BEGIN PHP\n";
1912 $readmecontent.= '$websitekey=basename(__DIR__);'."\n";
1913 $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.
1914 $readmecontent.= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
1915 $readmecontent.= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
1916 $readmecontent.= "ob_start();\n";
1917 $readmecontent.= "header('Cache-Control: max-age=3600, public, must-revalidate');\n";
1918 $readmecontent.= "header('Content-type: application/manifest+json');\n";
1919 $readmecontent.= "// END PHP ?>\n";*/
1920
1921 $licensecontent .= $dataposted."\n";
1922
1923 /*$readmecontent.= '<?php // BEGIN PHP'."\n";
1924 $readmecontent.= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "manifest");'."\n";
1925 $readmecontent.= "// END PHP ?>"."\n";*/
1926
1927 $result = dolSaveLicense($filelicense, $licensecontent);
1928 if (!$result) {
1929 $error++;
1930 setEventMessages('Failed to write file '.$filelicense, null, 'errors');
1931 }
1932 } else {
1933 $error++;
1934 }
1935
1936 // Save wrapper.php
1937 $result = dolSaveIndexPage($pathofwebsite, '', '', $filewrapper, $object);
1938
1939
1940 // Message if no error
1941 if (!$error) {
1942 setEventMessages($langs->trans("Saved"), null, 'mesgs');
1943 }
1944
1945 if (!GETPOSTISSET('updateandstay')) { // If we click on "Save And Stay", we don not make the redirect
1946 $action = 'preview';
1947 if ($backtopage) {
1948 $backtopage = preg_replace('/searchstring=[^&]*/', '', $backtopage); // Clean backtopage url
1949 header("Location: ".$backtopage);
1950 exit;
1951 }
1952 } else {
1953 $action = 'editcss';
1954 }
1955 }
1956 }
1957}
1958
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 {
2904 dol_print_error($db);
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 {
2965 dol_print_error($db);
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 //'/includes/jquery/plugins/jqueryscoped/jquery.scoped.js',
3077);
3078$arrayofcss = array();
3079
3080if (!getDolGlobalString('MAIN_ECM_DISABLE_JS')) {
3081 $arrayofjs[] = "includes/jquery/plugins/jqueryFileTree/jqueryFileTree.js";
3082}
3083
3084llxHeader('', $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">');
3085
3086print "\n";
3087print '<!-- Open form for all page -->'."\n";
3088print '<form action="'.$_SERVER["PHP_SELF"].($action == 'file_manager' ? '?uploadform=1' : '').'" method="POST" enctype="multipart/form-data" class="websiteformtoolbar">'."\n";
3089print '<input type="hidden" name="token" value="'.newToken().'">';
3090print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
3091print '<input type="hidden" name="dol_openinpopup" value="'.$dol_openinpopup.'">';
3092
3093if ($action == 'createsite') {
3094 print '<input type="hidden" name="action" value="addsite">';
3095}
3096if ($action == 'createcontainer') {
3097 print '<input type="hidden" name="action" value="addcontainer">';
3098}
3099if ($action == 'editcss') {
3100 print '<input type="hidden" name="action" value="updatecss">';
3101}
3102if ($action == 'editmenu') {
3103 print '<input type="hidden" name="action" value="updatemenu">';
3104}
3105if ($action == 'setashome') {
3106 print '<input type="hidden" name="action" value="updateashome">';
3107}
3108if ($action == 'editmeta') {
3109 print '<input type="hidden" name="action" value="updatemeta">';
3110}
3111if ($action == 'editsource') {
3112 print '<input type="hidden" name="action" value="updatesource">';
3113}
3114if ($action == 'editcontent') {
3115 print '<input type="hidden" name="action" value="updatecontent">';
3116}
3117if ($action == 'edit') {
3118 print '<input type="hidden" name="action" value="update">';
3119}
3120if ($action == 'importsite') {
3121 print '<input type="hidden" name="action" value="importsiteconfirm">';
3122}
3123if ($action == 'file_manager') {
3124 print '<input type="hidden" name="action" value="file_manager">';
3125}
3126if ($mode) {
3127 print '<input type="hidden" name="mode" value="'.$mode.'">';
3128}
3129if ($action == 'editsecurity') {
3130 print '<input type="hidden" name="action" value="updatesecurity">';
3131}
3132
3133print '<div>'."\n";
3134
3135// Add a margin under toolbar ?
3136$style = '';
3137if ($action != 'preview' && $action != 'editcontent' && $action != 'editsource' && !GETPOST('createpagefromclone', 'alphanohtml')) {
3138 $style = ' margin-bottom: 5px;';
3139}
3140
3141
3142$disabled = '';
3143if (!GETPOST('hide_websitemenu')) {
3144 if (!$user->hasRight('website', 'write')) {
3145 $disabled = ' disabled="disabled"';
3146 }
3147 $disabledexport = '';
3148 if (!$user->hasRight('website', 'export')) {
3149 $disabledexport = ' disabled="disabled"';
3150 }
3151
3152 if ($websitekey) {
3153 $virtualurl = '';
3154 $dataroot = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$websitekey;
3155 if (!empty($object->virtualhost)) {
3156 $virtualurl = $object->virtualhost;
3157 }
3158 }
3159
3160 $array = array();
3161 if ($object->id > 0) {
3162 $array = $objectpage->fetchAll($object->id, 'ASC,ASC', 'type_container,pageurl');
3163 $object->lines = $array;
3164 }
3165 if (!is_array($array) && $array < 0) {
3166 dol_print_error(null, $objectpage->error, $objectpage->errors);
3167 }
3168 $atleastonepage = (is_array($array) && count($array) > 0);
3169
3170 $websitepage = new WebsitePage($db);
3171 if ($pageid > 0) {
3172 $websitepage->fetch($pageid);
3173 }
3174
3175
3176 $disabled = '';
3177 $morecss = '';
3178 if (!$user->hasRight('website', 'write')) {
3179 $disabled = ' disabled="disabled"';
3180 $morecss = 'opacitymedium cursordefault';
3181 }
3182
3183 //var_dump($objectpage);exit;
3184 print '<div class="centpercent websitebar'.(GETPOST('dol_openinpopup', 'aZ09') ? ' hiddenforpopup' : '').'">'."\n";
3185
3186 //
3187 // Toolbar for websites
3188 //
3189
3190 print '<!-- Toolbar for website -->';
3191 if ($action != 'file_manager') {
3192 print '<div class="websiteselection hideonsmartphoneimp minwidth75 tdoverflowmax100 inline-block">';
3193 print $langs->trans("Website").': ';
3194 print '</div>';
3195
3196 // Button Add new website
3197 $urltocreatenewwebsite = $_SERVER["PHP_SELF"].'?action=createsite';
3198 if ($user->hasRight('website', 'write')) {
3199 print '<span class="websiteselection paddingrightonly">';
3200 print '<a href="'.$urltocreatenewwebsite.'" class=""'.$disabled.' title="'.dol_escape_htmltag($langs->trans("AddWebsite")).'"><span class="fa fa-plus-circle valignmiddle btnTitle-icon"><span></a>';
3201 print '</span>';
3202 }
3203
3204 // List of website
3205 print '<span class="websiteselection nopaddingrightimp">';
3206
3207 $out = '';
3208 $out .= '<select name="website" class="minwidth100 width200 maxwidth150onsmartphone" id="website">';
3209 if (empty($listofwebsites)) {
3210 $out .= '<option value="-1">&nbsp;</option>';
3211 }
3212
3213 // Loop on each sites
3214 $i = 0;
3215 foreach ($listofwebsites as $key => $valwebsite) {
3216 if (empty($websitekey)) {
3217 if ($action != 'createsite') {
3218 $websitekey = $valwebsite->ref;
3219 }
3220 }
3221
3222 $out .= '<option value="'.$valwebsite->ref.'"';
3223 if ($websitekey == $valwebsite->ref) {
3224 $out .= ' selected'; // To preselect a value
3225 }
3226 //$outoption = $valwebsite->getLibStatut(3).' '.$valwebsite->ref.' ';
3227 $outoption = (($valwebsite->status == $valwebsite::STATUS_DRAFT) ? '<span class="opacitymedium">' : '').$valwebsite->ref.(($valwebsite->status == $valwebsite::STATUS_DRAFT) ? '</span>' : '');
3228 $out .= ' data-html="'.dol_escape_htmltag($outoption).'"';
3229 $out .= '>';
3230 $out .= $valwebsite->ref;
3231 $out .= '</option>';
3232 $i++;
3233 }
3234 $out .= '</select>';
3235 $out .= ajax_combobox('website');
3236
3237 if (!empty($conf->use_javascript_ajax)) {
3238 $out .= '<script type="text/javascript">';
3239 $out .= 'jQuery(document).ready(function () {';
3240 $out .= ' jQuery("#website").change(function () {';
3241 $out .= ' console.log("We select "+jQuery("#website option:selected").val());';
3242 $out .= ' if (jQuery("#website option:selected").val() == \'-2\') {';
3243 $out .= ' window.location.href = "'.dol_escape_js($urltocreatenewwebsite).'";';
3244 $out .= ' } else {';
3245 $out .= ' window.location.href = "'.$_SERVER["PHP_SELF"].'?website="+jQuery("#website option:selected").val();';
3246 $out .= ' }';
3247 $out .= ' });';
3248 $out .= '});';
3249 $out .= '</script>';
3250 }
3251 print $out;
3252
3253 print '</span>';
3254
3255 // Switch offline/onine
3256 if (!empty($conf->use_javascript_ajax)) {
3257 print '<span class="websiteselection">';
3258 // Do not use ajax, we need a refresh of full page when we change status of a website
3259 //print '<div class="inline-block marginrightonly">';
3260 //print ajax_object_onoff($object, 'status', 'status', 'Online', 'Offline', array(), 'valignmiddle inline-block', 'statuswebsite');
3261 //print '</div>';
3262 if ($website->status == $website::STATUS_DRAFT) {
3263 $text_off = 'Offline';
3264 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>';
3265 } else {
3266 $text_off = 'Online';
3267 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>';
3268 }
3269 print '</span>';
3270 }
3271
3272 // Refresh / Reload web site (for non javascript browsers)
3273 if (empty($conf->use_javascript_ajax)) {
3274 print '<span class="websiteselection">';
3275 print '<input type="image" class="valignmiddle" src="'.img_picto('', 'refresh', '', 0, 1).'" name="refreshsite" value="'.$langs->trans("Load").'"'.$disabled.'>';
3276 print '</span>';
3277 }
3278
3279
3280 print '<span class="websiteselection">';
3281
3282 if ($websitekey && $websitekey != '-1' && ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone' || $action == 'deletesite')) {
3283 // Edit website properties
3284 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.'>';
3285 print img_picto('', 'setup');
3286 print '<span class="hideonsmartphone paddingleft">'.dol_escape_htmltag($langs->trans("EditCss")).'</span>';
3287 print '</a>';
3288
3289 // Import web site
3290 $importlabel = $langs->trans("ImportSite");
3291 $exportlabel = $langs->trans("ExportSite");
3292 if (!empty($conf->dol_optimize_smallscreen)) {
3293 $importlabel = $langs->trans("Import");
3294 $exportlabel = $langs->trans("Export");
3295 }
3296
3297 if ($atleastonepage) {
3298 print '<input type="submit" class="button bordertransp" disabled="disabled" value="'.dol_escape_htmltag($importlabel).'" name="importsite">';
3299 } else {
3300 print '<input type="submit" class="button bordertransp"'.$disabled.' value="'.dol_escape_htmltag($importlabel).'" name="importsite">';
3301 }
3302
3303 // // Export web site
3304 $extraCssClass = getDolGlobalString('WEBSITE_ALLOW_OVERWRITE_GIT_SOURCE') ? 'hideobject' : '';
3305 print '<input type="submit" class="button bordertransp ' . $extraCssClass . '" ' . $disabledexport . ' value="' . dol_escape_htmltag($exportlabel) . '" name="exportsite">';
3306
3307 if (getDolGlobalString('WEBSITE_ALLOW_OVERWRITE_GIT_SOURCE')) {
3308 // Overwrite template in sources
3309 $overwriteGitUrl = $_SERVER["PHP_SELF"] . '?action=overwritesite&website=' . urlencode($website->ref);
3310 print dolButtonToOpenExportDialog('exportpopup', $langs->trans('ExportOptions'), $langs->trans('ExportSite'), 'exportsite', $overwriteGitUrl, $website);
3311 //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>';
3312 }
3313
3314 // Clone web site
3315 print '<input type="submit" class="button bordertransp"'.$disabled.' value="'.dol_escape_htmltag($langs->trans("CloneSite")).'" name="createfromclone">';
3316
3317 // Delete website
3318 if (!$permissiontodelete) {
3319 $disabled = ' disabled="disabled"';
3320 $title = $langs->trans("NotEnoughPermissions");
3321 $url = '#';
3322 } else {
3323 if ($website->status == $website::STATUS_VALIDATED) {
3324 $disabled = ' disabled="disabled"';
3325 $title = $langs->trans("WebsiteMustBeDisabled", $langs->transnoentitiesnoconv($website->LibStatut(0, 0)));
3326 $url = '#';
3327 } else {
3328 $disabled = '';
3329 $title = $langs->trans("Delete");
3330 $url = $_SERVER["PHP_SELF"].'?action=deletesite&token='.newToken().'&website='.urlencode($website->ref);
3331 }
3332 }
3333 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>';
3334
3335 // Regenerate all pages
3336 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>';
3337
3338 // Generate site map
3339 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>';
3340
3341 // Find / replace tool
3342 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>';
3343 }
3344
3345 print '</span>';
3346
3347 if ($websitekey && $websitekey != '-1' && ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone' || $action == 'deletesite')) {
3348 print '<span class="websiteselection">';
3349
3350 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);
3351
3352 if (isModEnabled('category')) {
3353 //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>';
3354 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);
3355 }
3356
3357 print '</span>';
3358 }
3359 } else {
3360 print '<input type="hidden" name="website" id="website" value="'.$websitekey.'">';
3361 }
3362
3363
3364 print '<span class="websitetools">';
3365
3366 if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone' || $action == 'deletesite') {
3367 $urlext = $virtualurl;
3368 $urlint = $urlwithroot.'/public/website/index.php?website='.$websitekey;
3369
3370 print '<span class="websiteinputurl valignmiddle" id="websiteinputurl">';
3371 $linktotestonwebserver = '<a href="'.($virtualurl ? $virtualurl : '#').'" class="valignmiddle">';
3372 $linktotestonwebserver .= '<span class="hideonsmartphone paddingrightonly">'.$langs->trans("TestDeployOnWeb", $virtualurl).'</span>'.img_picto('', 'globe');
3373 $linktotestonwebserver .= '</a>';
3374
3375 $htmltext = '';
3376 if (empty($object->fk_default_home)) {
3377 $htmltext .= '<br><span class="error">'.$langs->trans("YouMustDefineTheHomePage").'</span><br><br>';
3378 } elseif (empty($virtualurl)) {
3379 //$htmltext .= '<br><span class="error">'.$langs->trans("VirtualHostUrlNotDefined").'</span><br><br>';
3380 } else {
3381 $htmltext .= '<br><center>'.$langs->trans("GoTo").' <a href="'.$virtualurl.'" target="_website">'.$virtualurl.' '.img_picto('', 'url').'</a></center><br>';
3382 }
3383 if (getDolGlobalString('WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER')) {
3384 $htmltext .= '<!-- Message defined translate key set into WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER -->';
3385 $htmltext .= '<br>'.$langs->trans(getDolGlobalString('WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER'));
3386 } else {
3387 $htmltext .= $langs->trans("ToDeployYourWebsiteOnLiveYouHave3Solutions").'<br><br>';
3388 $htmltext .= '<div class="titre inline-block">1</div> - '.$langs->trans("SetHereVirtualHost", $dataroot);
3389 $htmltext .= '<br>';
3390 $htmltext .= '<br>'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("ReadPerm"), DOL_DOCUMENT_ROOT);
3391 $htmltext .= '<br>'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("WritePerm"), '{s1}');
3392 $htmltext = str_replace('{s1}', DOL_DATA_ROOT.'/website<br>'.DOL_DATA_ROOT.'/medias', $htmltext);
3393
3394 $examplewithapache = "<VirtualHost *:80>\n";
3395 $examplewithapache .= '#php_admin_value open_basedir /tmp/:'.DOL_DOCUMENT_ROOT.':'.DOL_DATA_ROOT.':/dev/urandom'."\n";
3396 //$examplewithapache .= '#php_admin_value disable_functions "exec,passthru,shell_exec,system,popen,proc_open"'."\n"; This is not effective if not in php.ini
3397 $examplewithapache .= "\n";
3398 $examplewithapache .= 'DocumentRoot "'.DOL_DOCUMENT_ROOT.'"'."\n";
3399 $examplewithapache .= "\n";
3400 $examplewithapache .= '<Directory "'.DOL_DOCUMENT_ROOT.'">'."\n";
3401 $examplewithapache .= 'AllowOverride FileInfo Options
3402 Options -Indexes -MultiViews -FollowSymLinks -ExecCGI
3403 Require all granted
3404 </Directory>'."\n".'
3405 <Directory "'.DOL_DATA_ROOT.'/website">
3406 AllowOverride FileInfo Options
3407 Options -Indexes -MultiViews +FollowSymLinks -ExecCGI
3408 Require all granted
3409 </Directory>'."\n".'
3410 <Directory "'.DOL_DATA_ROOT.'/medias">
3411 AllowOverride FileInfo Options
3412 Options -Indexes -MultiViews -FollowSymLinks -ExecCGI
3413 Require all granted
3414 </Directory>'."\n";
3415
3416 $examplewithapache .= "\n";
3417 $examplewithapache .= "#ErrorLog /var/log/apache2/".$websitekey."_error_log\n";
3418 $examplewithapache .= "#TransferLog /var/log/apache2/".$websitekey."_access_log\n";
3419
3420 $examplewithapache .= "\n";
3421 $examplewithapache .= "# If you need include the payment page into a frame of the website,\n";
3422 $examplewithapache .= "# you need to make a proxy redirection of URLs required for the payment to your backoffice pages\n";
3423 $examplewithapache .= "#SSLProxyEngine On\n";
3424 $examplewithapache .= "#SSLProxyVerify none\n";
3425 $examplewithapache .= "#SSLProxyCheckPeerCN off\n";
3426 $examplewithapache .= "#SSLProxyCheckPeerName off\n";
3427 $examplewithapache .= "#ProxyPreserveHost Off\n";
3428 $examplewithapache .= '#ProxyPass "/public/payment/" "'.$urlwithroot.'/public/payment/'."\n";
3429 $examplewithapache .= '#ProxyPassReverse "/public/payment/" "'.$urlwithroot.'/public/payment/'."\n";
3430 $examplewithapache .= '#ProxyPass "/includes/" "'.$urlwithroot.'/includes/'."\n";
3431 $examplewithapache .= '#ProxyPassReverse "/includes/" "'.$urlwithroot.'/includes/'."\n";
3432 $examplewithapache .= '#ProxyPass "/theme/" "'.$urlwithroot.'/theme/'."\n";
3433 $examplewithapache .= '#ProxyPassReverse "/theme/" "'.$urlwithroot.'/theme/'."\n";
3434 $examplewithapache .= '#ProxyPass "/core/js/" "'.$urlwithroot.'/core/js/'."\n";
3435 $examplewithapache .= '#ProxyPassReverse "/core/js/" "'.$urlwithroot.'/core/js/'."\n";
3436 $examplewithapache .= "\n";
3437
3438 $examplewithapache .= "</VirtualHost>\n";
3439
3440 $htmltext .= '<br>'.$langs->trans("ExampleToUseInApacheVirtualHostConfig").':<br>';
3441 $htmltext .= '<div class="quatrevingtpercent exampleapachesetup wordbreak" spellcheck="false">'.dol_nl2br(dol_escape_htmltag($examplewithapache, 1, 1)).'</div>';
3442
3443 $htmltext .= '<br>';
3444 $htmltext .= '<div class="titre inline-block">2</div> - '.$langs->trans("YouCanAlsoTestWithPHPS");
3445 $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>';
3446 $htmltext .= ajax_autoselect("cliphpserver");
3447 $htmltext .= '<br>';
3448 $htmltext .= '<div class="titre inline-block">3</div> - '.$langs->trans("YouCanAlsoDeployToAnotherWHP");
3449 }
3450 print $form->textwithpicto($linktotestonwebserver, $htmltext, 1, 'none', 'valignmiddle', 0, 3, 'helpvirtualhost');
3451 print '</span>';
3452 }
3453
3454 if (in_array($action, array('editcss', 'editmenu', 'file_manager', 'replacesiteconfirm', 'editsecurity')) || in_array($mode, array('replacesite'))) {
3455 if (!$user->hasRight('website', 'write')) {
3456 $disabled = ' disabled';
3457 }
3458 if ($action == 'editcss' || $action == 'editsecurity') {
3459 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">';
3460 }
3461 if (preg_match('/^create/', $action) && $action != 'file_manager' && $action != 'replacesite' && $action != 'replacesiteconfirm') {
3462 print '<input type="submit" id="savefile" class="button buttonforacesave button-save small'.$disabled.'" value="'.dol_escape_htmltag($langs->trans("Save")).'" name="update">';
3463 }
3464 if (preg_match('/^edit/', $action) && $action != 'file_manager' && $action != 'replacesite' && $action != 'replacesiteconfirm') {
3465 print '<input type="submit" id="savefile" class="button buttonforacesave button-save small'.$disabled.'" value="'.dol_escape_htmltag($langs->trans("Save")).'" name="update">';
3466 }
3467 if ($action != 'preview') {
3468 print '<input type="submit" class="button button-cancel small" value="'.dol_escape_htmltag($langs->trans("Cancel")).'" name="cancel">';
3469 }
3470 }
3471
3472 print '</span>';
3473
3474 //
3475 // Toolbar for pages
3476 //
3477
3478 if ($websitekey && $websitekey != '-1' && (!in_array($action, array('editcss', 'editmenu', 'importsite', 'file_manager', 'replacesite', 'replacesiteconfirm', 'editsecurity'))) && (!in_array($mode, array('replacesite'))) && !$file_manager) {
3479 print '</div>'; // Close current websitebar to open a new one
3480
3481 print '<!-- Toolbar for websitepage -->';
3482 print '<div class="centpercent websitebar"'.($style ? ' style="'.$style.'"' : '').'>'."\n";
3483
3484 print '<div class="websiteselection hideonsmartphoneimp minwidth75 tdoverflowmax100 inline-block">';
3485 print $langs->trans("PageContainer").': ';
3486 print '</div>';
3487
3488 // Button Add new web page
3489 if ($user->hasRight('website', 'write')) {
3490 print '<span class="websiteselection paddingrightonly">';
3491 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>';
3492 print '</span>';
3493 }
3494
3495 $out = '';
3496
3497 $s = $formwebsite->selectContainer($website, 'pageid', $pageid, 0, $action, 'minwidth100 maxwidth200onsmartphone');
3498
3499 $out .= '<span class="websiteselection nopaddingrightimp">';
3500 $out .= $s;
3501 $out .= '</span>';
3502
3503 $urltocreatenewpage = $_SERVER["PHP_SELF"].'?action=createcontainer&token='.newToken().'&website='.urlencode($website->ref);
3504
3505 if (!empty($conf->use_javascript_ajax)) {
3506 $out .= '<script type="text/javascript">';
3507 $out .= 'jQuery(document).ready(function () {';
3508 $out .= ' jQuery("#pageid").change(function () {';
3509 $out .= ' console.log("We select "+jQuery("#pageid option:selected").val());';
3510 $out .= ' if (jQuery("#pageid option:selected").val() == \'-2\') {';
3511 $out .= ' window.location.href = "'.$urltocreatenewpage.'";';
3512 $out .= ' } else {';
3513 $out .= ' window.location.href = "'.$_SERVER["PHP_SELF"].'?website='.urlencode($website->ref).'&pageid="+jQuery("#pageid option:selected").val();';
3514 $out .= ' }';
3515 $out .= ' });';
3516 $out .= '});';
3517 $out .= '</script>';
3518 }
3519
3520 print $out;
3521
3522 // Button to switch status
3523 if (!empty($conf->use_javascript_ajax)) {
3524 print '<span class="websiteselection">';
3525 //print '<div class="inline-block marginrightonly">';
3526 if ($object->status == $object::STATUS_DRAFT) { // website is off, we do not allow to change status of page
3527 $text_off = 'SetWebsiteOnlineBefore';
3528 if ($websitepage->status == $websitepage::STATUS_DRAFT) { // page is off
3529 print '<span class="valignmiddle disabled opacitymedium">'.img_picto($langs->trans($text_off), 'switch_off', '', 0, 0, 0, '', $morecss).'</span>';
3530 } else {
3531 print '<span class="valignmiddle disabled opacitymedium">'.img_picto($langs->trans($text_off), 'switch_on', '', 0, 0, 0, '', $morecss).'</span>';
3532 }
3533 } else {
3534 if ($objectpage->type_container != 'setup') { // we do not allow to change status of setup pages
3535 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);
3536 }
3537 }
3538 //print '</div>';
3539 print '</span>';
3540 }
3541
3542 print '<span class="websiteselection">';
3543
3544 print '<input type="image" class="valignmiddle buttonwebsite hideonsmartphone" src="'.img_picto('', 'refresh', '', 0, 1).'" name="refreshpage" value="'.$langs->trans("Load").'"'.(($action != 'editsource') ? '' : ' disabled="disabled"').'>';
3545
3546 // Print nav arrows
3547 $pagepreviousid = 0;
3548 $pagenextid = 0;
3549 if ($pageid) {
3550 $sql = "SELECT MAX(rowid) as pagepreviousid FROM ".MAIN_DB_PREFIX."website_page WHERE rowid < ".((int) $pageid)." AND fk_website = ".((int) $object->id);
3551 $resql = $db->query($sql);
3552 if ($resql) {
3553 $obj = $db->fetch_object($resql);
3554 if ($obj) {
3555 $pagepreviousid = $obj->pagepreviousid;
3556 }
3557 } else {
3558 dol_print_error($db);
3559 }
3560 $sql = "SELECT MIN(rowid) as pagenextid FROM ".MAIN_DB_PREFIX."website_page WHERE rowid > ".((int) $pageid)." AND fk_website = ".((int) $object->id);
3561 $resql = $db->query($sql);
3562 if ($resql) {
3563 $obj = $db->fetch_object($resql);
3564 if ($obj) {
3565 $pagenextid = $obj->pagenextid;
3566 }
3567 } else {
3568 dol_print_error($db);
3569 }
3570 }
3571
3572 if ($pagepreviousid) {
3573 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>';
3574 } else {
3575 print '<span class="valignmiddle opacitymedium">'.img_previous($langs->trans("PreviousContainer")).'</span>';
3576 }
3577 if ($pagenextid) {
3578 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>';
3579 } else {
3580 print '<span class="valignmiddle opacitymedium">'.img_next($langs->trans("NextContainer")).'</span>';
3581 }
3582
3583 print '</span>';
3584
3585 if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone' || $action == 'deletesite') {
3586 $disabled = '';
3587 if (!$user->hasRight('website', 'write')) {
3588 $disabled = ' disabled="disabled"';
3589 }
3590
3591 // Confirmation delete site
3592 if ($action == 'deletesite') {
3593 // Create an array for form
3594 $formquestion = array(
3595 array('type' => 'checkbox', 'name' => 'delete_also_js', 'label' => $langs->trans("DeleteAlsoJs"), 'value' => 0),
3596 array('type' => 'checkbox', 'name' => 'delete_also_medias', 'label' => $langs->trans("DeleteAlsoMedias"), 'value' => 0),
3597 //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')),
3598 //array('type' => 'other','name' => 'newwebsite','label' => $langs->trans("WebSite"), 'value' => $formwebsite->selectWebsite($object->id, 'newwebsite', 0))
3599 );
3600
3601 if ($atleastonepage) {
3602 $langs->load("errors");
3603 $formquestion[] = array('type' => 'onecolumn', 'value' => '<div class="warning">'.$langs->trans("WarningPagesWillBeDeleted").'</div>');
3604 }
3605
3606 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteWebsite'), '', 'confirm_deletesite', $formquestion, 0, 1, 210 + ($atleastonepage ? 70 : 0), 580);
3607
3608 print $formconfirm;
3609 }
3610
3611 // Confirmation to clone
3612 if ($action == 'createfromclone') {
3613 // Create an array for form
3614 $formquestion = array(
3615 array('type' => 'text', 'name' => 'siteref', 'label' => $langs->trans("WebSite"), 'value' => 'copy_of_'.$object->ref)
3616 );
3617
3618 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('CloneSite'), '', 'confirm_createfromclone', $formquestion, 0, 1, 200);
3619
3620 print $formconfirm;
3621 }
3622
3623 if ($pageid > 0 && $atleastonepage) { // pageid can be set without pages, if homepage of site is set and all pages were removed
3624 // Confirmation to clone
3625 if ($action == 'createpagefromclone') {
3626 // Create an array for form
3627 $preselectedlanguage = GETPOST('newlang', 'aZ09') ? GETPOST('newlang', 'aZ09') : ''; // Dy default, we do not force any language on pages
3628 $onlylang = array();
3629 if ($website->otherlang) {
3630 if (!empty($website->lang)) {
3631 $onlylang[$website->lang] = $website->lang.' ('.$langs->trans("Default").')';
3632 }
3633 foreach (explode(',', $website->otherlang) as $langkey) {
3634 if (empty(trim($langkey))) {
3635 continue;
3636 }
3637 $onlylang[$langkey] = $langkey;
3638 }
3639 $textifempty = $langs->trans("Default");
3640 } else {
3641 $onlylang['none'] = 'none';
3642 $textifempty = $langs->trans("Default");
3643 }
3644
3645 $formheight = 300;
3646
3647 $formquestion = array(
3648 array('type' => 'hidden', 'name' => 'sourcepageurl', 'value' => $objectpage->pageurl),
3649 array('type' => 'other', 'tdclass' => 'fieldrequired', 'name' => 'newwebsite', 'label' => $langs->trans("WebSite"), 'value' => $formwebsite->selectWebsite((string) $object->id, 'newwebsite', 0)),
3650 array('type' => 'text', 'tdclass' => 'maxwidth200 fieldrequired', 'moreattr' => 'autofocus="autofocus"', 'name' => 'newtitle', 'label' => $langs->trans("WEBSITE_TITLE"), 'value' => $langs->trans("CopyOf").' '.$objectpage->title),
3651 array('type' => 'text', 'tdclass' => 'maxwidth200', 'name' => 'newpageurl', 'label' => $langs->trans("WEBSITE_PAGENAME"), 'value' => '')
3652 );
3653 if (count($onlylang) > 1) {
3654 $formquestion[] = array('type' => 'checkbox', 'tdclass' => 'maxwidth200', 'name' => 'is_a_translation', 'label' => $langs->trans("PageIsANewTranslation"), 'value' => 0, 'morecss' => 'margintoponly');
3655 $formheight += 50;
3656 }
3657
3658 $value = $formadmin->select_language($preselectedlanguage, 'newlang', 0, array(), $textifempty, 0, 0, 'minwidth200', 1, 0, 0, $onlylang, 1);
3659 $formquestion[] = array('type' => 'other', 'name' => 'newlang', 'label' => $form->textwithpicto($langs->trans("Language"), $langs->trans("DefineListOfAltLanguagesInWebsiteProperties")), 'value' => $value);
3660
3661 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?website='.$object->ref.'&pageid='.$pageid, $langs->trans('ClonePage'), '', 'confirm_createpagefromclone', $formquestion, 0, 1, $formheight, 550);
3662
3663 print $formconfirm;
3664 }
3665
3666 print '<span class="websiteselection">';
3667
3668 // Edit web page properties
3669 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.'>';
3670 print img_picto('', 'setup');
3671 print '<span class="hideonsmartphone paddingleft">'.dol_escape_htmltag($langs->trans("EditPageMeta")).'</span>';
3672 print '</a>';
3673
3674 // Edit HTML content
3675 print '<a href="'.$_SERVER["PHP_SELF"].'?website='.$object->ref.'&pageid='.$pageid.'&action=editsource&token='.newToken().'" class="button bordertransp"'.$disabled.'>';
3676 print img_picto('', 'code');
3677 print '<span class="hideonsmartphone paddingleft">'.dol_escape_htmltag($langs->trans($conf->dol_optimize_smallscreen ? "HTML" : "EditHTMLSource")).'</span>';
3678 print '</a>';
3679
3680 // Edit CKEditor
3681 if (getDolGlobalInt('WEBSITE_ALLOW_CKEDITOR')) {
3682 print '<a href="'.$_SERVER["PHP_SELF"].'?website='.$object->ref.'&pageid='.$pageid.'&action=editcontent&token='.newToken().'" class="button bordertransp"'.$disabled.'>'.dol_escape_htmltag("CKEditor").'</a>';
3683 } else {
3684 print '<!-- Add option WEBSITE_ALLOW_CKEDITOR to allow ckeditor -->';
3685 }
3686
3687 print '</span>';
3688
3689
3690 // Switch include dynamic content / edit inline
3691 print '<!-- button EditInLine and ShowSubcontainers -->'."\n";
3692 print '<div class="websiteselectionsection inline-block">';
3693
3694 // Force to show subcontainers if we are in setup mode
3695 if ($objectpage->type_container == 'setup') {
3696 dolibarr_set_const($db, 'WEBSITE_SUBCONTAINERSINLINE', 1);
3697 }
3698
3699 if ($objectpage->type_container != 'setup') {
3700 print '<div class="inline-block marginrightonly">'; // Button includes dynamic content
3701 print $langs->trans("ShowSubcontainers");
3702 if (!getDolGlobalString('WEBSITE_SUBCONTAINERSINLINE')) {
3703 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>';
3704 } else {
3705 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>';
3706 }
3707 print '</div>';
3708 }
3709
3710 print '<div class="inline-block marginrightonly">'; // Button edit inline
3711
3712 print '<span id="switchckeditorinline">'."\n";
3713 // Enable CKEditor inline with js on section and div with conteneditable=true
3714 print '<!-- Code to enabled edit inline ckeditor -->'."\n";
3715 print '<script type="text/javascript">
3716 $(document).ready(function() {
3717 var isEditingEnabled = '.(getDolGlobalString("WEBSITE_EDITINLINE") ? 'true' : 'false').';
3718 if (isEditingEnabled)
3719 {
3720 switchEditorOnline(true);
3721 }
3722
3723 $( "#switchckeditorinline" ).click(function() {
3724 switchEditorOnline();
3725 });
3726
3727 function switchEditorOnline(forceenable)
3728 {
3729 if (! isEditingEnabled || forceenable)
3730 {
3731 console.log("Enable inline edit for some html tags with contenteditable=true attribute");
3732
3733 jQuery(\'section[contenteditable="true"],div[contenteditable="true"],header[contenteditable="true"],main[contenteditable="true"],footer[contenteditable="true"]\').each(function(idx){
3734 var idtouse = $(this).attr(\'id\');
3735 console.log("Enable inline edit for "+idtouse);
3736 if (idtouse !== undefined) {
3737 var inlineditor = CKEDITOR.inline(idtouse, {
3738 // Allow some non-standard markup that we used in the introduction.
3739 // + a[target];div{float,display} ?
3740 extraAllowedContent: \'span(*);cite(*);q(*);dl(*);dt(*);dd(*);ul(*);li(*);header(*);main(*);footer(*);button(*);h1(*);h2(*);h3(*);\',
3741 //extraPlugins: \'sourcedialog\',
3742 removePlugins: \'flash,stylescombo,exportpdf,scayt,wsc,pagebreak,iframe,smiley\',
3743 // Show toolbar on startup (optional).
3744 // startupFocus: true
3745 });
3746
3747 // Custom bar tool
3748 // Note the Source tool does not work on inline
3749 inlineditor.config.toolbar = [
3750 [\'Templates\',\'NewPage\'],
3751 [\'Save\'],
3752 [\'Maximize\',\'Preview\'],
3753 [\'PasteText\'],
3754 [\'Undo\',\'Redo\',\'-\',\'Find\',\'Replace\',\'-\',\'SelectAll\',\'RemoveFormat\'],
3755 [\'CreateDiv\',\'ShowBlocks\'],
3756 [\'Form\', \'Checkbox\', \'Radio\', \'TextField\', \'Textarea\', \'Select\', \'Button\', \'ImageButton\', \'HiddenField\'],
3757 [\'Bold\',\'Italic\',\'Underline\',\'Strike\',\'Superscript\'],
3758 [\'NumberedList\',\'BulletedList\',\'-\',\'Outdent\',\'Indent\',\'Blockquote\'],
3759 [\'JustifyLeft\',\'JustifyCenter\',\'JustifyRight\',\'JustifyBlock\'],
3760 [\'Link\',\'Unlink\'],
3761 [\'Image\',\'Table\',\'HorizontalRule\'],
3762 [\'Styles\',\'Format\',\'Font\',\'FontSize\'],
3763 [\'TextColor\',\'BGColor\']
3764 ];
3765
3766 // Start editor
3767 //inlineditor.on(\'instanceReady\', function () {
3768 // ...
3769 //});
3770
3771 CKEDITOR.instances[idtouse].on(\'change\', function() {
3772 $(this.element.$).addClass(\'modified\');
3773 })
3774 } else {
3775 console.warn("A html section has the contenteditable=true attribute but has no id attribute");
3776 }
3777 })
3778
3779 isEditingEnabled = true;
3780
3781 // Trigger the function when clicking outside the elements with contenteditable=true attribute
3782 // so we can save the change.
3783 $(document).on(\'click\', function(e) {
3784 var target = $(e.target);
3785
3786 // Check if the click is outside the elements with contenteditable=true attribute
3787 if (!target.closest(\'[contenteditable="true"]\').length) {
3788 // Repeat through the elements with contenteditable="true" attribute
3789 $(\'[contenteditable="true"]\').each(function() {
3790 var idToUse = $(this).attr(\'id\');
3791 var elementType = $(this).prop("tagName").toLowerCase(); // Get the tag name (div, section, footer...)
3792 var instance = CKEDITOR.instances[idToUse];
3793
3794 // Check if the element has been modified
3795 if ($(this).hasClass(\'modified\')) {
3796 var content = instance.getData();
3797 content = "\\n" + content;
3798
3799 // Retrieving the content and ID of the element
3800 var elementId = $(this).attr(\'id\');
3801
3802 ';
3803 if (getDolGlobalString('WEBSITE_EDITINLINE_SAVE_CKEDITOR_EDIT')) {
3804 print '
3805 console.log("A change has been detected, we send new content for update with ajax");
3806
3807 // Sending data via AJAX to update section
3808 $.ajax({
3809 type: \'POST\',
3810 url: \'' . DOL_URL_ROOT . '/core/ajax/editinline.php\',
3811 data: {
3812 website_ref: \''.dol_escape_js($website->ref).'\',
3813 page_id: \'' . ((int) $websitepage->id) . '\',
3814 content: content,
3815 element_id: elementId,
3816 element_type: elementType,
3817 action: \'updatedElementContent\',
3818 token: \'' . newToken() . '\'
3819 },
3820 success: function(response) {
3821 console.log(response);
3822 var $lastWebsitebar = $(".websitebar").last();
3823 var $span = $("<span></span>").html("'.$langs->trans("Saved").'").css({
3824 \'display\': \'block\',
3825 \'position\': \'absolute\',
3826 \'margin-top\': \'6px\',
3827 \'right\': \'5px\',
3828 \'background-color\': \'#e3f0db\',
3829 \'color\': \'#446548\',
3830 \'font-size\': \'14px\',
3831 \'padding\': \'0px 5px\',
3832 \'z-index\': 1000
3833 });
3834 $lastWebsitebar.after($span);
3835
3836 // Close message after 2 seconds
3837 setTimeout(function() {
3838 $span.fadeOut(500, function() {
3839 $(this).remove();
3840 });
3841 }, 2000);
3842 }
3843 });
3844 ';
3845 } else {
3846 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");';
3847 }
3848 print '
3849
3850 $(this).removeClass(\'modified\');
3851 }
3852 });
3853 }
3854 });
3855
3856 } else {
3857 console.log("Disable inline edit");
3858 for(name in CKEDITOR.instances) {
3859 CKEDITOR.instances[name].destroy(true);
3860 }
3861 isEditingEnabled = false;
3862 }
3863 }
3864 });
3865 </script>';
3866 print $langs->trans("EditInLine");
3867 print '</span>';
3868
3869 //$disableeditinline = $websitepage->grabbed_from;
3870 $disableeditinline = 0;
3871 if ($disableeditinline) {
3872 //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">';
3873 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>';
3874 } else {
3875 //print '<input type="submit" class="button nobordertransp"'.$disabled.' value="'.dol_escape_htmltag($langs->trans("EditWithEditor")).'" name="editcontent">';
3876 if (!getDolGlobalString('WEBSITE_EDITINLINE')) {
3877 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>';
3878 } else {
3879 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>';
3880 }
3881 }
3882
3883 print '</div>';
3884
3885 print '</div>';
3886
3887 // Set page as homepage
3888 print '<span class="websiteselection">';
3889 if ($object->fk_default_home > 0 && $pageid == $object->fk_default_home) {
3890 //$disabled=' disabled="disabled"';
3891 //print '<span class="button bordertransp disabled"'.$disabled.' title="'.dol_escape_htmltag($langs->trans("SetAsHomePage")).'"><span class="fas fa-home"></span></span>';
3892 //print '<input type="submit" class="button bordertransp" disabled="disabled" value="'.dol_escape_htmltag($langs->trans("SetAsHomePage")).'" name="setashome">';
3893 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>';
3894 } else {
3895 //$disabled='';
3896 //print '<input type="submit" class="button bordertransp"'.$disabled.' value="'.dol_escape_htmltag($langs->trans("SetAsHomePage")).'" name="setashome">';
3897 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>';
3898 }
3899 print '<input type="submit" class="button bordertransp"'.$disabled.' value="'.dol_escape_htmltag($langs->trans("ClonePage")).'" name="createpagefromclone">';
3900
3901 // Delete
3902 if ($websitepage->status != $websitepage::STATUS_DRAFT) {
3903 $disabled = ' disabled="disabled"';
3904 $title = $langs->trans("WebpageMustBeDisabled", $langs->transnoentitiesnoconv($websitepage->LibStatut(0, 0)));
3905 $url = '#';
3906 } else {
3907 $disabled = '';
3908 $title = '';
3909 $url = $_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&pageid='.((int) $websitepage->id).'&website='.urlencode($website->ref); // action=delete for webpage, deletesite for website
3910 }
3911 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>';
3912 print '</span>';
3913 }
3914 }
3915
3916 //print '</span>'; // end website selection
3917
3918 print '<span class="websitetools">';
3919
3920 if (($pageid > 0 && $atleastonepage) && ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone' || $action == 'deletesite')) {
3921 $realpage = $urlwithroot.'/public/website/index.php?website='.$websitekey.'&pageref='.$websitepage->pageurl;
3922 $pagealias = $websitepage->pageurl;
3923
3924 $htmltext = $langs->trans("PreviewSiteServedByDolibarr", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $realpage, $langs->transnoentitiesnoconv("TestDeployOnWeb"));
3925 //$htmltext .= '<br>'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("ReadPerm"), '{s1}');
3926 //$htmltext = str_replace('{s1}', $dataroot.'<br>'.DOL_DATA_ROOT.'/medias<br>'.DOL_DOCUMENT_ROOT, $htmltext);
3927 //$htmltext .= '<br>'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("WritePerm"), '{s1}');
3928 //$htmltext = str_replace('{s1}', DOL_DATA_ROOT.'/medias', $htmltext);
3929
3930 print '<div class="websiteinputurl inline-block paddingright">';
3931 print '<a class="websitebuttonsitepreview inline-block" id="previewpage" href="'.$realpage.'&nocache='.dol_now().'" class="button" target="tab'.$websitekey.'" alt="'.dol_escape_htmltag($htmltext).'">';
3932 print $form->textwithpicto('', $htmltext, 1, 'preview');
3933 print '</a>'; // View page in new Tab
3934 print '</div>';
3935
3936 /*print '<div class="websiteinputurl inline-block" id="websiteinputpage">';
3937 print '<input type="text" id="previewpageurl" class="minwidth200imp" name="previewsite" value="'.$pagealias.'" disabled="disabled">';
3938 $htmltext = $langs->trans("PageNameAliasHelp", $langs->transnoentitiesnoconv("EditPageMeta"));
3939 print $form->textwithpicto('', $htmltext, 1, 'help', '', 0, 2, 'helppagealias');
3940 print '</div>';*/
3941
3942 /*
3943 $urlext = $virtualurl.'/'.$pagealias.'.php';
3944 $urlint = $urlwithroot.'/public/website/index.php?website='.$websitekey;
3945
3946 $htmltext = $langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $dataroot, $virtualurl ? $urlext : '<span class="error">'.$langs->trans("VirtualHostUrlNotDefined").'</span>');
3947
3948 print '<a class="websitebuttonsitepreview'.($virtualurl ? '' : ' websitebuttonsitepreviewdisabled cursornotallowed').'" id="previewpageext" href="'.$urlext.'" target="tab'.$websitekey.'ext" alt="'.dol_escape_htmltag($htmltext).'">';
3949 print $form->textwithpicto('', $htmltext, 1, 'preview_ext');
3950 print '</a>';
3951 */
3952 //print '<input type="submit" class="button" name="previewpage" target="tab'.$websitekey.'"value="'.$langs->trans("ViewPageInNewTab").'">';
3953
3954 // TODO Add js to save alias like we save virtual host name and use dynamic virtual host for url of id=previewpageext
3955 }
3956 if (!in_array($mode, array('replacesite')) && !in_array($action, array('editcss', 'editmenu', 'file_manager', 'replacesiteconfirm', 'createsite', 'createcontainer', 'createfromclone', 'createpagefromclone', 'deletesite', 'editsecurity'))) {
3957 if (!$user->hasRight('website', 'write')) {
3958 $disabled = ' disabled';
3959 }
3960 if ($action == 'editsource' || $action == 'editmeta') {
3961 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">';
3962 }
3963 if (preg_match('/^create/', $action)) {
3964 print '<input type="submit" id="savefile" class="button buttonforacesave button-save small'.$disabled.'" value="'.dol_escape_htmltag($langs->trans("Save")).'" name="update">';
3965 }
3966 if (preg_match('/^edit/', $action)) {
3967 print '<input type="submit" id="savefile" class="button buttonforacesave button-save small'.$disabled.'" value="'.dol_escape_htmltag($langs->trans("Save")).'" name="update">';
3968 }
3969 if ($action != 'preview') {
3970 print '<input type="submit" class="button button-cancel small" value="'.dol_escape_htmltag($langs->trans("Cancel")).'" name="cancel">';
3971 }
3972 }
3973
3974 print '</span>'; // end websitetools
3975
3976 print '<span class="websitehelp">';
3977 if ($action == 'editsource' || $action == 'editcontent' || GETPOST('editsource', 'alpha') || GETPOST('editcontent', 'alpha')) {
3978 $url = 'https://wiki.dolibarr.org/index.php/Module_Website';
3979
3980 $htmltext = '<small>';
3981 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource", $url);
3982 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSourceb", $url);
3983 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSourcec", $url);
3984 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSourced", $url);
3985 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource1", $url);
3986 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource2", $url);
3987 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource3", $url);
3988 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource4", $url);
3989 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSourceMore", $url);
3990 $htmltext .= '<br>';
3991 $htmltext .= '</small>';
3992 if ($conf->browser->layout == 'phone') {
3993 print $form->textwithpicto('', $htmltext, 1, 'help', 'inline-block', 1, 2, 'tooltipsubstitution');
3994 } else {
3995 //img_help(($tooltiptrigger != '' ? 2 : 1), $alt)
3996 print $form->textwithpicto($langs->trans("SyntaxHelp").' '.img_help(2, $langs->trans("SyntaxHelp")), $htmltext, 1, 'none', 'inline-block', 1, 2, 'tooltipsubstitution');
3997 }
3998 }
3999 print '</span>'; // end websitehelp
4000
4001
4002 if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone') {
4003 // Adding jquery code to change on the fly url of preview ext
4004 if (!empty($conf->use_javascript_ajax)) {
4005 print '<script type="text/javascript">
4006 jQuery(document).ready(function() {
4007 jQuery("#websiteinputurl").keyup(function() {
4008 console.log("Website external url modified "+jQuery("#previewsiteurl").val());
4009 if (jQuery("#previewsiteurl").val() != "" && jQuery("#previewsiteurl").val().startsWith("http"))
4010 {
4011 jQuery("a.websitebuttonsitepreviewdisabled img").css({ opacity: 1 });
4012 }
4013 else jQuery("a.websitebuttonsitepreviewdisabled img").css({ opacity: 0.2 });
4014 ';
4015 print '
4016 });
4017 jQuery("#previewsiteext,#previewpageext").click(function() {
4018
4019 newurl=jQuery("#previewsiteurl").val();
4020 if (! newurl.startsWith("http"))
4021 {
4022 alert(\''.dol_escape_js($langs->trans("ErrorURLMustStartWithHttp")).'\');
4023 return false;
4024 }
4025
4026 newpage=jQuery("#previewsiteurl").val() + "/" + jQuery("#previewpageurl").val() + ".php";
4027 console.log("Open url "+newurl);
4028 /* Save url */
4029 jQuery.ajax({
4030 method: "POST",
4031 url: "'.DOL_URL_ROOT.'/core/ajax/saveinplace.php",
4032 data: {
4033 field: \'editval_virtualhost\',
4034 element: \'website\',
4035 table_element: \'website\',
4036 fk_element: '.((int) $object->id).',
4037 value: newurl,
4038 },
4039 context: document.body
4040 });
4041
4042 jQuery("#previewsiteext").attr("href",newurl);
4043 jQuery("#previewpageext").attr("href",newpage);
4044 });
4045 });
4046 </script>';
4047 }
4048 }
4049 }
4050
4051 print '</div>'."\n"; // end current websitebar
4052}
4053
4054
4055$head = array();
4056
4057
4058/*
4059 * Edit Site HTML header and CSS
4060 */
4061
4062if ($action == 'editcss') {
4063 print '<div class="fiche">';
4064
4065 print '<br>';
4066
4067 if (!GETPOSTISSET('WEBSITE_CSS_INLINE')) {
4068 $csscontent = @file_get_contents($filecss);
4069 // Clean the php css file to remove php code and get only css part
4070 $csscontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $csscontent);
4071 } else {
4072 $csscontent = GETPOST('WEBSITE_CSS_INLINE', 'none');
4073 }
4074 if (!trim($csscontent)) {
4075 $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;}";
4076 }
4077
4078 if (!GETPOSTISSET('WEBSITE_JS_INLINE')) {
4079 $jscontent = @file_get_contents($filejs);
4080 // Clean the php js file to remove php code and get only js part
4081 $jscontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $jscontent);
4082 } else {
4083 $jscontent = GETPOST('WEBSITE_JS_INLINE', 'none');
4084 }
4085 if (!trim($jscontent)) {
4086 $jscontent = '/* JS content (all pages) */'."\n";
4087 }
4088
4089 if (!GETPOSTISSET('WEBSITE_HTML_HEADER')) {
4090 $htmlheadercontent = @file_get_contents($filehtmlheader);
4091 // Clean the php htmlheader file to remove php code and get only html part
4092 $htmlheadercontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $htmlheadercontent);
4093 } else {
4094 $htmlheadercontent = GETPOST('WEBSITE_HTML_HEADER', 'none'); // Must accept tags like '<script>' and '<link>'
4095 }
4096 if (!trim($htmlheadercontent)) {
4097 $htmlheadercontent = "<html>\n";
4098 $htmlheadercontent .= $htmlheadercontentdefault;
4099 $htmlheadercontent .= "</html>";
4100 } else {
4101 $htmlheadercontent = preg_replace('/^\s*<html>/ims', '', $htmlheadercontent);
4102 $htmlheadercontent = preg_replace('/<\/html>\s*$/ims', '', $htmlheadercontent);
4103 $htmlheadercontent = '<html>'."\n".trim($htmlheadercontent)."\n".'</html>';
4104 }
4105
4106 if (!GETPOSTISSET('WEBSITE_ROBOT')) {
4107 $robotcontent = @file_get_contents($filerobot);
4108 // Clean the php htmlheader file to remove php code and get only html part
4109 $robotcontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $robotcontent);
4110 } else {
4111 $robotcontent = GETPOST('WEBSITE_ROBOT', 'nohtml');
4112 }
4113 if (!trim($robotcontent)) {
4114 $robotcontent .= "# Robot file. Generated with ".DOL_APPLICATION_TITLE."\n";
4115 $robotcontent .= "User-agent: *\n";
4116 $robotcontent .= "Allow: /public/\n";
4117 $robotcontent .= "Disallow: /administrator/\n";
4118 }
4119
4120 if (!GETPOSTISSET('WEBSITE_HTACCESS')) {
4121 $htaccesscontent = @file_get_contents($filehtaccess);
4122 // Clean the php htaccesscontent file to remove php code and get only html part
4123 $htaccesscontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $htaccesscontent);
4124 } else {
4125 $htaccesscontent = GETPOST('WEBSITE_HTACCESS', 'nohtml'); // We must use 'nohtml' and not 'alphanohtml' because we must accept "
4126 }
4127
4128 if (!GETPOSTISSET('WEBSITE_MANIFEST_JSON')) {
4129 $manifestjsoncontent = @file_get_contents($filemanifestjson);
4130 // Clean the manifestjson file to remove php code and get only html part
4131 $manifestjsoncontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $manifestjsoncontent);
4132 } else {
4133 $manifestjsoncontent = trim(GETPOST('WEBSITE_MANIFEST_JSON', 'restricthtmlallowunvalid'));
4134 $manifestjsoncontent = str_replace('<?=', '<?php', $manifestjsoncontent);
4135 }
4136
4137 //if (!trim($manifestjsoncontent)) {
4138 //$manifestjsoncontent.="";
4139 //}
4140
4141 if (!GETPOSTISSET('WEBSITE_README')) {
4142 $readmecontent = @file_get_contents($filereadme);
4143 // Clean the readme file to remove php code and get only html part
4144 $readmecontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $readmecontent);
4145 } else {
4146 $readmecontent = GETPOST('WEBSITE_README', 'restricthtmlallowunvalid');
4147 }
4148 //if (!trim($readmecontent)) {
4149 //$readmecontent.="";
4150 //}
4151
4152 if (!GETPOSTISSET('WEBSITE_LICENSE')) {
4153 $licensecontent = @file_get_contents($filelicense);
4154 // Clean the readme file to remove php code and get only html part
4155 $licensecontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP( \?>)?\n*/ims', '', $licensecontent);
4156 } else {
4157 $licensecontent = GETPOST('WEBSITE_LICENSE', 'restricthtmlallowunvalid');
4158 }
4159 //if (!trim($licensecontent)) {
4160 //$readmecontent.="";
4161 //}
4162
4163 $head = websiteconfigPrepareHead($object);
4164 print dol_get_fiche_head($head, 'general', $langs->trans("General"), 0, 'website');
4165
4166 print '<!-- Edit Website properties (CSS, Language, ...) -->'."\n";
4167 print '<table class="border centpercent">';
4168
4169 // Website
4170 print '<tr><td class="titlefieldcreate fieldrequired">';
4171 print $langs->trans('WebSite');
4172 print '</td><td>';
4173 print $websitekey;
4174 print '</td></tr>';
4175
4176 // Status of web site
4177 if ($action != 'createcontainer') {
4178 if (empty($conf->use_javascript_ajax)) {
4179 print '<!-- Status of web site page -->'."\n";
4180 print '<tr><td class="fieldrequired">';
4181 print $langs->trans('Status');
4182 print '</td><td>';
4183 print $form->selectyesno('status', $object->status);
4184 print '</td></tr>';
4185 }
4186 }
4187
4188 // Main language
4189 print '<tr><td class="tdtop fieldrequired">';
4190 $htmltext = '';
4191 print $form->textwithpicto($langs->trans('MainLanguage'), $htmltext, 1, 'help', '', 0, 2, 'WEBSITE_LANG');
4192 print '</td><td>';
4193 print img_picto('', 'language', 'class="pictofixedwidth"');
4194 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);
4195 print '</td>';
4196 print '</tr>';
4197
4198 // Other languages
4199 print '<tr><td class="tdtop">';
4200 $htmltext = $langs->trans("Example").': fr,de,sv,it,pt';
4201 print $form->textwithpicto($langs->trans('OtherLanguages'), $htmltext, 1, 'help', '', 0, 2);
4202 print '</td><td>';
4203 print img_picto('', 'language', 'class="pictofixedwidth"');
4204 print '<input type="text" class="flat maxwidth200" value="'.(GETPOSTISSET('WEBSITE_OTHERLANG') ? GETPOST('WEBSITE_OTHERLANG', 'alpha') : $object->otherlang).'" name="WEBSITE_OTHERLANG">';
4205 print '</td>';
4206 print '</tr>';
4207
4208 // VirtualHost
4209 print '<tr><td class="tdtop">';
4210
4211 $htmltext = $langs->trans("VirtualhostDesc");
4212 print $form->textwithpicto($langs->trans('Virtualhost'), $htmltext, 1, 'help', '', 0, 2, 'virtualhosttooltip');
4213 print '</td><td>';
4214 print '<input type="text" class="flat minwidth300" value="'.(GETPOSTISSET('virtualhost') ? GETPOST('virtualhost', 'alpha') : $virtualurl).'" name="virtualhost">';
4215 print '</td>';
4216 print '</tr>';
4217
4218 // Favicon
4219 print '<tr><td>';
4220 print $form->textwithpicto($langs->trans('ImportFavicon'), $langs->trans('FaviconTooltip'));
4221 print '</td><td>';
4222 $maxfilesizearray = getMaxFileSizeArray();
4223 $maxmin = $maxfilesizearray['maxmin'];
4224 if ($maxmin > 0) {
4225 print '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
4226 }
4227 print '<input type="file" class="flat minwidth300" name="addedfile" id="addedfile"/>';
4228
4229 $uploadfolder = $conf->website->dir_output.'/'.$websitekey;
4230 if (dol_is_file($uploadfolder.'/favicon.png')) {
4231 print '<div class="inline-block valignmiddle marginrightonly">';
4232 print '<img style="max-height: 80px" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=website&file='.$websitekey.'/favicon.png">';
4233 print '</div>';
4234 }
4235 print '</tr></td>';
4236
4237 // CSS file
4238 print '<tr><td class="tdtop">';
4239 $htmlhelp = $langs->trans("CSSContentTooltipHelp");
4240 print $form->textwithpicto($langs->trans('WEBSITE_CSS_INLINE'), $htmlhelp, 1, 'help', '', 0, 2, 'csstooltip');
4241 print '</td><td>';
4242
4243 $poscursor = array('x' => GETPOST('WEBSITE_CSS_INLINE_x'), 'y' => GETPOST('WEBSITE_CSS_INLINE_y'));
4244 $doleditor = new DolEditor('WEBSITE_CSS_INLINE', $csscontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4245 print $doleditor->Create(1, '', true, 'CSS', 'css');
4246
4247 print '</td></tr>';
4248
4249 // JS file
4250 print '<tr><td class="tdtop">';
4251 $textwithhelp = $langs->trans('WEBSITE_JS_INLINE');
4252 $htmlhelp2 = $langs->trans("LinkAndScriptsHereAreNotLoadedInEditor").'<br>';
4253 print $form->textwithpicto($textwithhelp, $htmlhelp2, 1, 'warning', '', 0, 2, 'htmljstooltip2');
4254
4255 print '</td><td>';
4256
4257 $poscursor = array('x' => GETPOST('WEBSITE_JS_INLINE_x'), 'y' => GETPOST('WEBSITE_JS_INLINE_y'));
4258 $doleditor = new DolEditor('WEBSITE_JS_INLINE', $jscontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4259 print $doleditor->Create(1, '', true, 'JS', 'javascript');
4260
4261 print '</td></tr>';
4262
4263 // Common HTML header
4264 print '<tr><td class="tdtop">';
4265 print $langs->trans('WEBSITE_HTML_HEADER');
4266 $htmlhelp = $langs->trans("Example").' :<br>';
4267 $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.
4268 $textwithhelp = $form->textwithpicto('', $htmlhelp, 1, 'help', '', 0, 2, 'htmlheadertooltip');
4269 $htmlhelp2 = $langs->trans("LinkAndScriptsHereAreNotLoadedInEditor").'<br>';
4270 print $form->textwithpicto($textwithhelp, $htmlhelp2, 1, 'warning', '', 0, 2, 'htmlheadertooltip2');
4271 print '</td><td>';
4272
4273 $poscursor = array('x' => GETPOST('WEBSITE_HTML_HEADER_x'), 'y' => GETPOST('WEBSITE_HTML_HEADER_y'));
4274 $doleditor = new DolEditor('WEBSITE_HTML_HEADER', $htmlheadercontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4275 print $doleditor->Create(1, '', true, 'HTML Header', 'html');
4276
4277 print '</td></tr>';
4278
4279 // Robot file
4280 print '<tr><td class="tdtop">';
4281 print $langs->trans('WEBSITE_ROBOT');
4282 print '</td><td>';
4283
4284 $poscursor = array('x' => GETPOST('WEBSITE_ROBOT_x'), 'y' => GETPOST('WEBSITE_ROBOT_y'));
4285 $doleditor = new DolEditor('WEBSITE_ROBOT', $robotcontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4286 print $doleditor->Create(1, '', true, 'Robot file', 'text');
4287
4288 print '</td></tr>';
4289
4290 // .htaccess
4291 print '<tr><td class="tdtop">';
4292
4293 $textwithhelp3 = $langs->trans("Example").' :';
4294 $textwithhelp3 .= "<br># Order allow,deny\n";
4295 $textwithhelp3 .= "<br># Deny from all\n";
4296 $textwithhelp3 .= "<br># Require all granted\n";
4297
4298 print $form->textwithpicto($langs->trans('WEBSITE_HTACCESS'), $textwithhelp3, 1, 'help', '', 0, 2, 'htmlheadertooltip3');
4299 print '</td><td>';
4300
4301 $poscursor = array('x' => GETPOST('WEBSITE_HTACCESS_x'), 'y' => GETPOST('WEBSITE_HTACCESS_y'));
4302 $doleditor = new DolEditor('WEBSITE_HTACCESS', $htaccesscontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4303 print $doleditor->Create(1, '', true, $langs->trans("File").' .htaccess', 'text');
4304
4305 print '</td></tr>';
4306
4307 // Manifest.json
4308 print '<tr><td class="tdtop">';
4309 $htmlhelp = $langs->trans("Example").' :<br>';
4310 $htmlhelp .= '<small>'.dol_htmlentitiesbr($manifestjsoncontentdefault).'</small>';
4311 print $form->textwithpicto($langs->trans('WEBSITE_MANIFEST_JSON'), $htmlhelp, 1, 'help', '', 0, 2, 'manifestjsontooltip');
4312 print '</td><td>';
4313 print $langs->trans("UseManifest").': '.$form->selectyesno('use_manifest', $website->use_manifest, 1).'<br>';
4314
4315 $poscursor = array('x' => GETPOST('WEBSITE_MANIFEST_JSON_x'), 'y' => GETPOST('WEBSITE_MANIFEST_JSON_y'));
4316 $doleditor = new DolEditor('WEBSITE_MANIFEST_JSON', $manifestjsoncontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4317 print $doleditor->Create(1, '', true, $langs->trans("File").' manifest.json', 'text');
4318 print '</td></tr>';
4319
4320 // README.md
4321 print '<tr><td class="tdtop">';
4322 $htmlhelp = $langs->trans("EnterHereReadmeInformation");
4323 print $form->textwithpicto($langs->trans("File").' README.md', $htmlhelp, 1, 'help', '', 0, 2, 'readmetooltip');
4324 print '</td><td>';
4325
4326 $poscursor = array('x' => GETPOST('WEBSITE_README_x'), 'y' => GETPOST('WEBSITE_README_y'));
4327 $doleditor = new DolEditor('WEBSITE_README', $readmecontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4328 print $doleditor->Create(1, '', true, $langs->trans("File").' README.md', 'text');
4329
4330 print '</td></tr>';
4331
4332 // LICENSE
4333 print '<tr><td class="tdtop">';
4334 $htmlhelp = $langs->trans("EnterHereLicenseInformation");
4335 print $form->textwithpicto($langs->trans("File").' LICENSE', $htmlhelp, 1, 'help', '', 0, 2, 'licensetooltip');
4336 print '</td><td>';
4337
4338 $poscursor = array('x' => GETPOST('WEBSITE_LICENSE_x'), 'y' => GETPOST('WEBSITE_LICENSE_y'));
4339 $doleditor = new DolEditor('WEBSITE_LICENSE', $licensecontent, '', 220, 'ace', 'In', true, false, 'ace', 0, '100%', 0, $poscursor);
4340 print $doleditor->Create(1, '', true, $langs->trans("File").' LICENSE', 'text');
4341
4342 print '</td></tr>';
4343
4344 // RSS
4345 print '<tr><td class="tdtop">';
4346 $htmlhelp = $langs->trans('RSSFeedDesc');
4347 print $form->textwithpicto($langs->trans('RSSFeed'), $htmlhelp, 1, 'help', '', 0, 2, '');
4348 print '</td><td>';
4349 print '/wrapper.php?rss=1[&l=XX][&limit=99][&cachedelay=99]';
4350 print '</td></tr>';
4351
4352 print '</table>';
4353
4354 print dol_get_fiche_end();
4355
4356 print '</div>';
4357
4358 print '<br>';
4359}
4360
4361if ($action == 'editsecurity') {
4362 $selectarrayCSPDirectives = websiteGetContentPolicyDirectives();
4363 $selectarrayCSPSources = websiteGetContentPolicySources();
4364 $forceCSPArr = websiteGetContentPolicyToArray($forceCSP);
4365 print '<div class="fiche">';
4366 print '<br>';
4367
4368 $head = websiteconfigPrepareHead($object);
4369 print dol_get_fiche_head($head, 'security', $langs->trans("General"), -1, 'website');
4370
4371 print '<span class="opacitymedium">'.$langs->trans("HTTPHeaderEditor").'. '.$langs->trans("ReservedToAdvancedUsers").'.</span><br><br>';
4372
4373 print '<div class="div-table-responsive-no-min">';
4374 print '<table class="noborder centpercent">';
4375 print '<tr class="liste_titre">';
4376 print '<td>'.$langs->trans("HTTPHeader").'</td>';
4377 print '<td></td>'."\n";
4378 print '</tr>';
4379
4380 // Force RP
4381 print '<tr class="oddeven">';
4382 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>';
4383 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>';
4384 print '</tr>';
4385 // Force STS
4386 print '<tr class="oddeven">';
4387 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>';
4388 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>';
4389 print '</tr>';
4390 // Force PP
4391 print '<tr class="oddeven">';
4392 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>';
4393 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>';
4394 print '</tr>';
4395
4396 $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;";
4397
4398 // Force CSP - Content Security Policy
4399 print '<tr class="oddeven nohover">';
4400 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>';
4401 print '<td>';
4402
4403 print '<div class="div-table-responsive-no-min">';
4404
4405 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>';
4406
4407 print '<br class="selectaddcontentsecuritypolicy hidden">';
4408
4409 print '<div id="selectaddcontentsecuritypolicy" class="hidden selectaddcontentsecuritypolicy">';
4410 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');
4411 print ' ';
4412 print '<input type="hidden" id="select_source_WEBSITE_SECURITY_FORCECSP" name="select_source_WEBSITE_SECURITY_FORCECSP">';
4413 foreach ($selectarrayCSPSources as $key => $values) {
4414 print '<div class="div_WEBSITE_SECURITY_FORCECSP hidden inline-block maxwidth350" id="div_'.$key.'_WEBSITE_SECURITY_FORCECSP">';
4415 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');
4416 print '</div>';
4417 }
4418 print ' ';
4419 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>';
4420 print ' ';
4421 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>';
4422 print '<br><br>';
4423 print '</div>';
4424
4425 if (!empty($forceCSP)) {
4426 // Content Security Policy list of selected rules
4427 print '<br>';
4428 print '<div class="div-table-responsive-no-min">';
4429 print img_picto('', 'graph', 'class="pictofixedwidth"').$langs->trans("HierarchicView").'<br>';
4430 print '<ul>';
4431 foreach ($forceCSPArr as $directive => $sources) {
4432 print '<li>';
4433 if (in_array($directive, array_keys($selectarrayCSPDirectives))) {
4434 print '<span>'.$directive.'</span>';
4435 } else {
4436 print $form->textwithpicto($directive, $langs->trans("UnknowContentSecurityPolicyDirective"), 1, 'warning');
4437 }
4438 if (!empty($sources)) {
4439 print '<ul>';
4440 foreach ($sources as $key => $source) {
4441 print '<li><span>'.$source.'</span>&nbsp;<a href="'.$_SERVER["PHP_SELF"].'?websiteid='.$websiteid.'&action=removecspsource&sourcecsp='.$directive.'_'.$key.'&token='.newToken().'">'.img_delete().'</a></li>';
4442 }
4443 print '</ul>';
4444 } else {
4445 print '&nbsp;<a href="'.$_SERVER["PHP_SELF"].'?websiteid='.$websiteid.'&action=removecspsource&sourcecsp='.$directive.'&token='.newToken().'">'.img_delete().'</a>';
4446 }
4447 print '</li>';
4448 }
4449 print '</ul>';
4450 print '</div>';
4451 }
4452 print '</div>';
4453
4454 print '</td>';
4455 print '</tr>';
4456
4457 // Force CSPRO
4458 if (getDolGlobalString("WEBSITE_".$object->id."_SECURITY_FORCECSPRO")) {
4459 print '<tr class="oddeven">';
4460 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>';
4461 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>';
4462 print '</tr>';
4463 }
4464
4465 print '</table>';
4466 print '</div>';
4467
4468
4469 print '<div class="center">';
4470
4471 print '<input type="submit" class="button small" name="updateandstay" value="'.$langs->trans("Save").'">';
4472 print '<input class="button button-cancel small" type="submit" name="preview" value="'.$langs->trans("Cancel").'">';
4473
4474 print '</div>';
4475
4476
4477 print '<script>
4478 $(document).ready(function() {
4479 $("#btnaddcontentsecuritypolicy").on("click", function(){
4480 if($("#selectaddcontentsecuritypolicy").is(":visible")){
4481 console.log("We hide select to add Content Security Policy");
4482 $(".selectaddcontentsecuritypolicy").hide();
4483 } else {
4484 console.log("We show select to add Content Security Policy");
4485 $(".selectaddcontentsecuritypolicy").show();
4486 }
4487 });
4488
4489 $("#select_identifier_WEBSITE_SECURITY_FORCECSP").on("change", function() {
4490 key = $(this).find(":selected").data("directivetype");
4491 console.log("We hide all select div");
4492 $(".div_WEBSITE_SECURITY_FORCECSP").hide();
4493 $(".select_WEBSITE_SECURITY_FORCECSP").val(null).trigger("change");
4494 $(".div_input_data_WEBSITE_SECURITY_FORCECSP").hide();
4495 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",true);
4496 if (key == "none"){
4497 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",false);
4498 } else {
4499 console.log("We show div select with key "+key);
4500 $("#div_"+key+"_WEBSITE_SECURITY_FORCECSP").css("display", "inline-block");
4501 }
4502 });
4503
4504 $(".select_WEBSITE_SECURITY_FORCECSP").on("change", function() {
4505 keysource = $(this).find(":selected").data("sourcetype");
4506 $("#select_source_WEBSITE_SECURITY_FORCECSP").val($(this).val());
4507 console.log("We hide and show fields");
4508 if (keysource == "data" || keysource == "input") {
4509 $(".div_input_data_WEBSITE_SECURITY_FORCECSP").css("display", "inline-block");
4510 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",true);
4511 } else {
4512 $("#input_data_WEBSITE_SECURITY_FORCECSP").val("");
4513 $(".div_input_data_WEBSITE_SECURITY_FORCECSP").hide();
4514 if (keysource != undefined) {
4515 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",false);
4516 } else {
4517 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",true);
4518 }
4519 }
4520 });
4521
4522 $("#input_data_WEBSITE_SECURITY_FORCECSP").on("change keyup", function(){
4523 if ($(this).val() != "") {
4524 console.log("We show add button");
4525 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",false);
4526 } else {
4527 console.log("We hide add button");
4528 $("#btn_WEBSITE_SECURITY_FORCECSP").prop("disabled",true);
4529 }
4530 });
4531 });
4532 </script>';
4533
4534 print dol_get_fiche_end();
4535 print '</div>';
4536}
4537
4538
4539if ($action == 'createsite') {
4540 print '<div class="fiche">';
4541
4542 print '<br>';
4543
4544 /*$h = 0;
4545 $head = array();
4546
4547 $head[$h][0] = dol_buildpath('/website/index.php',1).'?id='.$object->id;
4548 $head[$h][1] = $langs->trans("AddWebsite");
4549 $head[$h][2] = 'card';
4550 $h++;
4551
4552 print dol_get_fiche_head($head, 'card', '', -1, 'website');
4553 */
4554 if ($action == 'createcontainer') {
4555 print load_fiche_titre($langs->trans("AddWebsite"));
4556 }
4557
4558 print '<!-- Add site -->'."\n";
4559 print '<div class="tabBar tabBarWithBottom">';
4560
4561 print '<table class="border centpercent">';
4562
4563 $siteref = $sitedesc = $sitelang = $siteotherlang = '';
4564 if (GETPOST('WEBSITE_REF')) {
4565 $siteref = GETPOST('WEBSITE_REF', 'aZ09');
4566 }
4567 if (GETPOST('WEBSITE_DESCRIPTION')) {
4568 $sitedesc = GETPOST('WEBSITE_DESCRIPTION', 'alpha');
4569 }
4570 if (GETPOST('WEBSITE_LANG')) {
4571 $sitelang = GETPOST('WEBSITE_LANG', 'aZ09');
4572 }
4573 if (GETPOST('WEBSITE_OTHERLANG')) {
4574 $siteotherlang = GETPOST('WEBSITE_OTHERLANG', 'aZ09comma');
4575 }
4576
4577 print '<tr><td class="titlefieldcreate fieldrequired">';
4578 print $form->textwithpicto($langs->trans('WebsiteName'), $langs->trans("Example").': MyPortal, www.mywebsite.com, ...');
4579 print '</td><td>';
4580 print '<input type="text" class="flat maxwidth300" name="WEBSITE_REF" value="'.dol_escape_htmltag($siteref).'" autofocus>';
4581 print '</td></tr>';
4582
4583 print '<tr><td class="fieldrequired">';
4584 print $langs->trans('MainLanguage');
4585 print '</td><td>';
4586 $shortlangcode = preg_replace('/[_-].*$/', '', trim($langs->defaultlang));
4587 print img_picto('', 'language', 'class="pictofixedwidth"');
4588 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);
4589 print '</td></tr>';
4590
4591 print '<tr><td>';
4592 $htmltext = $langs->trans("Example").': fr,de,sv,it,pt';
4593 print $form->textwithpicto($langs->trans('OtherLanguages'), $htmltext, 1, 'help', '', 0, 2);
4594 print '</td><td>';
4595 print img_picto('', 'language', 'class="pictofixedwidth"');
4596 print '<input type="text" class="flat minwidth300" name="WEBSITE_OTHERLANG" value="'.dol_escape_htmltag($siteotherlang).'">';
4597 print '</td></tr>';
4598
4599 print '<tr><td>';
4600 print $langs->trans('Description');
4601 print '</td><td>';
4602 print '<input type="text" class="flat minwidth500" name="WEBSITE_DESCRIPTION" value="'.dol_escape_htmltag($sitedesc).'">';
4603 print '</td></tr>';
4604
4605 print '<tr><td>';
4606
4607 $htmltext = $langs->trans("VirtualhostDesc");
4608 /*$htmltext = str_replace('{s1}', DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/<i>websiteref</i>', $htmltext);
4609 $htmltext .= '<br>';
4610 $htmltext .= '<br>'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("ReadPerm"), DOL_DOCUMENT_ROOT);
4611 $htmltext .= '<br>'.$langs->trans("CheckVirtualHostPerms", $langs->transnoentitiesnoconv("WritePerm"), '{s1}');
4612 $htmltext = str_replace('{s1}', DOL_DATA_ROOT.'/website<br>'.DOL_DATA_ROOT.'/medias', $htmltext);*/
4613
4614
4615 print $form->textwithpicto($langs->trans('Virtualhost'), $htmltext, 1, 'help', '', 0, 2, '');
4616 print '</td><td>';
4617 print '<input type="text" class="flat minwidth300" name="virtualhost" value="'.dol_escape_htmltag(GETPOST('virtualhost', 'alpha')).'">';
4618 print '</td></tr>';
4619
4620 print '</table>';
4621 print '</div>';
4622
4623 if ($action == 'createsite') {
4624 print '<div class="center">';
4625
4626 print '<input type="submit" class="button small" name="addcontainer" value="'.$langs->trans("Create").'">';
4627 print '<input class="button button-cancel small" type="submit" name="preview" value="'.$langs->trans("Cancel").'">';
4628
4629 print '</div>';
4630 }
4631
4632
4633 //print '</div>';
4634
4635 //print dol_get_fiche_end();
4636
4637 print '</div>';
4638
4639 print '<br>';
4640}
4641
4642// Page view to import a website template
4643if ($action == 'importsite') {
4644 print '<!-- action=importsite -->';
4645 print '<div class="fiche">';
4646
4647 print '<br>';
4648
4649 print load_fiche_titre($langs->trans("ImportSite"));
4650
4651 print dol_get_fiche_head(array(), '0', '', -1);
4652
4653 print '<span class="opacitymedium">'.$langs->trans("ZipOfWebsitePackageToImport").'</span><br><br>';
4654
4655
4656 $dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT);
4657 $allowimportsite = true;
4658 if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) {
4659 $allowimportsite = false;
4660 }
4661
4662 if ($allowimportsite) {
4663 $maxfilesizearray = getMaxFileSizeArray();
4664 $maxmin = $maxfilesizearray['maxmin'];
4665 if ($maxmin > 0) {
4666 print '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
4667 }
4668 print '<input class="flat minwidth400" type="file" name="userfile[]" accept=".zip">';
4669 print '<input type="submit" class="button small" name="buttonsubmitimportfile" value="'.dol_escape_htmltag($langs->trans("Upload")).'">';
4670 print '<input type="submit" class="button button-cancel small" name="preview" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
4671 print '<br><br><br>';
4672 } else {
4673 if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) {
4674 // Show clean corporate message
4675 $message = $langs->trans('InstallModuleFromWebHasBeenDisabledContactUs');
4676 } else {
4677 // Show technical generic message
4678 $message = $langs->trans("InstallModuleFromWebHasBeenDisabledByFile", $dolibarrdataroot.'/installmodules.lock');
4679 }
4680 print info_admin($message).'<br><br>';
4681 }
4682
4683
4684 print '<span class="opacitymedium">'.$langs->trans("ZipOfWebsitePackageToLoad").'</span><br><br>';
4685
4686 // This will scan the dir /doctemplates/websites and show all templates.
4687 showWebsiteTemplates($website, GETPOSTINT('importsite') == 2 ? 1 : 0);
4688
4689 print dol_get_fiche_end();
4690
4691 print '</div>';
4692
4693 print '<br>';
4694}
4695
4696if ($action == 'editmeta' || $action == 'createcontainer') { // Edit properties of a web site OR properties of a web page
4697 print '<div class="fiche">';
4698
4699 print '<br>';
4700
4701 /*$h = 0;
4702 $head = array();
4703
4704 $head[$h][0] = dol_buildpath('/website/index.php',1).'?id='.$object->id;
4705 $head[$h][1] = $langs->trans("AddPage");
4706 $head[$h][2] = 'card';
4707 $h++;
4708
4709 print dol_get_fiche_head($head, 'card', '', -1, 'website');
4710 */
4711 if ($action == 'createcontainer') {
4712 print load_fiche_titre($langs->trans("AddPage"));
4713 }
4714
4715 print '<!-- Edit or create page/container -->'."\n";
4716 //print '<div class="fichecenter">';
4717
4718 $hiddenfromfetchingafterload = ' hideobject';
4719 $hiddenmanuallyafterload = ' hideobject';
4720 if (GETPOST('radiocreatefrom') == 'checkboxcreatefromfetching') {
4721 $hiddenfromfetchingafterload = '';
4722 }
4723 if (GETPOST('radiocreatefrom') == 'checkboxcreatemanually') {
4724 $hiddenmanuallyafterload = '';
4725 }
4726
4727 if ($action == 'editmeta' || empty($conf->use_javascript_ajax)) { // No autohide/show in such case
4728 $hiddenfromfetchingafterload = '';
4729 $hiddenmanuallyafterload = '';
4730 }
4731
4732 if ($action == 'createcontainer') {
4733 print '<br>';
4734
4735 if (!empty($conf->use_javascript_ajax)) {
4736 print '<input type="radio" name="radiocreatefrom" id="checkboxcreatemanually" value="checkboxcreatemanually"'.(GETPOST('radiocreatefrom') == 'checkboxcreatemanually' ? ' checked' : '').'> ';
4737 }
4738 print '<label for="checkboxcreatemanually"><span class="opacitymediumxx">'.$langs->trans("OrEnterPageInfoManually").'</span></label><br>';
4739 print '<hr class="tablecheckboxcreatemanually'.$hiddenmanuallyafterload.'">';
4740 }
4741
4742
4743
4744 print '<table class="border tableforfield nobackground centpercent tablecheckboxcreatemanually'.$hiddenmanuallyafterload.'">';
4745
4746 if ($action != 'createcontainer') {
4747 print '<tr><td class="titlefield fieldrequired">';
4748 print $langs->trans('IDOfPage').' - '.$langs->trans('InternalURLOfPage');
4749 print '</td><td>';
4750 print $pageid;
4751 //print '</td></tr>';
4752
4753 //print '<tr><td class="titlefield fieldrequired">';
4754 //print $langs->trans('InternalURLOfPage');
4755 //print '</td><td>';
4756 print ' &nbsp; - &nbsp; ';
4757 print '/public/website/index.php?website='.urlencode($websitekey).'&pageid='.urlencode((string) $pageid);
4758 //if ($objectpage->grabbed_from) print ' - <span class="opacitymedium">'.$langs->trans('InitiallyGrabbedFrom').' '.$objectpage->grabbed_from.'</span>';
4759 print '</td></tr>';
4760
4761 $type_container = $objectpage->type_container;
4762 $pageurl = $objectpage->pageurl;
4763 $pagealiasalt = $objectpage->aliasalt;
4764 $pagetitle = $objectpage->title;
4765 $pagedescription = $objectpage->description;
4766 $pageimage = $objectpage->image;
4767 $pagekeywords = $objectpage->keywords;
4768 $pagelang = $objectpage->lang;
4769 $pageallowedinframes = $objectpage->allowed_in_frames;
4770 $pagehtmlheader = $objectpage->htmlheader;
4771 $pagedatecreation = (string) $objectpage->date_creation;
4772 $pagedatemodification = $objectpage->date_modification;
4773 $pageauthorid = $objectpage->fk_user_creat;
4774 $pageusermodifid = $objectpage->fk_user_modif;
4775 $pageauthoralias = $objectpage->author_alias;
4776 $pagestatus = $objectpage->status;
4777 } else { // $action = 'createcontainer'
4778 $type_container = 'page';
4779 $pageurl = '';
4780 $pagealiasalt = '';
4781 $pagetitle = '';
4782 $pagedescription = '';
4783 $pageimage = '';
4784 $pagekeywords = '';
4785 $pagelang = '';
4786 $pageallowedinframes = 0;
4787 $pagehtmlheader = '';
4788 $pagedatecreation = dol_now();
4789 $pagedatemodification = '';
4790 $pageauthorid = $user->id;
4791 $pageusermodifid = 0;
4792 $pageauthoralias = '';
4793 $pagestatus = 1;
4794 }
4795 if (GETPOST('WEBSITE_TITLE', 'alpha')) {
4796 $pagetitle = str_replace(array('<', '>'), '', GETPOST('WEBSITE_TITLE', 'alphanohtml'));
4797 }
4798 if (GETPOST('WEBSITE_PAGENAME', 'alpha')) {
4799 $pageurl = GETPOST('WEBSITE_PAGENAME', 'alpha');
4800 }
4801 if (GETPOST('WEBSITE_ALIASALT', 'alpha')) {
4802 $pagealiasalt = str_replace(array('<', '>'), '', GETPOST('WEBSITE_ALIASALT', 'alphanohtml'));
4803 }
4804 if (GETPOST('WEBSITE_DESCRIPTION', 'alpha')) {
4805 $pagedescription = str_replace(array('<', '>'), '', GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml'));
4806 }
4807 if (GETPOST('WEBSITE_IMAGE', 'alpha')) {
4808 $pageimage = GETPOST('WEBSITE_IMAGE', 'alpha');
4809 }
4810 if (GETPOST('WEBSITE_KEYWORDS', 'alpha')) {
4811 $pagekeywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml'));
4812 }
4813 if (GETPOST('WEBSITE_LANG', 'aZ09')) {
4814 $pagelang = GETPOST('WEBSITE_LANG', 'aZ09');
4815 }
4816 if (GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09')) {
4817 $pageallowedinframes = 1;
4818 }
4819 if (GETPOST('htmlheader', 'restricthtmlallowlinkscript')) { // Must accept tags like '<script>' and '<link>'
4820 $pagehtmlheader = GETPOST('htmlheader', 'none');
4821 }
4822
4823 if ($action != 'createcontainer') {
4824 if (empty($conf->use_javascript_ajax)) {
4825 print '<!-- Status of web site page -->'."\n";
4826 print '<tr><td class="fieldrequired">';
4827 print $langs->trans('Status');
4828 print '</td><td>';
4829 print $form->selectyesno('status', $objectpage->status);
4830 print '</td></tr>';
4831 }
4832 }
4833
4834 // Type of container
4835 print '<tr><td class="titlefield fieldrequired">';
4836 print $langs->trans('WEBSITE_TYPE_CONTAINER');
4837 print '</td><td>';
4838 print img_picto('', 'object_technic', 'class="paddingrightonly"').' ';
4839 print $formwebsite->selectTypeOfContainer('WEBSITE_TYPE_CONTAINER', (GETPOST('WEBSITE_TYPE_CONTAINER', 'alpha') ? GETPOST('WEBSITE_TYPE_CONTAINER', 'alpha') : $type_container), 0, '', 1, 'minwidth300');
4840 print '</td></tr>';
4841
4842 print '<script type="text/javascript">
4843 jQuery(document).ready(function() {
4844 jQuery("#selectWEBSITE_TYPE_CONTAINER").change(function() {
4845 console.log("We change type of page : "+jQuery("#selectWEBSITE_TYPE_CONTAINER").val());
4846 if (jQuery("#selectWEBSITE_TYPE_CONTAINER").val() == \'blogpost\') {
4847 jQuery(".trpublicauthor").show();
4848 } else {
4849 jQuery(".trpublicauthor").hide();
4850 }
4851 if (jQuery("#selectWEBSITE_TYPE_CONTAINER").val() == \'service\' || jQuery("#selectWEBSITE_TYPE_CONTAINER").val() == \'library\') {
4852 $(".spanprefix").html("_" + $("#selectWEBSITE_TYPE_CONTAINER").val() + "_");
4853 jQuery(".spanprefix").show();
4854 } else {
4855 jQuery(".spanprefix").hide();
4856 }
4857 });
4858
4859 // Force at init execution a first time of the handler change
4860 jQuery("#selectWEBSITE_TYPE_CONTAINER").trigger(\'change\');
4861 });
4862 </script>
4863 ';
4864
4865 // Title
4866 print '<tr><td class="fieldrequired">';
4867 print $langs->trans('WEBSITE_TITLE');
4868 print '</td><td>';
4869 print '<input type="text" class="flat quatrevingtpercent" name="WEBSITE_TITLE" id="WEBSITE_TITLE" value="'.dol_escape_htmltag($pagetitle).'" autofocus>';
4870 print '</td></tr>';
4871
4872 // Alias page
4873 print '<tr><td class="titlefieldcreate fieldrequired">';
4874 print $langs->trans('WEBSITE_PAGENAME');
4875 print '</td><td>';
4876 print '<span class="opacitymedium spanprefix hidden"></span> ';
4877 print '<input type="text" class="flat minwidth300" name="WEBSITE_PAGENAME" id="WEBSITE_PAGENAME" value="'.dol_escape_htmltag((string) preg_replace('/^_[a-z]+_/', '', (string) $pageurl)).'">';
4878 print '</td></tr>';
4879
4880 print '<script type="text/javascript">
4881 $(document).ready(function() {
4882 console.log("Manage prefix for service or library");
4883 if ($("#selectWEBSITE_TYPE_CONTAINER").val() == "service" || $("#selectWEBSITE_TYPE_CONTAINER").val() == "library") {
4884 $(".spanprefix").html("_" + $("#selectWEBSITE_TYPE_CONTAINER").val() + "_");
4885 $(".spanprefix").show();
4886 }
4887 $(".websiteformtoolbar").on("submit", function(event) {
4888 if ($("#selectWEBSITE_TYPE_CONTAINER").val() == "service" || $("#selectWEBSITE_TYPE_CONTAINER").val() == "library") {
4889 var prefix = "_" + $("#selectWEBSITE_TYPE_CONTAINER").val() + "_";
4890 var userInput = $("#WEBSITE_PAGENAME").val();
4891 var $inputField = $("#WEBSITE_PAGENAME");
4892 if (userInput.indexOf(prefix) !== 0) {
4893 $inputField.val(prefix + userInput);
4894 }
4895 }
4896 });
4897 });
4898 </script>
4899 ';
4900
4901 print '<tr><td class="titlefieldcreate">';
4902 $htmlhelp = $langs->trans("WEBSITE_ALIASALTDesc");
4903 print $form->textwithpicto($langs->trans('WEBSITE_ALIASALT'), $htmlhelp, 1, 'help', '', 0, 2, 'aliastooltip');
4904 print '</td><td>';
4905 print '<input type="text" class="flat minwidth500" name="WEBSITE_ALIASALT" value="'.dol_escape_htmltag($pagealiasalt).'">';
4906 print '</td></tr>';
4907
4908 print '<tr><td>';
4909 print $langs->trans('WEBSITE_DESCRIPTION');
4910 print '</td><td>';
4911 print '<input type="text" class="flat quatrevingtpercent" name="WEBSITE_DESCRIPTION" value="'.dol_escape_htmltag($pagedescription).'">';
4912 print '</td></tr>';
4913
4914 // Deprecated. Image for RSS or Thumbs are now taken from the content.
4915 if (getDolGlobalInt('WEBSITE_MANAGE_IMAGE_FOR_PAGES')) {
4916 print '<tr class="trimageforpage hidden"><td>';
4917 $htmlhelp = $langs->trans("WEBSITE_IMAGEDesc");
4918 print $form->textwithpicto($langs->trans('WEBSITE_IMAGE'), $htmlhelp, 1, 'help', '', 0, 2, 'imagetooltip');
4919 print '</td><td>';
4920 print '<input type="text" class="flat quatrevingtpercent" name="WEBSITE_IMAGE" value="'.dol_escape_htmltag($pageimage).'">';
4921 print '</td></tr>';
4922
4923 print '<script type="text/javascript">
4924 jQuery(document).ready(function() {
4925 jQuery("#selectWEBSITE_TYPE_CONTAINER").change(function() {
4926 console.log("We change type of page : "+jQuery("#selectWEBSITE_TYPE_CONTAINER").val());
4927 if (jQuery("#selectWEBSITE_TYPE_CONTAINER").val() == \'blogpost\') {
4928 jQuery(".trimageforpage").show();
4929 } else {
4930 jQuery(".trimageforpage").hide();
4931 }
4932 });
4933 });
4934 </script>
4935 ';
4936 }
4937
4938 // Keywords
4939 print '<tr><td>';
4940 $htmlhelp = $langs->trans("WEBSITE_KEYWORDSDesc");
4941 print $form->textwithpicto($langs->trans('WEBSITE_KEYWORDS'), $htmlhelp, 1, 'help', '', 0, 2, 'keywordtooltip');
4942 print '</td><td>';
4943 print '<input type="text" class="flat quatrevingtpercent" name="WEBSITE_KEYWORDS" value="'.dol_escape_htmltag($pagekeywords).'">';
4944 print '</td></tr>';
4945
4946 print '<tr><td>';
4947 print $langs->trans('Language');
4948 print '</td><td>';
4949 $onlykeys = array();
4950 if ($object->lang) {
4951 $onlykeys[$object->lang] = $object->lang;
4952 } else {
4953 $onlykeys[$langs->defaultlang] = $langs->defaultlang;
4954 }
4955 if ($object->otherlang) {
4956 $tmparray = explode(',', $object->otherlang);
4957 foreach ($tmparray as $key) {
4958 $tmpkey = trim($key);
4959 if (strlen($key) == 2) {
4960 $tmpkey = strtolower($key);
4961 }
4962 $onlykeys[$tmpkey] = $tmpkey;
4963 }
4964 }
4965 if (empty($object->lang) && empty($object->otherlang)) {
4966 $onlykeys = array(); // We keep full list of languages
4967 }
4968 print img_picto('', 'language', 'class="pictofixedwidth"').$formadmin->select_language($pagelang ? $pagelang : '', 'WEBSITE_LANG', 0, array(), '1', 0, 0, 'minwidth200', 0, 0, 0, $onlykeys, 1);
4969 $htmltext = $langs->trans("AvailableLanguagesAreDefinedIntoWebsiteProperties");
4970 print $form->textwithpicto('', $htmltext);
4971 print '</td></tr>';
4972
4973 // Translation of
4974 $translationof = 0;
4975 $translatedby = 0;
4976 print '<!-- Translation of --><tr><td>';
4977 print $langs->trans('TranslationLinks');
4978 print '</td><td>';
4979 if ($action != 'createcontainer') {
4980 // Has translation pages
4981 $sql = "SELECT rowid, lang from ".MAIN_DB_PREFIX."website_page where fk_page = ".((int) $objectpage->id);
4982 $resql = $db->query($sql);
4983 if ($resql) {
4984 $num_rows = $db->num_rows($resql);
4985 if ($num_rows > 0) {
4986 print '<span class="opacitymedium">'.$langs->trans('ThisPageHasTranslationPages').':</span>';
4987 $i = 0;
4988 $tmppage = new WebsitePage($db);
4989 $tmpstring = '';
4990 while ($obj = $db->fetch_object($resql)) {
4991 $result = $tmppage->fetch($obj->rowid);
4992 if ($result > 0) {
4993 if ($i > 0) {
4994 $tmpstring .= '<br>';
4995 }
4996 $tmpstring .= $tmppage->getNomUrl(1).' '.picto_from_langcode($tmppage->lang).' '.$tmppage->lang;
4997 // Button unlink
4998 $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>';
4999 $translatedby++;
5000 $i++;
5001 }
5002 }
5003 if ($i > 1) {
5004 print '<br>';
5005 } else {
5006 print ' ';
5007 }
5008 print $tmpstring;
5009 }
5010 } else {
5011 dol_print_error($db);
5012 }
5013 }
5014 if ((empty($translatedby) || ($objectpage->lang != $object->lang)) && ($action == 'editmeta' || $action == 'createcontainer' || $objectpage->fk_page > 0)) {
5015 $sourcepage = new WebsitePage($db);
5016 $result = 1;
5017 if ($objectpage->fk_page > 0) {
5018 $result = $sourcepage->fetch($objectpage->fk_page);
5019 if ($result == 0) {
5020 // not found, we can reset value to clean database
5021 // TODO
5022 }
5023 }
5024 if ($result >= 0) {
5025 if ($translatedby) {
5026 print '<br>';
5027 }
5028 $translationof = $objectpage->fk_page;
5029 print '<span class="opacitymedium">'.$langs->trans('ThisPageIsTranslationOf').'</span> ';
5030 print $sourcepage->getNomUrl(2).' '.$formwebsite->selectContainer($website, 'pageidfortranslation', ($translationof ? $translationof : -1), 1, $action, 'minwidth300', array($objectpage->id));
5031 if ($translationof > 0 && $sourcepage->lang) {
5032 print picto_from_langcode($sourcepage->lang).' '.$sourcepage->lang;
5033 // Button unlink
5034 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>';
5035 }
5036 }
5037 }
5038 print '</td></tr>';
5039
5040 // Categories
5041 if (isModEnabled('category') && $user->hasRight('categorie', 'lire')) {
5042 $disabled = '';
5043 $langs->load('categories');
5044
5045 print '<tr><td class="toptd">'.$form->editfieldkey('Categories', 'categories', '', $objectpage, 0).'</td><td>';
5046 print $form->selectCategories(Categorie::TYPE_WEBSITE_PAGE, 'categories', $objectpage);
5047 //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);
5048 print "</td></tr>";
5049 }
5050
5051 if (getDolGlobalString('WEBSITE_PAGE_SHOW_INTERNAL_LINKS_TO_OBJECT')) { // TODO Replace this with link into element_element ?
5052 print '<tr><td class="titlefieldcreate">';
5053 print 'ObjectClass';
5054 print '</td><td>';
5055 print '<input type="text" class="flat minwidth300" name="WEBSITE_OBJECTCLASS" placeholder="ClassName::/path/class/ObjectClass.class.php" >';
5056 print '</td></tr>';
5057
5058 print '<tr><td class="titlefieldcreate">';
5059 print 'ObjectID';
5060 print '</td><td>';
5061 print '<input type="text" class="flat minwidth300" name="WEBSITE_OBJECTID" >';
5062 print '</td></tr>';
5063 }
5064
5065 $fuser = new User($db);
5066
5067 // Date last modification
5068 if ($action != 'createcontainer') {
5069 print '<tr><td>';
5070 print $langs->trans('DateLastModification');
5071 print '</td><td>';
5072 print dol_print_date($pagedatemodification, 'dayhour', 'tzuser');
5073 print '</td></tr>';
5074
5075 print '<tr><td>';
5076 print $langs->trans('UserModification');
5077 print '</td><td>';
5078 if ($pageusermodifid > 0) {
5079 $fuser->fetch($pageusermodifid);
5080 print $fuser->getNomUrl(-1);
5081 } else {
5082 print '<span class="opacitymedium">'.$langs->trans("Unknown").'</span>';
5083 }
5084 print '</td></tr>';
5085 }
5086
5087 // Content - Example/templates of page
5088 $url = 'https://wiki.dolibarr.org/index.php/Module_Website';
5089 $htmltext = '<small>';
5090 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource", $url);
5091 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource1", $url);
5092 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource2", $url);
5093 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource3", $url);
5094 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSource4", $url);
5095 $htmltext .= $langs->transnoentitiesnoconv("YouCanEditHtmlSourceMore", $url);
5096 $htmltext .= '<br>';
5097 $htmltext .= '</small>';
5098
5099 $formmail = new FormMail($db);
5100 $formmail->withaiprompt = 'html';
5101 $formmail->withlayout = 'websitepage';
5102 $showlinktolayout = $formmail->withlayout;
5103 $showlinktoai = ($formmail->withaiprompt && isModEnabled('ai')) ? 'textgenerationwebpage' : '';
5104 if (($action == 'createcontainer' && $showlinktolayout) || ($action == 'createcontainer' && $showlinktoai)) {
5105 print '<tr><td class="titlefield tdtop">';
5106 if ($conf->browser->layout == 'phone') {
5107 print $form->textwithpicto('', $htmltext, 1, 'help', 'inline-block', 1, 2, 'tooltipsubstitution');
5108 } else {
5109 //img_help(($tooltiptrigger != '' ? 2 : 1), $alt)
5110 print $form->textwithpicto($langs->trans("PreviewPageContent").' '.img_help(2, $langs->trans("PreviewPageContent")), $htmltext, 1, 'none', 'inline-block', 1, 2, 'tooltipsubstitution');
5111 }
5112 print '</td><td class="tdtop">';
5113
5114 $out = '';
5115
5116 $showlinktolayoutlabel = $langs->trans("FillPageWithALayout");
5117 $showlinktoailabel = $langs->trans("FillPageWithAIContent");
5118 $htmlname = 'content';
5119 // Fill $out
5120 include DOL_DOCUMENT_ROOT.'/core/tpl/formlayoutai.tpl.php';
5121
5122 print $out;
5123 print '</td></tr>';
5124 }
5125
5126 if ($action == 'createcontainer') {
5127 print '<tr id="pageContent"><td class="tdtop">';
5128 if (!$showlinktolayout || !$showlinktoai) {
5129 if ($conf->browser->layout == 'phone') {
5130 print $form->textwithpicto('', $htmltext, 1, 'help', 'inline-block', 1, 2, 'tooltipsubstitution');
5131 } else {
5132 //img_help(($tooltiptrigger != '' ? 2 : 1), $alt)
5133 print $form->textwithpicto($showlinktolayout ? '' : ($langs->trans("PreviewPageContent").' '.img_help(2, $langs->trans("PreviewPageContent"))), $htmltext, 1, 'none', 'inline-block', 1, 2, 'tooltipsubstitution');
5134 }
5135 }
5136 print '</td><td>';
5137 //$doleditor = new DolEditor('content', GETPOST('content', 'restricthtmlallowunvalid'), '', 200, 'dolibarr_mailings', 'In', true, true, true, 40, '90%');
5138 $doleditor = new DolEditor('content', GETPOST('content', 'none'), '', 200, 'dolibarr_mailings', 'In', true, true, true, 40, '90%');
5139 $doleditor->Create();
5140 print '</div>';
5141 print '</td></tr>';
5142 }
5143
5144 // Date creation
5145 print '<tr><td>';
5146 print $langs->trans('DateCreation');
5147 print '</td><td>';
5148 print $form->selectDate($pagedatecreation, 'datecreation', 1, 1, 0, '', 1, 1);
5149 //print dol_print_date($pagedatecreation, 'dayhour');
5150 print '</td></tr>';
5151
5152 // Author
5153 print '<tr><td>';
5154 print $langs->trans('Author');
5155 print '</td><td>';
5156 if ($pageauthorid > 0) {
5157 $fuser->fetch($pageauthorid);
5158 print $fuser->getNomUrl(-1);
5159 } else {
5160 print '<span class="opacitymedium">'.$langs->trans("Unknown").'</span>';
5161 }
5162 print '</td></tr>';
5163
5164 // Author - public alias
5165 print '<tr class="trpublicauthor hidden"><td>';
5166 print $langs->trans('PublicAuthorAlias');
5167 print '</td><td>';
5168 print '<input type="text" class="flat minwidth300" name="WEBSITE_AUTHORALIAS" value="'.dol_escape_htmltag($pageauthoralias).'" placeholder="'.dol_escape_htmltag($langs->trans("Anonymous")).'">';
5169 print '</td></tr>';
5170
5171 // Web page header
5172 print '<tr><td class="tdhtmlheader tdtop">';
5173 $htmlhelp = $langs->trans("EditTheWebSiteForACommonHeader").'<br><br>';
5174 $htmlhelp .= $langs->trans("Examples").' :<br>';
5175 $htmlhelp .= '<span class="small">';
5176 $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.
5177 $htmlhelp .= '</span>';
5178 print $form->textwithpicto($langs->transnoentitiesnoconv('HtmlHeaderPage'), $htmlhelp, 1, 'help', '', 0, 2, 'htmlheadertooltip');
5179 print '</td><td>';
5180 $poscursor = array('x' => GETPOST('htmlheader_x'), 'y' => GETPOST('htmlheader_y'));
5181 $doleditor = new DolEditor('htmlheader', $pagehtmlheader, '', 160, 'ace', 'In', true, false, 'ace', ROWS_4, '100%', 0, $poscursor);
5182 print $doleditor->Create(1, '', true, 'HTML Header', 'html');
5183 print '</td></tr>';
5184
5185 // Allowed in frames
5186 print '<tr><td>';
5187 print $langs->trans('AllowedInFrames');
5188 //$htmlhelp = $langs->trans("AllowedInFramesDesc");
5189 //print $form->textwithpicto($langs->trans('AllowedInFrames'), $htmlhelp, 1, 'help', '', 0, 2, 'allowedinframestooltip');
5190 print '</td><td>';
5191 print '<input type="checkbox" class="flat" name="WEBSITE_ALLOWED_IN_FRAMES" value="1"'.($pageallowedinframes ? 'checked="checked"' : '').'>';
5192 print '</td></tr>';
5193
5194 print '</table>';
5195
5196
5197 if ($action == 'createcontainer') {
5198 $langs->load("website");
5199
5200 print '<div class="center tablecheckboxcreatemanually'.$hiddenmanuallyafterload.'">';
5201
5202 print '<input type="submit" class="button small buttonforacesave" name="addcontainer" value="'.$langs->trans("Create").'">';
5203 print '<input class="button button-cancel small" type="submit" name="preview" value="'.$langs->trans("Cancel").'">';
5204
5205 print '</div>';
5206
5207 print '<br>';
5208
5209 if (!empty($conf->use_javascript_ajax)) {
5210 print '<input type="radio" name="radiocreatefrom" id="checkboxcreatefromfetching" value="checkboxcreatefromfetching"'.(GETPOST('radiocreatefrom') == 'checkboxcreatefromfetching' ? ' checked' : '').'> ';
5211 }
5212 print '<label for="checkboxcreatefromfetching"><span class="opacitymediumxx">'.$langs->trans("CreateByFetchingExternalPage").'</span> <span class="small opacitymedium">('.$langs->trans("ForAdvancedWebmastersOnly").')</small></label><br>';
5213 print '<hr class="tablecheckboxcreatefromfetching'.$hiddenfromfetchingafterload.'">';
5214
5215 print info_admin($langs->trans("OnlyEditionOfSourceForGrabbedContentFuture"), 0, 0, 'warning tablecheckboxcreatefromfetching'.$hiddenfromfetchingafterload);
5216 print '<br>';
5217
5218 print '<table class="tableforfield centpercent tablecheckboxcreatefromfetching'.$hiddenfromfetchingafterload.'">';
5219 print '<tr><td class="titlefield tdtop">';
5220 print $langs->trans("URL");
5221 print '</td><td>';
5222 print '<input class="flat minwidth500 marginbottomonly" type="text" name="externalurl" value="'.dol_escape_htmltag(GETPOST('externalurl', 'alpha')).'" placeholder="https://externalsite/pagetofetch"> ';
5223 print '<br>';
5224 print '<div class="paddingtop">';
5225 print '<input class="flat paddingtop paddingright" type="checkbox" name="grabimages" value="1" checked="checked">';
5226 print '<span class="valignmiddle">'.$langs->trans("GrabImagesInto");
5227 print ' ';
5228 print $langs->trans("ImagesShouldBeSavedInto").' ';
5229 print '</span>';
5230 $arraygrabimagesinto = array('root' => $langs->trans("WebsiteRootOfImages"), 'subpage' => $langs->trans("SubdirOfPage"));
5231 print $form->selectarray('grabimagesinto', $arraygrabimagesinto, GETPOSTISSET('grabimagesinto') ? GETPOST('grabimagesinto') : 'root', 0, 0, 0, '', 0, 0, 0, '', 'minwidth75 valignmiddle', 1);
5232 print '</div>';
5233
5234 print '<input class="button small" style="margin-top: 5px" type="submit" name="fetchexternalurl" value="'.dol_escape_htmltag($langs->trans("FetchAndCreate")).'">';
5235 print '<input class="button button-cancel small" type="submit" name="preview" value="'.$langs->trans("Cancel").'">';
5236
5237 print '</td></tr>';
5238 print '</table>';
5239 }
5240
5241 if ($action == 'createcontainer') {
5242 print '<script type="text/javascript">
5243 jQuery(document).ready(function() {
5244 var disableautofillofalias = 0;
5245 var selectedm = \'\';
5246 var selectedf = \'\';
5247
5248 jQuery("#WEBSITE_TITLE").keyup(function() {
5249 if (disableautofillofalias == 0) {
5250 var valnospecial = jQuery("#WEBSITE_TITLE").val();
5251 valnospecial = valnospecial.replace(/[éèê]/g, \'e\').replace(/[à]/g, \'a\').replace(/[ù]/g, \'u\').replace(/[î]/g, \'i\');
5252 valnospecial = valnospecial.replace(/[ç]/g, \'c\').replace(/[ö]/g, \'o\');
5253 valnospecial = valnospecial.replace(/[^\w]/gi, \'-\').toLowerCase();
5254 valnospecial = valnospecial.replace(/\-+/g, \'-\').replace(/\-$/, \'\');
5255 console.log("disableautofillofalias=0 so we replace WEBSITE_TITLE with "+valnospecial);
5256 jQuery("#WEBSITE_PAGENAME").val(valnospecial);
5257 }
5258 });
5259 jQuery("#WEBSITE_PAGENAME").keyup(function() {
5260 if (jQuery("#WEBSITE_PAGENAME").val() == \'\') {
5261 disableautofillofalias = 0;
5262 } else {
5263 disableautofillofalias = 1;
5264 }
5265 });
5266 jQuery("#WEBSITE_PAGENAME").blur(function() {
5267 if (jQuery("#WEBSITE_PAGENAME").val() == \'\') {
5268 disableautofillofalias = 0;
5269 jQuery("#WEBSITE_TITLE").trigger(\'keyup\');
5270 }
5271 });
5272
5273 jQuery("#checkboxcreatefromfetching,#checkboxcreatemanually").click(function() {
5274 console.log("we select a method to create a new container "+jQuery("#checkboxcreatefromfetching:checked").val())
5275 jQuery(".tablecheckboxcreatefromfetching").hide();
5276 jQuery(".tablecheckboxcreatemanually").hide();
5277 if (typeof(jQuery("#checkboxcreatefromfetching:checked").val()) != \'undefined\') {
5278 console.log("show create from spider form");
5279 if (selectedf != \'createfromfetching\') {
5280 jQuery(".tablecheckboxcreatefromfetching").show();
5281 selectedf = \'createfromfetching\';
5282 selectedm = \'\';
5283 } else {
5284 jQuery(".tablecheckboxcreatefromfetching").hide();
5285 selectedf = \'\';
5286 }
5287 }
5288 if (typeof(jQuery("#checkboxcreatemanually:checked").val()) != \'undefined\') {
5289 console.log("show create from scratch or template form");
5290 if (selectedm != \'createmanually\') {
5291 jQuery(".tablecheckboxcreatemanually").show();
5292 selectedm = \'createmanually\';
5293 selectedf = \'\';
5294 } else {
5295 jQuery(".tablecheckboxcreatemanually").hide();
5296 selectedm = \'\';
5297 }
5298 }
5299 });
5300 });
5301 </script>';
5302 }
5303
5304 print '</div>';
5305
5306 print '<br>';
5307}
5308
5309
5310// Print formconfirm
5311if ($action == 'preview') {
5312 print $formconfirm;
5313}
5314
5315if ($action == 'editfile' || $action == 'file_manager' || $action == 'convertimgwebp' || $action == 'confirmconvertimgwebp') {
5316 print '<!-- Edit Media -->'."\n";
5317 print '<div class="fiche"><br>';
5318
5319 $module = 'medias';
5320 $formalreadyopen = 2; // So the form to submit a new file will not be open another time inside the core/tpl/filemanager.tpl.php
5321 if (empty($url)) {
5322 $url = DOL_URL_ROOT.'/website/index.php'; // Must be an url without param
5323 }
5324 include DOL_DOCUMENT_ROOT.'/core/tpl/filemanager.tpl.php';
5325
5326 print '</div>';
5327}
5328
5329if ($action == 'editmenu') {
5330 print '<!-- Edit Menu -->'."\n";
5331 print '<div class="center">'.$langs->trans("FeatureNotYetAvailable").'</center>';
5332}
5333
5334if ($action == 'editsource') {
5335 // Editing with source editor
5336
5337 $contentforedit = '';
5338 //$contentforedit.='<style scoped>'."\n"; // "scoped" means "apply to parent element only". Not yet supported by browsers
5339 //$contentforedit.=$csscontent;
5340 //$contentforedit.='</style>'."\n";
5341 $contentforedit .= $objectpage->content;
5342
5343 // We set maxheightwin in px. We take the height of screen in px and we remove a part for the top banner and more
5344 $maxheightwin = 480;
5345 if (isset($_SESSION["dol_screenheight"])) {
5346 if ($_SESSION["dol_screenheight"] > 680) {
5347 $maxheightwin = $_SESSION["dol_screenheight"] - 300; // We remove a height for header
5348 }
5349 if ($_SESSION["dol_screenheight"] > 800) {
5350 $maxheightwin = $_SESSION["dol_screenheight"] - 250; // We remove a height for header (on large width, risk to have header on 2 lines is lower)
5351 }
5352 }
5353
5354 $poscursor = array('x' => GETPOST('PAGE_CONTENT_x'), 'y' => GETPOST('PAGE_CONTENT_y'));
5355 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
5356 $doleditor = new DolEditor('PAGE_CONTENT', $contentforedit, '', $maxheightwin, 'Full', '', true, true, 'ace', ROWS_5, '40%', 0, $poscursor);
5357 $doleditor->Create(0, '', false, 'HTML Source', 'php');
5358}
5359
5360if ($action == 'editcontent') {
5361 // Editing with default ckeditor
5362
5363 $contentforedit = '';
5364 //$contentforedit.='<style scoped>'."\n"; // "scoped" means "apply to parent element only". Not yet supported by browsers
5365 //$contentforedit.=$csscontent;
5366 //$contentforedit.='</style>'."\n";
5367 $contentforedit .= $objectpage->content;
5368
5369 $nbrep = array();
5370 // If contentforedit has a string <img src="xxx", we replace the xxx with /viewimage.php?modulepart=medias&file=xxx except if xxx starts
5371 // with http, /viewimage.php or DOL_URL_ROOT./viewimage.phps
5372 $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);
5373
5374 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
5375 $poscursor = array('x' => GETPOST('PAGE_CONTENT_x'), 'y' => GETPOST('PAGE_CONTENT_y'));
5376 $doleditor = new DolEditor('PAGE_CONTENT', $contentforedit, '', 500, 'Full', '', true, true, true, ROWS_5, '90%', 0, $poscursor);
5377 $doleditor->Create(0, '', false);
5378}
5379
5380print "</div>\n";
5381print "</form>\n";
5382
5383
5384if ($mode == 'replacesite' || $massaction == 'replace') {
5385 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5386 print '<input type="hidden" name="token" value="'.newToken().'">';
5387 print '<input type="hidden" name="action" value="replacesiteconfirm">';
5388 print '<input type="hidden" name="mode" value="replacesite">';
5389 print '<input type="hidden" name="website" value="'.$website->ref.'">';
5390
5391
5392 print '<!-- Search page and replace string -->'."\n";
5393 print '<div class="fiche"><br>';
5394
5395 print load_fiche_titre($langs->trans("ReplaceWebsiteContent"), '', 'search');
5396
5397 print '<div class="fichecenter"><div class="fichehalfleft">';
5398
5399 print '<div class="tagtable">';
5400
5401 print '<div class="tagtr">';
5402 print '<div class="tagtd paddingrightonly opacitymedium">';
5403 print $langs->trans("SearchReplaceInto");
5404 print '</div>';
5405 print '<div class="tagtd">';
5406 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>';
5407 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>';
5408 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>';
5409 print '</div>';
5410 print '</div>';
5411
5412 print '<div class="tagtr">';
5413 print '<div class="tagtd paddingrightonly opacitymedium" style="padding-right: 10px !important">';
5414 print $langs->trans("SearchString");
5415 print '</div>';
5416 print '<div class="tagtd">';
5417 print '<input type="text" name="searchstring" value="'.dol_escape_htmltag($searchkey, 0, 0, '', 1).'" autofocus>';
5418 print '</div>';
5419 print '</div>';
5420
5421 print '</div>';
5422
5423 print '</div><div class="fichehalfleft">';
5424
5425 print '<div class="tagtable">';
5426
5427 print '<div class="tagtr">';
5428 print '<div class="tagtd paddingrightonly opacitymedium tdoverflowmax100onsmartphone" style="padding-right: 10px !important">';
5429 print $langs->trans("WEBSITE_TYPE_CONTAINER");
5430 print '</div>';
5431 print '<div class="tagtd">';
5432 print img_picto('', 'object_technic', 'class="pictofixedwidth"').' ';
5433 print $formwebsite->selectTypeOfContainer('optioncontainertype', (GETPOST('optioncontainertype', 'alpha') ? GETPOST('optioncontainertype', 'alpha') : ''), 1, '', 1, 'minwidth125 maxwidth400 widthcentpercentminusx');
5434 print '</div>';
5435 print '</div>';
5436
5437 print '<div class="tagtr">';
5438 print '<div class="tagtd paddingrightonly opacitymedium tdoverflowmax100onsmartphone" style="padding-right: 10px !important">';
5439 print $langs->trans("Language");
5440 print '</div>';
5441 print '<div class="tagtd">';
5442 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);
5443 print '</div>';
5444 print '</div>';
5445
5446 // Categories
5447 if (isModEnabled('category') && $user->hasRight('categorie', 'lire')) {
5448 print '<div class="tagtr">';
5449 print '<div class="tagtd paddingrightonly marginrightonly opacitymedium tdoverflowmax100onsmartphone" style="padding-right: 10px !important">';
5450 print $langs->trans("Category");
5451 print '</div>';
5452 print '<div class="tagtd">';
5453 //print $form->selectCategories(Categorie::TYPE_WEBSITE_PAGE, 'optioncategory', $object);
5454 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');
5455 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
5456 print ajax_combobox('optioncategory');
5457 print '</div>';
5458 print '</div>';
5459 }
5460
5461 print '</div>';
5462
5463 print '<input type="submit" class="button margintoponly" name="buttonreplacesitesearch" value="'.dol_escape_htmltag($langs->trans("Search")).'">';
5464
5465 print '</div></div>';
5466
5467 if ($mode == 'replacesite') {
5468 print '<!-- List of search result -->'."\n";
5469 print '<div class="rowsearchresult clearboth">';
5470
5471 print '<br>';
5472 print '<br>';
5473
5474 if ($listofpages['code'] == 'OK') {
5475 $arrayofselected = is_array($toselect) ? $toselect : array();
5476 $param = '';
5477 $nbtotalofrecords = count($listofpages['list']);
5478 $num = $limit;
5479 $permissiontodelete = $user->hasRight('website', 'delete');
5480
5481 // List of mass actions available
5482 $arrayofmassactions = array();
5483 if ($user->hasRight('website', 'writephp') && $searchkey) {
5484 $arrayofmassactions['replace'] = img_picto('', 'replacement', 'class="pictofixedwidth"').$langs->trans("Replace");
5485 }
5486 if ($user->hasRight('website', 'write')) {
5487 $langs->load("categories");
5488 $arrayofmassactions['setcategory'] = img_picto('', 'category', 'class="pictofixedwidth"').$langs->trans("ClassifyInCategory");
5489 }
5490 if ($user->hasRight('website', 'write')) {
5491 $langs->load("categories");
5492 $arrayofmassactions['delcategory'] = img_picto('', 'category', 'class="pictofixedwidth"').$langs->trans("RemoveCategory");
5493 }
5494 if ($permissiontodelete) {
5495 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
5496 }
5497 if (GETPOSTINT('nomassaction') || in_array($massaction, array('presend', 'predelete'))) {
5498 $arrayofmassactions = array();
5499 }
5500
5501 $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
5502 $massactionbutton .= '<div class="massactionother massactionreplace hidden">';
5503 $massactionbutton .= $langs->trans("ReplaceString");
5504 $massactionbutton .= ' <input type="text" name="replacestring" value="'.dol_escape_htmltag(GETPOST('replacestring', 'none')).'">';
5505 $massactionbutton .= '</div>';
5506 $massactionbutton .= '<div class="massactionother massactionsetcategory massactiondelcategory hidden">';
5507 $massactionbutton .= img_picto('', 'category', 'class="pictofixedwidth"');
5508 $massactionbutton .= $form->select_all_categories(Categorie::TYPE_WEBSITE_PAGE, GETPOSTISSET('setcategory') ? GETPOST('setcategory') : '', 'setcategory', 64, 0, 0, 0, 'minwidth300 alignstart');
5509 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
5510 $massactionbutton .= ajax_combobox('setcategory');
5511 $massactionbutton .= '</div>';
5512
5513 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
5514
5515 //$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields
5516 $selectedfields = '';
5517 $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
5518
5519 print_barre_liste($langs->trans("Results"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'generic', 0, '', '', $limit, 1, 1, 1);
5520
5521 $topicmail = "WebsitePageRef";
5522 $modelmail = "websitepage_send";
5523 $objecttmp = new WebsitePage($db);
5524 $trackid = 'wsp'.$object->id;
5525 include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
5526
5527 $param = 'mode=replacesite&website='.urlencode($website->ref);
5528 $param .= '&searchstring='.urlencode($searchkey);
5529 if (GETPOST('optionpagecontent')) {
5530 $param .= '&optionpagecontent=content';
5531 }
5532 if (GETPOST('optionmeta')) {
5533 $param .= '&optionmeta=meta';
5534 }
5535 if (GETPOST('optionsitefiles')) {
5536 $param .= '&optionsitefiles=optionsitefiles';
5537 }
5538 if (GETPOST('optioncontainertype')) {
5539 $param .= '&optioncontainertype='.GETPOST('optioncontainertype', 'aZ09');
5540 }
5541 if (GETPOST('optionlanguage')) {
5542 $param .= '&optionlanguage='.GETPOST('optionlanguage', 'aZ09');
5543 }
5544 if (GETPOST('optioncategory')) {
5545 $param .= '&optioncategory='.GETPOST('optioncategory', 'aZ09');
5546 }
5547
5548 print '<div class="div-table-responsive-no-min">';
5549 print '<table class="noborder centpercent">';
5550 print '<tr class="liste_titre">';
5551 // Action column
5552 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
5553 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
5554 }
5555 print getTitleFieldOfList("Type", 0, $_SERVER['PHP_SELF'], 'type_container', '', $param, '', $sortfield, $sortorder, '')."\n";
5556 print getTitleFieldOfList("Page", 0, $_SERVER['PHP_SELF'], 'pageurl', '', $param, '', $sortfield, $sortorder, '')."\n";
5557 print getTitleFieldOfList("Language", 0, $_SERVER['PHP_SELF'], 'lang', '', $param, '', $sortfield, $sortorder, 'center ')."\n";
5558 print getTitleFieldOfList("Categories", 0, $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'center ')."\n";
5559 print getTitleFieldOfList("", 0, $_SERVER['PHP_SELF']);
5560 print getTitleFieldOfList("UserCreation", 0, $_SERVER['PHP_SELF'], 'fk_user_creat', '', $param, '', $sortfield, $sortorder, '')."\n";
5561 print getTitleFieldOfList("DateCreation", 0, $_SERVER['PHP_SELF'], 'date_creation', '', $param, '', $sortfield, $sortorder, 'center ')."\n"; // Date creation
5562 print getTitleFieldOfList("DateLastModification", 0, $_SERVER['PHP_SELF'], 'tms', '', $param, '', $sortfield, $sortorder, 'center ')."\n"; // Date last modif
5563 print getTitleFieldOfList("", 0, $_SERVER['PHP_SELF']);
5564 // Action column
5565 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
5566 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
5567 }
5568 print '</tr>';
5569
5570 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
5571 $c = new Categorie($db);
5572
5573 $totalnbwords = 0;
5574
5575 foreach ($listofpages['list'] as $answerrecord) {
5576 if (is_object($answerrecord) && get_class($answerrecord) == 'WebsitePage') {
5577 $param = '?mode=replacesite';
5578 $param .= '&websiteid='.$website->id;
5579 $param .= '&optionpagecontent='.GETPOST('optionpagecontent', 'aZ09');
5580 $param .= '&optionmeta='.GETPOST('optionmeta', 'aZ09');
5581 $param .= '&optionsitefiles='.GETPOST('optionsitefiles', 'aZ09');
5582 $param .= '&optioncontainertype='.GETPOST('optioncontainertype', 'aZ09');
5583 $param .= '&optionlanguage='.GETPOST('optionlanguage', 'aZ09');
5584 $param .= '&optioncategory='.GETPOST('optioncategory', 'aZ09');
5585 $param .= '&searchstring='.urlencode($searchkey);
5586
5587 print '<tr>';
5588
5589 // Action column
5590 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
5591 print '<td class="nowrap center">';
5592
5593 print '<!-- Status of page -->'."\n";
5594 if ($massactionbutton || $massaction) {
5595 $selected = 0;
5596 if (in_array($answerrecord->id, $arrayofselected)) {
5597 $selected = 1;
5598 }
5599 print '<input id="'.$answerrecord->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$answerrecord->id.'"'.($selected ? ' checked="checked"' : '').'>';
5600 }
5601 print '</td>';
5602 }
5603
5604 // Type of container
5605 print '<td class="nowraponall">';
5606 //print $langs->trans("Container").'<br>';
5607 if (!empty($conf->cache['type_of_container'][$answerrecord->type_container])) {
5608 print $langs->trans($conf->cache['type_of_container'][$answerrecord->type_container]);
5609 } else {
5610 print $langs->trans($answerrecord->type_container);
5611 }
5612 print '</td>';
5613
5614 // Container url and label
5615 $titleofpage = ($answerrecord->title ? $answerrecord->title : $langs->trans("NoTitle"));
5616 print '<td class="tdoverflowmax300" title="'.dol_escape_htmltag($titleofpage).'">';
5617 print $answerrecord->getNomUrl(1);
5618 print ' <span class="opacitymedium">('.dol_escape_htmltag($titleofpage).')</span>';
5619 //print '</td>';
5620 //print '<td class="tdoverflow100">';
5621 print '<br>';
5622 print '<span class="opacitymedium">'.dol_escape_htmltag($answerrecord->description ? $answerrecord->description : $langs->trans("NoDescription")).'</span>';
5623 print '</td>';
5624
5625 // Language
5626 print '<td class="center">';
5627 print picto_from_langcode($answerrecord->lang, $answerrecord->lang);
5628 print '</td>';
5629
5630 // Categories - Tags
5631 print '<td class="center">';
5632 if (isModEnabled('category') && $user->hasRight('categorie', 'lire')) {
5633 // Get current categories
5634 $existing = $c->containing($answerrecord->id, Categorie::TYPE_WEBSITE_PAGE, 'object');
5635 if (is_array($existing)) {
5636 foreach ($existing as $tmpcategory) {
5637 //var_dump($tmpcategory);
5638 print img_object($langs->trans("Category").' : '.$tmpcategory->label, 'category', 'style="padding-left: 2px; padding-right: 2px; color: #'.($tmpcategory->color != '' ? $tmpcategory->color : '888').'"');
5639 }
5640 }
5641 }
5642 //var_dump($existing);
5643 print '</td>';
5644
5645 // Number of words
5646 print '<td class="center nowraponall">';
5647 $textwithouthtml = dol_string_nohtmltag(dolStripPhpCode($answerrecord->content));
5648 $characterMap = 'áàéèëíóúüñùç0123456789';
5649 $nbofwords = str_word_count($textwithouthtml, 0, $characterMap);
5650 if ($nbofwords) {
5651 print $nbofwords.' '.$langs->trans("words");
5652 $totalnbwords += $nbofwords;
5653 }
5654 print '</td>';
5655
5656 // Author
5657 print '<td class="tdoverflowmax125">';
5658 if (!empty($answerrecord->fk_user_creat)) {
5659 if (empty($conf->cache['user'][$answerrecord->fk_user_creat])) {
5660 $tmpuser = new User($db);
5661 $tmpuser->fetch($answerrecord->fk_user_creat);
5662 $conf->cache['user'][$answerrecord->fk_user_creat] = $tmpuser;
5663 } else {
5664 $tmpuser = $conf->cache['user'][$answerrecord->fk_user_creat];
5665 }
5666 print $tmpuser->getNomUrl(-1, '', 0, 0, 0, 0, 'login');
5667 }
5668 print '</td>';
5669
5670 // Date creation
5671 print '<td class="center nowraponall">';
5672 print dol_print_date($answerrecord->date_creation, 'dayhour');
5673 print '</td>';
5674
5675 // Date last modification
5676 print '<td class="center nowraponall">';
5677 print dol_print_date($answerrecord->date_modification, 'dayhour');
5678 print '</td>';
5679
5680 // Edit properties, HTML sources, status
5681 print '<td class="tdwebsitesearchresult right nowraponall">';
5682 $disabled = '';
5683 $urltoedithtmlsource = $_SERVER["PHP_SELF"].'?action=editmeta&token='.newToken().'&websiteid='.$website->id.'&pageid='.$answerrecord->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"].$param);
5684 if (!$user->hasRight('website', 'write')) {
5685 $disabled = ' disabled';
5686 $urltoedithtmlsource = '';
5687 }
5688 print '<a class="editfielda marginleftonly marginrightonly '.$disabled.'" href="'.$urltoedithtmlsource.'" title="'.$langs->trans("EditPageMeta").'">'.img_picto($langs->trans("EditPageMeta"), 'pencil-ruler').'</a>';
5689
5690 $disabled = '';
5691 $urltoedithtmlsource = $_SERVER["PHP_SELF"].'?action=editsource&token='.newToken().'&websiteid='.$website->id.'&pageid='.$answerrecord->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"].$param);
5692 if (!$user->hasRight('website', 'write')) {
5693 $disabled = ' disabled';
5694 $urltoedithtmlsource = '';
5695 }
5696 print '<a class="editfielda marginleftonly marginrightonly '.$disabled.'" href="'.$urltoedithtmlsource.'" title="'.$langs->trans("EditHTMLSource").'">'.img_picto($langs->trans("EditHTMLSource"), 'edit').'</a>';
5697
5698 print '<span class="marginleftonly marginrightonly"></span>';
5699 print ajax_object_onoff($answerrecord, 'status', 'status', 'Enabled', 'Disabled', array(), 'valignmiddle inline-block');
5700
5701 print '</td>';
5702
5703 // Action column
5704 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
5705 print '<td class="nowrap center">';
5706
5707 print '<!-- Status of page -->'."\n";
5708 if ($massactionbutton || $massaction) {
5709 $selected = 0;
5710 if (in_array($answerrecord->id, $arrayofselected)) {
5711 $selected = 1;
5712 }
5713 print '<input id="'.$answerrecord->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$answerrecord->id.'"'.($selected ? ' checked="checked"' : '').'>';
5714 }
5715 print '</td>';
5716 }
5717
5718 print '</tr>';
5719 } else {
5720 // $answerrecord is not list of WebsitePage
5721 '@phan-var-force array{type:string} $answerrecord';
5722 $param = '?mode=replacesite';
5723 $param .= '&websiteid='.$website->id;
5724 $param .= '&optionpagecontent='.GETPOST('optionpagecontent', 'aZ09');
5725 $param .= '&optionmeta='.GETPOST('optionmeta', 'aZ09');
5726 $param .= '&optionsitefiles='.GETPOST('optionsitefiles', 'aZ09');
5727 $param .= '&optioncontainertype='.GETPOST('optioncontainertype', 'aZ09');
5728 $param .= '&optionlanguage='.GETPOST('optionlanguage', 'aZ09');
5729 $param .= '&optioncategory='.GETPOST('optioncategory', 'aZ09');
5730 $param .= '&searchstring='.urlencode($searchkey);
5731
5732 print '<tr>';
5733
5734 // Action column
5735 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
5736 print '<td class="nowrap center">';
5737 print '</td>';
5738 }
5739
5740 // Type of container
5741 print '<td>';
5742 $translateofrecordtype = array(
5743 'website_csscontent' => 'WEBSITE_CSS_INLINE',
5744 'website_jscontent' => 'WEBSITE_JS_INLINE',
5745 'website_robotcontent' => 'WEBSITE_ROBOT',
5746 'website_htmlheadercontent' => 'WEBSITE_HTML_HEADER',
5747 'website_htaccess' => 'WEBSITE_HTACCESS',
5748 'website_readme' => 'WEBSITE_README',
5749 'website_manifestjson' => 'WEBSITE_MANIFEST_JSON'
5750 );
5751 print '<span class="opacitymedium">';
5752 if (!empty($translateofrecordtype[$answerrecord['type']])) {
5753 print $langs->trans($translateofrecordtype[$answerrecord['type']]);
5754 } else {
5755 print $answerrecord['type'];
5756 }
5757 print '</span>';
5758 print '</td>';
5759
5760 // Container url and label
5761 print '<td>';
5762 $backtopageurl = $_SERVER["PHP_SELF"].$param;
5763 print '<a href="'.$_SERVER["PHP_SELF"].'?action=editcss&token='.newToken().'&website='.urlencode($website->ref).'&backtopage='.urlencode($backtopageurl).'">'.$langs->trans("EditCss").'</a>';
5764 print '</td>';
5765
5766 // Language
5767 print '<td>';
5768 print '</td>';
5769
5770 // Categories - Tags
5771 print '<td>';
5772 print '</td>';
5773
5774 // Nb of words
5775 print '<td>';
5776 print '</td>';
5777
5778 print '<td>';
5779 print '</td>';
5780
5781 print '<td>';
5782 print '</td>';
5783
5784 // Date last modification
5785 print '<td class="center nowraponall">';
5786 //print dol_print_date(filemtime());
5787 print '</td>';
5788
5789 // Edit properties, HTML sources, status
5790 print '<td>';
5791 print '</td>';
5792
5793 // Action column
5794 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
5795 print '<td class="nowrap center">';
5796 print '</td>';
5797 }
5798
5799 print '</tr>';
5800 }
5801 }
5802
5803 if (count($listofpages['list']) >= 2) {
5804 // Total
5805 print '<tr class="lite_titre">';
5806
5807 // Action column
5808 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
5809 print '<td class="nowrap center">';
5810 print '</td>';
5811 }
5812
5813 // Type of container
5814 print '<td>';
5815 print $langs->trans("Total");
5816 print '</td>';
5817
5818 // Container url and label
5819 print '<td>';
5820 print '</td>';
5821
5822 // Language
5823 print '<td>';
5824 print '</td>';
5825
5826 // Categories - Tags
5827 print '<td>';
5828 print '</td>';
5829
5830 // Nb of words
5831 print '<td class="center nowraponall">';
5832 print $totalnbwords.' '.$langs->trans("words");
5833 print '</td>';
5834
5835 print '<td>';
5836 print '</td>';
5837
5838 print '<td>';
5839 print '</td>';
5840
5841 // Date last modification
5842 print '<td>';
5843 print '</td>';
5844
5845 // Edit properties, HTML sources, status
5846 print '<td>';
5847 print '</td>';
5848
5849 // Action column
5850 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
5851 print '<td class="nowrap center">';
5852 print '</td>';
5853 }
5854
5855 print '</tr>';
5856 }
5857
5858 print '</table>';
5859 print '</div>';
5860 print '<br>';
5861 } else {
5862 print '<div class="warning">'.$listofpages['message'].'</div>';
5863 }
5864
5865 print '</div>';
5866 }
5867
5868 print '</form>';
5869}
5870
5871if ((empty($action) || $action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone') && !in_array($mode, array('replacesite'))) {
5872 if ($pageid > 0 && $atleastonepage) {
5873 // $filejs
5874 // $filecss
5875 // $filephp
5876
5877 // Output page under the Dolibarr top menu
5878 $objectpage->fetch($pageid);
5879
5880 $jscontent = @file_get_contents($filejs);
5881
5882 $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";
5883
5884 // Include a html so we can benefit of the header of page.
5885 // Note: We can't use iframe as it can be used to include another external html file
5886 // Note: We can't use frame as it is deprecated.
5887 /*if ($includepageintoaframeoradiv == 'iframe')
5888 {
5889 $out .= "<iframe><body></html>";
5890 }*/
5891 $out .= "\n<html><head>\n";
5892 $out .= "<!-- htmlheader/style of page from database -->\n";
5893 $out .= dolWebsiteReplacementOfLinks($object, $objectpage->htmlheader, 1, 'htmlheader');
5894
5895 $out .= "<!-- htmlheader/style of website from files -->\n";
5896 // TODO Keep only the <link> or the <script> tags
5897 /*
5898 $htmlheadercontent = @file_get_contents($filehtmlheader);
5899 $dom = new DOMDocument;
5900 @$dom->loadHTML($htmlheadercontent);
5901 $styles = $dom->getElementsByTagName('link');
5902 $scripts = $dom->getElementsByTagName('script');
5903 foreach($styles as $stylescursor)
5904 {
5905 $out.=$stylescursor;
5906 }
5907 foreach($scripts as $scriptscursor)
5908 {
5909 $out.=$scriptscursor;
5910 }
5911 */
5912
5913 $out .= "</head>\n";
5914 $out .= "\n";
5915 $out .= "<body>\n";
5916
5917
5918 $out .= '<div id="websitecontentundertopmenu" class="websitecontentundertopmenu boostrap-iso">'."\n";
5919
5920 // REPLACEMENT OF LINKS When page called by website editor
5921
5922 $out .= '<!-- style of website from file -->'."\n";
5923 $out .= '<style scoped>'."\n"; // "scoped" means "apply to parent element only and not grand parent". No more supported by browsers, snif !
5924 $tmpout = '';
5925 $tmpout .= '/* Include website CSS file */'."\n";
5926 //$csscontent = @file_get_contents($filecss);
5927 if (dol_is_file($filecss)) {
5928 ob_start();
5929 include $filecss;
5930 $csscontent = ob_get_contents();
5931 ob_end_clean();
5932 } else {
5933 $csscontent = '';
5934 }
5935 $tmpout .= dolWebsiteReplacementOfLinks($object, $csscontent, 1, 'css');
5936 $tmpout .= '/* Include style from the HTML header of page */'."\n";
5937 // Clean the html header of page to get only <style> content
5938 $tmp = preg_split('(<style[^>]*>|</style>)', $objectpage->htmlheader);
5939 $tmpstyleinheader = '';
5940 $i = 0;
5941 foreach ($tmp as $valtmp) {
5942 $i++;
5943 if ($i % 2 == 0) {
5944 $tmpstyleinheader .= $valtmp."\n";
5945 }
5946 }
5947 $tmpout .= $tmpstyleinheader."\n";
5948 // Clean style that may affect global style of Dolibarr
5949 $tmpout = preg_replace('/}[\s\n]*body\s*{[^}]+}/ims', '}', $tmpout);
5950 $out .= $tmpout;
5951 $out .= '</style>'."\n";
5952
5953 // Note: <div>, <section>, ... with contenteditable="true" inside this can be edited with inline ckeditor
5954
5955 // Do not enable the contenteditable when page was grabbed, ckeditor is removing span and adding borders,
5956 // so editable will be available only from container created from scratch
5957 //$out.='<div id="bodywebsite" class="bodywebsite"'.($objectpage->grabbed_from ? ' contenteditable="true"' : '').'>'."\n";
5958 $out .= '<div id="divbodywebsite" class="bodywebsite bodywebpage-'.$objectpage->ref.'">'."\n";
5959
5960 $newcontent = $objectpage->content;
5961
5962 // If mode WEBSITE_SUBCONTAINERSINLINE is on
5963 if (getDolGlobalString('WEBSITE_SUBCONTAINERSINLINE')) {
5964 // TODO Check file $filephp exists, if not create it.
5965
5966 //var_dump($filetpl);
5967 $filephp = $filetpl;
5968
5969 // Get session info and obfuscate session cookie
5970 $savsessionname = session_name();
5971 $savsessionid = $_COOKIE[$savsessionname];
5972 $_COOKIE[$savsessionname] = 'obfuscatedcookie';
5973
5974 ob_start();
5975 try {
5976 $res = include $filephp;
5977 if (empty($res)) {
5978 print "ERROR: Failed to include file '".$filephp."'. Try to edit and re-save page with this ID.";
5979 }
5980 } catch (Exception $e) {
5981 print $e->getMessage();
5982 }
5983 $newcontent = ob_get_contents();
5984 ob_end_clean();
5985
5986 // Restore data
5987 $_COOKIE[$savsessionname] = $savsessionid;
5988 }
5989
5990 // Change the contenteditable to "true" or "false" when mode Edit Inline is on or off
5991 if (!getDolGlobalString('WEBSITE_EDITINLINE')) {
5992 // Remove the contenteditable="true"
5993 $newcontent = preg_replace('/(div|section|header|main|footer)(\s[^>]*)contenteditable="true"/', '\1\2', $newcontent);
5994 } else {
5995 // Keep the contenteditable="true" when mode Edit Inline is on
5996 }
5997 $out .= dolWebsiteReplacementOfLinks($object, $newcontent, 0, 'html', $objectpage->id)."\n";
5998 //$out.=$newcontent;
5999
6000 $out .= '</div>'."\n";
6001
6002 $out .= '</div> <!-- End div id=websitecontentundertopmenu -->'."\n";
6003
6004 /*if ($includepageintoaframeoradiv == 'iframe')
6005 {
6006 $out .= "</body></html></iframe>";
6007 }*/
6008 $out .= "\n</body></html>\n";
6009
6010 $out .= "\n".'<!-- End page content '.$filetpl.' -->'."\n\n";
6011
6012 print $out;
6013
6014 /*
6015 file_put_contents($filetpl, $out);
6016 dolChmod($filetpl);
6017
6018 // Output file on browser
6019 dol_syslog("index.php include $filetpl $filename content-type=$type");
6020 $original_file_osencoded=dol_osencode($filetpl); // New file name encoded in OS encoding charset
6021
6022 // This test if file exists should be useless. We keep it to find bug more easily
6023 if (! file_exists($original_file_osencoded))
6024 {
6025 dol_print_error(0,$langs->trans("ErrorFileDoesNotExists",$original_file));
6026 exit;
6027 }
6028
6029 //include_once $original_file_osencoded;
6030 */
6031
6032 /*print '<iframe class="websiteiframenoborder centpercent" src="'.DOL_URL_ROOT.'/public/website/index.php?website='.$websitekey.'&pageid='.$pageid.'"/>';
6033 print '</iframe>';*/
6034 } else {
6035 if (empty($websitekey) || $websitekey == '-1') {
6036 print '<br><br><div class="center previewnotyetavailable"><span class="">'.$langs->trans("NoWebSiteCreateOneFirst").'</span></div><br><br><br>';
6037 print '<div class="center"><div class="logo_setup"></div></div>';
6038 } else {
6039 print '<br><br><div class="center previewnotyetavailable"><span class="">'.$langs->trans("PreviewOfSiteNotYetAvailable", $object->ref).'</span></div><br><br><br>';
6040 print '<div class="center"><div class="logo_setup"></div></div>';
6041 }
6042 }
6043}
6044
6045// End of page
6046llxFooter();
6047$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:475
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:793
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:331
$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 permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new Form...
Class permettant la generation de composants html autre 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:171
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.
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)
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.
ajax_autoselect($htmlname, $addlink='', $textonlink='Link')
Make content of an input box selected when we click into input field.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
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.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
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.
getURLContent($url, $postorget='GET', $param='', $followlocation=1, $addheaders=array(), $allowedschemes=array('http', 'https'), $localurl=0, $ssl_verifypeer=-1, $timeoutconnect=0, $timeoutresponse=0, $otherCurlOptions=array())
Function to get a content from an URL (use proxy if proxy defined).
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.
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.