PageRenderTime 14ms CodeModel.GetById 3ms app.highlight 111ms RepoModel.GetById 1ms app.codeStats 1ms

/ModuleInstall/ModuleInstaller.php

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