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