websitepage.class.php 31 KB

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