websitepage.class.php 32 KB

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