dolibarr 25.0.0-alpha
api_websites.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2026 Laurent Destailleur <eldy@users.sourceforge.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18use Luracast\Restler\RestException;
19
20require_once DOL_DOCUMENT_ROOT.'/website/class/website.class.php';
21require_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php';
22require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';
23require_once DOL_DOCUMENT_ROOT.'/core/lib/website2.lib.php';
24
37class Websites extends DolibarrApi
38{
42 public $website;
43
47 public $websitepage;
48
52 public function __construct()
53 {
54 global $db;
55
56 $this->db = $db;
57 $this->website = new Website($this->db);
58 $this->websitepage = new WebsitePage($this->db);
59 }
60
76 public function get($id)
77 {
78 return $this->_fetchWebsite($id);
79 }
80
96 public function getByRef($ref)
97 {
98 return $this->_fetchWebsite(0, $ref);
99 }
100
120 public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '', $properties = '')
121 {
122 if (!DolibarrApiAccess::$user->hasRight('website', 'read')) {
123 throw new RestException(403);
124 }
125
126 $obj_ret = array();
127
128 $sql = "SELECT t.rowid, t.ref";
129 $sql .= " FROM ".$this->db->prefix()."website as t";
130 $sql .= " WHERE t.entity IN (".getEntity('website').")";
131
132 // Add sql filters
133 if ($sqlfilters) {
134 $errormessage = '';
135 $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
136 if ($errormessage) {
137 throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
138 }
139 }
140
141 $sqlTotals = str_replace('SELECT t.rowid, t.ref', 'SELECT count(t.rowid) as total', $sql);
142
143 $sql .= $this->db->order($sortfield, $sortorder);
144 if ($limit) {
145 if ($page < 0) {
146 $page = 0;
147 }
148 $offset = $limit * $page;
149 $sql .= $this->db->plimit($limit + 1, $offset);
150 }
151
152 $result = $this->db->query($sql);
153 if ($result) {
154 $num = $this->db->num_rows($result);
155 $min = min($num, ($limit <= 0 ? $num : $limit));
156 $i = 0;
157 while ($i < $min) {
158 $obj = $this->db->fetch_object($result);
159 $website_static = new Website($this->db);
160 if ($website_static->fetch($obj->rowid)) {
161 $obj_ret[] = $this->_filterObjectProperties($this->_cleanObjectDatas($website_static), $properties);
162 }
163 $i++;
164 }
165 } else {
166 throw new RestException(503, 'Error when retrieve website list : '.$this->db->lasterror());
167 }
168
169 // If pagination data is requested (page > 0), the response will contain element data with all values and element pagination with pagination data
170 if ($page > 0) {
171 $totalsResult = $this->db->query($sqlTotals);
172 $total = $this->db->fetch_object($totalsResult)->total;
173
174 $tmp = $obj_ret;
175 $obj_ret = array();
176
177 $obj_ret['data'] = $tmp;
178 $obj_ret['pagination'] = array(
179 'total' => (int) $total,
180 'page' => $page,
181 'page_count' => (int) ceil((int) $total / $limit),
182 'limit' => $limit
183 );
184 }
185
186 return $obj_ret;
187 }
188
212 public function indexPages($id, $sortfield = "t.pageurl", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '', $properties = '')
213 {
214 if (!DolibarrApiAccess::$user->hasRight('website', 'read')) {
215 throw new RestException(403);
216 }
217
218 $result = $this->website->fetch($id);
219 if (!$result) {
220 throw new RestException(404, 'Website not found');
221 }
222
223 if (!DolibarrApi::_checkAccessToResource('website', $this->website->id)) {
224 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
225 }
226
227 $obj_ret = array();
228
229 $sql = "SELECT t.rowid, t.pageurl";
230 $sql .= " FROM ".$this->db->prefix()."website_page as t";
231 $sql .= " WHERE t.fk_website = ".((int) $id);
232
233 // Add sql filters
234 if ($sqlfilters) {
235 $errormessage = '';
236 $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
237 if ($errormessage) {
238 throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
239 }
240 }
241
242 $sqlTotals = str_replace('SELECT t.rowid, t.pageurl', 'SELECT count(t.rowid) as total', $sql);
243
244 $sql .= $this->db->order($sortfield, $sortorder);
245 if ($limit) {
246 if ($page < 0) {
247 $page = 0;
248 }
249 $offset = $limit * $page;
250 $sql .= $this->db->plimit($limit + 1, $offset);
251 }
252
253 $result = $this->db->query($sql);
254 if ($result) {
255 $num = $this->db->num_rows($result);
256 $min = min($num, ($limit <= 0 ? $num : $limit));
257 $i = 0;
258 while ($i < $min) {
259 $obj = $this->db->fetch_object($result);
260 $page_static = new WebsitePage($this->db);
261 if ($page_static->fetch($obj->rowid)) {
262 $obj_ret[] = $this->_filterObjectProperties($this->_cleanObjectDatas($page_static), $properties);
263 }
264 $i++;
265 }
266 } else {
267 throw new RestException(503, 'Error when retrieve page list : '.$this->db->lasterror());
268 }
269
270 if ($page > 0) {
271 $totalsResult = $this->db->query($sqlTotals);
272 $total = $this->db->fetch_object($totalsResult)->total;
273
274 $tmp = $obj_ret;
275 $obj_ret = array();
276
277 $obj_ret['data'] = $tmp;
278 $obj_ret['pagination'] = array(
279 'total' => (int) $total,
280 'page' => $page,
281 'page_count' => (int) ceil((int) $total / $limit),
282 'limit' => $limit
283 );
284 }
285
286 return $obj_ret;
287 }
288
305 public function getPage($id, $pageid)
306 {
307 if (!DolibarrApiAccess::$user->hasRight('website', 'read')) {
308 throw new RestException(403);
309 }
310
311 $result = $this->website->fetch($id);
312 if (!$result) {
313 throw new RestException(404, 'Website not found');
314 }
315
316 if (!DolibarrApi::_checkAccessToResource('website', $this->website->id)) {
317 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
318 }
319
320 $result = $this->websitepage->fetch($pageid);
321 if (!$result) {
322 throw new RestException(404, 'Page not found');
323 }
324
325 // Check that the page belongs to the website
326 if ($this->websitepage->fk_website != $this->website->id) {
327 throw new RestException(404, 'Page not found for this website');
328 }
329
330 return $this->_cleanObjectDatas($this->websitepage);
331 }
332
354 public function putPage($id, $pageid, $request_data = null)
355 {
356 if (!DolibarrApiAccess::$user->hasRight('website', 'write')) {
357 throw new RestException(403);
358 }
359
360 $result = $this->website->fetch($id);
361 if (!$result) {
362 throw new RestException(404, 'Website not found');
363 }
364
365 if (!DolibarrApi::_checkAccessToResource('website', $this->website->id)) {
366 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
367 }
368
369 $result = $this->websitepage->fetch($pageid);
370 if (!$result) {
371 throw new RestException(404, 'Page not found');
372 }
373
374 // Check that the page belongs to the website
375 if ($this->websitepage->fk_website != $this->website->id) {
376 throw new RestException(404, 'Page not found for this website');
377 }
378
379 // Keep the old PHP content to detect if PHP content changed
380 $phpfullcodestringold = dolKeepOnlyPhpCode($this->websitepage->content);
381
382 // Apply request data to the page object
383 foreach ($request_data as $field => $value) {
384 if ($field == 'id' || $field == 'rowid') {
385 continue;
386 }
387 if ($field == 'fk_website') {
388 // Do not allow changing the website ownership of a page via this endpoint
389 continue;
390 }
391 if ($field === 'caller') {
392 $this->websitepage->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
393 continue;
394 }
395 if ($field == 'array_options' && is_array($value)) {
396 foreach ($value as $index => $val) {
397 $this->websitepage->array_options[$index] = $this->_checkValExtrafieldsForAPI($index, $val, $this->websitepage);
398 }
399 continue;
400 }
401 $this->websitepage->$field = $this->_checkValForAPI($field, $value, $this->websitepage);
402 }
403
404 // Security: check PHP content if user does not have writephp permission
405 $phpfullcodestring = dolKeepOnlyPhpCode($this->websitepage->content);
406 if ($phpfullcodestringold != $phpfullcodestring) {
407 if (!DolibarrApiAccess::$user->hasRight('website', 'writephp')) {
408 throw new RestException(403, 'NotAllowedToAddDynamicContent');
409 }
410 }
411
412 // Clean data: remove head section from content (same as web interface)
413 $this->websitepage->content = preg_replace('/<head>.*<\/head>/ims', '', $this->websitepage->content);
414
415 // Update the page in database
416 $result = $this->websitepage->update(DolibarrApiAccess::$user);
417 if ($result < 0) {
418 throw new RestException(500, $this->websitepage->errorsToString());
419 }
420
421 // Regenerate static files on disk (same as web interface in index.php)
422 $this->_regeneratePageFiles($this->website, $this->websitepage);
423
424 return $this->_cleanObjectDatas($this->websitepage);
425 }
426
427 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
438 protected function _cleanObjectDatas($object)
439 {
440 // phpcs:enable
441 $object = parent::_cleanObjectDatas($object);
442
443 // Remove properties not relevant for the website API response and not already cleaned by the parent
444 unset($object->canvas);
445 unset($object->name);
446 unset($object->lastname);
447 unset($object->firstname);
448 unset($object->civility_id);
449 unset($object->statut);
450 unset($object->region_id);
451 unset($object->state_id);
452 unset($object->country_id);
453 unset($object->country_code);
454 unset($object->barcode_type);
455 unset($object->barcode_type_coder);
456 unset($object->total_ht);
457 unset($object->total_tva);
458 unset($object->total_localtax1);
459 unset($object->total_localtax2);
460 unset($object->total_ttc);
461 unset($object->user);
462 unset($object->fk_account);
463 unset($object->shipping_method_id);
464 unset($object->fk_incoterms);
465 unset($object->label_incoterms);
466 unset($object->location_incoterms);
467 unset($object->multicurrency_code);
468 unset($object->multicurrency_tx);
469 unset($object->multicurrency_total_ht);
470 unset($object->multicurrency_total_ttc);
471 unset($object->multicurrency_total_tva);
472 unset($object->multicurrency_total_localtax1);
473 unset($object->multicurrency_total_localtax2);
474
475 unset($object->mode_reglement_id);
476 unset($object->cond_reglement_id);
477 unset($object->demand_reason_id);
478 unset($object->transport_mode_id);
479 unset($object->shipping_method);
480 unset($object->model_pdf);
481 unset($object->last_main_doc);
482 unset($object->lines);
483 unset($object->actiontypecode);
484 unset($object->civility_code);
485 unset($object->date_cloture);
486 unset($object->user_closing_id);
487 unset($object->totalpaid);
488 unset($object->totalpaid_multicurrency);
489 unset($object->cond_reglement_supplier_id);
490 unset($object->deposit_percent);
491 unset($object->warehouse_id);
492 unset($object->array_languages);
493 unset($object->contacts_ids);
494 unset($object->contacts_ids_internal);
495 unset($object->other_linked_objects);
496 unset($object->linkedObjectsIds);
497 unset($object->origin_type);
498 unset($object->origin_id);
499 unset($object->product);
500 unset($object->fk_project);
501 unset($object->contact_id);
502 unset($object->validation);
503 unset($object->user_validation_id);
504 unset($object->tms);
505
506 return $object;
507 }
508
522 private function _fetchWebsite($id, $ref = '')
523 {
524 if (empty($id) && empty($ref)) {
525 throw new RestException(400, 'bad value for parameter id or ref');
526 }
527
528 if (!DolibarrApiAccess::$user->hasRight('website', 'read')) {
529 throw new RestException(403);
530 }
531
532 $result = $this->website->fetch($id, $ref);
533 if (!$result) {
534 throw new RestException(404, 'Website not found');
535 }
536
537 if (!DolibarrApi::_checkAccessToResource('website', $this->website->id)) {
538 throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
539 }
540
541 return $this->_cleanObjectDatas($this->website);
542 }
543
553 private function _regeneratePageFiles($website, $websitepage)
554 {
555 global $conf;
556 global $dolibarr_main_data_root;
557
558 $pathofwebsite = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$website->ref;
559
560 $filemaster = $pathofwebsite.'/master.inc.php';
561 $filealias = $pathofwebsite.'/'.$websitepage->pageurl.'.php';
562 $filetpl = $pathofwebsite.'/page'.$websitepage->id.'.tpl.php';
563
564 dol_mkdir($pathofwebsite);
565
566 // Regenerate the master.inc.php
567 $result = dolSaveMasterFile($filemaster);
568 if (!$result) {
569 dol_syslog("Failed to write the master file ".$filemaster, LOG_WARNING);
570 }
571
572 // Save page alias
573 $result = dolSavePageAlias($filealias, $website, $websitepage);
574 if (!$result) {
575 dol_syslog("Failed to write the alias file ".basename($filealias), LOG_WARNING);
576 }
577
578 // Save page content (the .tpl.php file)
579 $result = dolSavePageContent($filetpl, $website, $websitepage, 1);
580 if (!$result) {
581 dol_syslog("Failed to write the tpl file ".$filetpl, LOG_WARNING);
582 }
583 }
584}
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Class for API REST v1.
Definition api.class.php:35
_checkValExtrafieldsForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
_filterObjectProperties($object, $properties)
Filter properties that will be returned on object.
_checkValForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
static _checkAccessToResource($resource, $resource_id=0, $dbtablename='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $parenttableforentity='')
Check access by user to a given resource.
Class Website.
indexPages($id, $sortfield="t.pageurl", $sortorder='ASC', $limit=100, $page=0, $sqlfilters='', $properties='')
List pages of a website.
index($sortfield="t.rowid", $sortorder='ASC', $limit=100, $page=0, $sqlfilters='', $properties='')
List websites.
getByRef($ref)
Get properties of a website object by ref.
_cleanObjectDatas($object)
Clean sensible object datas @phpstan-template T.
putPage($id, $pageid, $request_data=null)
Update a website page.
__construct()
Constructor.
getPage($id, $pageid)
Get properties of a website page by id.
_regeneratePageFiles($website, $websitepage)
Regenerate static page files on disk (master.inc.php, alias, tpl content).
_fetchWebsite($id, $ref='')
Get properties of a website object.
dolKeepOnlyPhpCode($str)
Keep only PHP code part from a HTML string page.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0, $forbiddenfields=array())
forgeSQLFromUniversalSearchCriteria
sanitizeVal($out='', $check='alphanohtml', $filter=null, $options=null)
Return a sanitized or empty value after checking value against a rule.
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)
dolSaveMasterFile($filemaster)
Save content of a page on disk.
dolSavePageAlias($filealias, $object, $objectpage)
Save an alias page on disk (A page that include the reference page).
dolSavePageContent($filetpl, Website $object, WebsitePage $objectpage, $backupold=0)
Save content of a page on disk (page name is generally ID_of_page.php).