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