website.class.php 50 KB

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