PageRenderTime 79ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 1ms

/SugarCRM/ModuleInstall/ModuleInstaller.php

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