PageRenderTime 63ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/ModuleInstall/ModuleInstaller.php

https://github.com/vincentamari/SuperSweetAdmin
PHP | 2351 lines | 1891 code | 218 blank | 242 comment | 415 complexity | 3445fef26e0ea0d86f0b93e97bf6ec26 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, AGPL-3.0, LGPL-2.1
  1. <?php
  2. if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
  3. /*********************************************************************************
  4. * SugarCRM is a customer relationship management program developed by
  5. * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
  6. *
  7. * This program is free software; you can redistribute it and/or modify it under
  8. * the terms of the GNU Affero General Public License version 3 as published by the
  9. * Free Software Foundation with the addition of the following permission added
  10. * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
  11. * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
  12. * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
  13. *
  14. * This program is distributed in the hope that it will be useful, but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  16. * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  17. * details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License along with
  20. * this program; if not, see http://www.gnu.org/licenses or write to the Free
  21. * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  22. * 02110-1301 USA.
  23. *
  24. * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
  25. * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
  26. *
  27. * The interactive user interfaces in modified source and object code versions
  28. * of this program must display Appropriate Legal Notices, as required under
  29. * Section 5 of the GNU Affero General Public License version 3.
  30. *
  31. * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
  32. * these Appropriate Legal Notices must retain the display of the "Powered by
  33. * SugarCRM" logo. If the display of the logo is not reasonably feasible for
  34. * technical reasons, the Appropriate Legal Notices must display the words
  35. * "Powered by SugarCRM".
  36. ********************************************************************************/
  37. /*
  38. * ModuleInstaller - takes an installation package from files in the custom/Extension/X directories, and moves them into custom/X to install them.
  39. * If a directory has multiple files they are concatenated together.
  40. * Relevant directories (X) are Layoutdefs, Vardefs, Include (bean stuff), Language, TableDictionary (relationships)
  41. *
  42. * Installation steps that involve more than just copying files:
  43. * 1. installing custom fields - calls bean->custom_fields->addField
  44. * 2. installing relationships - calls createTableParams to build the relationship table, and createRelationshipMeta to add the relationship to the relationship table
  45. * 3. rebuilding the relationships - at almost the last step in install(), calls modules/Administration/RebuildRelationship.php
  46. * 4. repair indices - uses "modules/Administration/RepairIndex.php";
  47. */
  48. require_once('include/utils/progress_bar_utils.php');
  49. require_once('ModuleInstall/ModuleScanner.php');
  50. define('DISABLED_PATH', 'Disabled');
  51. class ModuleInstaller{
  52. var $modules = array();
  53. var $silent = false;
  54. var $base_dir = '';
  55. var $modulesInPackage = array();
  56. function ModuleInstaller(){
  57. $this->ms = new ModuleScanner();
  58. $this->modules = get_module_dir_list();
  59. $this->db = & DBManagerFactory::getInstance();
  60. }
  61. /*
  62. * ModuleInstaller->install includes the manifest.php from the base directory it has been given. If it has been asked to do an upgrade it checks to see if there is
  63. * an upgrade_manifest defined in the manifest; if not it errors. It then adds the bean into the custom/Extension/application/Ext/Include/<module>.php - sets beanList, beanFiles
  64. * and moduleList - and then calls ModuleInstaller->merge_files('Ext/Include', 'modules.ext.php', '', true) to merge the individual module files into a combined file
  65. * /custom/Extension/application/Ext/Include/modules.ext.php (which now contains a list of all $beanList, $beanFiles and $moduleList for all extension modules) -
  66. * this file modules.ext.php is included at the end of modules.php.
  67. *
  68. * Finally it runs over a list of defined tasks; then install_beans, then install_custom_fields, then clear the Vardefs, run a RepairAndClear, then finally call rebuild_relationships.
  69. */
  70. function install($base_dir, $is_upgrade = false, $previous_version = ''){
  71. if(defined('TEMPLATE_URL'))SugarTemplateUtilities::disableCache();
  72. if(!empty($GLOBALS['sugar_config']['moduleInstaller']['packageScan'])){
  73. $this->ms->scanPackage($base_dir);
  74. if($this->ms->hasIssues()){
  75. $this->ms->displayIssues();
  76. sugar_cleanup(true);
  77. }
  78. }
  79. global $app_strings, $mod_strings;
  80. $this->base_dir = $base_dir;
  81. $total_steps = 5; //minimum number of steps with no tasks
  82. $current_step = 0;
  83. $tasks = array(
  84. 'pre_execute',
  85. 'install_copy',
  86. 'install_images',
  87. 'install_menus',
  88. 'install_dcactions',
  89. 'install_userpage',
  90. 'install_dashlets',
  91. 'install_administration',
  92. 'install_connectors',
  93. 'install_vardefs',
  94. 'install_layoutdefs',
  95. 'install_layoutfields',
  96. 'install_relationships',
  97. 'install_languages',
  98. 'install_logichooks',
  99. 'post_execute',
  100. 'reset_opcodes',
  101. );
  102. $total_steps += count($tasks);
  103. if(file_exists($this->base_dir . '/manifest.php')){
  104. if(!$this->silent){
  105. $current_step++;
  106. display_progress_bar('install', $current_step, $total_steps);
  107. echo '<div id ="displayLoglink" ><a href="#" onclick="document.getElementById(\'displayLog\').style.display=\'\'">'
  108. .$app_strings['LBL_DISPLAY_LOG'].'</a> </div><div id="displayLog" style="display:none">';
  109. }
  110. include($this->base_dir . '/manifest.php');
  111. if($is_upgrade && !empty($previous_version)){
  112. //check if the upgrade path exists
  113. if(!empty($upgrade_manifest)){
  114. if(!empty($upgrade_manifest['upgrade_paths'])){
  115. if(!empty($upgrade_manifest['upgrade_paths'][$previous_version])){
  116. $installdefs = $upgrade_manifest['upgrade_paths'][$previous_version];
  117. }else{
  118. $errors[] = 'No Upgrade Path Found in manifest.';
  119. $this->abort($errors);
  120. }//fi
  121. }//fi
  122. }//fi
  123. }//fi
  124. $this->id_name = $installdefs['id'];
  125. $this->installdefs = $installdefs;
  126. $installed_modules = array();
  127. $tab_modules = array();
  128. if(isset($installdefs['beans'])){
  129. $str = "<?php \n //WARNING: The contents of this file are auto-generated\n";
  130. foreach($installdefs['beans'] as $bean){
  131. if(!empty($bean['module']) && !empty($bean['class']) && !empty($bean['path'])){
  132. $module = $bean['module'];
  133. $class = $bean['class'];
  134. $path = $bean['path'];
  135. $str .= "\$beanList['$module'] = '$class';\n";
  136. $str .= "\$beanFiles['$class'] = '$path';\n";
  137. if($bean['tab']){
  138. $str .= "\$moduleList[] = '$module';\n";
  139. $this->install_user_prefs($module, empty($bean['hide_by_default']));
  140. $tab_modules[] = $module;
  141. }else{
  142. $str .= "\$modules_exempt_from_availability_check['$module'] = '$module';\n";
  143. $str .= "\$modInvisList[] = '$module';\n";
  144. }
  145. $installed_modules[] = $module;
  146. }else{
  147. $errors[] = 'Bean array not well defined.';
  148. $this->abort($errors);
  149. }
  150. }
  151. $str.= "\n?>";
  152. if(!file_exists("custom/Extension/application/Ext/Include")){
  153. mkdir_recursive("custom/Extension/application/Ext/Include", true);
  154. }
  155. $out = sugar_fopen("custom/Extension/application/Ext/Include/$this->id_name.php", 'w');
  156. fwrite($out,$str);
  157. fclose($out);
  158. $this->rebuild_modules();
  159. }
  160. if(!$this->silent){
  161. $current_step++;
  162. update_progress_bar('install', $current_step, $total_steps);
  163. }
  164. foreach($tasks as $task){
  165. $this->$task();
  166. if(!$this->silent){
  167. $current_step++;
  168. update_progress_bar('install', $current_step, $total_steps);
  169. }
  170. }
  171. $this->install_beans($installed_modules);
  172. if(!$this->silent){
  173. $current_step++;
  174. update_progress_bar('install', $total_steps, $total_steps);
  175. }
  176. if(isset($installdefs['custom_fields'])){
  177. $this->log(translate('LBL_MI_IN_CUSTOMFIELD'));
  178. $this->install_custom_fields($installdefs['custom_fields']);
  179. }
  180. if(!$this->silent){
  181. $current_step++;
  182. update_progress_bar('install', $current_step, $total_steps);
  183. echo '</div>';
  184. }
  185. if(!$this->silent){
  186. $current_step++;
  187. update_progress_bar('install', $current_step, $total_steps);
  188. echo '</div>';
  189. }
  190. $selectedActions = array(
  191. 'clearTpls',
  192. 'clearJsFiles',
  193. 'clearDashlets',
  194. 'clearVardefs',
  195. 'clearJsLangFiles',
  196. 'rebuildAuditTables',
  197. 'repairDatabase',
  198. );
  199. VardefManager::clearVardef();
  200. global $beanList, $beanFiles, $moduleList;
  201. if (file_exists('custom/application/Ext/Include/modules.ext.php'))
  202. {
  203. include('custom/application/Ext/Include/modules.ext.php');
  204. }
  205. require_once("modules/Administration/upgrade_custom_relationships.php");
  206. upgrade_custom_relationships($installed_modules);
  207. $this->rebuild_all(true);
  208. require_once('modules/Administration/QuickRepairAndRebuild.php');
  209. $rac = new RepairAndClear();
  210. $rac->repairAndClearAll($selectedActions, $installed_modules,true, false);
  211. $this->rebuild_relationships();
  212. UpdateSystemTabs('Add',$tab_modules);
  213. //clear the unified_search_module.php file
  214. require_once('modules/Home/UnifiedSearchAdvanced.php');
  215. UnifiedSearchAdvanced::unlinkUnifiedSearchModulesFile();
  216. $this->log('<br><b>' . translate('LBL_MI_COMPLETE') . '</b>');
  217. }else{
  218. die("No \$installdefs Defined In $this->base_dir/manifest.php");
  219. }
  220. }
  221. function install_user_prefs($module, $hide_from_user=false){
  222. UserPreference::updateAllUserPrefs('display_tabs', $module, '', true, !$hide_from_user);
  223. UserPreference::updateAllUserPrefs('hide_tabs', $module, '', true, $hide_from_user);
  224. UserPreference::updateAllUserPrefs('remove_tabs', $module, '', true, $hide_from_user);
  225. }
  226. function uninstall_user_prefs($module){
  227. UserPreference::updateAllUserPrefs('display_tabs', $module, '', true, true);
  228. UserPreference::updateAllUserPrefs('hide_tabs', $module, '', true, true);
  229. UserPreference::updateAllUserPrefs('remove_tabs', $module, '', true, true);
  230. }
  231. function pre_execute(){
  232. require_once($this->base_dir . '/manifest.php');
  233. if(isset($this->installdefs['pre_execute']) && is_array($this->installdefs['pre_execute'])){
  234. foreach($this->installdefs['pre_execute'] as $includefile){
  235. require_once(str_replace('<basepath>', $this->base_dir, $includefile));
  236. }
  237. }
  238. }
  239. function post_execute(){
  240. require_once($this->base_dir . '/manifest.php');
  241. if(isset($this->installdefs['post_execute']) && is_array($this->installdefs['post_execute'])){
  242. foreach($this->installdefs['post_execute'] as $includefile){
  243. require_once(str_replace('<basepath>', $this->base_dir, $includefile));
  244. }
  245. }
  246. }
  247. function pre_uninstall(){
  248. require_once($this->base_dir . '/manifest.php');
  249. if(isset($this->installdefs['pre_uninstall']) && is_array($this->installdefs['pre_uninstall'])){
  250. foreach($this->installdefs['pre_uninstall'] as $includefile){
  251. require_once(str_replace('<basepath>', $this->base_dir, $includefile));
  252. }
  253. }
  254. }
  255. function post_uninstall(){
  256. require_once($this->base_dir . '/manifest.php');
  257. if(isset($this->installdefs['post_uninstall']) && is_array($this->installdefs['post_uninstall'])){
  258. foreach($this->installdefs['post_uninstall'] as $includefile){
  259. require_once(str_replace('<basepath>', $this->base_dir, $includefile));
  260. }
  261. }
  262. }
  263. /*
  264. * ModuleInstaller->install_copy gets the copy section of installdefs in the manifest and calls copy_path to copy each path (file or directory) to its final location
  265. * (specified as from and to in the manifest), replacing <basepath> by the base_dir value passed in to install.
  266. */
  267. function install_copy(){
  268. if(isset($this->installdefs['copy'])){
  269. /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:22:11 PM */
  270. $backup_path = clean_path( remove_file_extension(urldecode(hashToFile($_REQUEST['install_file'])))."-restore" );
  271. /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
  272. foreach($this->installdefs['copy'] as $cp){
  273. $GLOBALS['log']->debug("Copying ..." . $cp['from']. " to " .$cp['to'] );
  274. /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:22:11 PM */
  275. //$this->copy_path($cp['from'], $cp['to']);
  276. $this->copy_path($cp['from'], $cp['to'], $backup_path);
  277. /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
  278. }
  279. //here we should get the module list again as we could have copied something to the modules dir
  280. $this->modules = get_module_dir_list();
  281. }
  282. }
  283. function uninstall_copy(){
  284. if(!empty($this->installdefs['copy'])){
  285. foreach($this->installdefs['copy'] as $cp){
  286. $cp['to'] = clean_path(str_replace('<basepath>', $this->base_dir, $cp['to']));
  287. $cp['from'] = clean_path(str_replace('<basepath>', $this->base_dir, $cp['from']));
  288. $GLOBALS['log']->debug('Unlink ' . $cp['to']);
  289. /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:22:11 PM */
  290. //rmdir_recursive($cp['to']);
  291. $backup_path = clean_path( remove_file_extension(urldecode(hashToFile($_REQUEST['install_file'])))."-restore/".$cp['to'] );
  292. $this->uninstall_new_files($cp, $backup_path);
  293. $this->copy_path($backup_path, $cp['to'], $backup_path, true);
  294. /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
  295. }
  296. $backup_path = clean_path( remove_file_extension(urldecode(hashToFile($_REQUEST['install_file'])))."-restore");
  297. if(file_exists($backup_path))
  298. rmdir_recursive($backup_path);
  299. }
  300. }
  301. /**
  302. * Removes any files that were added by the loaded module. If the files already existed prior to install
  303. * it will be handled by copy_path with the uninstall parameter.
  304. *
  305. */
  306. function uninstall_new_files($cp, $backup_path){
  307. $zip_files = $this->dir_get_files($cp['from'],$cp['from']);
  308. $backup_files = $this->dir_get_files($backup_path, $backup_path);
  309. foreach($zip_files as $k=>$v){
  310. //if it's not a backup then it is probably a new file but we'll check that it is not in the md5.files first
  311. if(!isset($backup_files[$k])){
  312. $to = $cp['to'] . $k;
  313. //if it's not a sugar file then we remove it otherwise we can't restor it
  314. if(!$this->ms->sugarFileExists($to)){
  315. $GLOBALS['log']->debug('ModuleInstaller[uninstall_new_file] deleting file ' . $to);
  316. if(file_exists($to)) {
  317. unlink($to);
  318. }
  319. }else{
  320. $GLOBALS['log']->fatal('ModuleInstaller[uninstall_new_file] Could not remove file ' . $to . ' as no backup file was found to restore to');
  321. }
  322. }
  323. }
  324. //lets check if the directory is empty if it is we will delete it as well
  325. $files_remaining = $this->dir_file_count($cp['to']);
  326. if(file_exists($cp['to']) && $files_remaining == 0){
  327. $GLOBALS['log']->debug('ModuleInstaller[uninstall_new_file] deleting directory ' . $cp['to']);
  328. rmdir_recursive($cp['to']);
  329. }
  330. }
  331. function install_dashlets(){
  332. if(isset($this->installdefs['dashlets'])){
  333. foreach($this->installdefs['dashlets'] as $cp){
  334. $this->log(translate('LBL_MI_IN_DASHLETS') . $cp['name']);
  335. $cp['from'] = str_replace('<basepath>', $this->base_dir, $cp['from']);
  336. $path = 'custom/modules/Home/Dashlets/' . $cp['name'] . '/';
  337. $GLOBALS['log']->debug("Installing Dashlet " . $cp['name'] . "..." . $cp['from'] );
  338. if(!file_exists($path)){
  339. mkdir_recursive($path, true);
  340. }
  341. copy_recursive($cp['from'] , $path);
  342. }
  343. include('modules/Administration/RebuildDashlets.php');
  344. }
  345. }
  346. function uninstall_dashlets(){
  347. if(isset($this->installdefs['dashlets'])){
  348. foreach($this->installdefs['dashlets'] as $cp){
  349. $this->log(translate('LBL_MI_UN_DASHLETS') . $cp['name']);
  350. $path = 'custom/modules/Home/Dashlets/' . $cp['name'];
  351. $GLOBALS['log']->debug('Unlink ' .$path);
  352. if (file_exists($path))
  353. rmdir_recursive($path);
  354. }
  355. include('modules/Administration/RebuildDashlets.php');
  356. }
  357. }
  358. function install_images(){
  359. if(isset($this->installdefs['image_dir'])){
  360. $this->log( translate('LBL_MI_IN_IMAGES') );
  361. $this->copy_path($this->installdefs['image_dir'] , 'custom/themes');
  362. }
  363. }
  364. function install_menus(){
  365. if(isset($this->installdefs['menu'])){
  366. $this->log(translate('LBL_MI_IN_MENUS'));
  367. foreach($this->installdefs['menu'] as $menu){
  368. $menu['from'] = str_replace('<basepath>', $this->base_dir, $menu['from']);
  369. $GLOBALS['log']->debug("Installing Menu ..." . $menu['from']. " for " .$menu['to_module'] );
  370. $path = 'custom/Extension/modules/' . $menu['to_module']. '/Ext/Menus';
  371. if($menu['to_module'] == 'application'){
  372. $path ='custom/Extension/' . $menu['to_module']. '/Ext/Menus';
  373. }
  374. if(!file_exists($path)){
  375. mkdir_recursive($path, true);
  376. }
  377. copy_recursive($menu['from'] , $path . '/'. $this->id_name . '.php');
  378. }
  379. $this->rebuild_menus();
  380. }
  381. }
  382. function uninstall_menus(){
  383. if(isset($this->installdefs['menu'])){
  384. $this->log(translate('LBL_MI_UN_MENUS'));
  385. foreach($this->installdefs['menu'] as $menu){
  386. $menu['from'] = str_replace('<basepath>', $this->base_dir, $menu['from']);
  387. $GLOBALS['log']->debug("Uninstalling Menu ..." . $menu['from']. " for " .$menu['to_module'] );
  388. $path = 'custom/Extension/modules/' . $menu['to_module']. '/Ext/Menus';
  389. if($menu['to_module'] == 'application'){
  390. $path ='custom/Extension/' . $menu['to_module']. '/Ext/Menus';
  391. }
  392. if (sugar_is_file($path . '/'. $this->id_name . '.php', 'w'))
  393. {
  394. rmdir_recursive( $path . '/'. $this->id_name . '.php');
  395. }
  396. else if (sugar_is_file($path . '/'. DISABLED_PATH . '/'. $this->id_name . '.php', 'w'))
  397. {
  398. rmdir_recursive( $path . '/'. DISABLED_PATH . '/'. $this->id_name . '.php');
  399. }
  400. }
  401. $this->rebuild_menus();
  402. }
  403. }
  404. function install_dcactions(){
  405. if(isset($this->installdefs['dcaction'])){
  406. $this->log(translate('LBL_MI_IN_MENUS'));
  407. foreach($this->installdefs['dcaction'] as $action){
  408. $action['from'] = str_replace('<basepath>', $this->base_dir, $action['from']);
  409. $GLOBALS['log']->debug("Installing DCActions ..." . $action['from']);
  410. $path = 'custom/Extension/application/Ext/DashletContainer/Containers';
  411. if(!file_exists($path)){
  412. mkdir_recursive($path, true);
  413. }
  414. copy_recursive($action['from'] , $path . '/'. $this->id_name . '.php');
  415. }
  416. $this->rebuild_dashletcontainers();
  417. }
  418. }
  419. function uninstall_dcactions(){
  420. if(isset($this->installdefs['dcaction'])){
  421. $this->log(translate('LBL_MI_UN_MENUS'));
  422. foreach($this->installdefs['dcaction'] as $action){
  423. $action['from'] = str_replace('<basepath>', $this->base_dir, $action['from']);
  424. $GLOBALS['log']->debug("Uninstalling DCActions ..." . $action['from'] );
  425. $path = 'custom/Extension/application/Ext/DashletContainer/Containers';
  426. if (sugar_is_file($path . '/'. $this->id_name . '.php', 'w'))
  427. {
  428. rmdir_recursive( $path . '/'. $this->id_name . '.php');
  429. }
  430. else if (sugar_is_file($path . '/'. DISABLED_PATH . '/'. $this->id_name . '.php', 'w'))
  431. {
  432. rmdir_recursive( $path . '/'. DISABLED_PATH . '/'. $this->id_name . '.php');
  433. }
  434. }
  435. $this->rebuild_dashletcontainers();
  436. }
  437. }
  438. function install_administration(){
  439. if(isset($this->installdefs['administration'])){
  440. $this->log(translate('LBL_MI_IN_ADMIN'));
  441. foreach($this->installdefs['administration'] as $administration){
  442. $administration['from'] = str_replace('<basepath>', $this->base_dir, $administration['from']);
  443. $GLOBALS['log']->debug("Installing Administration Section ..." . $administration['from'] );
  444. $path = 'custom/Extension/modules/Administration/Ext/Administration';
  445. if(!file_exists($path)){
  446. mkdir_recursive($path, true);
  447. }
  448. copy_recursive($administration['from'] , $path . '/'. $this->id_name . '.php');
  449. }
  450. $this->rebuild_administration();
  451. }
  452. }
  453. function uninstall_administration(){
  454. if(isset($this->installdefs['administration'])){
  455. $this->log(translate('LBL_MI_UN_ADMIN'));
  456. foreach($this->installdefs['administration'] as $administration){
  457. $administration['from'] = str_replace('<basepath>', $this->base_dir, $administration['from']);
  458. $GLOBALS['log']->debug("Uninstalling Administration Section ..." . $administration['from'] );
  459. $path = 'custom/Extension/modules/Administration/Ext/Administration';
  460. if (sugar_is_file($path . '/'. $this->id_name . '.php', "w"))
  461. rmdir_recursive( $path . '/'. $this->id_name . '.php');
  462. else if (sugar_is_file($path . '/'. DISABLED_PATH . "/" . $this->id_name . '.php', "w"))
  463. rmdir_recursive( $path . '/'. DISABLED_PATH . "/" . $this->id_name . '.php');
  464. }
  465. $this->rebuild_administration();
  466. }
  467. }
  468. function install_connectors(){
  469. if(isset($this->installdefs['connectors'])){
  470. foreach($this->installdefs['connectors'] as $cp){
  471. $this->log(translate('LBL_MI_IN_CONNECTORS') . $cp['name']);
  472. $dir = str_replace('_','/',$cp['name']);
  473. $cp['connector'] = str_replace('<basepath>', $this->base_dir, $cp['connector']);
  474. $source_path = 'custom/modules/Connectors/connectors/sources/' . $dir. '/';
  475. $GLOBALS['log']->debug("Installing Connector " . $cp['name'] . "..." . $cp['connector'] );
  476. if(!file_exists($source_path)){
  477. mkdir_recursive($source_path, true);
  478. }
  479. copy_recursive($cp['connector'] , $source_path);
  480. //Install optional formatter code if it is specified
  481. if(!empty($cp['formatter'])) {
  482. $cp['formatter'] = str_replace('<basepath>', $this->base_dir, $cp['formatter']);
  483. $formatter_path = 'custom/modules/Connectors/connectors/formatters/' . $dir. '/';
  484. if(!file_exists($formatter_path)){
  485. mkdir_recursive($formatter_path, true);
  486. }
  487. copy_recursive($cp['formatter'] , $formatter_path);
  488. }
  489. }
  490. require_once('include/connectors/utils/ConnectorUtils.php');
  491. ConnectorUtils::installSource($cp['name']);
  492. }
  493. }
  494. function uninstall_connectors(){
  495. if(isset($this->installdefs['connectors'])){
  496. foreach($this->installdefs['connectors'] as $cp){
  497. $this->log(translate('LBL_MI_UN_CONNECTORS') . $cp['name']);
  498. $dir = str_replace('_','/',$cp['name']);
  499. $source_path = 'custom/modules/Connectors/connectors/sources/' . $dir;
  500. $formatter_path = 'custom/modules/Connectors/connectors/formatters/' . $dir;
  501. $GLOBALS['log']->debug('Unlink ' .$source_path);
  502. rmdir_recursive($source_path);
  503. rmdir_recursive($formatter_path);
  504. }
  505. require_once('include/connectors/utils/ConnectorUtils.php');
  506. //ConnectorUtils::getConnectors(true);
  507. ConnectorUtils::uninstallSource($cp['name']);
  508. }
  509. }
  510. function install_userpage(){
  511. if(isset($this->installdefs['user_page'])){
  512. $this->log(translate('LBL_MI_IN_USER'));
  513. foreach($this->installdefs['user_page'] as $userpage){
  514. $userpage['from'] = str_replace('<basepath>', $this->base_dir, $userpage['from']);
  515. $GLOBALS['log']->debug("Installing User Page Section ..." . $userpage['from'] );
  516. $path = 'custom/Extension/modules/Users/Ext/UserPage';
  517. if(!file_exists($path)){
  518. mkdir_recursive($path, true);
  519. }
  520. copy_recursive($userpage['from'] , $path . '/'. $this->id_name . '.php');
  521. }
  522. $this->rebuild_userpage();
  523. }
  524. }
  525. function uninstall_userpage(){
  526. if(isset($this->installdefs['user_page'])){
  527. $this->log(translate('LBL_MI_UN_USER') );
  528. foreach($this->installdefs['user_page'] as $userpage){
  529. $userpage['from'] = str_replace('<basepath>', $this->base_dir, $userpage['from']);
  530. $GLOBALS['log']->debug("Uninstalling User Page Section ..." . $userpage['from'] );
  531. $path = 'custom/Extension/modules/Users/Ext/UserPage';
  532. rmdir_recursive( $path . '/'. $this->id_name . '.php');
  533. }
  534. $this->rebuild_userpage();
  535. }
  536. }
  537. /*
  538. * ModuleInstaller->install_vardefs uses the vardefs section of the installdefs and copies from the 'from' path (replacing <basepath> as usual) to either
  539. * custom/Extension/modules/<module>/Ext/Vardefs or custom/Extension/<module>/Ext/Vardefs if the 'to_module' value in the installdefs is set to 'application'.
  540. * Finally rebuild_vardefs() is used to merge /Ext/Vardefs into vardefs.ext.php
  541. */
  542. function install_vardefs(){
  543. if(isset($this->installdefs['vardefs'])){
  544. $this->log(translate('LBL_MI_IN_VAR') );
  545. foreach($this->installdefs['vardefs'] as $vardefs){
  546. $vardefs['from'] = str_replace('<basepath>', $this->base_dir, $vardefs['from']);
  547. $this->install_vardef($vardefs['from'], $vardefs['to_module'], $this->id_name);
  548. }
  549. $this->rebuild_vardefs();
  550. }
  551. }
  552. function uninstall_vardefs(){
  553. if(isset($this->installdefs['vardefs'])){
  554. $this->log(translate('LBL_MI_UN_VAR') );
  555. foreach($this->installdefs['vardefs'] as $vardefs){
  556. $vardefs['from'] = str_replace('<basepath>', $this->base_dir, $vardefs['from']);
  557. $GLOBALS['log']->debug("Uninstalling Vardefs ..." . $vardefs['from'] . " for " .$vardefs['to_module']);
  558. $path = 'custom/Extension/modules/' . $vardefs['to_module']. '/Ext/Vardefs';
  559. if($vardefs['to_module'] == 'application'){
  560. $path ='custom/Extension/' . $vardefs['to_module']. '/Ext/Vardefs';
  561. }
  562. if(file_exists($path . '/'. $this->id_name . '.php'))
  563. {
  564. rmdir_recursive( $path . '/'. $this->id_name . '.php');
  565. }
  566. else if(file_exists($path . '/'. DISABLED_PATH . '/'. $this->id_name . '.php'))
  567. {
  568. rmdir_recursive($path . '/'. DISABLED_PATH . '/'. $this->id_name . '.php');
  569. }
  570. else if (file_exists($path . '/'. basename($vardefs['from'] )))
  571. {
  572. rmdir_recursive( $path . '/'. basename($vardefs['from'] ));
  573. }
  574. else if(file_exists($path . '/'. DISABLED_PATH . '/'. basename($vardefs['from'])))
  575. {
  576. rmdir_recursive($path . '/'. DISABLED_PATH . '/'. basename($vardefs['from']));
  577. }
  578. }
  579. $this->rebuild_vardefs();
  580. }
  581. }
  582. function install_vardef($from, $to_module){
  583. $GLOBALS['log']->debug("Installing Vardefs ..." . $from . " for " .$to_module);
  584. $path = 'custom/Extension/modules/' . $to_module. '/Ext/Vardefs';
  585. if($to_module == 'application'){
  586. $path ='custom/Extension/' . $to_module. '/Ext/Vardefs';
  587. }
  588. if(!file_exists($path)){
  589. mkdir_recursive($path, true);
  590. }
  591. copy_recursive($from , $path.'/'. basename($from));
  592. }
  593. /*
  594. * ModuleInstaller->install_layoutdefs installs the $layout_defs variable (subpanel definitions) from Ext/Layoutdefs to the to_module location of
  595. * custom/Extension/modules/' . $to_module. '/Ext/Layoutdefs/<$module>.php. before calling rebuild_layoutdefs which merge_files Ext/Layoutdefs/, 'layoutdefs.ext.php'. Note that this is not used for the viewdefs in the metadata directory - they are installed through the install_copy() operation that just takes the contents of the module directory and places it in the /modules area.
  596. */
  597. function install_layoutdefs(){
  598. if(isset($this->installdefs['layoutdefs'])){
  599. $this->log(translate('LBL_MI_IN_SUBPANEL') );
  600. foreach($this->installdefs['layoutdefs'] as $layoutdefs){
  601. $layoutdefs['from'] = str_replace('<basepath>', $this->base_dir, $layoutdefs['from']);
  602. $this->install_layoutdef($layoutdefs['from'], $layoutdefs['to_module'], $this->id_name);
  603. }
  604. $this->rebuild_layoutdefs();
  605. }
  606. }
  607. function uninstall_layoutdefs(){
  608. if(isset($this->installdefs['layoutdefs'])){
  609. $this->log(translate('LBL_MI_UN_SUBPANEL') );
  610. foreach($this->installdefs['layoutdefs'] as $layoutdefs){
  611. $layoutdefs['from'] = str_replace('<basepath>', $this->base_dir, $layoutdefs['from']);
  612. $GLOBALS['log']->debug("Uninstalling Layoutdefs ..." . $layoutdefs['from'] . " for " .$layoutdefs['to_module']);
  613. $path = 'custom/Extension/modules/' . $layoutdefs['to_module']. '/Ext/Layoutdefs';
  614. if($layoutdefs['to_module'] == 'application'){
  615. $path ='custom/Extension/' . $layoutdefs['to_module']. '/Ext/Layoutdefs';
  616. }
  617. if (file_exists($path . '/'. $this->id_name . '.php'))
  618. {
  619. rmdir_recursive( $path . '/'. $this->id_name . '.php');
  620. }
  621. else if (file_exists($path . '/'. DISABLED_PATH . '/' . $this->id_name . '.php'))
  622. {
  623. rmdir_recursive($path . '/'. DISABLED_PATH . '/' . $this->id_name . '.php');
  624. }
  625. else if (file_exists($path . '/'. basename($layoutdefs['from'] )))
  626. {
  627. rmdir_recursive( $path . '/'. basename($layoutdefs['from'] ));
  628. }
  629. else if(file_exists($path . '/'. DISABLED_PATH . '/'. basename($layoutdefs['from'])))
  630. {
  631. rmdir_recursive($path . '/'. DISABLED_PATH . '/'. basename($layoutdefs['from']));
  632. }
  633. }
  634. $this->rebuild_layoutdefs();
  635. }
  636. }
  637. function install_layoutdef($from, $to_module){
  638. $GLOBALS['log']->debug("Installing Layout Defs ..." . $from . " for " .$to_module);
  639. $path = 'custom/Extension/modules/' . $to_module. '/Ext/Layoutdefs';
  640. if($to_module == 'application'){
  641. $path ='custom/Extension/' . $to_module. '/Ext/Layoutdefs';
  642. }
  643. if(!file_exists($path)){
  644. mkdir_recursive($path, true);
  645. }
  646. copy_recursive($from , $path.'/'. basename($from));
  647. }
  648. function install_languages()
  649. {
  650. $languages = array();
  651. if(isset($this->installdefs['language']))
  652. {
  653. $this->log(translate('LBL_MI_IN_LANG') );
  654. foreach($this->installdefs['language'] as $packs)
  655. {
  656. $modules[]=$packs['to_module'];
  657. $languages[$packs['language']] = $packs['language'];
  658. $packs['from'] = str_replace('<basepath>', $this->base_dir, $packs['from']);
  659. $GLOBALS['log']->debug("Installing Language Pack ..." . $packs['from'] . " for " .$packs['to_module']);
  660. $path = 'custom/Extension/modules/' . $packs['to_module']. '/Ext/Language';
  661. if($packs['to_module'] == 'application'){
  662. $path ='custom/Extension/' . $packs['to_module']. '/Ext/Language';
  663. }
  664. if(!file_exists($path)){
  665. mkdir_recursive($path, true);
  666. }
  667. copy_recursive($packs['from'] , $path.'/'.$packs['language'].'.'. $this->id_name . '.php');
  668. }
  669. $this->rebuild_languages($languages, $modules);
  670. }
  671. }
  672. function uninstall_languages(){
  673. $languages = array();
  674. if(isset($this->installdefs['language'])){
  675. $this->log(translate('LBL_MI_UN_LANG') );
  676. foreach($this->installdefs['language'] as $packs){
  677. $modules[]=$packs['to_module'];
  678. $languages[$packs['language']] = $packs['language'];
  679. $packs['from'] = str_replace('<basepath>', $this->base_dir, $packs['from']);
  680. $GLOBALS['log']->debug("Uninstalling Language Pack ..." . $packs['from'] . " for " .$packs['to_module']);
  681. $path = 'custom/Extension/modules/' . $packs['to_module']. '/Ext/Language';
  682. if($packs['to_module'] == 'application'){
  683. $path ='custom/Extension/' . $packs['to_module']. '/Ext/Language';
  684. }
  685. if (sugar_is_file($path.'/'.$packs['language'].'.'. $this->id_name . '.php', 'w')) {
  686. rmdir_recursive( $path.'/'.$packs['language'].'.'. $this->id_name . '.php');
  687. } else if (sugar_is_file($path.'/'.DISABLED_PATH.'/'.$packs['language'].'.'. $this->id_name . '.php', 'w')) {
  688. rmdir_recursive($path.'/'.DISABLED_PATH.'/'.$packs['language'].'.'. $this->id_name . '.php', 'w');
  689. }
  690. }
  691. $this->rebuild_languages($languages, $modules);
  692. }
  693. }
  694. // Functions for adding and removing logic hooks from uploaded files
  695. // Since one class/file can be used by multiple logic hooks, I'm not going to touch the file labeled in the logic_hook entry
  696. /* The module hook definition should look like this:
  697. $installdefs = array(
  698. ... blah blah ...
  699. 'logic_hooks' => array(
  700. array('module' => 'Accounts',
  701. 'hook' => 'after_save',
  702. 'order' => 99,
  703. 'description' => 'Account sample logic hook',
  704. 'file' => 'modules/Sample/sample_account_logic_hook_file.php',
  705. 'class' => 'SampleLogicClass',
  706. 'function' => 'accountAfterSave',
  707. ),
  708. ),
  709. ... blah blah ...
  710. );
  711. */
  712. function install_logichooks() {
  713. // Since the logic hook files get copied over with the rest of the module directory, we just need to enable them
  714. $this->enable_logichooks();
  715. }
  716. function uninstall_logichooks() {
  717. // Since the logic hook files get removed with the rest of the module directory, we just need to disable them
  718. $this->disable_logichooks();
  719. }
  720. function enable_logichooks() {
  721. if(empty($this->installdefs['logic_hooks']) || !is_array($this->installdefs['logic_hooks'])) {
  722. return;
  723. }
  724. foreach($this->installdefs['logic_hooks'] as $hook ) {
  725. check_logic_hook_file($hook['module'], $hook['hook'], array($hook['order'], $hook['description'], $hook['file'], $hook['class'], $hook['function']));
  726. }
  727. }
  728. function disable_logichooks() {
  729. if(empty($this->installdefs['logic_hooks']) || !is_array($this->installdefs['logic_hooks'])) {
  730. return;
  731. }
  732. foreach($this->installdefs['logic_hooks'] as $hook ) {
  733. remove_logic_hook($hook['module'], $hook['hook'], array($hook['order'], $hook['description'], $hook['file'], $hook['class'], $hook['function']));
  734. }
  735. }
  736. /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
  737. function copy_path($from, $to, $backup_path='', $uninstall=false){
  738. //function copy_path($from, $to){
  739. /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
  740. $to = str_replace('<basepath>', $this->base_dir, $to);
  741. if(!$uninstall) {
  742. $from = str_replace('<basepath>', $this->base_dir, $from);
  743. $GLOBALS['log']->debug('Copy ' . $from);
  744. }
  745. else {
  746. $from = str_replace('<basepath>', $backup_path, $from);
  747. //$GLOBALS['log']->debug('Restore ' . $from);
  748. }
  749. $from = clean_path($from);
  750. $to = clean_path($to);
  751. $dir = dirname($to);
  752. //there are cases where if we need to create a directory in the root directory
  753. if($dir == '.' && is_dir($from)){
  754. $dir = $to;
  755. }
  756. if(!sugar_is_dir($dir, 'instance'))
  757. mkdir_recursive($dir, true);
  758. /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
  759. if(empty($backup_path)) {
  760. /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
  761. if(!copy_recursive($from, $to)){
  762. die('Failed to copy ' . $from. ' ' . $to);
  763. }
  764. /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
  765. }
  766. elseif(!$this->copy_recursive_with_backup($from, $to, $backup_path, $uninstall)){
  767. die('Failed to copy ' . $from. ' to ' . $to);
  768. }
  769. /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
  770. }
  771. function install_custom_fields($fields){
  772. global $beanList, $beanFiles;
  773. include('include/modules.php');
  774. require_once('modules/DynamicFields/FieldCases.php');
  775. foreach($fields as $field){
  776. $installed = false;
  777. if(isset($beanList[ $field['module']])){
  778. $class = $beanList[ $field['module']];
  779. if(!isset($field['ext4']))$field['ext4'] = '';
  780. if(!isset($field['mass_update']))$field['mass_update'] = 0;
  781. if(!isset($field['duplicate_merge']))$field['duplicate_merge'] = 0;
  782. if(!isset($field['help']))$field['help'] = '';
  783. if(file_exists($beanFiles[$class])){
  784. require_once($beanFiles[$class]);
  785. $mod = new $class();
  786. $installed = true;
  787. $fieldObject = get_widget($field['type']);
  788. $fieldObject->populateFromRow($field);
  789. $mod->custom_fields->use_existing_labels = true;
  790. $mod->custom_fields->addFieldObject($fieldObject);
  791. }
  792. }
  793. if(!$installed){
  794. $GLOBALS['log']->debug('Could not install custom field ' . $field['name'] . ' for module ' . $field['module'] . ': Module does not exist');
  795. }
  796. }
  797. }
  798. function uninstall_custom_fields($fields){
  799. global $beanList, $beanFiles;
  800. require_once('modules/DynamicFields/DynamicField.php');
  801. $dyField = new DynamicField();
  802. foreach($fields as $field){
  803. $class = $beanList[ $field['module']];
  804. if(file_exists($beanFiles[$class])){
  805. require_once($beanFiles[$class]);
  806. $mod = new $class();
  807. $dyField->bean = $mod;
  808. $dyField->module = $field['module'];
  809. $dyField->deleteField($field['name']);
  810. }
  811. }
  812. }
  813. /*
  814. * ModuleInstaller->install_relationships calls install_relationship for every file included in the module package that defines a relationship, and then
  815. * writes a custom/Extension/application/Ext/TableDictionary/$module.php file containing an include_once for every relationship metadata file passed to install_relationship.
  816. * Next it calls install_vardef and install_layoutdef. Finally, it rebuilds the vardefs and layoutdefs (by calling merge_files as usual), and then calls merge_files to merge
  817. * everything in 'Ext/TableDictionary/' into 'tabledictionary.ext.php'
  818. */
  819. function install_relationships ()
  820. {
  821. if (isset ( $this->installdefs [ 'relationships' ] ))
  822. {
  823. $this->log ( translate ( 'LBL_MI_IN_RELATIONSHIPS' ) ) ;
  824. $str = "<?php \n //WARNING: The contents of this file are auto-generated\n" ;
  825. $save_table_dictionary = false ;
  826. if (! file_exists ( "custom/Extension/application/Ext/TableDictionary" ))
  827. {
  828. mkdir_recursive ( "custom/Extension/application/Ext/TableDictionary", true ) ;
  829. }
  830. foreach ( $this->installdefs [ 'relationships' ] as $key => $relationship )
  831. {
  832. $filename = basename ( $relationship [ 'meta_data' ] ) ;
  833. $this->copy_path ( $relationship [ 'meta_data' ], 'custom/metadata/' . $filename ) ;
  834. $this->install_relationship ( 'custom/metadata/' . $filename ) ;
  835. $save_table_dictionary = true ;
  836. if (! empty ( $relationship [ 'module_vardefs' ] ))
  837. {
  838. $relationship [ 'module_vardefs' ] = str_replace ( '<basepath>', $this->base_dir, $relationship [ 'module_vardefs' ] ) ;
  839. $this->install_vardef ( $relationship [ 'module_vardefs' ], $relationship [ 'module' ] ) ;
  840. }
  841. if (! empty ( $relationship [ 'module_layoutdefs' ] ))
  842. {
  843. $relationship [ 'module_layoutdefs' ] = str_replace ( '<basepath>', $this->base_dir, $relationship [ 'module_layoutdefs' ] ) ;
  844. $this->install_layoutdef ( $relationship [ 'module_layoutdefs' ], $relationship [ 'module' ] ) ;
  845. }
  846. $relName = strpos($filename, "MetaData") !== false ? substr($filename, 0, strlen($filename) - 12) : $filename;
  847. $out = sugar_fopen ( "custom/Extension/application/Ext/TableDictionary/$relName.php", 'w' ) ;
  848. fwrite ( $out, $str . "include('custom/metadata/$filename');\n\n?>" ) ;
  849. fclose ( $out ) ;
  850. }
  851. $this->rebuild_vardefs () ;
  852. $this->rebuild_layoutdefs () ;
  853. if ($save_table_dictionary)
  854. {
  855. $this->rebuild_tabledictionary () ;
  856. }
  857. }
  858. }
  859. /*
  860. * Install_relationship obtains a set of relationship definitions from the filename passed in as a parameter.
  861. * For each definition it calls db->createTableParams to build the relationships table if it does not exist,
  862. * and SugarBean::createRelationshipMeta to add the relationship into the 'relationships' table.
  863. */
  864. function install_relationship($file)
  865. {
  866. $_REQUEST['moduleInstaller'] = true;
  867. if(!file_exists($file))
  868. {
  869. $GLOBALS['log']->debug( 'File does not exists : '.$file);
  870. return;
  871. }
  872. include($file);
  873. $rel_dictionary = $dictionary;
  874. foreach ($rel_dictionary as $rel_name => $rel_data)
  875. {
  876. $table = ''; // table is actually optional
  877. // check if we have a table definition - not all relationships require a join table
  878. if ( isset( $rel_data[ 'table' ] ) )
  879. {
  880. $table = $rel_data[ 'table' ];
  881. if(!$this->db->tableExists($table))
  882. {
  883. $this->db->createTableParams($table, $rel_data[ 'fields' ], $rel_data[ 'indices' ]);
  884. }
  885. }
  886. if(!$this->silent)
  887. $GLOBALS['log']->debug("Processing relationship meta for ". $rel_name."...");
  888. SugarBean::createRelationshipMeta($rel_name, $this->db,$table,$rel_dictionary,'');
  889. Relationship::delete_cache();
  890. if(!$this->silent)
  891. $GLOBALS['log']->debug( 'done<br>');
  892. }
  893. }
  894. function install_layoutfields() {
  895. if (!empty ( $this->installdefs [ 'layoutfields' ] ))
  896. {
  897. foreach ( $this->installdefs [ 'layoutfields' ] as $fieldSet )
  898. {
  899. if (!empty($fieldSet['additional_fields']))
  900. {
  901. $this->addFieldsToLayout($fieldSet['additional_fields']);
  902. }
  903. }
  904. }
  905. }
  906. function uninstall_layoutfields() {
  907. if (!empty ( $this->installdefs [ 'layoutfields' ] ))
  908. {
  909. foreach ( $this->installdefs [ 'layoutfields' ] as $fieldSet )
  910. {
  911. if (!empty($fieldSet['additional_fields']))
  912. {
  913. $this->removeFieldsFromLayout($fieldSet['additional_fields']);
  914. }
  915. }
  916. }
  917. }
  918. function uninstall_relationship($file, $rel_dictionary = null){
  919. if ($rel_dictionary == null)
  920. {
  921. if(!file_exists($file)){
  922. $GLOBALS['log']->debug( 'File does not exists : '.$file);
  923. return;
  924. }
  925. include($file);
  926. $rel_dictionary = $dictionary;
  927. }
  928. foreach ($rel_dictionary as $rel_name => $rel_data)
  929. {
  930. if (!empty($rel_data['table'])){
  931. $table = $rel_data['table'];
  932. }
  933. else{
  934. $table = ' One-to-Many ';
  935. }
  936. if ($this->db->tableExists($table) && isset($GLOBALS['mi_remove_tables']) && $GLOBALS['mi_remove_tables'])
  937. {
  938. SugarBean::removeRelationshipMeta($rel_name, $this->db,$table,$rel_dictionary,'');
  939. $this->db->dropTableName($table);
  940. if(!$this->silent) $this->log( translate('LBL_MI_UN_RELATIONSHIPS_DROP') . $table);
  941. }
  942. //Delete Layout defs
  943. // check to see if we have any vardef or layoutdef entries to remove - must have a relationship['module'] parameter if we do
  944. if (!isset($rel_data[ 'module' ]))
  945. $mods = array(
  946. $rel_data['relationships'][$rel_name]['lhs_module'],
  947. $rel_data['relationships'][$rel_name]['rhs_module'],
  948. );
  949. else
  950. $mods = array($rel_data[ 'module' ]);
  951. $filename = "$rel_name.php";
  952. foreach($mods as $mod) {
  953. if ($mod != 'application' ) {
  954. $basepath = "custom/Extension/modules/$mod/Ext/";
  955. } else {
  956. $basepath = "custom/Extension/application/Ext/";
  957. }
  958. foreach (array($filename , "custom" . $filename) as $fn) {
  959. //remove any vardefs
  960. $path = $basepath . "Vardefs/$fn" ;
  961. if (file_exists( $path ))
  962. rmdir_recursive( $path );
  963. //remove any layoutdefs
  964. $path = $basepath . "Layoutdefs/$fn" ;
  965. if( file_exists( $path ))
  966. {
  967. rmdir_recursive( $path );
  968. }
  969. }
  970. }
  971. foreach (array($filename , "custom" . $filename) as $fn) {
  972. // remove the table dictionary extension
  973. if ( file_exists("custom/Extension/application/Ext/TableDictionary/$fn"))
  974. unlink("custom/Extension/application/Ext/TableDictionary/$fn");
  975. if (file_exists("custom/metadata/{$rel_name}MetaData.php"))
  976. unlink( "custom/metadata/{$rel_name}MetaData.php" );
  977. }
  978. }
  979. }
  980. function uninstall_relationships($include_studio_relationships = false){
  981. $relationships = array();
  982. //Find and remove studio created relationships.
  983. global $beanList, $beanFiles, $dictionary;
  984. //Load up the custom relationship definitions.
  985. if(file_exists('custom/application/Ext/TableDictionary/tabledictionary.ext.php')){
  986. include('custom/application/Ext/TableDictionary/tabledictionary.ext.php');
  987. }
  988. //Find all the relatioships/relate fields involving this module.
  989. $rels_to_remove = array();
  990. foreach($beanList as $mod => $bean) {
  991. VardefManager::loadVardef($mod, $bean);
  992. //We can skip modules that are in this package as they will be removed anyhow
  993. if (!in_array($mod, $this->modulesInPackage) && !empty($dictionary[$bean]) && !empty($dictionary[$bean]['fields']))
  994. {
  995. $field_defs = $dictionary[$bean]['fields'];
  996. foreach($field_defs as $field => $def)
  997. {
  998. //Weed out most fields first
  999. if (isset ($def['type']))
  1000. {
  1001. //Custom relationships created in the relationship editor
  1002. if ($def['type'] == "link" && !empty($def['relationship']) && !empty($dictionary[$def['relationship']]))
  1003. {
  1004. $rel_name = $def['relationship'];
  1005. $rel_def = $dictionary[$rel_name]['relationships'][$rel_name];
  1006. //Check against mods to be removed.
  1007. foreach($this->modulesInPackage as $removed_mod) {
  1008. if ($rel_def['lhs_module'] == $removed_mod || $rel_def['rhs_module'] == $removed_mod )
  1009. {
  1010. $dictionary[$rel_name]['from_studio'] = true;
  1011. $relationships[$rel_name] = $dictionary[$rel_name];
  1012. }
  1013. }
  1014. }
  1015. //Custom "relate" fields created in studio also need to be removed
  1016. if ($def['type'] == 'relate' && isset($def['module'])) {
  1017. foreach($this->modulesInPackage as $removed_mod) {
  1018. if ($def['module'] == $removed_mod)
  1019. {
  1020. require_once 'modules/ModuleBuilder/Module/StudioModule.php' ;
  1021. $studioMod = new StudioModule ( $mod );
  1022. $studioMod->removeFieldFromLayouts( $field );
  1023. if (isset($def['custom_module'])) {
  1024. require_once ('modules/DynamicFields/DynamicField.php') ;
  1025. require_once ($beanFiles [ $bean ]) ;
  1026. $seed = new $bean ( ) ;
  1027. $df = new DynamicField ( $mod ) ;
  1028. $df->setup ( $seed ) ;
  1029. //Need to load the entire field_meta_data for some field types
  1030. $field_obj = $df->getFieldWidget($mod, $field);
  1031. $field_obj->delete ( $df ) ;
  1032. }
  1033. }
  1034. }
  1035. }
  1036. }
  1037. }
  1038. }
  1039. }
  1040. $this->uninstall_relationship(null, $relationships);
  1041. if(isset($this->installdefs['relationships'])) {
  1042. $relationships = $this->installdefs['relationships'];
  1043. $this->log(translate('LBL_MI_UN_RELATIONSHIPS') );
  1044. foreach($relationships as $relationship)
  1045. {
  1046. // remove the metadata entry
  1047. $filename = basename ( $relationship['meta_data'] );
  1048. $pathname = (file_exists("custom/metadata/$filename")) ? "custom/metadata/$filename" : "metadata/$filename" ;
  1049. if(isset($GLOBALS['mi_remove_tables']) && $GLOBALS['mi_remove_tables'])
  1050. $this->uninstall_relationship( $pathname );
  1051. if (file_exists($pathname))
  1052. unlink( $pathname );
  1053. }
  1054. }
  1055. if (file_exists("custom/Extension/application/Ext/TableDictionary/{$this->id_name}.php"))
  1056. unlink("custom/Extension/application/Ext/TableDictionary/{$this->id_name}.php");
  1057. Relationship::delete_cache();
  1058. $this->rebuild_tabledictionary();
  1059. }
  1060. function uninstall($base_dir){
  1061. if(defined('TEMPLATE_URL'))SugarTemplateUtilities::disableCache();
  1062. global $app_strings;
  1063. $total_steps = 5; //min steps with no tasks
  1064. $current_step = 0;
  1065. $this->base_dir = $base_dir;
  1066. $tasks = array(
  1067. 'pre_uninstall',
  1068. 'uninstall_relationships',
  1069. 'uninstall_copy',
  1070. 'uninstall_dcactions',
  1071. 'uninstall_menus',
  1072. 'uninstall_dashlets',
  1073. 'uninstall_userpage',
  1074. 'uninstall_administration',
  1075. 'uninstall_connectors',
  1076. 'uninstall_vardefs',
  1077. 'uninstall_layoutdefs',
  1078. 'uninstall_layoutfields',
  1079. 'uninstall_languages',
  1080. 'uninstall_logichooks',
  1081. 'post_uninstall',
  1082. );
  1083. $total_steps += count($tasks); //now the real number of steps
  1084. if(file_exists($this->base_dir . '/manifest.php')){
  1085. if(!$this->silent){
  1086. $current_step++;
  1087. display_progress_bar('install', $current_step, $total_steps);
  1088. echo '<div id ="displayLoglink" ><a href="#" onclick="toggleDisplay(\'displayLog\')">'.$app_strings['LBL_DISPLAY_LOG'].'</a> </div><div id="displayLog" style="display:none">';
  1089. }
  1090. global $moduleList;
  1091. include($this->base_dir . '/manifest.php');
  1092. $this->installdefs = $installdefs;
  1093. $this->id_name = $this->installdefs['id'];
  1094. $installed_modules = array();
  1095. if(isset($this->installdefs['beans'])){
  1096. foreach($this->installdefs['beans'] as $bean){
  1097. $installed_modules[] = $bean['module'];
  1098. $this->uninstall_user_prefs($bean['module']);
  1099. }
  1100. $this->modulesInPackage = $installed_modules;
  1101. $this->uninstall_beans($installed_modules);
  1102. $this->uninstall_customizations($installed_modules);
  1103. if(!$this->silent){
  1104. $current_step++;
  1105. update_progress_bar('install', $total_steps, $total_steps);
  1106. }
  1107. if (sugar_is_file("custom/Extension/application/Ext/Include/$this->id_name.php", 'w'))
  1108. rmdir_recursive("custom/Extension/application/Ext/Include/$this->id_name.php");
  1109. else if(sugar_is_file("custom/Extension/application/Ext/Include/" . DISABLED_PATH . "/$this->id_name.php", 'w'))
  1110. rmdir_recursive("custom/Extension/application/Ext/Include/" . DISABLED_PATH . "/$this->id_name.php");
  1111. $this->rebuild_modules();
  1112. }
  1113. if(!$this->silent){
  1114. $current_step++;
  1115. update_progress_bar('install', $current_step, $total_steps);
  1116. }
  1117. foreach($tasks as $task){
  1118. $this->$task();
  1119. if(!$this->silent){
  1120. $current_step++;
  1121. update_progress_bar('install', $current_step, $total_steps);
  1122. }
  1123. }
  1124. if(isset($installdefs['custom_fields']) && (isset($GLOBALS['mi_remove_tables']) && $GLOBALS['mi_remove_tables'])){
  1125. $this->log(translate('LBL_MI_UN_CUSTOMFIELD'));
  1126. $this->uninstall_custom_fields($installdefs['custom_fields']);
  1127. }
  1128. if(!$this->silent){
  1129. $current_step++;
  1130. update_progress_bar('install', $current_step, $total_steps);
  1131. echo '</div>';
  1132. }
  1133. //since we are passing $silent = true to rebuildAll() in that method it will set $this->silent = true, so
  1134. //we need to save the setting to set it back after rebuildAll() completes.
  1135. $silentBak = $this->silent;
  1136. $this->rebuild_all(true);
  1137. $this->silent = $silentBak;
  1138. //#27877, If the request from MB redeploy a custom module , we will not remove the ACL actions for this package.
  1139. if( !isset($_REQUEST['action']) || $_REQUEST['action']!='DeployPackage' ){
  1140. $this->remove_acl_actions();
  1141. }
  1142. //end
  1143. if(!$this->silent){
  1144. $current_step++;
  1145. update_progress_bar('install', $current_step, $total_steps);
  1146. echo '</div>';
  1147. }
  1148. UpdateSystemTabs('Restore',$installed_modules);
  1149. //clear the unified_search_module.php file
  1150. require_once('modules/Home/UnifiedSearchAdvanced.php');
  1151. UnifiedSearchAdvanced::unlinkUnifiedSearchModulesFile();
  1152. $this->log('<br><b>' . translate('LBL_MI_COMPLETE') . '</b>');
  1153. if(!$this->silent){
  1154. update_progress_bar('install', $total_steps, $total_steps);
  1155. }
  1156. }else{
  1157. die("No manifest.php Defined In $this->base_dir/manifest.php");
  1158. }
  1159. }
  1160. function rebuild_languages($languages, $modules=""){
  1161. foreach($languages as $language=>$value){
  1162. $this->log(translate('LBL_MI_REBUILDING') . " Language...$language");
  1163. $this->merge_files('Ext/Language/', $language.'.lang.ext.php', $language);
  1164. if($modules!=""){
  1165. foreach($modules as $module){
  1166. LanguageManager::clearLanguageCache($module, $language);
  1167. }
  1168. }
  1169. }
  1170. sugar_cache_reset();
  1171. }
  1172. function rebuild_vardefs(){
  1173. $this->log(translate('LBL_MI_REBUILDING') . " Vardefs...");
  1174. $this->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
  1175. sugar_cache_reset();
  1176. }
  1177. function rebuild_layoutdefs(){
  1178. $this->log(translate('LBL_MI_REBUILDING') . " Layoutdefs...");
  1179. $this->merge_files('Ext/Layoutdefs/', 'layoutdefs.ext.php');
  1180. }
  1181. function rebuild_menus(){
  1182. $this->log(translate('LBL_MI_REBUILDING') . " Menus...");
  1183. $this->merge_files('Ext/Menus/', 'menu.ext.php');
  1184. }
  1185. function rebuild_dashletcontainers(){
  1186. $this->log(translate('LBL_MI_REBUILDING') . " DC Actions...");
  1187. $this->merge_files('Ext/DashletContainer/Containers/', 'dcactions.ext.php');
  1188. }
  1189. function rebuild_modules(){
  1190. $this->log(translate('LBL_MI_REBUILDING') . " Modules...");
  1191. $this->merge_files('Ext/Include/', 'modules.ext.php', '', true);
  1192. }
  1193. function rebuild_administration(){
  1194. $this->log(translate('LBL_MI_REBUILDING') . " administration " . translate('LBL_MI_SECTION'));
  1195. $this->merge_files('Ext/Administration/', 'administration.ext.php');
  1196. }
  1197. function rebuild_userpage(){
  1198. $this->log(translate('LBL_MI_REBUILDING') . " User Page " . translate('LBL_MI_SECTION'));
  1199. $this->merge_files('Ext/UserPage/', 'userpage.ext.php');
  1200. }
  1201. function rebuild_tabledictionary(){
  1202. $this->log(translate('LBL_MI_REBUILDING') . " administration " . translate('LBL_MI_SECTION'));
  1203. $this->merge_files('Ext/TableDictionary/', 'tabledictionary.ext.php');
  1204. }
  1205. function rebuild_relationships() {
  1206. if(!$this->silent) echo translate('LBL_MI_REBUILDING') . ' Relationships';
  1207. $_REQUEST['silent'] = true;
  1208. global $beanFiles;
  1209. include('include/modules.php');
  1210. include("modules/Administration/RebuildRelationship.php");
  1211. }
  1212. function remove_acl_actions() {
  1213. global $beanFiles, $beanList, $current_user;
  1214. include('include/modules.php');
  1215. include("modules/ACL/remove_actions.php");
  1216. }
  1217. /**
  1218. * Wrapper call to modules/Administration/RepairIndex.php
  1219. */
  1220. function repair_indices() {
  1221. global $current_user,$beanFiles,$dictionary;
  1222. $this->log(translate('LBL_MI_REPAIR_INDICES'));
  1223. $_REQUEST['silent'] = true; // local var flagging echo'd output in repair script
  1224. $_REQUEST['mode'] = 'execute'; // flag to just go ahead and run the script
  1225. include("modules/Administration/RepairIndex.php");
  1226. }
  1227. /**
  1228. * Rebuilds the extension files found in custom/Extension
  1229. * @param boolean $silent
  1230. */
  1231. function rebuild_all($silent=false){
  1232. if(defined('TEMPLATE_URL'))SugarTemplateUtilities::disableCache();
  1233. $this->silent=$silent;
  1234. global $sugar_config;
  1235. //Check for new module extensions
  1236. $this->rebuild_modules();
  1237. $this->rebuild_languages($sugar_config['languages']);
  1238. $this->rebuild_vardefs();
  1239. $this->rebuild_layoutdefs();
  1240. $this->rebuild_menus();
  1241. $this->rebuild_dashletcontainers();
  1242. $this->rebuild_userpage();
  1243. $this->rebuild_administration();
  1244. $this->rebuild_relationships();
  1245. $this->rebuild_tabledictionary();
  1246. //$this->repair_indices();
  1247. $this->reset_opcodes();
  1248. sugar_cache_reset();
  1249. }
  1250. /*
  1251. * ModuleInstaller->merge_files runs over the list of all modules already installed in /modules. For each $module it reads the contents of every file in
  1252. * custom/Extension/modules/$module/<path> (_override files last) and concatenates them to custom/modules/$module/<path>/<file>.
  1253. * Then it does the same thing in custom/Extension/application/<path>, concatenating those files and copying the result to custom/application/<path>/<file>
  1254. */
  1255. function merge_files($path, $name, $filter = '', $application = false){
  1256. if(!$application){
  1257. $GLOBALS['log']->debug( get_class($this)."->merge_files() : merging module files in custom/Extension/modules/<module>/$path to custom/modules/<module>/$path$name");
  1258. foreach($this->modules as $module){
  1259. //$GLOBALS['log']->debug("Merging Files for: ".$module);
  1260. //$GLOBALS['log']->debug("Merging Files for path: ".$path);
  1261. $extension = "<?php \n //WARNING: The contents of this file are auto-generated\n";
  1262. $extpath = "modules/$module/$path";
  1263. $module_install = 'custom/Extension/'.$extpath;
  1264. $shouldSave = false;
  1265. if(is_dir($module_install)){
  1266. $dir = dir($module_install);
  1267. $shouldSave = true;
  1268. $override = array();
  1269. while($entry = $dir->read()){
  1270. if((empty($filter) || substr_count($entry, $filter) > 0) && is_file($module_install.'/'.$entry)
  1271. && $entry != '.' && $entry != '..' && strtolower(substr($entry, -4)) == ".php")
  1272. {
  1273. if (substr($entry, 0, 9) == '_override') {
  1274. $override[] = $entry;
  1275. } else {
  1276. $file = file_get_contents($module_install . '/' . $entry);
  1277. $GLOBALS['log']->debug(get_class($this)."->merge_files(): found {$module_install}{$entry}") ;
  1278. $extension .= "\n". str_replace(array('<?php', '?>', '<?PHP', '<?'), array('','', '' ,'') , $file);
  1279. }
  1280. }
  1281. }
  1282. foreach ($override as $entry) {
  1283. $file = file_get_contents($module_install . '/' . $entry);
  1284. $extension .= "\n". str_replace(array('<?php', '?>', '<?PHP', '<?'), array('','', '' ,'') , $file);
  1285. }
  1286. }
  1287. $extension .= "\n?>";
  1288. if($shouldSave){
  1289. if(!file_exists("custom/$extpath")){
  1290. mkdir_recursive("custom/$extpath", true);
  1291. }
  1292. $out = sugar_fopen("custom/$extpath/$name", 'w');
  1293. fwrite($out,$extension);
  1294. fclose($out);
  1295. }else{
  1296. if(file_exists("custom/$extpath/$name")){
  1297. unlink("custom/$extpath/$name");
  1298. }
  1299. }
  1300. }
  1301. }
  1302. $GLOBALS['log']->debug("Merging application files for $name in $path");
  1303. //Now the application stuff
  1304. $extension = "<?php \n //WARNING: The contents of this file are auto-generated\n";
  1305. $extpath = "application/$path";
  1306. $module_install = 'custom/Extension/'.$extpath;
  1307. $shouldSave = false;
  1308. if(is_dir($module_install)){
  1309. $dir = dir($module_install);
  1310. while($entry = $dir->read()){
  1311. $shouldSave = true;
  1312. if((empty($filter) || substr_count($entry, $filter) > 0) && is_file($module_install.'/'.$entry)
  1313. && $entry != '.' && $entry != '..' && strtolower(substr($entry, -4)) == ".php")
  1314. {
  1315. $file = file_get_contents($module_install . '/' . $entry);
  1316. $extension .= "\n". str_replace(array('<?php', '?>', '<?PHP', '<?'), array('','', '' ,'') , $file);
  1317. }
  1318. }
  1319. }
  1320. $extension .= "\n?>";
  1321. if($shouldSave){
  1322. if(!file_exists("custom/$extpath")){
  1323. mkdir_recursive("custom/$extpath", true);
  1324. }
  1325. $out = sugar_fopen("custom/$extpath/$name", 'w');
  1326. fwrite($out,$extension);
  1327. fclose($out);
  1328. }else{
  1329. if(file_exists("custom/$extpath/$name")){
  1330. unlink("custom/$extpath/$name");
  1331. }
  1332. }
  1333. }
  1334. /*
  1335. * ModuleInstaller->install_beans runs through the list of beans given, instantiates each bean, calls bean->create_tables, and then calls SugarBean::createRelationshipMeta for the
  1336. * bean/module.
  1337. */
  1338. function install_beans($beans){
  1339. include('include/modules.php');
  1340. foreach($beans as $bean){
  1341. $this->log( translate('LBL_MI_IN_BEAN') . " $bean");
  1342. if(isset($beanList[$bean])){
  1343. $class = $beanList[$bean];
  1344. if(file_exists($beanFiles[$class])){
  1345. require_once($beanFiles[$class]);
  1346. $mod = new $class();
  1347. //#30273
  1348. if(is_subclass_of($mod, 'SugarBean') && $mod->disable_vardefs == false ){
  1349. $GLOBALS['log']->debug( "Creating Tables Bean : $bean");
  1350. $mod->create_tables();
  1351. SugarBean::createRelationshipMeta($mod->getObjectName(), $mod->db,$mod->table_name,'',$mod->module_dir);
  1352. }
  1353. }else{
  1354. $GLOBALS['log']->debug( "File Does Not Exist:" . $beanFiles[$class] );
  1355. }
  1356. }
  1357. }
  1358. }
  1359. function uninstall_beans($beans){
  1360. include('include/modules.php');
  1361. foreach($beans as $bean){
  1362. $this->log( translate('LBL_MI_UN_BEAN') . " $bean");
  1363. if(isset($beanList[$bean])){
  1364. $class = $beanList[$bean];
  1365. if(file_exists($beanFiles[$class])){
  1366. require_once($beanFiles[$class]);
  1367. $mod = new $class();
  1368. if(is_subclass_of($mod, 'SugarBean')){
  1369. $GLOBALS['log']->debug( "Drop Tables : $bean");
  1370. if(isset($GLOBALS['mi_remove_tables']) && $GLOBALS['mi_remove_tables'])
  1371. $mod->drop_tables();
  1372. }
  1373. }else{
  1374. $GLOBALS['log']->debug( "File Does Not Exist:" . $beanFiles[$class] );
  1375. }
  1376. }
  1377. }
  1378. }
  1379. /**
  1380. * Remove any customizations made within Studio while the module was installed.
  1381. */
  1382. function uninstall_customizations($beans){
  1383. foreach($beans as $bean){
  1384. $dirs = array(
  1385. 'custom/modules/' . $bean,
  1386. 'custom/Extension/modules/' . $bean
  1387. );
  1388. foreach($dirs as $dir)
  1389. {
  1390. if(is_dir($dir)){
  1391. rmdir_recursive($dir);
  1392. }
  1393. }
  1394. }
  1395. }
  1396. function log($str){
  1397. $GLOBALS['log']->debug('ModuleInstaller:'. $str);
  1398. if(!$this->silent){
  1399. echo $str . '<br>';
  1400. }
  1401. }
  1402. /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:15:18 PM */
  1403. function copy_recursive_with_backup( $source, $dest, $backup_path, $uninstall=false ) {
  1404. if(is_file($source)) {
  1405. if($uninstall) {
  1406. $GLOBALS['log']->debug("Restoring ... " . $source. " to " .$dest );
  1407. if(copy( $source, $dest)) {
  1408. if(is_writable($dest))
  1409. sugar_touch( $dest, filemtime($source) );
  1410. return(unlink($source));
  1411. }
  1412. else {
  1413. $GLOBALS['log']->debug( "Can't restore file: " . $source );
  1414. return true;
  1415. }
  1416. }
  1417. else {
  1418. if(file_exists($dest)) {
  1419. $rest = clean_path($backup_path."/$dest");
  1420. if( !is_dir(dirname($rest)) )
  1421. mkdir_recursive(dirname($rest), true);
  1422. $GLOBALS['log']->debug("Backup ... " . $dest. " to " .$rest );
  1423. if(copy( $dest, $rest)) {
  1424. if(is_writable($rest))
  1425. sugar_touch( $rest, filemtime($dest) );
  1426. }
  1427. else {
  1428. $GLOBALS['log']->debug( "Can't backup file: " . $dest );
  1429. }
  1430. }
  1431. return( copy( $source, $dest ) );
  1432. }
  1433. }
  1434. elseif(!is_dir($source)) {
  1435. if($uninstall) {
  1436. if(is_file($dest))
  1437. return(unlink($dest));
  1438. else {
  1439. //don't do anything we already cleaned up the files using uninstall_new_files
  1440. return true;
  1441. }
  1442. }
  1443. else
  1444. return false;
  1445. }
  1446. if( !is_dir($dest) && !$uninstall){
  1447. sugar_mkdir( $dest );
  1448. }
  1449. $status = true;
  1450. $d = dir( $source );
  1451. while( $f = $d->read() ){
  1452. if( $f == "." || $f == ".." ){
  1453. continue;
  1454. }
  1455. $status &= $this->copy_recursive_with_backup( "$source/$f", "$dest/$f", $backup_path, $uninstall );
  1456. }
  1457. $d->close();
  1458. return( $status );
  1459. }
  1460. private function dir_get_files($path, $base_path){
  1461. $files = array();
  1462. if(!is_dir($path))return $files;
  1463. $d = dir($path);
  1464. while ($e = $d->read()){
  1465. //ignore invisible files . .. ._MACOSX
  1466. if(substr($e, 0, 1) == '.')continue;
  1467. if(is_file($path . '/' . $e))$files[str_replace($base_path , '', $path . '/' . $e)] = str_replace($base_path , '', $path . '/' . $e);
  1468. if(is_dir($path . '/' . $e))$files = array_merge($files, $this->dir_get_files($path . '/' . $e, $base_path));
  1469. }
  1470. $d->close();
  1471. return $files;
  1472. }
  1473. private function dir_file_count($path){
  1474. //if its a file then it has at least 1 file in the directory
  1475. if(is_file($path)) return 1;
  1476. if(!is_dir($path)) return 0;
  1477. $d = dir($path);
  1478. $count = 0;
  1479. while ($e = $d->read()){
  1480. //ignore invisible files . .. ._MACOSX
  1481. if(substr($e, 0, 1) == '.')continue;
  1482. if(is_file($path . '/' . $e))$count++;
  1483. if(is_dir($path . '/' . $e))$count += $this->dir_file_count($path . '/' . $e);
  1484. }
  1485. $d->close();
  1486. return $count;
  1487. }
  1488. /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:15:34 PM */
  1489. /**
  1490. * Static function which allows a module developer to abort their progress, pass in an array of errors and
  1491. * redirect back to the main module loader page
  1492. *
  1493. * @param errors an array of error messages which will be displayed on the
  1494. * main module loader page once it is loaded.
  1495. */
  1496. function abort($errors = array()){
  1497. //set the errors onto the session so we can display them one the moduler loader page loads
  1498. $_SESSION['MODULEINSTALLER_ERRORS'] = $errors;
  1499. echo '<META HTTP-EQUIV="Refresh" content="0;url=index.php?module=Administration&action=UpgradeWizard&view=module">';
  1500. die();
  1501. //header('Location: index.php?module=Administration&action=UpgradeWizard&view=module');
  1502. }
  1503. /**
  1504. * Return the set of errors stored in the SESSION
  1505. *
  1506. * @return an array of errors
  1507. */
  1508. function getErrors(){
  1509. if(!empty($_SESSION['MODULEINSTALLER_ERRORS'])){
  1510. $errors = $_SESSION['MODULEINSTALLER_ERRORS'];
  1511. unset($_SESSION['MODULEINSTALLER_ERRORS']);
  1512. return $errors;
  1513. }
  1514. else
  1515. return null;
  1516. }
  1517. /*
  1518. * Add any fields to the DetailView and EditView of the appropriate modules
  1519. * Only add into deployed modules, as addFieldsToUndeployedLayouts has done this already for undeployed modules (and the admin might have edited the layouts already)
  1520. * @param array $layoutAdditions An array of module => fieldname
  1521. * return null
  1522. */
  1523. function addFieldsToLayout($layoutAdditions) {
  1524. require_once 'modules/ModuleBuilder/parsers/views/GridLayoutMetaDataParser.php' ;
  1525. // these modules either lack editviews/detailviews or use custom mechanisms for the editview/detailview.
  1526. // In either case, we don't want to attempt to add a relate field to them
  1527. // would be better if GridLayoutMetaDataParser could handle this gracefully, so we don't have to maintain this list here
  1528. $invalidModules = array ( 'emails' , 'kbdocuments' ) ;
  1529. foreach ( $layoutAdditions as $deployedModuleName => $fieldName )
  1530. {
  1531. if ( ! in_array( strtolower ( $deployedModuleName ) , $invalidModules ) )
  1532. {
  1533. foreach ( array ( MB_EDITVIEW , MB_DETAILVIEW ) as $view )
  1534. {
  1535. $GLOBALS [ 'log' ]->debug ( get_class ( $this ) . ": adding $fieldName to $view layout for module $deployedModuleName" ) ;
  1536. $parser = new GridLayoutMetaDataParser ( $view, $deployedModuleName ) ;
  1537. $parser->addField ( array ( 'name' => $fieldName ) ) ;
  1538. $parser->handleSave ( false ) ;
  1539. }
  1540. }
  1541. }
  1542. }
  1543. function removeFieldsFromLayout($layoutAdditions) {
  1544. require_once 'modules/ModuleBuilder/parsers/views/GridLayoutMetaDataParser.php' ;
  1545. // these modules either lack editviews/detailviews or use custom mechanisms for the editview/detailview.
  1546. // In either case, we don't want to attempt to add a relate field to them
  1547. // would be better if GridLayoutMetaDataParser could handle this gracefully, so we don't have to maintain this list here
  1548. $invalidModules = array ( 'emails' , 'kbdocuments' ) ;
  1549. foreach ( $layoutAdditions as $deployedModuleName => $fieldName )
  1550. {
  1551. if ( ! in_array( strtolower ( $deployedModuleName ) , $invalidModules ) )
  1552. {
  1553. foreach ( array ( MB_EDITVIEW , MB_DETAILVIEW ) as $view )
  1554. {
  1555. $GLOBALS [ 'log' ]->debug ( get_class ( $this ) . ": adding $fieldName to $view layout for module $deployedModuleName" ) ;
  1556. $parser = new GridLayoutMetaDataParser ( $view, $deployedModuleName ) ;
  1557. $parser->removeField ( $fieldName ) ;
  1558. $parser->handleSave ( false ) ;
  1559. }
  1560. }
  1561. }
  1562. }
  1563. ///////////////////
  1564. //********** DISABLE/ENABLE FUNCTIONS
  1565. ///////////////////
  1566. function enable($base_dir, $is_upgrade = false, $previous_version = ''){
  1567. global $app_strings;
  1568. $this->base_dir = $base_dir;
  1569. $total_steps = 3; //minimum number of steps with no tasks
  1570. $current_step = 0;
  1571. $tasks = array(
  1572. 'enable_copy',
  1573. 'enable_menus',
  1574. 'enable_userpage',
  1575. 'enable_dashlets',
  1576. 'enable_administration',
  1577. 'enable_vardefs',
  1578. 'enable_layoutdefs',
  1579. 'enable_relationships',
  1580. 'enable_languages',
  1581. 'enable_logichooks',
  1582. 'reset_opcodes',
  1583. );
  1584. $total_steps += count($tasks);
  1585. if(file_exists($this->base_dir . '/manifest.php')){
  1586. if(!$this->silent){
  1587. $current_step++;
  1588. display_progress_bar('install', $current_step, $total_steps);
  1589. echo '<div id ="displayLoglink" ><a href="#" onclick="toggleDisplay(\'displayLog\')">'.$app_strings['LBL_DISPLAY_LOG'].'</a> </div><div id="displayLog" style="display:none">';
  1590. }
  1591. require_once($this->base_dir . '/manifest.php');
  1592. if($is_upgrade && !empty($previous_version)){
  1593. //check if the upgrade path exists
  1594. if(!empty($upgrade_manifest)){
  1595. if(!empty($upgrade_manifest['upgrade_paths'])){
  1596. if(!empty($upgrade_manifest['upgrade_paths'][$previous_version])){
  1597. $installdefs = $upgrade_manifest['upgrade_paths'][$previous_version];
  1598. }else{
  1599. $errors[] = 'No Upgrade Path Found in manifest.';
  1600. $this->abort($errors);
  1601. }//fi
  1602. }//fi
  1603. }//fi
  1604. }//fi
  1605. $this->id_name = $installdefs['id'];
  1606. $this->installdefs = $installdefs;
  1607. $installed_modules = array();
  1608. if(isset($installdefs['beans'])){
  1609. foreach($this->installdefs['beans'] as $bean){
  1610. $installed_modules[] = $bean['module'];
  1611. }
  1612. if(!file_exists("custom/Extension/application/Ext/Include")){
  1613. mkdir_recursive("custom/Extension/application/Ext/Include", true);
  1614. }
  1615. if (file_exists("custom/Extension/application/Ext/Include/".DISABLED_PATH.'/'. $this->id_name . '.php'))
  1616. rename("custom/Extension/application/Ext/Include/".DISABLED_PATH.'/'. $this->id_name . '.php',"custom/Extension/application/Ext/Include/$this->id_name.php");
  1617. $this->rebuild_modules();
  1618. }
  1619. if(!$this->silent){
  1620. $current_step++;
  1621. update_progress_bar('install', $current_step, $total_steps);
  1622. }
  1623. foreach($tasks as $task){
  1624. $this->$task();
  1625. if(!$this->silent){
  1626. $current_step++;
  1627. update_progress_bar('install', $current_step, $total_steps);
  1628. }
  1629. }
  1630. if(!$this->silent){
  1631. $current_step++;
  1632. update_progress_bar('install', $current_step, $total_steps);
  1633. echo '</div>';
  1634. }
  1635. UpdateSystemTabs('Add',$installed_modules);
  1636. $GLOBALS['log']->debug('Complete');
  1637. }else{
  1638. die("No \$installdefs Defined In $this->base_dir/manifest.php");
  1639. }
  1640. }
  1641. function disable($base_dir){
  1642. global $app_strings;
  1643. $total_steps = 3; //min steps with no tasks
  1644. $current_step = 0;
  1645. $this->base_dir = $base_dir;
  1646. $tasks = array(
  1647. 'disable_copy',
  1648. 'disable_menus',
  1649. 'disable_dashlets',
  1650. 'disable_userpage',
  1651. 'disable_administration',
  1652. 'disable_vardefs',
  1653. 'disable_layoutdefs',
  1654. 'disable_relationships',
  1655. 'disable_languages',
  1656. 'disable_logichooks',
  1657. 'reset_opcodes',
  1658. );
  1659. $total_steps += count($tasks); //now the real number of steps
  1660. if(file_exists($this->base_dir . '/manifest.php')){
  1661. if(!$this->silent){
  1662. $current_step++;
  1663. display_progress_bar('install', $current_step, $total_steps);
  1664. echo '<div id ="displayLoglink" ><a href="#" onclick="toggleDisplay(\'displayLog\')">'.$app_strings['LBL_DISPLAY_LOG'].'</a> </div><div id="displayLog" style="display:none">';
  1665. }
  1666. require_once($this->base_dir . '/manifest.php');
  1667. $this->installdefs = $installdefs;
  1668. $this->id_name = $this->installdefs['id'];
  1669. $installed_modules = array();
  1670. if(isset($this->installdefs['beans'])){
  1671. foreach($this->installdefs['beans'] as $bean){
  1672. $installed_modules[] = $bean['module'];
  1673. }
  1674. mkdir_recursive("custom/Extension/application/Ext/Include/".DISABLED_PATH, true);
  1675. //Clear any older disabled version
  1676. if (file_exists("custom/Extension/application/Ext/Include/".DISABLED_PATH.'/'. $this->id_name . '.php'))
  1677. rmdir_recursive("custom/Extension/application/Ext/Include/".DISABLED_PATH.'/'. $this->id_name . '.php');
  1678. if (file_exists("custom/Extension/application/Ext/Include/$this->id_name.php"))
  1679. rename("custom/Extension/application/Ext/Include/$this->id_name.php", "custom/Extension/application/Ext/Include/".DISABLED_PATH.'/'. $this->id_name . '.php');
  1680. $this->rebuild_modules();
  1681. }
  1682. if(!$this->silent){
  1683. $current_step++;
  1684. update_progress_bar('install', $current_step, $total_steps);
  1685. }
  1686. foreach($tasks as $task){
  1687. $this->$task();
  1688. if(!$this->silent){
  1689. $current_step++;
  1690. update_progress_bar('install', $current_step, $total_steps);
  1691. }
  1692. }
  1693. if(!$this->silent){
  1694. $current_step++;
  1695. update_progress_bar('install', $current_step, $total_steps);
  1696. echo '</div>';
  1697. }
  1698. UpdateSystemTabs('Restore',$installed_modules);
  1699. }else{
  1700. die("No manifest.php Defined In $this->base_dir/manifest.php");
  1701. }
  1702. }
  1703. function enable_vardef($to_module){
  1704. if(isset($this->installdefs['vardefs'])){
  1705. foreach($this->installdefs['vardefs'] as $vardefs){
  1706. $GLOBALS['log']->debug("Enabling Vardefs ..." .$to_module);
  1707. $path = 'custom/Extension/modules/' . $to_module. '/Ext/Vardefs';
  1708. if($to_module == 'application'){
  1709. $path ='custom/Extension/' . $to_module. '/Ext/Vardefs';
  1710. }
  1711. if(!file_exists($path)){
  1712. mkdir_recursive($path, true);
  1713. }
  1714. if (file_exists($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php'))
  1715. rename($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php', $path . '/'. $this->id_name . '.php');
  1716. if (file_exists($path . '/'.DISABLED_PATH.'/'. basename($vardefs['from'])))
  1717. rename($path . '/'.DISABLED_PATH.'/'. basename($vardefs['from']), $path . '/'. basename($vardefs['from']));
  1718. }
  1719. }
  1720. }
  1721. function enable_vardefs(){
  1722. if(isset($this->installdefs['vardefs'])){
  1723. foreach($this->installdefs['vardefs'] as $vardefs){
  1724. $vardefs['from'] = str_replace('<basepath>', $this->base_dir, $vardefs['from']);
  1725. $GLOBALS['log']->debug("Enabling Vardefs ..." . $vardefs['from'] . " for " .$vardefs['to_module']);
  1726. $path = 'custom/Extension/modules/' . $vardefs['to_module']. '/Ext/Vardefs';
  1727. if($vardefs['to_module'] == 'application'){
  1728. $path ='custom/Extension/' . $vardefs['to_module']. '/Ext/Vardefs';
  1729. }
  1730. if(file_exists($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php'))
  1731. rename( $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php', $path . '/'. $this->id_name . '.php');
  1732. if (file_exists($path . '/'.DISABLED_PATH.'/'. basename($vardefs['from'])))
  1733. rename($path . '/'.DISABLED_PATH.'/'. basename($vardefs['from']), $path . '/'. basename($vardefs['from']));
  1734. }
  1735. $this->rebuild_vardefs();
  1736. }
  1737. }
  1738. function disable_vardefs(){
  1739. $GLOBALS['log']->debug("Disabling Vardefs ".var_export($this->installdefs, true));
  1740. if(isset($this->installdefs['vardefs'])){
  1741. foreach($this->installdefs['vardefs'] as $vardefs){
  1742. $vardefs['from'] = str_replace('<basepath>', $this->base_dir, $vardefs['from']);
  1743. $GLOBALS['log']->debug("Disabling Vardefs ..." . $vardefs['from'] . " for " .$vardefs['to_module']);
  1744. $path = 'custom/Extension/modules/' . $vardefs['to_module']. '/Ext/Vardefs';
  1745. if($vardefs['to_module'] == 'application'){
  1746. $path ='custom/Extension/' . $vardefs['to_module']. '/Ext/Vardefs';
  1747. }
  1748. if(file_exists($path . '/'. $this->id_name . '.php')) {
  1749. mkdir_recursive($path . '/'.DISABLED_PATH, true);
  1750. rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
  1751. }
  1752. if(file_exists($path . '/'. basename($vardefs['from'])))
  1753. {
  1754. mkdir_recursive($path . '/'.DISABLED_PATH, true);
  1755. rename( $path . '/'. basename($vardefs['from']), $path . '/'.DISABLED_PATH.'/'.basename($vardefs['from']));
  1756. }
  1757. }
  1758. $this->rebuild_vardefs();
  1759. }
  1760. }
  1761. function enable_relationships(){
  1762. if(isset($this->installdefs['relationships'])){
  1763. $str = "<?php \n //WARNING: The contents of this file are auto-generated\n";
  1764. $save_table_dictionary = false;
  1765. foreach($this->installdefs['relationships'] as $relationship){
  1766. $filename =basename($relationship['meta_data']);
  1767. $save_table_dictionary = true;
  1768. $str .= "include_once('metadata/$filename');\n";
  1769. if (empty($relationship['module']))
  1770. continue;
  1771. if(!empty($relationship['module_vardefs'])){
  1772. $this->enable_vardef($relationship['module']);
  1773. }
  1774. if(!empty($relationship['module_layoutdefs'])){
  1775. $this->enable_layoutdef($relationship['module']);
  1776. }
  1777. }
  1778. $this->rebuild_vardefs();
  1779. $this->rebuild_layoutdefs();
  1780. if($save_table_dictionary){
  1781. if(!file_exists("custom/Extension/application/Ext/TableDictionary")){
  1782. mkdir_recursive("custom/Extension/application/Ext/TableDictionary", true);
  1783. }
  1784. if (file_exists("custom/Extension/application/Ext/TableDictionary/".DISABLED_PATH."/$this->id_name.php"))
  1785. rename("custom/Extension/application/Ext/TableDictionary/".DISABLED_PATH."/$this->id_name.php", "custom/Extension/application/Ext/TableDictionary/$this->id_name.php");
  1786. $this->rebuild_tabledictionary();
  1787. }
  1788. }
  1789. }
  1790. function disable_relationships($action = 'disable'){
  1791. if(isset($this->installdefs['relationships'])){
  1792. foreach($this->installdefs['relationships'] as $relationship){
  1793. $filename = basename($relationship['meta_data']);
  1794. $relName = substr($filename, -12) == "MetaData.php" ? substr($filename,0,strlen($filename) - 12) : "";
  1795. if (empty($relationship['module']) && empty($relName))
  1796. continue;
  1797. //remove the vardefs
  1798. if (empty($relName))
  1799. $path = 'custom/Extension/modules/' . $relationship['module']. '/Ext/Vardefs';
  1800. if(!empty($relationship['module']) && $relationship['module'] == 'application'){
  1801. $path ='custom/Extension/' . $relationship['module']. '/Ext/Vardefs';
  1802. }
  1803. if(!empty($relationship['module_vardefs']) && file_exists($path . '/'. $this->id_name . '.php')){
  1804. mkdir_recursive($path . '/'.DISABLED_PATH, true);
  1805. rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
  1806. }
  1807. //remove the layoutdefs
  1808. if ( !empty($relationship['module']) ) {
  1809. $path = 'custom/Extension/modules/' . $relationship['module']. '/Ext/Layoutdefs';
  1810. if($relationship['module'] == 'application'){
  1811. $path ='custom/Extension/' . $relationship['module']. '/Ext/Layoutdefs';
  1812. }
  1813. }
  1814. if(!empty($relationship['module_layoutdefs']) && file_exists($path . '/'. $this->id_name . '.php')){
  1815. mkdir_recursive($path . '/'.DISABLED_PATH, true);
  1816. rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
  1817. }
  1818. }
  1819. if(file_exists("custom/Extension/application/Ext/TableDictionary/$this->id_name.php")){
  1820. mkdir_recursive("custom/Extension/application/Ext/TableDictionary/".DISABLED_PATH, true);
  1821. rename("custom/Extension/application/Ext/TableDictionary/$this->id_name.php", "custom/Extension/application/Ext/TableDictionary/".DISABLED_PATH."/$this->id_name.php");
  1822. }
  1823. $this->rebuild_tabledictionary();
  1824. $this->rebuild_vardefs();
  1825. $this->rebuild_layoutdefs();
  1826. }
  1827. }
  1828. function enable_layoutdefs(){
  1829. if(isset($this->installdefs['layoutdefs'])){
  1830. foreach($this->installdefs['layoutdefs'] as $layoutdefs){
  1831. $this->enable_layoutdef($layoutdefs['to_module'], $this->id_name);
  1832. }
  1833. $this->rebuild_layoutdefs();
  1834. }
  1835. }
  1836. function enable_layoutdef($to_module){
  1837. $GLOBALS['log']->debug("Enabling Layout Defs ..." .$to_module);
  1838. if(isset($this->installdefs['layoutdefs'])){
  1839. foreach($this->installdefs['layoutdefs'] as $layoutdefs){
  1840. $path = 'custom/Extension/modules/' . $to_module. '/Ext/Layoutdefs';
  1841. if($to_module == 'application'){
  1842. $path ='custom/Extension/' . $to_module. '/Ext/Layoutdefs';
  1843. }
  1844. if (file_exists($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php'))
  1845. {
  1846. rename($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php', $path . '/'. $this->id_name . '.php');
  1847. }
  1848. if (file_exists($path . '/'.DISABLED_PATH.'/'. basename($layoutdefs['from'])))
  1849. {
  1850. rename($path . '/'.DISABLED_PATH.'/'. basename($layoutdefs['from']), $path . '/'. basename($layoutdefs['from']));
  1851. }
  1852. }
  1853. }
  1854. }
  1855. function disable_layoutdefs(){
  1856. if(isset($this->installdefs['layoutdefs'])){
  1857. foreach($this->installdefs['layoutdefs'] as $layoutdefs){
  1858. $layoutdefs['from'] = str_replace('<basepath>', $this->base_dir, $layoutdefs['from']);
  1859. $GLOBALS['log']->debug("Disabling Layoutdefs ..." . $layoutdefs['from'] . " for " .$layoutdefs['to_module']);
  1860. $path = 'custom/Extension/modules/' . $layoutdefs['to_module']. '/Ext/Layoutdefs';
  1861. if($layoutdefs['to_module'] == 'application'){
  1862. $path ='custom/Extension/' . $layoutdefs['to_module']. '/Ext/Layoutdefs';
  1863. }
  1864. if (file_exists($path . '/'. $this->id_name . '.php'))
  1865. {
  1866. mkdir_recursive($path . '/'.DISABLED_PATH, true);
  1867. rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
  1868. }else if (file_exists($path . '/'. basename($layoutdefs['from'])))
  1869. {
  1870. mkdir_recursive($path . '/'.DISABLED_PATH, true);
  1871. rename( $path . '/'. basename($layoutdefs['from']), $path . '/'.DISABLED_PATH.'/'. basename($layoutdefs['from']));
  1872. }
  1873. }
  1874. $this->rebuild_layoutdefs();
  1875. }
  1876. }
  1877. function enable_menus(){
  1878. if(isset($this->installdefs['menu'])){
  1879. foreach($this->installdefs['menu'] as $menu){
  1880. $menu['from'] = str_replace('<basepath>', $this->base_dir, $menu['from']);
  1881. $GLOBALS['log']->debug("Enabling Menu ..." . $menu['from']. " for " .$menu['to_module'] );
  1882. $path = 'custom/Extension/modules/' . $menu['to_module']. '/Ext/Menus';
  1883. if($menu['to_module'] == 'application'){
  1884. $path ='custom/Extension/' . $menu['to_module']. '/Ext/Menus';
  1885. }
  1886. if(file_exists($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php')){
  1887. rename($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php', $path . '/'. $this->id_name . '.php');
  1888. }
  1889. }
  1890. $this->rebuild_menus();
  1891. }
  1892. }
  1893. function disable_menus(){
  1894. if(isset($this->installdefs['menu'])){
  1895. foreach($this->installdefs['menu'] as $menu){
  1896. $menu['from'] = str_replace('<basepath>', $this->base_dir, $menu['from']);
  1897. $GLOBALS['log']->debug("Disabling Menu ..." . $menu['from']. " for " .$menu['to_module'] );
  1898. $path = 'custom/Extension/modules/' . $menu['to_module']. '/Ext/Menus';
  1899. if($menu['to_module'] == 'application'){
  1900. $path ='custom/Extension/' . $menu['to_module']. '/Ext/Menus';
  1901. }
  1902. if (file_exists( $path . '/'. $this->id_name . '.php'))
  1903. {
  1904. mkdir_recursive($path . '/'.DISABLED_PATH, true);
  1905. rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
  1906. }
  1907. }
  1908. $this->rebuild_menus();
  1909. }
  1910. }
  1911. function enable_administration(){
  1912. if(isset($this->installdefs['administration'])){
  1913. foreach($this->installdefs['administration'] as $administration){
  1914. $administration['from'] = str_replace('<basepath>', $this->base_dir, $administration['from']);
  1915. $GLOBALS['log']->debug("Installing Administration Section ..." . $administration['from'] );
  1916. $path = 'custom/Extension/modules/Administration/Ext/Administration';
  1917. if(file_exists($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php')){
  1918. rename($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php', $path . '/'. $this->id_name . '.php');
  1919. }
  1920. }
  1921. $this->rebuild_administration();
  1922. }
  1923. }
  1924. function disable_administration(){
  1925. if(isset($this->installdefs['administration'])){
  1926. foreach($this->installdefs['administration'] as $administration){
  1927. $administration['from'] = str_replace('<basepath>', $this->base_dir, $administration['from']);
  1928. $GLOBALS['log']->debug("Uninstalling Administration Section ..." . $administration['from'] );
  1929. $path = 'custom/Extension/modules/Administration/Ext/Administration';
  1930. if (file_exists($path . '/'. $this->id_name . '.php'))
  1931. {
  1932. mkdir_recursive($path . '/'.DISABLED_PATH, true);
  1933. rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
  1934. }
  1935. }
  1936. $this->rebuild_administration();
  1937. }
  1938. }
  1939. function enable_dashlets(){
  1940. if(isset($this->installdefs['dashlets'])){
  1941. foreach($this->installdefs['dashlets'] as $cp){
  1942. $cp['from'] = str_replace('<basepath>', $this->base_dir, $cp['from']);
  1943. $path = 'custom/modules/Home/Dashlets/' . $cp['name'] . '/';
  1944. $disabled_path = 'custom/modules/Home/'.DISABLED_PATH.'Dashlets/' . $cp['name'];
  1945. $GLOBALS['log']->debug("Enabling Dashlet " . $cp['name'] . "..." . $cp['from'] );
  1946. if (file_exists($disabled_path))
  1947. {
  1948. rename($disabled_path, $path);
  1949. }
  1950. }
  1951. include('modules/Administration/RebuildDashlets.php');
  1952. }
  1953. }
  1954. function disable_dashlets(){
  1955. if(isset($this->installdefs['dashlets'])){
  1956. foreach($this->installdefs['dashlets'] as $cp){
  1957. $path = 'custom/modules/Home/Dashlets/' . $cp['name'];
  1958. $disabled_path = 'custom/modules/Home/'.DISABLED_PATH.'Dashlets/' . $cp['name'];
  1959. $GLOBALS['log']->debug('Disabling ' .$path);
  1960. if (file_exists($path))
  1961. {
  1962. mkdir_recursive('custom/modules/Home/'.DISABLED_PATH.'Dashlets/', true);
  1963. rename( $path, $disabled_path);
  1964. }
  1965. }
  1966. include('modules/Administration/RebuildDashlets.php');
  1967. }
  1968. }
  1969. function enable_languages(){
  1970. $languages = array();
  1971. if(isset($this->installdefs['language'])){
  1972. foreach($this->installdefs['language'] as $packs){
  1973. $languages[$packs['language']] = $packs['language'];
  1974. $packs['from'] = str_replace('<basepath>', $this->base_dir, $packs['from']);
  1975. $GLOBALS['log']->debug("Installing Language Pack ..." . $packs['from'] . " for " .$packs['to_module']);
  1976. $path = 'custom/Extension/modules/' . $packs['to_module']. '/Ext/Language';
  1977. if($packs['to_module'] == 'application'){
  1978. $path ='custom/Extension/' . $packs['to_module']. '/Ext/Language';
  1979. }
  1980. if(!file_exists($path)){
  1981. mkdir_recursive($path, true);
  1982. }
  1983. if (file_exists($path.'/'.DISABLED_PATH.'/'.$packs['language'].'.'. $this->id_name . '.php'))
  1984. rename($path.'/'.DISABLED_PATH.'/'.$packs['language'].'.'. $this->id_name . '.php', $path.'/'.$packs['language'].'.'. $this->id_name . '.php');
  1985. }
  1986. $this->rebuild_languages($languages);
  1987. }
  1988. }
  1989. function disable_languages(){
  1990. $languages = array();
  1991. if(isset($this->installdefs['language'])){
  1992. foreach($this->installdefs['language'] as $packs){
  1993. $languages[$packs['language']] = $packs['language'];
  1994. $packs['from'] = str_replace('<basepath>', $this->base_dir, $packs['from']);
  1995. $GLOBALS['log']->debug("Uninstalling Language Pack ..." . $packs['from'] . " for " .$packs['to_module']);
  1996. $path = 'custom/Extension/modules/' . $packs['to_module']. '/Ext/Language';
  1997. if($packs['to_module'] == 'application'){
  1998. $path ='custom/Extension/' . $packs['to_module']. '/Ext/Language';
  1999. }
  2000. mkdir_recursive($path . '/'.DISABLED_PATH, true);
  2001. if (file_exists($path.'/'.$packs['language'].'.'. $this->id_name . '.php'))
  2002. rename($path.'/'.$packs['language'].'.'. $this->id_name . '.php', $path.'/'.DISABLED_PATH.'/'.$packs['language'].'.'. $this->id_name . '.php');
  2003. }
  2004. $this->rebuild_languages($languages);
  2005. }
  2006. }
  2007. function enable_userpage(){
  2008. if(isset($this->installdefs['user_page'])){
  2009. foreach($this->installdefs['user_page'] as $userpage){
  2010. $userpage['from'] = str_replace('<basepath>', $this->base_dir, $userpage['from']);
  2011. $GLOBALS['log']->debug("Installing User Page Section ..." . $userpage['from'] );
  2012. $path = 'custom/Extension/modules/Users/Ext/UserPage';
  2013. if(file_exists($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php')){
  2014. rename($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php', $path . '/'. $this->id_name . '.php');
  2015. }
  2016. }
  2017. $this->rebuild_userpage();
  2018. }
  2019. }
  2020. function disable_userpage(){
  2021. if(isset($this->installdefs['user_page'])){
  2022. foreach($this->installdefs['user_page'] as $userpage){
  2023. $userpage['from'] = str_replace('<basepath>', $this->base_dir, $userpage['from']);
  2024. $GLOBALS['log']->debug("Uninstalling User Page Section ..." . $userpage['from'] );
  2025. $path = 'custom/Extension/modules/Users/Ext/UserPage';
  2026. if (file_exists( $path . '/'. $this->id_name . '.php')) {
  2027. mkdir_recursive($path . '/'.DISABLED_PATH, true);
  2028. rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
  2029. }
  2030. }
  2031. $this->rebuild_userpage();
  2032. }
  2033. }
  2034. function enable_copy(){
  2035. //copy files back onto file system. first perform md5 check to determine if anything has been modified
  2036. //here we should just go through the files in the -restore directory and copy those back
  2037. if(isset($GLOBALS['mi_overwrite_files']) && $GLOBALS['mi_overwrite_files']){
  2038. if(!empty($this->installdefs['copy'])){
  2039. foreach($this->installdefs['copy'] as $cp){
  2040. $cp['to'] = clean_path(str_replace('<basepath>', $this->base_dir, $cp['to']));
  2041. $backup_path = clean_path( remove_file_extension(urldecode(hashToFile($_REQUEST['install_file'])))."-restore/".$cp['to'] );
  2042. //check if this file exists in the -restore directory
  2043. if(file_exists($backup_path)){
  2044. //since the file exists, then we want do an md5 of the install version and the file system version
  2045. //if(is_file($backup_path) && md5_file($backup_path) == md5_file($cp['to'])){
  2046. //since the files are the same then we can safely move back from the -restore
  2047. //directory into the file system
  2048. $GLOBALS['log']->debug("ENABLE COPY:: FROM: ".$cp['from']. " TO: ".$cp['to']);
  2049. $this->copy_path($cp['from'], $cp['to']);
  2050. /*}else{
  2051. //since they are not equal then we need to prompt the user
  2052. }*/
  2053. }//fi
  2054. }//rof
  2055. }//fi
  2056. }//fi
  2057. }
  2058. function disable_copy(){
  2059. //when we disable we want to copy the -restore files back into the file system
  2060. //but we should check the version in the module install against the version on the file system
  2061. //if they match then we can copy the file back, but otherwise we should ask the user.
  2062. // $GLOBALS['log']->debug('ModuleInstaller.php->disable_copy()');
  2063. if(isset($GLOBALS['mi_overwrite_files']) && $GLOBALS['mi_overwrite_files']){
  2064. // $GLOBALS['log']->debug('ModuleInstaller.php->disable_copy():mi_overwrite_files=true');
  2065. if(!empty($this->installdefs['copy'])){
  2066. // $GLOBALS['log']->debug('ModuleInstaller.php->disable_copy(): installdefs not empty');
  2067. foreach($this->installdefs['copy'] as $cp){
  2068. $cp['to'] = clean_path(str_replace('<basepath>', $this->base_dir, $cp['to']));
  2069. $backup_path = clean_path( remove_file_extension(urldecode(hashToFile($_REQUEST['install_file'])))."-restore/".$cp['to'] ); // bug 16966 tyoung - replaced missing assignment to $backup_path
  2070. //check if this file exists in the -restore directory
  2071. // $GLOBALS['log']->debug("ModuleInstaller.php->disable_copy(): backup_path=".$backup_path);
  2072. if(file_exists($backup_path)){
  2073. //since the file exists, then we want do an md5 of the install version and the file system version
  2074. $from = str_replace('<basepath>', $this->base_dir, $cp['from']);
  2075. //if(is_file($from) && md5_file($from) == md5_file($cp['to'])){
  2076. //since the files are the same then we can safely move back from the -restore
  2077. //directory into the file system
  2078. $GLOBALS['log']->debug("DISABLE COPY:: FROM: ".$backup_path. " TO: ".$cp['to']);
  2079. $this->copy_path($backup_path, $cp['to']);
  2080. /*}else{
  2081. //since they are not equal then we need to prompt the user
  2082. }*/
  2083. }//fi
  2084. }//rof
  2085. }//fi
  2086. }//fi
  2087. }
  2088. public function reset_opcodes()
  2089. {
  2090. /* Bug 39354 - added function_exists check. Not optimal fix, but safe nonetheless.
  2091. * This is for the upgrade to 6.1 from pre 6.1, since the utils files haven't been updated to 6.1 when this is called,
  2092. * but this file has been updated to 6.1
  2093. */
  2094. if(function_exists('sugar_clean_opcodes')){
  2095. sugar_clean_opcodes();
  2096. }
  2097. }
  2098. }
  2099. function UpdateSystemTabs($action, $installed_modules){
  2100. require_once("modules/MySettings/TabController.php");
  2101. $controller = new TabController();
  2102. $isSystemTabsInDB = $controller->is_system_tabs_in_db();
  2103. if ($isSystemTabsInDB && !empty($installed_modules))
  2104. {
  2105. global $moduleList;
  2106. switch ($action)
  2107. {
  2108. case 'Restore' :
  2109. $currentTabs = $controller->get_system_tabs();
  2110. foreach ($installed_modules as $module)
  2111. {
  2112. if(in_array($module, $currentTabs)){
  2113. unset($currentTabs[$module]);
  2114. }
  2115. }
  2116. $controller->set_system_tabs($currentTabs);;
  2117. break;
  2118. case 'Add' :
  2119. $currentTabs = $controller->get_system_tabs();
  2120. foreach ($installed_modules as $module)
  2121. {
  2122. if(!in_array($module, $currentTabs)){
  2123. $currentTabs[$module] = $module;
  2124. }
  2125. }
  2126. $controller->set_system_tabs($currentTabs);
  2127. default:
  2128. break;
  2129. }
  2130. }
  2131. }
  2132. ?>