modulebuilder.lib.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. <?php
  2. /* Copyright (C) 2009-2010 Laurent Destailleur <eldy@users.sourceforge.net>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. * or see https://www.gnu.org/
  17. */
  18. /**
  19. * \file htdocs/core/lib/modulebuilder.lib.php
  20. * \brief Set of function for modulebuilder management
  21. */
  22. /**
  23. * Regenerate files .class.php
  24. *
  25. * @param string $destdir Directory
  26. * @param string $module Module name
  27. * @param string $objectname Name of object
  28. * @param string $newmask New mask
  29. * @param string $readdir Directory source (use $destdir when not defined)
  30. * @param string $addfieldentry Array of 1 field entry to add array('key'=>,'type'=>,''label'=>,'visible'=>,'enabled'=>,'position'=>,'notnull'=>','index'=>,'searchall'=>,'comment'=>,'help'=>,'isameasure')
  31. * @param string $delfieldentry Id of field to remove
  32. * @return int|object <=0 if KO, Object if OK
  33. * @see rebuildObjectSql()
  34. */
  35. function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = '', $addfieldentry = array(), $delfieldentry = '')
  36. {
  37. global $db, $langs;
  38. if (empty($objectname)) {
  39. return -6;
  40. }
  41. if (empty($readdir)) {
  42. $readdir = $destdir;
  43. }
  44. if (!empty($addfieldentry['arrayofkeyval']) && !is_array($addfieldentry['arrayofkeyval'])) {
  45. dol_print_error('', 'Bad parameter addfieldentry with a property arrayofkeyval defined but that is not an array.');
  46. return -7;
  47. }
  48. $error = 0;
  49. // Check parameters
  50. if (is_array($addfieldentry) && count($addfieldentry) > 0) {
  51. if (empty($addfieldentry['name'])) {
  52. setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Name")), null, 'errors');
  53. return -2;
  54. }
  55. if (empty($addfieldentry['label'])) {
  56. setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Label")), null, 'errors');
  57. return -2;
  58. }
  59. if (!preg_match('/^(integer|price|sellist|varchar|double|text|html|duration)/', $addfieldentry['type'])
  60. && !preg_match('/^(boolean|smallint|real|date|datetime|timestamp|phone|mail|url|ip|password)$/', $addfieldentry['type'])) {
  61. setEventMessages($langs->trans('BadValueForType', $addfieldentry['type']), null, 'errors');
  62. return -2;
  63. }
  64. }
  65. $pathoffiletoeditsrc = $readdir.'/class/'.strtolower($objectname).'.class.php';
  66. $pathoffiletoedittarget = $destdir.'/class/'.strtolower($objectname).'.class.php'.($readdir != $destdir ? '.new' : '');
  67. if (!dol_is_file($pathoffiletoeditsrc)) {
  68. $langs->load("errors");
  69. setEventMessages($langs->trans("ErrorFileNotFound", $pathoffiletoeditsrc), null, 'errors');
  70. return -3;
  71. }
  72. //$pathoffiletoedittmp=$destdir.'/class/'.strtolower($objectname).'.class.php.tmp';
  73. //dol_delete_file($pathoffiletoedittmp, 0, 1, 1);
  74. try {
  75. include_once $pathoffiletoeditsrc;
  76. if (class_exists($objectname)) {
  77. $object = new $objectname($db);
  78. } else {
  79. return -4;
  80. }
  81. // Backup old file
  82. dol_copy($pathoffiletoedittarget, $pathoffiletoedittarget.'.back', $newmask, 1);
  83. // Edit class files
  84. $contentclass = file_get_contents(dol_osencode($pathoffiletoeditsrc), 'r');
  85. // Update ->fields (to add or remove entries defined into $addfieldentry)
  86. if (count($object->fields)) {
  87. if (is_array($addfieldentry) && count($addfieldentry)) {
  88. $name = $addfieldentry['name'];
  89. unset($addfieldentry['name']);
  90. $object->fields[$name] = $addfieldentry;
  91. }
  92. if (!empty($delfieldentry)) {
  93. $name = $delfieldentry;
  94. unset($object->fields[$name]);
  95. }
  96. }
  97. dol_sort_array($object->fields, 'position');
  98. $i = 0;
  99. $texttoinsert = '// BEGIN MODULEBUILDER PROPERTIES'."\n";
  100. $texttoinsert .= "\t".'/**'."\n";
  101. $texttoinsert .= "\t".' * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.'."\n";
  102. $texttoinsert .= "\t".' */'."\n";
  103. $texttoinsert .= "\t".'public $fields=array('."\n";
  104. if (count($object->fields)) {
  105. foreach ($object->fields as $key => $val) {
  106. $i++;
  107. $texttoinsert .= "\t\t'".$key."' => array('type'=>'".$val['type']."',";
  108. $texttoinsert .= " 'label'=>'".$val['label']."',";
  109. if (!empty($val['picto'])) {
  110. $texttoinsert .= " 'picto'=>'".$val['picto']."',";
  111. }
  112. $texttoinsert .= " 'enabled'=>'".($val['enabled'] !== '' ? $val['enabled'] : 1)."',";
  113. $texttoinsert .= " 'position'=>".($val['position'] !== '' ? $val['position'] : 50).",";
  114. $texttoinsert .= " 'notnull'=>".(empty($val['notnull']) ? 0 : $val['notnull']).",";
  115. $texttoinsert .= " 'visible'=>".($val['visible'] !== '' ? $val['visible'] : -1).",";
  116. if (!empty($val['noteditable'])) {
  117. $texttoinsert .= " 'noteditable'=>'".$val['noteditable']."',";
  118. }
  119. if (!empty($val['alwayseditable'])) {
  120. $texttoinsert .= " 'alwayseditable'=>'".$val['alwayseditable']."',";
  121. }
  122. if (!empty($val['default']) || (isset($val['default']) && $val['default'] === '0')) {
  123. $texttoinsert .= " 'default'=>'".$val['default']."',";
  124. }
  125. if (!empty($val['index'])) {
  126. $texttoinsert .= " 'index'=>".$val['index'].",";
  127. }
  128. if (!empty($val['foreignkey'])) {
  129. $texttoinsert .= " 'foreignkey'=>'".$val['foreignkey']."',";
  130. }
  131. if (!empty($val['searchall'])) {
  132. $texttoinsert .= " 'searchall'=>".$val['searchall'].",";
  133. }
  134. if (!empty($val['isameasure'])) {
  135. $texttoinsert .= " 'isameasure'=>'".$val['isameasure']."',";
  136. }
  137. if (!empty($val['css'])) {
  138. $texttoinsert .= " 'css'=>'".$val['css']."',";
  139. }
  140. if (!empty($val['cssview'])) {
  141. $texttoinsert .= " 'cssview'=>'".$val['cssview']."',";
  142. }
  143. if (!empty($val['csslist'])) {
  144. $texttoinsert .= " 'csslist'=>'".$val['csslist']."',";
  145. }
  146. if (!empty($val['help'])) {
  147. $texttoinsert .= " 'help'=>\"".preg_replace('/"/', '', $val['help'])."\",";
  148. }
  149. if (!empty($val['showoncombobox'])) {
  150. $texttoinsert .= " 'showoncombobox'=>'".$val['showoncombobox']."',";
  151. }
  152. if (!empty($val['disabled'])) {
  153. $texttoinsert .= " 'disabled'=>'".$val['disabled']."',";
  154. }
  155. if (!empty($val['autofocusoncreate'])) {
  156. $texttoinsert .= " 'autofocusoncreate'=>'".$val['autofocusoncreate']."',";
  157. }
  158. if (!empty($val['arrayofkeyval'])) {
  159. $texttoinsert .= " 'arrayofkeyval'=>array(";
  160. $i = 0;
  161. foreach ($val['arrayofkeyval'] as $key2 => $val2) {
  162. if ($i) {
  163. $texttoinsert .= ", ";
  164. }
  165. $texttoinsert .= "'".$key2."'=>'".$val2."'";
  166. $i++;
  167. }
  168. $texttoinsert .= "),";
  169. }
  170. if (!empty($val['validate'])) {
  171. $texttoinsert .= " 'validate'=>'".$val['validate']."',";
  172. }
  173. if (!empty($val['comment'])) {
  174. $texttoinsert .= " 'comment'=>\"".preg_replace('/"/', '', $val['comment'])."\"";
  175. }
  176. $texttoinsert .= "),\n";
  177. //print $texttoinsert;
  178. }
  179. }
  180. $texttoinsert .= "\t".');'."\n";
  181. //print ($texttoinsert);exit;
  182. if (count($object->fields)) {
  183. //$typetotypephp=array('integer'=>'integer', 'duration'=>'integer', 'varchar'=>'string');
  184. foreach ($object->fields as $key => $val) {
  185. $i++;
  186. //$typephp=$typetotypephp[$val['type']];
  187. $texttoinsert .= "\t".'public $'.$key.";";
  188. //if ($key == 'rowid') $texttoinsert.= ' AUTO_INCREMENT PRIMARY KEY';
  189. //if ($key == 'entity') $texttoinsert.= ' DEFAULT 1';
  190. //$texttoinsert.= ($val['notnull']?' NOT NULL':'');
  191. //if ($i < count($object->fields)) $texttoinsert.=";";
  192. $texttoinsert .= "\n";
  193. }
  194. }
  195. $texttoinsert .= "\t".'// END MODULEBUILDER PROPERTIES';
  196. //print($texttoinsert);
  197. $contentclass = preg_replace('/\/\/ BEGIN MODULEBUILDER PROPERTIES.*END MODULEBUILDER PROPERTIES/ims', $texttoinsert, $contentclass);
  198. //print $contentclass;
  199. dol_mkdir(dirname($pathoffiletoedittarget));
  200. //file_put_contents($pathoffiletoedittmp, $contentclass);
  201. $result = file_put_contents(dol_osencode($pathoffiletoedittarget), $contentclass);
  202. if ($result) {
  203. @chmod($pathoffiletoedittarget, octdec($newmask));
  204. } else {
  205. $error++;
  206. }
  207. return $error ? -1 : $object;
  208. } catch (Exception $e) {
  209. print $e->getMessage();
  210. return -5;
  211. }
  212. }
  213. /**
  214. * Save data into a memory area shared by all users, all sessions on server
  215. *
  216. * @param string $destdir Directory
  217. * @param string $module Module name
  218. * @param string $objectname Name of object
  219. * @param string $newmask New mask
  220. * @param string $readdir Directory source (use $destdir when not defined)
  221. * @param Object $object If object was already loaded/known, it is pass to avoid another include and new.
  222. * @param string $moduletype 'external' or 'internal'
  223. * @return int <=0 if KO, >0 if OK
  224. * @see rebuildObjectClass()
  225. */
  226. function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir = '', $object = null, $moduletype = 'external')
  227. {
  228. global $db, $langs;
  229. $error = 0;
  230. if (empty($objectname)) {
  231. return -1;
  232. }
  233. if (empty($readdir)) {
  234. $readdir = $destdir;
  235. }
  236. $pathoffiletoclasssrc = $readdir.'/class/'.strtolower($objectname).'.class.php';
  237. // Edit .sql file
  238. if ($moduletype == 'internal') {
  239. $pathoffiletoeditsrc = '/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql';
  240. if (! dol_is_file($readdir.$pathoffiletoeditsrc)) {
  241. $pathoffiletoeditsrc = '/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'-'.strtolower($module).'.sql';
  242. if (! dol_is_file($readdir.$pathoffiletoeditsrc)) {
  243. $pathoffiletoeditsrc = '/../install/mysql/tables/llx_'.strtolower($module).'-'.strtolower($module).'.sql';
  244. if (! dol_is_file($readdir.$pathoffiletoeditsrc)) {
  245. $pathoffiletoeditsrc = '/../install/mysql/tables/llx_'.strtolower($module).'.sql';
  246. }
  247. }
  248. }
  249. } else {
  250. $pathoffiletoeditsrc = '/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql';
  251. if (! dol_is_file($readdir.$pathoffiletoeditsrc)) {
  252. $pathoffiletoeditsrc = '/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'-'.strtolower($module).'.sql';
  253. if (! dol_is_file($readdir.$pathoffiletoeditsrc)) {
  254. $pathoffiletoeditsrc = '/sql/llx_'.strtolower($module).'-'.strtolower($module).'.sql';
  255. if (! dol_is_file($readdir.$pathoffiletoeditsrc)) {
  256. $pathoffiletoeditsrc = '/sql/llx_'.strtolower($module).'.sql';
  257. }
  258. }
  259. }
  260. }
  261. // Complete path to be full path
  262. $pathoffiletoedittarget = $destdir.$pathoffiletoeditsrc.($readdir != $destdir ? '.new' : '');
  263. $pathoffiletoeditsrc = $readdir.$pathoffiletoeditsrc;
  264. if (!dol_is_file($pathoffiletoeditsrc)) {
  265. $langs->load("errors");
  266. setEventMessages($langs->trans("ErrorFileNotFound", $pathoffiletoeditsrc), null, 'errors');
  267. return -1;
  268. }
  269. // Load object from myobject.class.php
  270. try {
  271. if (!is_object($object)) {
  272. include_once $pathoffiletoclasssrc;
  273. if (class_exists($objectname)) {
  274. $object = new $objectname($db);
  275. } else {
  276. return -1;
  277. }
  278. }
  279. } catch (Exception $e) {
  280. print $e->getMessage();
  281. }
  282. // Backup old file
  283. dol_copy($pathoffiletoedittarget, $pathoffiletoedittarget.'.back', $newmask, 1);
  284. $contentsql = file_get_contents(dol_osencode($pathoffiletoeditsrc), 'r');
  285. $i = 0;
  286. $texttoinsert = '-- BEGIN MODULEBUILDER FIELDS'."\n";
  287. if (count($object->fields)) {
  288. foreach ($object->fields as $key => $val) {
  289. $i++;
  290. $type = $val['type'];
  291. $type = preg_replace('/:.*$/', '', $type); // For case type = 'integer:Societe:societe/class/societe.class.php'
  292. if ($type == 'html') {
  293. $type = 'text'; // html modulebuilder type is a text type in database
  294. } elseif ($type == 'price') {
  295. $type = 'double'; // html modulebuilder type is a text type in database
  296. } elseif (in_array($type, array('link', 'sellist', 'duration'))) {
  297. $type = 'integer';
  298. }
  299. $texttoinsert .= "\t".$key." ".$type;
  300. if ($key == 'rowid') {
  301. $texttoinsert .= ' AUTO_INCREMENT PRIMARY KEY';
  302. } elseif ($type == 'timestamp') {
  303. $texttoinsert .= ' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP';
  304. }
  305. if ($key == 'entity') {
  306. $texttoinsert .= ' DEFAULT 1';
  307. } else {
  308. if (!empty($val['default'])) {
  309. if (preg_match('/^null$/i', $val['default'])) {
  310. $texttoinsert .= " DEFAULT NULL";
  311. } elseif (preg_match('/varchar/', $type)) {
  312. $texttoinsert .= " DEFAULT '".$db->escape($val['default'])."'";
  313. } else {
  314. $texttoinsert .= (($val['default'] > 0) ? ' DEFAULT '.$val['default'] : '');
  315. }
  316. }
  317. }
  318. $texttoinsert .= ((!empty($val['notnull']) && $val['notnull'] > 0) ? ' NOT NULL' : '');
  319. if ($i < count($object->fields)) {
  320. $texttoinsert .= ", ";
  321. }
  322. $texttoinsert .= "\n";
  323. }
  324. }
  325. $texttoinsert .= "\t".'-- END MODULEBUILDER FIELDS';
  326. $contentsql = preg_replace('/-- BEGIN MODULEBUILDER FIELDS.*END MODULEBUILDER FIELDS/ims', $texttoinsert, $contentsql);
  327. $result = file_put_contents($pathoffiletoedittarget, $contentsql);
  328. if ($result) {
  329. @chmod($pathoffiletoedittarget, octdec($newmask));
  330. } else {
  331. $error++;
  332. setEventMessages($langs->trans("ErrorFailToCreateFile", $pathoffiletoedittarget), null, 'errors');
  333. }
  334. // Edit .key.sql file
  335. $pathoffiletoeditsrc = preg_replace('/\.sql$/', '.key.sql', $pathoffiletoeditsrc);
  336. $pathoffiletoedittarget = preg_replace('/\.sql$/', '.key.sql', $pathoffiletoedittarget);
  337. $pathoffiletoedittarget = preg_replace('/\.sql.new$/', '.key.sql.new', $pathoffiletoedittarget);
  338. $contentsql = file_get_contents(dol_osencode($pathoffiletoeditsrc), 'r');
  339. $i = 0;
  340. $texttoinsert = '-- BEGIN MODULEBUILDER INDEXES'."\n";
  341. if (count($object->fields)) {
  342. foreach ($object->fields as $key => $val) {
  343. $i++;
  344. if (!empty($val['index'])) {
  345. $texttoinsert .= "ALTER TABLE llx_".strtolower($module).'_'.strtolower($objectname)." ADD INDEX idx_".strtolower($module).'_'.strtolower($objectname)."_".$key." (".$key.");";
  346. $texttoinsert .= "\n";
  347. }
  348. if (!empty($val['foreignkey'])) {
  349. $tmp = explode('.', $val['foreignkey']);
  350. if (!empty($tmp[0]) && !empty($tmp[1])) {
  351. $texttoinsert .= "ALTER TABLE llx_".strtolower($module).'_'.strtolower($objectname)." ADD CONSTRAINT llx_".strtolower($module).'_'.strtolower($objectname)."_".$key." FOREIGN KEY (".$key.") REFERENCES llx_".preg_replace('/^llx_/', '', $tmp[0])."(".$tmp[1].");";
  352. $texttoinsert .= "\n";
  353. }
  354. }
  355. }
  356. }
  357. $texttoinsert .= '-- END MODULEBUILDER INDEXES';
  358. $contentsql = preg_replace('/-- BEGIN MODULEBUILDER INDEXES.*END MODULEBUILDER INDEXES/ims', $texttoinsert, $contentsql);
  359. dol_mkdir(dirname($pathoffiletoedittarget));
  360. $result2 = file_put_contents($pathoffiletoedittarget, $contentsql);
  361. if ($result2) {
  362. @chmod($pathoffiletoedittarget, octdec($newmask));
  363. } else {
  364. $error++;
  365. setEventMessages($langs->trans("ErrorFailToCreateFile", $pathoffiletoedittarget), null, 'errors');
  366. }
  367. return $error ? -1 : 1;
  368. }