1<?php 2/* Copyright (C) 2007-2018 Laurent Destailleur <eldy@users.sourceforge.net> 3 * Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es> 4 * Copyright (C) 2015 Florian Henry <florian.henry@open-concept.pro> 5 * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr> 6 * Copyright (C) 2020 Nicolas ZABOURI <info@inovea-conseil.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22/** 23 * \file htdocs/website/class/websitepage.class.php 24 * \ingroup website 25 * \brief File for the CRUD class of websitepage (Create/Read/Update/Delete) 26 */ 27 28// Put here all includes required by your class file 29require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; 30//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; 31//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; 32 33/** 34 * Class Websitepage 35 */ 36class WebsitePage extends CommonObject 37{ 38 /** 39 * @var string Id to identify managed objects 40 */ 41 public $element = 'websitepage'; 42 43 /** 44 * @var string Name of table without prefix where object is stored 45 */ 46 public $table_element = 'website_page'; 47 48 /** 49 * @var string String with name of icon for websitepage. Must be the part after the 'object_' into object_myobject.png 50 */ 51 public $picto = 'file-code'; 52 53 54 /** 55 * @var int ID 56 */ 57 public $fk_website; 58 59 public $pageurl; 60 public $aliasalt; 61 public $type_container; 62 63 /** 64 * @var string title 65 */ 66 public $title; 67 /** 68 * @var string description 69 */ 70 public $description; 71 /** 72 * @var string image 73 */ 74 public $image; 75 /** 76 * @var string keywords 77 */ 78 public $keywords; 79 /** 80 * @var string language code ('en', 'fr', 'en-gb', ..) 81 */ 82 public $lang; 83 84 public $allowed_in_frames; 85 public $htmlheader; 86 public $content; 87 public $grabbed_from; 88 89 /** 90 * @var int Status 91 */ 92 public $status; 93 94 /** 95 * @var integer|string date_creation 96 */ 97 public $date_creation; 98 99 /** 100 * @var integer|string date_modification 101 */ 102 public $date_modification; 103 104 /** 105 * @var string author_alias 106 */ 107 public $author_alias; 108 109 /** 110 * @var string path of external object 111 */ 112 public $object_type; 113 114 /** 115 * @var string id of external object 116 */ 117 public $fk_object; 118 119 const STATUS_DRAFT = 0; 120 const STATUS_VALIDATED = 1; 121 122 123 /** 124 * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') 125 * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" 126 * 'label' the translation key. 127 * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) 128 * 'position' is the sort order of field. 129 * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). 130 * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) 131 * 'noteditable' says if field is not editable (1 or 0) 132 * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. 133 * 'index' if we want an index in database. 134 * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). 135 * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. 136 * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). 137 * 'css' is the CSS style to use on field. For example: 'maxwidth200' 138 * 'help' is a string visible as a tooltip on field 139 * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record 140 * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. 141 * 'arraykeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel") 142 * 'comment' is not used. You can store here any text of your choice. It is not used by application. 143 * 144 * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. 145 */ 146 147 // BEGIN MODULEBUILDER PROPERTIES 148 /** 149 * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. 150 */ 151 public $fields = array( 152 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'index'=>1, 'position'=>1, 'comment'=>'Id'), 153 'pageurl' =>array('type'=>'varchar(16)', 'label'=>'WEBSITE_PAGENAME', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'comment'=>'Ref/alias of page'), 154 'aliasalt' =>array('type'=>'varchar(255)', 'label'=>'AliasAlt', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'index'=>0, 'position'=>11, 'searchall'=>0, 'comment'=>'Alias alternative of page'), 155 'type_container' =>array('type'=>'varchar(16)', 'label'=>'Type', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'index'=>0, 'position'=>12, 'comment'=>'Type of container'), 156 'title' =>array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'searchall'=>1, 'help'=>'UseTextBetween5And70Chars'), 157 'description' =>array('type'=>'varchar(255)', 'label'=>'Description', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'searchall'=>1), 158 'image' =>array('type'=>'varchar(255)', 'label'=>'Image', 'enabled'=>1, 'visible'=>1, 'position'=>32, 'searchall'=>0, 'help'=>'Relative path of media. Used if Type is "blogpost"'), 159 'keywords' =>array('type'=>'varchar(255)', 'label'=>'Keywords', 'enabled'=>1, 'visible'=>1, 'position'=>45, 'searchall'=>0), 160 'lang' =>array('type'=>'varchar(6)', 'label'=>'Lang', 'enabled'=>1, 'notnull'=>-1, 'visible'=>1, 'position'=>45, 'searchall'=>0), 161 //'status' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'index'=>true, 'position'=>1000), 162 'fk_website' =>array('type'=>'integer', 'label'=>'WebsiteId', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'position'=>40, 'searchall'=>0, 'foreignkey'=>'websitepage.rowid'), 163 'fk_page' =>array('type'=>'integer', 'label'=>'ParentPageId', 'enabled'=>1, 'visible'=>1, 'notnull'=>-1, 'position'=>45, 'searchall'=>0, 'foreignkey'=>'website.rowid'), 164 'allowed_in_frames' =>array('type'=>'integer', 'label'=>'AllowedInFrames', 'enabled'=>1, 'visible'=>-1, 'position'=>48, 'searchall'=>0, 'default'=>0), 165 'htmlheader' =>array('type'=>'text', 'label'=>'HtmlHeader', 'enabled'=>1, 'visible'=>0, 'position'=>50, 'searchall'=>0), 166 'content' =>array('type'=>'mediumtext', 'label'=>'Content', 'enabled'=>1, 'visible'=>0, 'position'=>51, 'searchall'=>0), 167 'grabbed_from' =>array('type'=>'varchar(255)', 'label'=>'GrabbedFrom', 'enabled'=>1, 'visible'=>1, 'index'=>1, 'position'=>400, 'comment'=>'URL page content was grabbed from'), 168 'date_creation' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>500), 169 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>501), 170 //'date_valid' =>array('type'=>'datetime', 'label'=>'DateValidation', 'enabled'=>1, 'visible'=>-1, 'position'=>502), 171 'fk_user_creat' =>array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>510), 172 'author_alias' =>array('type'=>'varchar(64)', 'label'=>'AuthorAlias', 'enabled'=>1, 'visible'=>-1, 'index'=>0, 'position'=>511, 'comment'=>'Author alias'), 173 'fk_user_modif' =>array('type'=>'integer', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-1, 'position'=>512), 174 //'fk_user_valid' =>array('type'=>'integer', 'label'=>'UserValidation', 'enabled'=>1, 'visible'=>-1, 'position'=>512), 175 'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-1, 'index'=>1, 'position'=>1000, 'notnull'=>-1), 176 'object_type' => array('type' => 'varchar(255)', 'label' => 'ObjectType', 'enabled'=>1, 'visible'=>0, 'position'=>46, 'searchall'=>0, 'help'=>''), 177 'fk_object' => array('type' => 'varchar(255)', 'label' => 'ObjectId', 'enabled'=>1, 'visible'=>0, 'position'=>47, 'searchall'=>0, 'help'=>'') 178 ); 179 // END MODULEBUILDER PROPERTIES 180 181 182 // If this object has a subtable with lines 183 184 // /** 185 // * @var string Name of subtable line 186 // */ 187 //public $table_element_line = 'mymodule_myobjectline'; 188 189 /** 190 * @var string Field with ID of parent key if this field has a parent or for child tables 191 */ 192 public $fk_element = 'fk_website_page'; 193 194 // /** 195 // * @var string Name of subtable class that manage subtable lines 196 // */ 197 //public $class_element_line = 'MyObjectline'; 198 199 /** 200 * @var array List of child tables. To test if we can delete object. 201 */ 202 //protected $childtables=array(); 203 204 /** 205 * @var array List of child tables. To know object to delete on cascade. 206 */ 207 protected $childtablesoncascade = array('categorie_website_page'); 208 209 210 211 /** 212 * Constructor 213 * 214 * @param DoliDb $db Database handler 215 */ 216 public function __construct(DoliDB $db) 217 { 218 $this->db = $db; 219 } 220 221 /** 222 * Create object into database 223 * 224 * @param User $user User that creates 225 * @param bool $notrigger false=launch triggers after, true=disable triggers 226 * @return int <0 if KO, Id of created object if OK 227 */ 228 public function create(User $user, $notrigger = false) 229 { 230 $this->description = dol_trunc($this->description, 255, 'right', 'utf-8', 1); 231 $this->keywords = dol_trunc($this->keywords, 255, 'right', 'utf-8', 1); 232 if ($this->aliasalt) $this->aliasalt = ','.preg_replace('/,+$/', '', preg_replace('/^,+/', '', $this->aliasalt)).','; // content in database must be ',xxx,...,yyy,' 233 234 // Remove spaces and be sure we have main language only 235 $this->lang = preg_replace('/[_-].*$/', '', trim($this->lang)); // en_US or en-US -> en 236 237 return $this->createCommon($user, $notrigger); 238 } 239 240 /** 241 * Load object in memory from the database 242 * 243 * @param int $id Id object. 244 * - If this is 0, the value into $page will be used. If not found or $page not defined, the default page of website_id will be used or the first page found if not set. 245 * - If value is < 0, we must exclude this ID. 246 * @param string $website_id Web site id (page name must also be filled if this parameter is used) 247 * @param string $page Page name (website id must also be filled if this parameter is used). Exemple 'myaliaspage' or 'fr/myaliaspage' 248 * @param string $aliasalt Alternative alias to search page (slow) 249 * 250 * @return int <0 if KO, 0 if not found, >0 if OK 251 */ 252 public function fetch($id, $website_id = null, $page = null, $aliasalt = null) 253 { 254 dol_syslog(__METHOD__, LOG_DEBUG); 255 256 $sql = 'SELECT'; 257 $sql .= ' t.rowid,'; 258 $sql .= " t.fk_website,"; 259 $sql .= ' t.type_container,'; 260 $sql .= " t.pageurl,"; 261 $sql .= " t.aliasalt,"; 262 $sql .= " t.title,"; 263 $sql .= " t.description,"; 264 $sql .= " t.image,"; 265 $sql .= " t.keywords,"; 266 $sql .= " t.htmlheader,"; 267 $sql .= " t.content,"; 268 $sql .= " t.lang,"; 269 $sql .= " t.fk_page,"; 270 $sql .= " t.allowed_in_frames,"; 271 $sql .= " t.status,"; 272 $sql .= " t.grabbed_from,"; 273 $sql .= " t.date_creation,"; 274 $sql .= " t.tms as date_modification,"; 275 $sql .= " t.fk_user_creat,"; 276 $sql .= " t.author_alias,"; 277 $sql .= " t.fk_user_modif,"; 278 $sql .= " t.import_key,"; 279 $sql .= " t.object_type,"; 280 $sql .= " t.fk_object"; 281 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; 282 //$sql .= ' WHERE entity IN ('.getEntity('website').')'; // entity is on website level 283 $sql .= ' WHERE 1 = 1'; 284 if ($id > 0) 285 { 286 $sql .= ' AND t.rowid = '.$id; 287 } 288 else { 289 if ($id < 0) $sql .= ' AND t.rowid <> '.abs($id); 290 if (null !== $website_id) { 291 $sql .= " AND t.fk_website = '".$this->db->escape($website_id)."'"; 292 if ($page) { 293 $pagetouse = $page; 294 $langtouse = ''; 295 $tmppage = explode('/', $page); 296 if (!empty($tmppage[1])) { 297 $pagetouse = $tmppage[1]; 298 if (strlen($tmppage[0])) $langtouse = $tmppage[0]; 299 } 300 $sql .= " AND t.pageurl = '".$this->db->escape($pagetouse)."'"; 301 if ($langtouse) $sql .= " AND t.lang = '".$this->db->escape($langtouse)."'"; 302 } 303 if ($aliasalt) $sql .= " AND (t.aliasalt LIKE '%,".$this->db->escape($aliasalt).",%' OR t.aliasalt LIKE '%, ".$this->db->escape($aliasalt).",%')"; 304 } 305 } 306 $sql .= $this->db->plimit(1); 307 308 $resql = $this->db->query($sql); 309 if ($resql) { 310 $numrows = $this->db->num_rows($resql); 311 if ($numrows) { 312 $obj = $this->db->fetch_object($resql); 313 314 $this->id = $obj->rowid; 315 316 $this->fk_website = $obj->fk_website; 317 $this->type_container = $obj->type_container; 318 319 $this->pageurl = $obj->pageurl; 320 $this->ref = $obj->pageurl; 321 $this->aliasalt = preg_replace('/,+$/', '', preg_replace('/^,+/', '', $obj->aliasalt)); 322 323 $this->title = $obj->title; 324 $this->description = $obj->description; 325 $this->image = $obj->image; 326 $this->keywords = $obj->keywords; 327 $this->htmlheader = $obj->htmlheader; 328 $this->content = $obj->content; 329 $this->lang = $obj->lang; 330 $this->fk_page = $obj->fk_page; 331 $this->allowed_in_frames = $obj->allowed_in_frames; 332 $this->status = $obj->status; 333 $this->grabbed_from = $obj->grabbed_from; 334 $this->date_creation = $this->db->jdate($obj->date_creation); 335 $this->date_modification = $this->db->jdate($obj->date_modification); 336 $this->fk_user_creat = $obj->fk_user_creat; 337 $this->author_alias = $obj->author_alias; 338 $this->fk_user_modif = $obj->fk_user_modif; 339 $this->import_key = $obj->import_key; 340 $this->object_type = $obj->object_type; 341 $this->fk_object = $obj->fk_object; 342 } 343 $this->db->free($resql); 344 345 if ($numrows) { 346 return 1; 347 } else { 348 return 0; 349 } 350 } else { 351 $this->errors[] = 'Error '.$this->db->lasterror(); 352 dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); 353 354 return -1; 355 } 356 } 357 358 /** 359 * Return array of all web site pages. 360 * 361 * @param string $websiteid Web site 362 * @param string $sortorder Sort Order 363 * @param string $sortfield Sort field 364 * @param int $limit limit 365 * @param int $offset Offset 366 * @param array $filter Filter array 367 * @param string $filtermode Filter mode (AND or OR) 368 * @return array|int int <0 if KO, array of pages if OK 369 */ 370 public function fetchAll($websiteid, $sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') 371 { 372 dol_syslog(__METHOD__, LOG_DEBUG); 373 374 $records = array(); 375 376 $sql = 'SELECT'; 377 $sql .= ' t.rowid,'; 378 $sql .= " t.fk_website,"; 379 $sql .= " t.type_container,"; 380 $sql .= " t.pageurl,"; 381 $sql .= " t.aliasalt,"; 382 $sql .= " t.title,"; 383 $sql .= " t.description,"; 384 $sql .= " t.image,"; 385 $sql .= " t.keywords,"; 386 $sql .= " t.htmlheader,"; 387 $sql .= " t.content,"; 388 $sql .= " t.lang,"; 389 $sql .= " t.fk_page,"; 390 $sql .= " t.allowed_in_frames,"; 391 $sql .= " t.status,"; 392 $sql .= " t.grabbed_from,"; 393 $sql .= " t.date_creation,"; 394 $sql .= " t.tms as date_modification,"; 395 $sql .= " t.fk_user_creat,"; 396 $sql .= " t.author_alias,"; 397 $sql .= " t.fk_user_modif,"; 398 $sql .= " t.import_key,"; 399 $sql .= " t.object_type,"; 400 $sql .= " t.fk_object"; 401 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; 402 $sql .= ' WHERE t.fk_website = '.$websiteid; 403 // Manage filter (same than into countAll) 404 $sqlwhere = array(); 405 if (count($filter) > 0) { 406 foreach ($filter as $key => $value) { 407 if ($key == 't.rowid' || $key == 't.fk_website' || $key == 'status') { 408 $sqlwhere[] = $key.' = '.$value; 409 } elseif ($key == 'type_container') { 410 $sqlwhere[] = $key." = '".$this->db->escape($value)."'"; 411 } elseif ($key == 'lang' || $key == 't.lang') { 412 $listoflang = array(); 413 $foundnull = 0; 414 foreach (explode(',', $value) as $tmpvalue) { 415 if ($tmpvalue == 'null') { 416 $foundnull++; 417 continue; 418 } 419 $listoflang[] = "'".$this->db->escape(substr(str_replace("'", '', $tmpvalue), 0, 2))."'"; 420 } 421 $stringtouse = $key." IN (".join(',', $listoflang).")"; 422 if ($foundnull) $stringtouse = '('.$stringtouse.' OR '.$key.' IS NULL)'; 423 $sqlwhere[] = $stringtouse; 424 } else { 425 $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; 426 } 427 } 428 } 429 if (count($sqlwhere) > 0) { 430 $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; 431 } 432 433 if (!empty($sortfield)) { 434 $sql .= $this->db->order($sortfield, $sortorder); 435 } 436 if (!empty($limit)) { 437 $sql .= ' '.$this->db->plimit($limit, $offset); 438 } 439 440 $resql = $this->db->query($sql); 441 if ($resql) { 442 $num = $this->db->num_rows($resql); 443 444 while ($obj = $this->db->fetch_object($resql)) 445 { 446 $record = new self($this->db); 447 448 $record->id = $obj->rowid; 449 $record->fk_website = $obj->fk_website; 450 $record->type_container = $obj->type_container; 451 $record->pageurl = $obj->pageurl; 452 $record->aliasalt = preg_replace('/,+$/', '', preg_replace('/^,+/', '', $obj->aliasalt)); 453 $record->title = $obj->title; 454 $record->description = $obj->description; 455 $record->image = $obj->image; 456 $record->keywords = $obj->keywords; 457 $record->htmlheader = $obj->htmlheader; 458 $record->content = $obj->content; 459 $record->lang = $obj->lang; 460 $record->fk_page = $obj->fk_page; 461 $record->allowed_in_frames = $obj->allowed_in_frames; 462 $record->status = $obj->status; 463 $record->grabbed_from = $obj->grabbed_from; 464 $record->date_creation = $this->db->jdate($obj->date_creation); 465 $record->date_modification = $this->db->jdate($obj->date_modification); 466 $record->fk_user_creat = $obj->fk_user_creat; 467 $record->author_alias = $obj->author_alias; 468 $record->fk_user_modif = $obj->fk_user_modif; 469 $record->import_key = $obj->import_key; 470 $record->object_type = $obj->object_type; 471 $record->fk_object = $obj->fk_object; 472 //var_dump($record->id); 473 $records[$record->id] = $record; 474 } 475 $this->db->free($resql); 476 477 return $records; 478 } else { 479 $this->error = 'Error '.$this->db->lasterror(); 480 $this->errors[] = $this->error; 481 dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); 482 483 return -1; 484 } 485 } 486 487 /** 488 * Count objects in the database. 489 * 490 * @param string $websiteid Web site 491 * @param array $filter Filter array 492 * @param string $filtermode Filter mode (AND or OR) 493 * @return int int <0 if KO, array of pages if OK 494 */ 495 public function countAll($websiteid, array $filter = array(), $filtermode = 'AND') 496 { 497 dol_syslog(__METHOD__, LOG_DEBUG); 498 499 $result = 0; 500 501 $sql = 'SELECT COUNT(t.rowid) as nb'; 502 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; 503 $sql .= ' WHERE t.fk_website = '.$websiteid; 504 // Manage filter (same than into fetchAll) 505 $sqlwhere = array(); 506 if (count($filter) > 0) { 507 foreach ($filter as $key => $value) { 508 if ($key == 't.rowid' || $key == 't.fk_website' || $key == 'status') { 509 $sqlwhere[] = $key.' = '.$value; 510 } elseif ($key == 'type_container') { 511 $sqlwhere[] = $key." = '".$this->db->escape($value)."'"; 512 } elseif ($key == 'lang' || $key == 't.lang') { 513 $listoflang = array(); 514 $foundnull = 0; 515 foreach (explode(',', $value) as $tmpvalue) { 516 if ($tmpvalue == 'null') { 517 $foundnull++; 518 continue; 519 } 520 $listoflang[] = "'".$this->db->escape(substr(str_replace("'", '', $tmpvalue), 0, 2))."'"; 521 } 522 $stringtouse = $key." IN (".join(',', $listoflang).")"; 523 if ($foundnull) $stringtouse = '('.$stringtouse.' OR '.$key.' IS NULL)'; 524 $sqlwhere[] = $stringtouse; 525 } else { 526 $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; 527 } 528 } 529 } 530 if (count($sqlwhere) > 0) { 531 $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; 532 } 533 534 $resql = $this->db->query($sql); 535 if ($resql) { 536 $obj = $this->db->fetch_object($resql); 537 if ($obj) { 538 $result = $obj->nb; 539 } 540 541 $this->db->free($resql); 542 543 return $result; 544 } else { 545 $this->error = 'Error '.$this->db->lasterror(); 546 $this->errors[] = $this->error; 547 dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); 548 549 return -1; 550 } 551 } 552 553 /** 554 * Update object into database 555 * 556 * @param User $user User that modifies 557 * @param bool $notrigger false=launch triggers after, true=disable triggers 558 * @return int <0 if KO, >0 if OK 559 */ 560 public function update(User $user, $notrigger = false) 561 { 562 $this->description = dol_trunc($this->description, 255, 'right', 'utf-8', 1); 563 $this->keywords = dol_trunc($this->keywords, 255, 'right', 'utf-8', 1); 564 if ($this->aliasalt) $this->aliasalt = ','.preg_replace('/,+$/', '', preg_replace('/^,+/', '', $this->aliasalt)).','; // content in database must be ',xxx,...,yyy,' 565 566 // Remove spaces and be sure we have main language only 567 $this->lang = preg_replace('/[_-].*$/', '', trim($this->lang)); // en_US or en-US -> en 568 569 if ($this->fk_page > 0) { 570 if (empty($this->lang)) { 571 $this->error = "ErrorLanguageMandatoryIfPageSetAsTranslationOfAnother"; 572 return -1; 573 } 574 $tmppage = new WebsitePage($this->db); 575 $tmppage->fetch($this->fk_page); 576 if ($tmppage->lang == $this->lang) { 577 $this->error = "ErrorLanguageOfTranslatedPageIsSameThanThisPage"; 578 return -1; 579 } 580 } 581 582 return $this->updateCommon($user, $notrigger); 583 } 584 585 /** 586 * Delete object in database 587 * 588 * @param User $user User that deletes 589 * @param bool $notrigger false=launch triggers after, true=disable triggers 590 * @return int <0 if KO, >0 if OK 591 */ 592 public function delete(User $user, $notrigger = false) 593 { 594 $error = 0; 595 596 // Delete all child tables 597 if (!$error) { 598 foreach ($this->childtablesoncascade as $table) 599 { 600 $sql = "DELETE FROM ".MAIN_DB_PREFIX.$table; 601 $sql .= " WHERE fk_website_page = ".(int) $this->id; 602 603 $result = $this->db->query($sql); 604 if (!$result) { 605 $error++; 606 $this->errors[] = $this->db->lasterror(); 607 break; 608 } 609 } 610 } 611 612 if (!$error) { 613 $result = $this->deleteCommon($user, $trigger); 614 if ($result <= 0) 615 { 616 $error++; 617 } 618 } 619 620 if (!$error) 621 { 622 $websiteobj = new Website($this->db); 623 $result = $websiteobj->fetch($this->fk_website); 624 625 if ($result > 0) 626 { 627 global $dolibarr_main_data_root; 628 $pathofwebsite = $dolibarr_main_data_root.'/website/'.$websiteobj->ref; 629 630 $filealias = $pathofwebsite.'/'.$this->pageurl.'.php'; 631 $filetpl = $pathofwebsite.'/page'.$this->id.'.tpl.php'; 632 633 dol_delete_file($filealias); 634 dol_delete_file($filetpl); 635 } else { 636 $this->error = $websiteobj->error; 637 $this->errors = $websiteobj->errors; 638 } 639 } 640 641 if (!$error) { 642 return 1; 643 } else { 644 return -1; 645 } 646 } 647 648 /** 649 * Load an object from its id and create a new one in database 650 * 651 * @param User $user User making the clone 652 * @param int $fromid Id of object to clone 653 * @param string $newref New ref/alias of page 654 * @param string $newlang New language 655 * @param int $istranslation 1=New page is a translation of the cloned page. 656 * @param int $newwebsite 0=Same web site, >0=Id of new website 657 * @param string $newtitle New title 658 * @return mixed New object created, <0 if KO 659 */ 660 public function createFromClone(User $user, $fromid, $newref, $newlang = '', $istranslation = 0, $newwebsite = 0, $newtitle = '') 661 { 662 global $hookmanager, $langs; 663 664 $now = dol_now(); 665 $error = 0; 666 667 dol_syslog(__METHOD__, LOG_DEBUG); 668 669 $object = new self($this->db); 670 671 // Clean parameters 672 if (empty($newref) && !empty($newtitle)) { 673 $newref = strtolower(dol_sanitizeFileName(preg_replace('/\s+/', '-', $newtitle), '-', 1)); 674 } 675 676 // Check parameters 677 if (empty($newref)) { 678 $langs->load("errors"); 679 $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("WEBSITE_TITLE")); 680 return -1; 681 } 682 683 $this->db->begin(); 684 685 // Load source object 686 $object->fetch($fromid); 687 // Reset object 688 $object->id = 0; 689 690 // Clear fields 691 $object->ref = $newref; 692 $object->pageurl = $newref; 693 $object->aliasalt = ''; 694 $object->fk_user_creat = $user->id; 695 $object->author_alias = ''; 696 $object->date_creation = $now; 697 $object->title = ($newtitle == '1' ? $object->title : ($newtitle ? $newtitle : $object->title)); 698 $object->description = $object->title; 699 if (!empty($newlang)) $object->lang = $newlang; 700 if ($istranslation) $object->fk_page = $fromid; 701 else $object->fk_page = 0; 702 if (!empty($newwebsite)) $object->fk_website = $newwebsite; 703 $object->import_key = ''; 704 705 // Create clone 706 $object->context['createfromclone'] = 'createfromclone'; 707 $result = $object->create($user); 708 if ($result < 0) { 709 $error++; 710 $this->error = $object->error; 711 $this->errors = $object->errors; 712 dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); 713 } 714 715 unset($object->context['createfromclone']); 716 717 // End 718 if (!$error) { 719 $this->db->commit(); 720 721 return $object; 722 } else { 723 $this->db->rollback(); 724 725 return -1; 726 } 727 } 728 729 /** 730 * Return a link to the user card (with optionaly the picto) 731 * Use this->id,this->lastname, this->firstname 732 * 733 * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) 734 * @param string $option On what the link point to 735 * @param integer $notooltip 1=Disable tooltip 736 * @param int $maxlen Max length of visible user name 737 * @param string $morecss Add more css on link 738 * @return string String with URL 739 */ 740 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $maxlen = 24, $morecss = '') 741 { 742 global $langs, $conf, $db; 743 global $dolibarr_main_authentication, $dolibarr_main_demo; 744 global $menumanager; 745 746 $result = ''; 747 748 $label = '<u>'.$langs->trans("Page").'</u>'; 749 $label .= '<br>'; 750 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref.'<br>'; 751 $label .= '<b>'.$langs->trans('ID').':</b> '.$this->id.'<br>'; 752 $label .= '<b>'.$langs->trans('Title').':</b> '.$this->title.'<br>'; 753 $label .= '<b>'.$langs->trans('Language').':</b> '.$this->lang; 754 755 $url = DOL_URL_ROOT.'/website/index.php?websiteid='.$this->fk_website.'&pageid='.$this->id; 756 757 $linkclose = ''; 758 if (empty($notooltip)) 759 { 760 if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) 761 { 762 $label = $langs->trans("ShowMyObject"); 763 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; 764 } 765 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; 766 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; 767 } 768 else $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); 769 770 $linkstart = '<a href="'.$url.'"'; 771 $linkstart .= $linkclose.'>'; 772 $linkend = '</a>'; 773 774 //$linkstart = $linkend = ''; 775 776 $result .= $linkstart; 777 if ($withpicto) $result .= img_picto(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); 778 if ($withpicto != 2) $result .= $this->ref; 779 $result .= $linkend; 780 781 return $result; 782 } 783 784 /** 785 * Retourne le libelle du status d'un user (actif, inactif) 786 * 787 * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto 788 * @return string Label of status 789 */ 790 public function getLibStatut($mode = 0) 791 { 792 return $this->LibStatut($this->status, $mode); 793 } 794 795 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 796 /** 797 * Renvoi le libelle d'un status donne 798 * 799 * @param int $status Id status 800 * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto 801 * @return string Label of status 802 */ 803 public function LibStatut($status, $mode = 0) 804 { 805 // phpcs:enable 806 global $langs; 807 808 if (empty($this->labelStatus) || empty($this->labelStatusShort)) 809 { 810 global $langs; 811 //$langs->load("mymodule"); 812 $this->labelStatus[self::STATUS_DRAFT] = $langs->trans('Disabled'); 813 $this->labelStatus[self::STATUS_VALIDATED] = $langs->trans('Enabled'); 814 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans('Disabled'); 815 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans('Enabled'); 816 } 817 818 $statusType = 'status5'; 819 if ($status == self::STATUS_VALIDATED) $statusType = 'status4'; 820 821 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); 822 } 823 824 /** 825 * Sets object to given categories. 826 * 827 * Deletes object from existing categories not supplied. 828 * Adds it to non existing supplied categories. 829 * Existing categories are left untouch. 830 * 831 * @param int[]|int $categories Category ID or array of Categories IDs 832 * @return int <0 if KO, >0 if OK 833 */ 834 public function setCategories($categories) 835 { 836 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; 837 return $this->setCategoriesCommon($categories, Categorie::TYPE_WEBSITE_PAGE); 838 } 839 840 /** 841 * Initialise object with example values 842 * Id must be 0 if object instance is a specimen 843 * 844 * @return void 845 */ 846 public function initAsSpecimen() 847 { 848 global $user; 849 850 $this->id = 0; 851 852 $now = dol_now(); 853 854 $this->fk_website = ''; 855 $this->type_container = 'page'; 856 $this->pageurl = 'specimen'; 857 $this->aliasalt = 'specimenalt'; 858 $this->title = 'My Page'; 859 $this->description = 'This is my page'; 860 $this->image = ''; 861 $this->keywords = 'keyword1, keyword2'; 862 $this->allowed_in_frames = 1; 863 $this->htmlheader = ''; 864 $this->content = '<html><body>This is a html content</body></html>'; 865 $this->status = ''; 866 $this->grabbed_from = ''; 867 $this->date_creation = $now - (24 * 30 * 3600); 868 $this->date_modification = $now - (24 * 7 * 3600); 869 $this->fk_user_creat = $user->id; 870 $this->author_alias = 'mypublicpseudo'; 871 } 872} 873