website.class.php 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557
  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) 2018 Frédéric France <frederic.france@netlogic.fr>
  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/website.class.php
  23. * \ingroup website
  24. * \brief File for the CRUD class of website (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 Website
  32. */
  33. class Website extends CommonObject
  34. {
  35. /**
  36. * @var string Id to identify managed objects
  37. */
  38. public $element = 'website';
  39. /**
  40. * @var string Name of table without prefix where object is stored
  41. */
  42. public $table_element = 'website';
  43. /**
  44. * @var array Does website support multicompany module ? 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
  45. */
  46. public $ismultientitymanaged = 1;
  47. /**
  48. * @var string String with name of icon for website. Must be the part after the 'object_' into object_myobject.png
  49. */
  50. public $picto = 'globe';
  51. /**
  52. * @var int Entity
  53. */
  54. public $entity;
  55. /**
  56. * @var string Ref
  57. */
  58. public $ref;
  59. /**
  60. * @var string description
  61. */
  62. public $description;
  63. /**
  64. * @var string Main language of web site
  65. */
  66. public $lang;
  67. /**
  68. * @var string List of languages of web site ('fr', 'es_MX', ...)
  69. */
  70. public $otherlang;
  71. /**
  72. * @var int Status
  73. */
  74. public $status;
  75. /**
  76. * @var integer|string date_creation
  77. */
  78. public $date_creation;
  79. /**
  80. * @var integer|string date_modification
  81. */
  82. public $date_modification;
  83. /**
  84. * @var integer
  85. */
  86. public $fk_default_home;
  87. /**
  88. * @var int User Create Id
  89. */
  90. public $fk_user_creat;
  91. /**
  92. * @var string
  93. */
  94. public $virtualhost;
  95. /**
  96. * @var int
  97. */
  98. public $use_manifest;
  99. /**
  100. * @var int
  101. */
  102. public $position;
  103. /**
  104. * List of containers
  105. *
  106. * @var array
  107. */
  108. public $lines;
  109. const STATUS_DRAFT = 0;
  110. const STATUS_VALIDATED = 1;
  111. /**
  112. * Constructor
  113. *
  114. * @param DoliDb $db Database handler
  115. */
  116. public function __construct(DoliDB $db)
  117. {
  118. $this->db = $db;
  119. return 1;
  120. }
  121. /**
  122. * Create object into database
  123. *
  124. * @param User $user User that creates
  125. * @param bool $notrigger false=launch triggers after, true=disable triggers
  126. *
  127. * @return int <0 if KO, Id of created object if OK
  128. */
  129. public function create(User $user, $notrigger = false)
  130. {
  131. global $conf, $langs;
  132. dol_syslog(__METHOD__, LOG_DEBUG);
  133. $error = 0;
  134. $now = dol_now();
  135. // Clean parameters
  136. if (isset($this->entity)) {
  137. $this->entity = (int) $this->entity;
  138. }
  139. if (isset($this->ref)) {
  140. $this->ref = trim($this->ref);
  141. }
  142. if (isset($this->description)) {
  143. $this->description = trim($this->description);
  144. }
  145. if (isset($this->status)) {
  146. $this->status = (int) $this->status;
  147. }
  148. if (empty($this->date_creation)) {
  149. $this->date_creation = $now;
  150. }
  151. if (empty($this->date_modification)) {
  152. $this->date_modification = $now;
  153. }
  154. // Remove spaces and be sure we have main language only
  155. $this->lang = preg_replace('/[_-].*$/', '', trim($this->lang)); // en_US or en-US -> en
  156. $tmparray = explode(',', $this->otherlang);
  157. if (is_array($tmparray)) {
  158. foreach ($tmparray as $key => $val) {
  159. // It possible we have empty val here if postparam WEBSITE_OTHERLANG is empty or set like this : 'en,,sv' or 'en,sv,'
  160. if (empty(trim($val))) {
  161. unset($tmparray[$key]);
  162. continue;
  163. }
  164. $tmparray[$key] = preg_replace('/[_-].*$/', '', trim($val)); // en_US or en-US -> en
  165. }
  166. $this->otherlang = join(',', $tmparray);
  167. }
  168. // Check parameters
  169. if (empty($this->entity)) {
  170. $this->entity = $conf->entity;
  171. }
  172. if (empty($this->lang)) {
  173. $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("MainLanguage"));
  174. return -1;
  175. }
  176. // Insert request
  177. $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.'(';
  178. $sql .= 'entity,';
  179. $sql .= 'ref,';
  180. $sql .= 'description,';
  181. $sql .= 'lang,';
  182. $sql .= 'otherlang,';
  183. $sql .= 'status,';
  184. $sql .= 'fk_default_home,';
  185. $sql .= 'virtualhost,';
  186. $sql .= 'fk_user_creat,';
  187. $sql .= 'date_creation,';
  188. $sql .= 'position,';
  189. $sql .= 'tms';
  190. $sql .= ') VALUES (';
  191. $sql .= ' '.((empty($this->entity) && $this->entity != '0') ? 'NULL' : $this->entity).',';
  192. $sql .= ' '.(!isset($this->ref) ? 'NULL' : "'".$this->db->escape($this->ref)."'").',';
  193. $sql .= ' '.(!isset($this->description) ? 'NULL' : "'".$this->db->escape($this->description)."'").',';
  194. $sql .= ' '.(!isset($this->lang) ? 'NULL' : "'".$this->db->escape($this->lang)."'").',';
  195. $sql .= ' '.(!isset($this->otherlang) ? 'NULL' : "'".$this->db->escape($this->otherlang)."'").',';
  196. $sql .= ' '.(!isset($this->status) ? '1' : $this->status).',';
  197. $sql .= ' '.(!isset($this->fk_default_home) ? 'NULL' : $this->fk_default_home).',';
  198. $sql .= ' '.(!isset($this->virtualhost) ? 'NULL' : "'".$this->db->escape($this->virtualhost)."'").",";
  199. $sql .= ' '.(!isset($this->fk_user_creat) ? $user->id : $this->fk_user_creat).',';
  200. $sql .= ' '.(!isset($this->date_creation) || dol_strlen($this->date_creation) == 0 ? 'NULL' : "'".$this->db->idate($this->date_creation)."'").",";
  201. $sql .= ' '.((int) $this->position).",";
  202. $sql .= ' '.(!isset($this->date_modification) || dol_strlen($this->date_modification) == 0 ? 'NULL' : "'".$this->db->idate($this->date_modification)."'");
  203. $sql .= ')';
  204. $this->db->begin();
  205. $resql = $this->db->query($sql);
  206. if (!$resql) {
  207. $error++;
  208. $this->errors[] = 'Error '.$this->db->lasterror();
  209. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  210. }
  211. if (!$error) {
  212. $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
  213. // Create subdirectory per language
  214. $tmplangarray = explode(',', $this->otherlang);
  215. if (is_array($tmplangarray)) {
  216. dol_mkdir($conf->website->dir_output.'/'.$this->ref);
  217. foreach ($tmplangarray as $val) {
  218. if (trim($val) == $this->lang) {
  219. continue;
  220. }
  221. dol_mkdir($conf->website->dir_output.'/'.$this->ref.'/'.trim($val));
  222. }
  223. }
  224. // Uncomment this and change MYOBJECT to your own tag if you
  225. // want this action to call a trigger.
  226. // if (!$notrigger) {
  227. // // Call triggers
  228. // $result = $this->call_trigger('MYOBJECT_CREATE',$user);
  229. // if ($result < 0) $error++;
  230. // // End call triggers
  231. // }
  232. }
  233. if (!$error) {
  234. $stringtodolibarrfile = "# Some properties for Dolibarr web site CMS\n";
  235. $stringtodolibarrfile .= "param=value\n";
  236. //print $conf->website->dir_output.'/'.$this->ref.'/.dolibarr';exit;
  237. file_put_contents($conf->website->dir_output.'/'.$this->ref.'/.dolibarr', $stringtodolibarrfile);
  238. }
  239. // Commit or rollback
  240. if ($error) {
  241. $this->db->rollback();
  242. return -1 * $error;
  243. } else {
  244. $this->db->commit();
  245. return $this->id;
  246. }
  247. }
  248. /**
  249. * Load object in memory from the database
  250. *
  251. * @param int $id Id object
  252. * @param string $ref Ref
  253. * @return int <0 if KO, 0 if not found, >0 if OK
  254. */
  255. public function fetch($id, $ref = null)
  256. {
  257. dol_syslog(__METHOD__, LOG_DEBUG);
  258. $sql = 'SELECT';
  259. $sql .= ' t.rowid,';
  260. $sql .= " t.entity,";
  261. $sql .= " t.ref,";
  262. $sql .= " t.position,";
  263. $sql .= " t.description,";
  264. $sql .= " t.lang,";
  265. $sql .= " t.otherlang,";
  266. $sql .= " t.status,";
  267. $sql .= " t.fk_default_home,";
  268. $sql .= " t.use_manifest,";
  269. $sql .= " t.virtualhost,";
  270. $sql .= " t.fk_user_creat,";
  271. $sql .= " t.fk_user_modif,";
  272. $sql .= " t.date_creation,";
  273. $sql .= " t.tms as date_modification";
  274. $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
  275. $sql .= ' WHERE t.entity IN ('.getEntity('website').')';
  276. if (!empty($ref)) {
  277. $sql .= " AND t.ref = '".$this->db->escape($ref)."'";
  278. } else {
  279. $sql .= ' AND t.rowid = '.(int) $id;
  280. }
  281. $resql = $this->db->query($sql);
  282. if ($resql) {
  283. $numrows = $this->db->num_rows($resql);
  284. if ($numrows) {
  285. $obj = $this->db->fetch_object($resql);
  286. $this->id = $obj->rowid;
  287. $this->entity = $obj->entity;
  288. $this->ref = $obj->ref;
  289. $this->position = $obj->position;
  290. $this->description = $obj->description;
  291. $this->lang = $obj->lang;
  292. $this->otherlang = $obj->otherlang;
  293. $this->status = $obj->status;
  294. $this->fk_default_home = $obj->fk_default_home;
  295. $this->virtualhost = $obj->virtualhost;
  296. $this->use_manifest = $obj->use_manifest;
  297. $this->fk_user_creat = $obj->fk_user_creat;
  298. $this->fk_user_modif = $obj->fk_user_modif;
  299. $this->date_creation = $this->db->jdate($obj->date_creation);
  300. $this->date_modification = $this->db->jdate($obj->date_modification);
  301. }
  302. $this->db->free($resql);
  303. if ($numrows > 0) {
  304. // Lines
  305. $this->fetchLines();
  306. }
  307. if ($numrows > 0) {
  308. return 1;
  309. } else {
  310. return 0;
  311. }
  312. } else {
  313. $this->errors[] = 'Error '.$this->db->lasterror();
  314. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  315. return -1;
  316. }
  317. }
  318. /**
  319. * Load object lines in memory from the database
  320. *
  321. * @return int <0 if KO, 0 if not found, >0 if OK
  322. */
  323. public function fetchLines()
  324. {
  325. $this->lines = array();
  326. // Load lines with object MyObjectLine
  327. return count($this->lines) ? 1 : 0;
  328. }
  329. /**
  330. * Load all object in memory ($this->records) from the database
  331. *
  332. * @param string $sortorder Sort Order
  333. * @param string $sortfield Sort field
  334. * @param int $limit offset limit
  335. * @param int $offset offset limit
  336. * @param array $filter filter array
  337. * @param string $filtermode filter mode (AND or OR)
  338. *
  339. * @return int <0 if KO, >0 if OK
  340. */
  341. public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
  342. {
  343. dol_syslog(__METHOD__, LOG_DEBUG);
  344. $sql = 'SELECT';
  345. $sql .= ' t.rowid,';
  346. $sql .= " t.entity,";
  347. $sql .= " t.ref,";
  348. $sql .= " t.description,";
  349. $sql .= " t.lang,";
  350. $sql .= " t.otherlang,";
  351. $sql .= " t.status,";
  352. $sql .= " t.fk_default_home,";
  353. $sql .= " t.virtualhost,";
  354. $sql .= " t.fk_user_creat,";
  355. $sql .= " t.fk_user_modif,";
  356. $sql .= " t.date_creation,";
  357. $sql .= " t.tms as date_modification";
  358. $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
  359. $sql .= ' WHERE t.entity IN ('.getEntity('website').')';
  360. // Manage filter
  361. $sqlwhere = array();
  362. if (count($filter) > 0) {
  363. foreach ($filter as $key => $value) {
  364. $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'";
  365. }
  366. }
  367. if (count($sqlwhere) > 0) {
  368. $sql .= ' AND '.implode(' '.$filtermode.' ', $sqlwhere);
  369. }
  370. if (!empty($sortfield)) {
  371. $sql .= $this->db->order($sortfield, $sortorder);
  372. }
  373. if (!empty($limit)) {
  374. $sql .= $this->db->plimit($limit, $offset);
  375. }
  376. $this->records = array();
  377. $resql = $this->db->query($sql);
  378. if ($resql) {
  379. $num = $this->db->num_rows($resql);
  380. while ($obj = $this->db->fetch_object($resql)) {
  381. $line = new self($this->db);
  382. $line->id = $obj->rowid;
  383. $line->entity = $obj->entity;
  384. $line->ref = $obj->ref;
  385. $line->description = $obj->description;
  386. $line->lang = $obj->lang;
  387. $line->otherlang = $obj->otherlang;
  388. $line->status = $obj->status;
  389. $line->fk_default_home = $obj->fk_default_home;
  390. $line->virtualhost = $obj->virtualhost;
  391. $this->fk_user_creat = $obj->fk_user_creat;
  392. $this->fk_user_modif = $obj->fk_user_modif;
  393. $line->date_creation = $this->db->jdate($obj->date_creation);
  394. $line->date_modification = $this->db->jdate($obj->date_modification);
  395. $this->records[$line->id] = $line;
  396. }
  397. $this->db->free($resql);
  398. return $num;
  399. } else {
  400. $this->errors[] = 'Error '.$this->db->lasterror();
  401. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  402. return -1;
  403. }
  404. }
  405. /**
  406. * Update object into database
  407. *
  408. * @param User $user User that modifies
  409. * @param bool $notrigger false=launch triggers after, true=disable triggers
  410. *
  411. * @return int <0 if KO, >0 if OK
  412. */
  413. public function update(User $user, $notrigger = false)
  414. {
  415. global $conf, $langs;
  416. $error = 0;
  417. dol_syslog(__METHOD__, LOG_DEBUG);
  418. // Clean parameters
  419. if (isset($this->entity)) {
  420. $this->entity = (int) $this->entity;
  421. }
  422. if (isset($this->ref)) {
  423. $this->ref = trim($this->ref);
  424. }
  425. if (isset($this->description)) {
  426. $this->description = trim($this->description);
  427. }
  428. if (isset($this->status)) {
  429. $this->status = (int) $this->status;
  430. }
  431. // Remove spaces and be sure we have main language only
  432. $this->lang = preg_replace('/[_-].*$/', '', trim($this->lang)); // en_US or en-US -> en
  433. $tmparray = explode(',', $this->otherlang);
  434. if (is_array($tmparray)) {
  435. foreach ($tmparray as $key => $val) {
  436. // It possible we have empty val here if postparam WEBSITE_OTHERLANG is empty or set like this : 'en,,sv' or 'en,sv,'
  437. if (empty(trim($val))) {
  438. unset($tmparray[$key]);
  439. continue;
  440. }
  441. $tmparray[$key] = preg_replace('/[_-].*$/', '', trim($val)); // en_US or en-US -> en
  442. }
  443. $this->otherlang = join(',', $tmparray);
  444. }
  445. if (empty($this->lang)) {
  446. $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("MainLanguage"));
  447. return -1;
  448. }
  449. // Check parameters
  450. // Put here code to add a control on parameters values
  451. // Update request
  452. $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET';
  453. $sql .= ' entity = '.(isset($this->entity) ? $this->entity : "null").',';
  454. $sql .= ' ref = '.(isset($this->ref) ? "'".$this->db->escape($this->ref)."'" : "null").',';
  455. $sql .= ' description = '.(isset($this->description) ? "'".$this->db->escape($this->description)."'" : "null").',';
  456. $sql .= ' lang = '.(isset($this->lang) ? "'".$this->db->escape($this->lang)."'" : "null").',';
  457. $sql .= ' otherlang = '.(isset($this->otherlang) ? "'".$this->db->escape($this->otherlang)."'" : "null").',';
  458. $sql .= ' status = '.(isset($this->status) ? $this->status : "null").',';
  459. $sql .= ' fk_default_home = '.(($this->fk_default_home > 0) ? $this->fk_default_home : "null").',';
  460. $sql .= ' use_manifest = '.((int) $this->use_manifest).',';
  461. $sql .= ' virtualhost = '.(($this->virtualhost != '') ? "'".$this->db->escape($this->virtualhost)."'" : "null").',';
  462. $sql .= ' fk_user_modif = '.(!isset($this->fk_user_modif) ? $user->id : $this->fk_user_modif).',';
  463. $sql .= ' date_creation = '.(!isset($this->date_creation) || dol_strlen($this->date_creation) != 0 ? "'".$this->db->idate($this->date_creation)."'" : 'null').',';
  464. $sql .= ' tms = '.(dol_strlen($this->date_modification) != 0 ? "'".$this->db->idate($this->date_modification)."'" : "'".$this->db->idate(dol_now())."'");
  465. $sql .= ' WHERE rowid='.((int) $this->id);
  466. $this->db->begin();
  467. $resql = $this->db->query($sql);
  468. if (!$resql) {
  469. $error++;
  470. $this->errors[] = 'Error '.$this->db->lasterror();
  471. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  472. }
  473. if (!$error && !$notrigger) {
  474. // Uncomment this and change MYOBJECT to your own tag if you
  475. // want this action calls a trigger.
  476. // Create subdirectory per language
  477. $tmplangarray = explode(',', $this->otherlang);
  478. if (is_array($tmplangarray)) {
  479. dol_mkdir($conf->website->dir_output.'/'.$this->ref);
  480. foreach ($tmplangarray as $val) {
  481. if (trim($val) == $this->lang) {
  482. continue;
  483. }
  484. dol_mkdir($conf->website->dir_output.'/'.$this->ref.'/'.trim($val));
  485. }
  486. }
  487. //// Call triggers
  488. //$result=$this->call_trigger('MYOBJECT_MODIFY',$user);
  489. //if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
  490. //// End call triggers
  491. }
  492. // Commit or rollback
  493. if ($error) {
  494. $this->db->rollback();
  495. return -1 * $error;
  496. } else {
  497. $this->db->commit();
  498. return 1;
  499. }
  500. }
  501. /**
  502. * Delete object in database
  503. *
  504. * @param User $user User that deletes
  505. * @param bool $notrigger false=launch triggers after, true=disable triggers
  506. *
  507. * @return int <0 if KO, >0 if OK
  508. */
  509. public function delete(User $user, $notrigger = false)
  510. {
  511. dol_syslog(__METHOD__, LOG_DEBUG);
  512. $error = 0;
  513. $this->db->begin();
  514. if (!$error) {
  515. if (!$notrigger) {
  516. // Uncomment this and change MYOBJECT to your own tag if you
  517. // want this action calls a trigger.
  518. //// Call triggers
  519. //$result=$this->call_trigger('MYOBJECT_DELETE',$user);
  520. //if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
  521. //// End call triggers
  522. }
  523. }
  524. if (!$error) {
  525. $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element;
  526. $sql .= ' WHERE rowid='.((int) $this->id);
  527. $resql = $this->db->query($sql);
  528. if (!$resql) {
  529. $error++;
  530. $this->errors[] = 'Error '.$this->db->lasterror();
  531. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  532. }
  533. }
  534. if (!$error && !empty($this->ref)) {
  535. $pathofwebsite = DOL_DATA_ROOT.'/website/'.$this->ref;
  536. dol_delete_dir_recursive($pathofwebsite);
  537. }
  538. // Commit or rollback
  539. if ($error) {
  540. $this->db->rollback();
  541. return -1 * $error;
  542. } else {
  543. $this->db->commit();
  544. return 1;
  545. }
  546. }
  547. /**
  548. * Load a website its id and create a new one in database.
  549. * This copy website directories, regenerate all the pages + alias pages and recreate the medias link.
  550. *
  551. * @param User $user User making the clone
  552. * @param int $fromid Id of object to clone
  553. * @param string $newref New ref
  554. * @param string $newlang New language
  555. * @return mixed New object created, <0 if KO
  556. */
  557. public function createFromClone($user, $fromid, $newref, $newlang = '')
  558. {
  559. global $conf, $langs;
  560. global $dolibarr_main_data_root;
  561. $now = dol_now();
  562. $error = 0;
  563. dol_syslog(__METHOD__, LOG_DEBUG);
  564. $object = new self($this->db);
  565. // Check no site with ref exists
  566. if ($object->fetch(0, $newref) > 0) {
  567. $this->error = 'ErrorNewRefIsAlreadyUsed';
  568. return -1;
  569. }
  570. $this->db->begin();
  571. // Load source object
  572. $object->fetch($fromid);
  573. $oldidforhome = $object->fk_default_home;
  574. $oldref = $object->ref;
  575. $pathofwebsiteold = $dolibarr_main_data_root.'/website/'.$oldref;
  576. $pathofwebsitenew = $dolibarr_main_data_root.'/website/'.$newref;
  577. dol_delete_dir_recursive($pathofwebsitenew);
  578. $fileindex = $pathofwebsitenew.'/index.php';
  579. // Reset some properties
  580. unset($object->id);
  581. unset($object->fk_user_creat);
  582. unset($object->import_key);
  583. // Clear fields
  584. $object->ref = $newref;
  585. $object->fk_default_home = 0;
  586. $object->virtualhost = '';
  587. $object->date_creation = $now;
  588. $object->fk_user_creat = $user->id;
  589. $object->position = ((int) $object->position) + 1;
  590. $object->status = self::STATUS_DRAFT;
  591. if (empty($object->lang)) {
  592. $object->lang = substr($langs->defaultlang, 0, 2); // Should not happen. Protection for corrupted site with no languages
  593. }
  594. // Create clone
  595. $object->context['createfromclone'] = 'createfromclone';
  596. $result = $object->create($user);
  597. if ($result < 0) {
  598. $error++;
  599. $this->error = $object->error;
  600. $this->errors = $object->errors;
  601. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  602. }
  603. if (!$error) {
  604. dolCopyDir($pathofwebsiteold, $pathofwebsitenew, $conf->global->MAIN_UMASK, 0, null, 2);
  605. // Check symlink to medias and restore it if ko
  606. $pathtomedias = DOL_DATA_ROOT.'/medias'; // Target
  607. $pathtomediasinwebsite = $pathofwebsitenew.'/medias'; // Source / Link name
  608. if (!is_link(dol_osencode($pathtomediasinwebsite))) {
  609. dol_syslog("Create symlink for ".$pathtomedias." into name ".$pathtomediasinwebsite);
  610. dol_mkdir(dirname($pathtomediasinwebsite)); // To be sure dir for website exists
  611. $result = symlink($pathtomedias, $pathtomediasinwebsite);
  612. }
  613. // Copy images and js dir
  614. $pathofmediasjsold = DOL_DATA_ROOT.'/medias/js/'.$oldref;
  615. $pathofmediasjsnew = DOL_DATA_ROOT.'/medias/js/'.$newref;
  616. dolCopyDir($pathofmediasjsold, $pathofmediasjsnew, $conf->global->MAIN_UMASK, 0);
  617. $pathofmediasimageold = DOL_DATA_ROOT.'/medias/image/'.$oldref;
  618. $pathofmediasimagenew = DOL_DATA_ROOT.'/medias/image/'.$newref;
  619. dolCopyDir($pathofmediasimageold, $pathofmediasimagenew, $conf->global->MAIN_UMASK, 0);
  620. $newidforhome = 0;
  621. // Duplicate pages
  622. $objectpages = new WebsitePage($this->db);
  623. $listofpages = $objectpages->fetchAll($fromid);
  624. foreach ($listofpages as $pageid => $objectpageold) {
  625. // Delete old file
  626. $filetplold = $pathofwebsitenew.'/page'.$pageid.'.tpl.php';
  627. dol_delete_file($filetplold);
  628. // Create new file
  629. $objectpagenew = $objectpageold->createFromClone($user, $pageid, $objectpageold->pageurl, '', 0, $object->id, 1);
  630. //print $pageid.' = '.$objectpageold->pageurl.' -> '.$objectpagenew->id.' = '.$objectpagenew->pageurl.'<br>';
  631. if (is_object($objectpagenew) && $objectpagenew->pageurl) {
  632. $filealias = $pathofwebsitenew.'/'.$objectpagenew->pageurl.'.php';
  633. $filetplnew = $pathofwebsitenew.'/page'.$objectpagenew->id.'.tpl.php';
  634. // Save page alias
  635. $result = dolSavePageAlias($filealias, $object, $objectpagenew);
  636. if (!$result) {
  637. setEventMessages('Failed to write file '.$filealias, null, 'errors');
  638. }
  639. $result = dolSavePageContent($filetplnew, $object, $objectpagenew);
  640. if (!$result) {
  641. setEventMessages('Failed to write file '.$filetplnew, null, 'errors');
  642. }
  643. if ($pageid == $oldidforhome) {
  644. $newidforhome = $objectpagenew->id;
  645. }
  646. } else {
  647. setEventMessages($objectpageold->error, $objectpageold->errors, 'errors');
  648. $error++;
  649. }
  650. }
  651. }
  652. if (!$error) {
  653. // Restore id of home page
  654. $object->fk_default_home = $newidforhome;
  655. $res = $object->update($user);
  656. if (!($res > 0)) {
  657. $error++;
  658. setEventMessages($object->error, $object->errors, 'errors');
  659. }
  660. if (!$error) {
  661. $filetpl = $pathofwebsitenew.'/page'.$newidforhome.'.tpl.php';
  662. $filewrapper = $pathofwebsitenew.'/wrapper.php';
  663. // Re-generates the index.php page to be the home page, and re-generates the wrapper.php
  664. //--------------------------------------------------------------------------------------
  665. $result = dolSaveIndexPage($pathofwebsitenew, $fileindex, $filetpl, $filewrapper);
  666. }
  667. }
  668. unset($object->context['createfromclone']);
  669. // End
  670. if (!$error) {
  671. $this->db->commit();
  672. return $object;
  673. } else {
  674. $this->db->rollback();
  675. return -1;
  676. }
  677. }
  678. /**
  679. * Return a link to the user card (with optionally the picto)
  680. * Use this->id,this->lastname, this->firstname
  681. *
  682. * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
  683. * @param string $option On what the link point to
  684. * @param integer $notooltip 1=Disable tooltip
  685. * @param int $maxlen Max length of visible user name
  686. * @param string $morecss Add more css on link
  687. * @return string String with URL
  688. */
  689. public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $maxlen = 24, $morecss = '')
  690. {
  691. global $langs, $conf, $db;
  692. global $dolibarr_main_authentication, $dolibarr_main_demo;
  693. global $menumanager;
  694. $result = '';
  695. $companylink = '';
  696. $label = '<u>'.$langs->trans("WebSite").'</u>';
  697. $label .= '<br>';
  698. $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref.'<br>';
  699. $label .= '<b>'.$langs->trans('MainLanguage').':</b> '.$this->lang;
  700. $linkstart = '<a href="'.DOL_URL_ROOT.'/website/card.php?id='.$this->id.'"';
  701. $linkstart .= ($notooltip ? '' : ' title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip'.($morecss ? ' '.$morecss : '').'"');
  702. $linkstart .= '>';
  703. $linkend = '</a>';
  704. $linkstart = $linkend = '';
  705. if ($withpicto) {
  706. $result .= ($linkstart.img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? '' : 'class="classfortooltip"')).$linkend);
  707. if ($withpicto != 2) {
  708. $result .= ' ';
  709. }
  710. }
  711. $result .= $linkstart.$this->ref.$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. * Initialise object with example values
  752. * Id must be 0 if object instance is a specimen
  753. *
  754. * @return void
  755. */
  756. public function initAsSpecimen()
  757. {
  758. global $user;
  759. $this->id = 0;
  760. $this->specimen = 1;
  761. $this->entity = 1;
  762. $this->ref = 'myspecimenwebsite';
  763. $this->description = 'A specimen website';
  764. $this->lang = 'en';
  765. $this->otherlang = 'fr,es';
  766. $this->status = 1;
  767. $this->fk_default_home = null;
  768. $this->virtualhost = 'http://myvirtualhost';
  769. $this->fk_user_creat = $user->id;
  770. $this->fk_user_modif = $user->id;
  771. $this->date_creation = dol_now();
  772. $this->tms = dol_now();
  773. }
  774. /**
  775. * Generate a zip with all data of web site.
  776. *
  777. * @return string Path to file with zip or '' if error
  778. */
  779. public function exportWebSite()
  780. {
  781. global $conf, $mysoc;
  782. $website = $this;
  783. if (empty($website->id) || empty($website->ref)) {
  784. setEventMessages("Website id or ref is not defined", null, 'errors');
  785. return '';
  786. }
  787. dol_syslog("Create temp dir ".$conf->website->dir_temp);
  788. dol_mkdir($conf->website->dir_temp);
  789. if (!is_writable($conf->website->dir_temp)) {
  790. setEventMessages("Temporary dir ".$conf->website->dir_temp." is not writable", null, 'errors');
  791. return '';
  792. }
  793. $destdir = $conf->website->dir_temp.'/'.$website->ref;
  794. dol_syslog("Clear temp dir ".$destdir);
  795. $count = 0; $countreallydeleted = 0;
  796. $counttodelete = dol_delete_dir_recursive($destdir, $count, 1, 0, $countreallydeleted);
  797. if ($counttodelete != $countreallydeleted) {
  798. setEventMessages("Failed to clean temp directory ".$destdir, null, 'errors');
  799. return '';
  800. }
  801. $arrayreplacementinfilename = array();
  802. $arrayreplacementincss = array();
  803. $arrayreplacementincss['file=image/'.$website->ref.'/'] = "file=image/__WEBSITE_KEY__/";
  804. $arrayreplacementincss['file=js/'.$website->ref.'/'] = "file=js/__WEBSITE_KEY__/";
  805. $arrayreplacementincss['medias/image/'.$website->ref.'/'] = "medias/image/__WEBSITE_KEY__/";
  806. $arrayreplacementincss['medias/js/'.$website->ref.'/'] = "medias/js/__WEBSITE_KEY__/";
  807. if ($mysoc->logo_small) {
  808. $arrayreplacementincss['file=logos%2Fthumbs%2F'.$mysoc->logo_small] = "file=logos%2Fthumbs%2F__LOGO_SMALL_KEY__";
  809. }
  810. if ($mysoc->logo_mini) {
  811. $arrayreplacementincss['file=logos%2Fthumbs%2F'.$mysoc->logo_mini] = "file=logos%2Fthumbs%2F__LOGO_MINI_KEY__";
  812. }
  813. if ($mysoc->logo) {
  814. $arrayreplacementincss['file=logos%2Fthumbs%2F'.$mysoc->logo] = "file=logos%2Fthumbs%2F__LOGO_KEY__";
  815. }
  816. // Create output directories
  817. dol_syslog("Create containers dir");
  818. dol_mkdir($conf->website->dir_temp.'/'.$website->ref.'/containers');
  819. dol_mkdir($conf->website->dir_temp.'/'.$website->ref.'/medias/image/websitekey');
  820. dol_mkdir($conf->website->dir_temp.'/'.$website->ref.'/medias/js/websitekey');
  821. // Copy files into 'containers'
  822. $srcdir = $conf->website->dir_output.'/'.$website->ref;
  823. $destdir = $conf->website->dir_temp.'/'.$website->ref.'/containers';
  824. dol_syslog("Copy content from ".$srcdir." into ".$destdir);
  825. dolCopyDir($srcdir, $destdir, 0, 1, $arrayreplacementinfilename, 2);
  826. // Copy files into medias/image
  827. $srcdir = DOL_DATA_ROOT.'/medias/image/'.$website->ref;
  828. $destdir = $conf->website->dir_temp.'/'.$website->ref.'/medias/image/websitekey';
  829. dol_syslog("Copy content from ".$srcdir." into ".$destdir);
  830. dolCopyDir($srcdir, $destdir, 0, 1, $arrayreplacementinfilename);
  831. // Copy files into medias/js
  832. $srcdir = DOL_DATA_ROOT.'/medias/js/'.$website->ref;
  833. $destdir = $conf->website->dir_temp.'/'.$website->ref.'/medias/js/websitekey';
  834. dol_syslog("Copy content from ".$srcdir." into ".$destdir);
  835. dolCopyDir($srcdir, $destdir, 0, 1, $arrayreplacementinfilename);
  836. // Make some replacement into some files
  837. $cssindestdir = $conf->website->dir_temp.'/'.$website->ref.'/containers/styles.css.php';
  838. dolReplaceInFile($cssindestdir, $arrayreplacementincss);
  839. $htmldeaderindestdir = $conf->website->dir_temp.'/'.$website->ref.'/containers/htmlheader.html';
  840. dolReplaceInFile($htmldeaderindestdir, $arrayreplacementincss);
  841. // Build sql file
  842. $filesql = $conf->website->dir_temp.'/'.$website->ref.'/website_pages.sql';
  843. $fp = fopen($filesql, "w");
  844. if (empty($fp)) {
  845. setEventMessages("Failed to create file ".$filesql, null, 'errors');
  846. return '';
  847. }
  848. $objectpages = new WebsitePage($this->db);
  849. $listofpages = $objectpages->fetchAll($website->id);
  850. // Assign ->newid and ->newfk_page
  851. $i = 1;
  852. foreach ($listofpages as $pageid => $objectpageold) {
  853. $objectpageold->newid = $i;
  854. $i++;
  855. }
  856. $i = 1;
  857. foreach ($listofpages as $pageid => $objectpageold) {
  858. // Search newid
  859. $newfk_page = 0;
  860. foreach ($listofpages as $pageid2 => $objectpageold2) {
  861. if ($pageid2 == $objectpageold->fk_page) {
  862. $newfk_page = $objectpageold2->newid;
  863. break;
  864. }
  865. }
  866. $objectpageold->newfk_page = $newfk_page;
  867. $i++;
  868. }
  869. foreach ($listofpages as $pageid => $objectpageold) {
  870. $allaliases = $objectpageold->pageurl;
  871. $allaliases .= ($objectpageold->aliasalt ? ','.$objectpageold->aliasalt : '');
  872. $line = '-- Page ID '.$objectpageold->id.' -> '.$objectpageold->newid.'__+MAX_llx_website_page__ - Aliases '.$allaliases.' --;'; // newid start at 1, 2...
  873. $line .= "\n";
  874. fputs($fp, $line);
  875. // Warning: We must keep llx_ here. It is a generic SQL.
  876. $line = 'INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, aliasalt, title, description, lang, image, keywords, status, date_creation, tms, import_key, grabbed_from, type_container, htmlheader, content, author_alias)';
  877. $line .= " VALUES(";
  878. $line .= $objectpageold->newid."__+MAX_llx_website_page__, ";
  879. $line .= ($objectpageold->newfk_page ? $this->db->escape($objectpageold->newfk_page)."__+MAX_llx_website_page__" : "null").", ";
  880. $line .= "__WEBSITE_ID__, ";
  881. $line .= "'".$this->db->escape($objectpageold->pageurl)."', ";
  882. $line .= "'".$this->db->escape($objectpageold->aliasalt)."', ";
  883. $line .= "'".$this->db->escape($objectpageold->title)."', ";
  884. $line .= "'".$this->db->escape($objectpageold->description)."', ";
  885. $line .= "'".$this->db->escape($objectpageold->lang)."', ";
  886. $line .= "'".$this->db->escape($objectpageold->image)."', ";
  887. $line .= "'".$this->db->escape($objectpageold->keywords)."', ";
  888. $line .= "'".$this->db->escape($objectpageold->status)."', ";
  889. $line .= "'".$this->db->idate($objectpageold->date_creation)."', ";
  890. $line .= "'".$this->db->idate($objectpageold->date_modification)."', ";
  891. $line .= ($objectpageold->import_key ? "'".$this->db->escape($objectpageold->import_key)."'" : "null").", ";
  892. $line .= "'".$this->db->escape($objectpageold->grabbed_from)."', ";
  893. $line .= "'".$this->db->escape($objectpageold->type_container)."', ";
  894. $stringtoexport = $objectpageold->htmlheader;
  895. $stringtoexport = str_replace(array("\r\n", "\r", "\n"), "__N__", $stringtoexport);
  896. $stringtoexport = str_replace('file=image/'.$website->ref.'/', "file=image/__WEBSITE_KEY__/", $stringtoexport);
  897. $stringtoexport = str_replace('file=js/'.$website->ref.'/', "file=js/__WEBSITE_KEY__/", $stringtoexport);
  898. $stringtoexport = str_replace('medias/image/'.$website->ref.'/', "medias/image/__WEBSITE_KEY__/", $stringtoexport);
  899. $stringtoexport = str_replace('medias/js/'.$website->ref.'/', "medias/js/__WEBSITE_KEY__/", $stringtoexport);
  900. $stringtoexport = str_replace('file=logos%2Fthumbs%2F'.$mysoc->logo_small, "file=logos%2Fthumbs%2F__LOGO_SMALL_KEY__", $stringtoexport);
  901. $stringtoexport = str_replace('file=logos%2Fthumbs%2F'.$mysoc->logo_mini, "file=logos%2Fthumbs%2F__LOGO_MINI_KEY__", $stringtoexport);
  902. $stringtoexport = str_replace('file=logos%2Fthumbs%2F'.$mysoc->logo, "file=logos%2Fthumbs%2F__LOGO_KEY__", $stringtoexport);
  903. $line .= "'".$this->db->escape(str_replace(array("\r\n", "\r", "\n"), "__N__", $stringtoexport))."', "; // Replace \r \n to have record on 1 line
  904. $stringtoexport = $objectpageold->content;
  905. $stringtoexport = str_replace(array("\r\n", "\r", "\n"), "__N__", $stringtoexport);
  906. $stringtoexport = str_replace('file=image/'.$website->ref.'/', "file=image/__WEBSITE_KEY__/", $stringtoexport);
  907. $stringtoexport = str_replace('file=js/'.$website->ref.'/', "file=js/__WEBSITE_KEY__/", $stringtoexport);
  908. $stringtoexport = str_replace('medias/image/'.$website->ref.'/', "medias/image/__WEBSITE_KEY__/", $stringtoexport);
  909. $stringtoexport = str_replace('medias/js/'.$website->ref.'/', "medias/js/__WEBSITE_KEY__/", $stringtoexport);
  910. $stringtoexport = str_replace('file=logos%2Fthumbs%2F'.$mysoc->logo_small, "file=logos%2Fthumbs%2F__LOGO_SMALL_KEY__", $stringtoexport);
  911. $stringtoexport = str_replace('file=logos%2Fthumbs%2F'.$mysoc->logo_mini, "file=logos%2Fthumbs%2F__LOGO_MINI_KEY__", $stringtoexport);
  912. $stringtoexport = str_replace('file=logos%2Fthumbs%2F'.$mysoc->logo, "file=logos%2Fthumbs%2F__LOGO_KEY__", $stringtoexport);
  913. // When we have a link src="image/websiteref/file.png" into html content
  914. $stringtoexport = str_replace('="image/'.$website->ref.'/', '="image/__WEBSITE_KEY__/', $stringtoexport);
  915. $line .= "'".$this->db->escape($stringtoexport)."', "; // Replace \r \n to have record on 1 line
  916. $line .= "'".$this->db->escape($objectpageold->author_alias)."'";
  917. $line .= ");";
  918. $line .= "\n";
  919. fputs($fp, $line);
  920. // Add line to update home page id during import
  921. //var_dump($this->fk_default_home.' - '.$objectpageold->id.' - '.$objectpageold->newid);exit;
  922. if ($this->fk_default_home > 0 && ($objectpageold->id == $this->fk_default_home) && ($objectpageold->newid > 0)) { // This is the record with home page
  923. // Warning: We must keep llx_ here. It is a generic SQL.
  924. $line = "UPDATE llx_website SET fk_default_home = ".($objectpageold->newid > 0 ? $this->db->escape($objectpageold->newid)."__+MAX_llx_website_page__" : "null")." WHERE rowid = __WEBSITE_ID__;";
  925. $line .= "\n";
  926. fputs($fp, $line);
  927. }
  928. }
  929. $line .= "\n-- For Dolibarr v14+ --\n";
  930. $line .= "UPDATE llx_website SET fk_default_lang = '".$this->db->escape($this->fk_default_lang)."' WHERE rowid = __WEBSITE_ID__;\n";
  931. $line .= "UPDATE llx_website SET otherlang = '".$this->db->escape($this->otherlang)."' WHERE rowid = __WEBSITE_ID__;\n";
  932. $line .= "\n";
  933. fputs($fp, $line);
  934. fclose($fp);
  935. if (!empty($conf->global->MAIN_UMASK)) {
  936. @chmod($filesql, octdec($conf->global->MAIN_UMASK));
  937. }
  938. // Build zip file
  939. $filedir = $conf->website->dir_temp.'/'.$website->ref.'/.';
  940. $fileglob = $conf->website->dir_temp.'/'.$website->ref.'/website_'.$website->ref.'-*.zip';
  941. $filename = $conf->website->dir_temp.'/'.$website->ref.'/website_'.$website->ref.'-'.dol_print_date(dol_now(), 'dayhourlog').'-V'.((float) DOL_VERSION).'.zip';
  942. dol_delete_file($fileglob, 0);
  943. $result = dol_compress_file($filedir, $filename, 'zip');
  944. if ($result > 0) {
  945. return $filename;
  946. } else {
  947. global $errormsg;
  948. $this->error = $errormsg;
  949. return '';
  950. }
  951. }
  952. /**
  953. * Open a zip with all data of web site and load it into database.
  954. *
  955. * @param string $pathtofile Path of zip file
  956. * @return int <0 if KO, Id of new website if OK
  957. */
  958. public function importWebSite($pathtofile)
  959. {
  960. global $conf, $mysoc;
  961. $error = 0;
  962. $object = $this;
  963. if (empty($object->ref)) {
  964. $this->error = 'Function importWebSite called on object not loaded (object->ref is empty)';
  965. return -1;
  966. }
  967. dol_delete_dir_recursive($conf->website->dir_temp.'/'.$object->ref);
  968. dol_mkdir($conf->website->dir_temp.'/'.$object->ref);
  969. $filename = basename($pathtofile);
  970. if (!preg_match('/^website_(.*)-(.*)$/', $filename, $reg)) {
  971. $this->errors[] = 'Bad format for filename '.$filename.'. Must be website_XXX-VERSION.';
  972. return -1;
  973. }
  974. $result = dol_uncompress($pathtofile, $conf->website->dir_temp.'/'.$object->ref);
  975. if (!empty($result['error'])) {
  976. $this->errors[] = 'Failed to unzip file '.$pathtofile.'.';
  977. return -1;
  978. }
  979. $arrayreplacement = array();
  980. $arrayreplacement['__WEBSITE_ID__'] = $object->id;
  981. $arrayreplacement['__WEBSITE_KEY__'] = $object->ref;
  982. $arrayreplacement['__N__'] = $this->db->escape("\n"); // Restore \n
  983. $arrayreplacement['__LOGO_SMALL_KEY__'] = $this->db->escape($mysoc->logo_small);
  984. $arrayreplacement['__LOGO_MINI_KEY__'] = $this->db->escape($mysoc->logo_mini);
  985. $arrayreplacement['__LOGO_KEY__'] = $this->db->escape($mysoc->logo);
  986. // Copy containers
  987. dolCopyDir($conf->website->dir_temp.'/'.$object->ref.'/containers', $conf->website->dir_output.'/'.$object->ref, 0, 1); // Overwrite if exists
  988. // Make replacement into css and htmlheader file
  989. $cssindestdir = $conf->website->dir_output.'/'.$object->ref.'/styles.css.php';
  990. $result = dolReplaceInFile($cssindestdir, $arrayreplacement);
  991. $htmldeaderindestdir = $conf->website->dir_output.'/'.$object->ref.'/htmlheader.html';
  992. $result = dolReplaceInFile($htmldeaderindestdir, $arrayreplacement);
  993. // Now generate the master.inc.php page
  994. $filemaster = $conf->website->dir_output.'/'.$object->ref.'/master.inc.php';
  995. $result = dolSaveMasterFile($filemaster);
  996. if (!$result) {
  997. $this->errors[] = 'Failed to write file '.$filemaster;
  998. $error++;
  999. }
  1000. dolCopyDir($conf->website->dir_temp.'/'.$object->ref.'/medias/image/websitekey', $conf->website->dir_output.'/'.$object->ref.'/medias/image/'.$object->ref, 0, 1); // Medias can be shared, do not overwrite if exists
  1001. dolCopyDir($conf->website->dir_temp.'/'.$object->ref.'/medias/js/websitekey', $conf->website->dir_output.'/'.$object->ref.'/medias/js/'.$object->ref, 0, 1); // Medias can be shared, do not overwrite if exists
  1002. $sqlfile = $conf->website->dir_temp.'/'.$object->ref.'/website_pages.sql';
  1003. $result = dolReplaceInFile($sqlfile, $arrayreplacement);
  1004. $this->db->begin();
  1005. // Search the $maxrowid because we need it later
  1006. $sqlgetrowid = 'SELECT MAX(rowid) as max from '.MAIN_DB_PREFIX.'website_page';
  1007. $resql = $this->db->query($sqlgetrowid);
  1008. if ($resql) {
  1009. $obj = $this->db->fetch_object($resql);
  1010. $maxrowid = $obj->max;
  1011. }
  1012. // Load sql record
  1013. $runsql = run_sql($sqlfile, 1, '', 0, '', 'none', 0, 1); // The maxrowid of table is searched into this function two
  1014. if ($runsql <= 0) {
  1015. $this->errors[] = 'Failed to load sql file '.$sqlfile;
  1016. $error++;
  1017. }
  1018. $objectpagestatic = new WebsitePage($this->db);
  1019. // Make replacement of IDs
  1020. $fp = fopen($sqlfile, "r");
  1021. if ($fp) {
  1022. while (!feof($fp)) {
  1023. $reg = array();
  1024. // Warning fgets with second parameter that is null or 0 hang.
  1025. $buf = fgets($fp, 65000);
  1026. if (preg_match('/^-- Page ID (\d+)\s[^\s]+\s(\d+).*Aliases\s(.*)\s--;/i', $buf, $reg)) {
  1027. $oldid = $reg[1];
  1028. $newid = ($reg[2] + $maxrowid);
  1029. $aliasesarray = explode(',', $reg[3]);
  1030. dol_syslog("Found ID ".$oldid." to replace with ID ".$newid." and shortcut aliases to create: ".$reg[3]);
  1031. dol_move($conf->website->dir_output.'/'.$object->ref.'/page'.$oldid.'.tpl.php', $conf->website->dir_output.'/'.$object->ref.'/page'.$newid.'.tpl.php', 0, 1, 0, 0);
  1032. $objectpagestatic->fetch($newid);
  1033. // The move is not enough, so we regenerate page
  1034. $filetpl = $conf->website->dir_output.'/'.$object->ref.'/page'.$newid.'.tpl.php';
  1035. $result = dolSavePageContent($filetpl, $object, $objectpagestatic);
  1036. if (!$result) {
  1037. $this->errors[] = 'Failed to write file '.basename($filetpl);
  1038. $error++;
  1039. }
  1040. // Regenerate alternative aliases pages
  1041. if (is_array($aliasesarray)) {
  1042. foreach ($aliasesarray as $aliasshortcuttocreate) {
  1043. if (trim($aliasshortcuttocreate)) {
  1044. $filealias = $conf->website->dir_output.'/'.$object->ref.'/'.trim($aliasshortcuttocreate).'.php';
  1045. $result = dolSavePageAlias($filealias, $object, $objectpagestatic);
  1046. if (!$result) {
  1047. $this->errors[] = 'Failed to write file '.basename($filealias);
  1048. $error++;
  1049. }
  1050. }
  1051. }
  1052. }
  1053. }
  1054. }
  1055. }
  1056. // Read record of website that has been updated by the run_sql function previously called so we can get the
  1057. // value of fk_default_home that is ID of home page
  1058. $sql = 'SELECT fk_default_home FROM '.MAIN_DB_PREFIX.'website WHERE rowid = '.((int) $object->id);
  1059. $resql = $this->db->query($sql);
  1060. if ($resql) {
  1061. $obj = $this->db->fetch_object($resql);
  1062. if ($obj) {
  1063. $object->fk_default_home = $obj->fk_default_home;
  1064. } else {
  1065. //$this->errors[] = 'Failed to get the Home page';
  1066. //$error++;
  1067. }
  1068. }
  1069. // Regenerate index page to point to the new index page
  1070. $pathofwebsite = $conf->website->dir_output.'/'.$object->ref;
  1071. dolSaveIndexPage($pathofwebsite, $pathofwebsite.'/index.php', $pathofwebsite.'/page'.$object->fk_default_home.'.tpl.php', $pathofwebsite.'/wrapper.php');
  1072. if ($error) {
  1073. $this->db->rollback();
  1074. return -1;
  1075. } else {
  1076. $this->db->commit();
  1077. return $object->id;
  1078. }
  1079. }
  1080. /**
  1081. * Rebuild all files of a containers of a website. Rebuild also the wrapper.php file. TODO Add other files too.
  1082. * Note: Files are already regenerated during importWebSite so this function is useless when importing a website.
  1083. *
  1084. * @return int <0 if KO, >=0 if OK
  1085. */
  1086. public function rebuildWebSiteFiles()
  1087. {
  1088. global $conf;
  1089. $error = 0;
  1090. $object = $this;
  1091. if (empty($object->ref)) {
  1092. $this->error = 'Function rebuildWebSiteFiles called on object not loaded (object->ref is empty)';
  1093. return -1;
  1094. }
  1095. $objectpagestatic = new WebsitePage($this->db);
  1096. $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'website_page WHERE fk_website = '.((int) $this->id);
  1097. $resql = $this->db->query($sql);
  1098. if (!$resql) {
  1099. $this->error = $this->db->lasterror();
  1100. return -1;
  1101. }
  1102. $num = $this->db->num_rows($resql);
  1103. // Loop on each container/page
  1104. $i = 0;
  1105. while ($i < $num) {
  1106. $obj = $this->db->fetch_object($resql);
  1107. $newid = $obj->rowid;
  1108. $objectpagestatic->fetch($newid);
  1109. $aliasesarray = explode(',', $objectpagestatic->aliasalt);
  1110. $filetpl = $conf->website->dir_output.'/'.$object->ref.'/page'.$newid.'.tpl.php';
  1111. $result = dolSavePageContent($filetpl, $object, $objectpagestatic);
  1112. if (!$result) {
  1113. $this->errors[] = 'Failed to write file '.basename($filetpl);
  1114. $error++;
  1115. }
  1116. // Add main alias to list of alternative aliases
  1117. if (!empty($objectpagestatic->pageurl) && !in_array($objectpagestatic->pageurl, $aliasesarray)) {
  1118. $aliasesarray[] = $objectpagestatic->pageurl;
  1119. }
  1120. // Regenerate all aliases pages (pages with a natural name)
  1121. if (is_array($aliasesarray)) {
  1122. foreach ($aliasesarray as $aliasshortcuttocreate) {
  1123. if (trim($aliasshortcuttocreate)) {
  1124. $filealias = $conf->website->dir_output.'/'.$object->ref.'/'.trim($aliasshortcuttocreate).'.php';
  1125. $result = dolSavePageAlias($filealias, $object, $objectpagestatic);
  1126. if (!$result) {
  1127. $this->errors[] = 'Failed to write file '.basename($filealias);
  1128. $error++;
  1129. }
  1130. }
  1131. }
  1132. }
  1133. $i++;
  1134. }
  1135. if (!$error) {
  1136. // Save wrapper.php
  1137. $pathofwebsite = $conf->website->dir_output.'/'.$object->ref;
  1138. $filewrapper = $pathofwebsite.'/wrapper.php';
  1139. dolSaveIndexPage($pathofwebsite, '', '', $filewrapper);
  1140. }
  1141. if ($error) {
  1142. return -1;
  1143. } else {
  1144. return $num;
  1145. }
  1146. }
  1147. /**
  1148. * Return if web site is a multilanguage web site. Return false if there is only 0 or 1 language.
  1149. *
  1150. * @return boolean True if web site is a multilanguage web site
  1151. */
  1152. public function isMultiLang()
  1153. {
  1154. return (empty($this->otherlang) ? false : true);
  1155. }
  1156. /**
  1157. * Component to select language inside a container (Full CSS Only)
  1158. *
  1159. * @param array|string $languagecodes 'auto' to show all languages available for page, or language codes array like array('en','fr','de','es')
  1160. * @param Translate $weblangs Language Object
  1161. * @param string $morecss More CSS class on component
  1162. * @param string $htmlname Suffix for HTML name
  1163. * @return string HTML select component
  1164. */
  1165. public function componentSelectLang($languagecodes, $weblangs, $morecss = '', $htmlname = '')
  1166. {
  1167. global $websitepagefile, $website;
  1168. if (!is_object($weblangs)) {
  1169. return 'ERROR componentSelectLang called with parameter $weblangs not defined';
  1170. }
  1171. $arrayofspecialmainlanguages = array(
  1172. 'en'=>'en_US',
  1173. 'sq'=>'sq_AL',
  1174. 'ar'=>'ar_SA',
  1175. 'eu'=>'eu_ES',
  1176. 'bn'=>'bn_DB',
  1177. 'bs'=>'bs_BA',
  1178. 'ca'=>'ca_ES',
  1179. 'zh'=>'zh_CN',
  1180. 'cs'=>'cs_CZ',
  1181. 'da'=>'da_DK',
  1182. 'et'=>'et_EE',
  1183. 'ka'=>'ka_GE',
  1184. 'el'=>'el_GR',
  1185. 'he'=>'he_IL',
  1186. 'kn'=>'kn_IN',
  1187. 'km'=>'km_KH',
  1188. 'ko'=>'ko_KR',
  1189. 'lo'=>'lo_LA',
  1190. 'nb'=>'nb_NO',
  1191. 'fa'=>'fa_IR',
  1192. 'sr'=>'sr_RS',
  1193. 'sl'=>'sl_SI',
  1194. 'uk'=>'uk_UA',
  1195. 'vi'=>'vi_VN'
  1196. );
  1197. // Load tmppage if we have $websitepagefile defined
  1198. $tmppage = new WebsitePage($this->db);
  1199. $pageid = 0;
  1200. if (!empty($websitepagefile)) {
  1201. $websitepagefileshort = basename($websitepagefile);
  1202. if ($websitepagefileshort == 'index.php') {
  1203. $pageid = $website->fk_default_home;
  1204. } else {
  1205. $pageid = str_replace(array('.tpl.php', 'page'), array('', ''), $websitepagefileshort);
  1206. }
  1207. if ($pageid > 0) {
  1208. $tmppage->fetch($pageid);
  1209. }
  1210. }
  1211. // Fill $languagecodes array with existing translation, nothing if none
  1212. if (!is_array($languagecodes) && $pageid > 0) {
  1213. $languagecodes = array();
  1214. $sql = "SELECT wp.rowid, wp.lang, wp.pageurl, wp.fk_page";
  1215. $sql .= " FROM ".MAIN_DB_PREFIX."website_page as wp";
  1216. $sql .= " WHERE wp.fk_website = ".((int) $website->id);
  1217. $sql .= " AND (wp.fk_page = ".((int) $pageid)." OR wp.rowid = ".((int) $pageid);
  1218. if ($tmppage->fk_page > 0) {
  1219. $sql .= " OR wp.fk_page = ".((int) $tmppage->fk_page)." OR wp.rowid = ".((int) $tmppage->fk_page);
  1220. }
  1221. $sql .= ")";
  1222. $resql = $this->db->query($sql);
  1223. if ($resql) {
  1224. while ($obj = $this->db->fetch_object($resql)) {
  1225. $newlang = $obj->lang;
  1226. if ($obj->rowid == $pageid) {
  1227. $newlang = $obj->lang;
  1228. }
  1229. if (!in_array($newlang, $languagecodes)) {
  1230. $languagecodes[] = $newlang;
  1231. }
  1232. }
  1233. }
  1234. }
  1235. // Now $languagecodes is always an array. Example array('en', 'fr', 'es');
  1236. $languagecodeselected = substr($weblangs->defaultlang, 0, 2); // Because we must init with a value, but real value is the lang of main parent container
  1237. if (!empty($websitepagefile)) {
  1238. $pageid = str_replace(array('.tpl.php', 'page'), array('', ''), basename($websitepagefile));
  1239. if ($pageid > 0) {
  1240. $pagelang = substr($tmppage->lang, 0, 2);
  1241. $languagecodeselected = substr($pagelang, 0, 2);
  1242. if (!in_array($pagelang, $languagecodes)) {
  1243. $languagecodes[] = $pagelang; // We add language code of page into combo list
  1244. }
  1245. }
  1246. }
  1247. $weblangs->load('languages');
  1248. //var_dump($weblangs->defaultlang);
  1249. $url = $_SERVER["REQUEST_URI"];
  1250. $url = preg_replace('/(\?|&)l=([a-zA-Z_]*)/', '', $url); // We remove param l from url
  1251. //$url = preg_replace('/(\?|&)lang=([a-zA-Z_]*)/', '', $url); // We remove param lang from url
  1252. $url .= (preg_match('/\?/', $url) ? '&' : '?').'l=';
  1253. if (!preg_match('/^\//', $url)) {
  1254. $url = '/'.$url;
  1255. }
  1256. $HEIGHTOPTION = 40;
  1257. $MAXHEIGHT = 4 * $HEIGHTOPTION;
  1258. $nboflanguage = count($languagecodes);
  1259. $out = '<!-- componentSelectLang'.$htmlname.' -->'."\n";
  1260. $out .= '<style>';
  1261. $out .= '.componentSelectLang'.$htmlname.':hover { height: '.min($MAXHEIGHT, ($HEIGHTOPTION * $nboflanguage)).'px; overflow-x: hidden; overflow-y: '.((($HEIGHTOPTION * $nboflanguage) > $MAXHEIGHT) ? ' scroll' : 'hidden').'; }'."\n";
  1262. $out .= '.componentSelectLang'.$htmlname.' li { line-height: '.$HEIGHTOPTION.'px; }'."\n";
  1263. $out .= '.componentSelectLang'.$htmlname.' {
  1264. display: inline-block;
  1265. padding: 0;
  1266. height: '.$HEIGHTOPTION.'px;
  1267. overflow: hidden;
  1268. transition: all .3s ease;
  1269. margin: 0 0 0 0;
  1270. vertical-align: top;
  1271. }
  1272. .componentSelectLang'.$htmlname.':hover, .componentSelectLang'.$htmlname.':hover a { background-color: #fff; color: #000 !important; }
  1273. ul.componentSelectLang'.$htmlname.' { width: 150px; }
  1274. ul.componentSelectLang'.$htmlname.':hover .fa { visibility: hidden; }
  1275. .componentSelectLang'.$htmlname.' a { text-decoration: none; width: 100%; }
  1276. .componentSelectLang'.$htmlname.' li { display: block; padding: 0px 15px; margin-left: 0; margin-right: 0; }
  1277. .componentSelectLang'.$htmlname.' li:hover { background-color: #EEE; }
  1278. ';
  1279. $out .= '</style>';
  1280. $out .= '<ul class="componentSelectLang'.$htmlname.($morecss ? ' '.$morecss : '').'">';
  1281. if ($languagecodeselected) {
  1282. // Convert $languagecodeselected into a long language code
  1283. if (strlen($languagecodeselected) == 2) {
  1284. $languagecodeselected = (empty($arrayofspecialmainlanguages[$languagecodeselected]) ? $languagecodeselected.'_'.strtoupper($languagecodeselected) : $arrayofspecialmainlanguages[$languagecodeselected]);
  1285. }
  1286. $countrycode = strtolower(substr($languagecodeselected, -2));
  1287. $label = $weblangs->trans("Language_".$languagecodeselected);
  1288. if ($countrycode == 'us') {
  1289. $label = preg_replace('/\s*\(.*\)/', '', $label);
  1290. }
  1291. $out .= '<a href="'.$url.substr($languagecodeselected, 0, 2).'"><li><img height="12px" src="/medias/image/common/flags/'.$countrycode.'.png" style="margin-right: 5px;"/><span class="websitecomponentlilang">'.$label.'</span>';
  1292. $out .= '<span class="fa fa-caret-down" style="padding-left: 5px;" />';
  1293. $out .= '</li></a>';
  1294. }
  1295. $i = 0;
  1296. if (is_array($languagecodes)) {
  1297. foreach ($languagecodes as $languagecode) {
  1298. // Convert $languagecode into a long language code
  1299. if (strlen($languagecode) == 2) {
  1300. $languagecode = (empty($arrayofspecialmainlanguages[$languagecode]) ? $languagecode.'_'.strtoupper($languagecode) : $arrayofspecialmainlanguages[$languagecode]);
  1301. }
  1302. if ($languagecode == $languagecodeselected) {
  1303. continue; // Already output
  1304. }
  1305. $countrycode = strtolower(substr($languagecode, -2));
  1306. $label = $weblangs->trans("Language_".$languagecode);
  1307. if ($countrycode == 'us') {
  1308. $label = preg_replace('/\s*\(.*\)/', '', $label);
  1309. }
  1310. $out .= '<a href="'.$url.substr($languagecode, 0, 2).'"><li><img height="12px" src="/medias/image/common/flags/'.$countrycode.'.png" style="margin-right: 5px;"/><span class="websitecomponentlilang">'.$label.'</span>';
  1311. if (empty($i) && empty($languagecodeselected)) {
  1312. $out .= '<span class="fa fa-caret-down" style="padding-left: 5px;" />';
  1313. }
  1314. $out .= '</li></a>';
  1315. $i++;
  1316. }
  1317. }
  1318. $out .= '</ul>';
  1319. return $out;
  1320. }
  1321. }