]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/UpgradeWizard/SugarMerge/EditViewMerge.php
Release 6.5.15
[Github/sugarcrm.git] / modules / UpgradeWizard / SugarMerge / EditViewMerge.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2013 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  * Description:  Defines the English language pack for the base application.
41  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
42  * All Rights Reserved.
43  * Contributor(s): ______________________________________..
44  ********************************************************************************/
45  
46 /**
47  * This is the base class that all other SugarMerge objects extend 
48  *
49  */
50 class EditViewMerge{
51         /**
52          * The variable name that is used with the file for example in editviewdefs and detailviewdefs it is $viewdefs
53          *
54          * @var STRING
55          */
56         protected $varName = 'viewdefs';
57         /**
58          * Enter the name of the parameter used in the $varName for example in editviewdefs and detailviewdefs it is 'EditView' and 'DetailView' respectively - $viewdefs['EditView']
59          *
60          * @var STRING
61          */
62         protected $viewDefs = 'EditView';
63         /**
64          * this will store the meta data for the original file
65          *
66          * @var ARRAY
67          */
68         protected $originalData = array();
69         /**
70          * this will store the meta data for the new file
71          *
72          * @var ARRAY
73          */
74         protected $newData = array();
75         /**
76          * this will store the meta data for the custom file
77          *
78          * @var ARRAY
79          */
80         protected $customData = array();
81         /**
82          * this will store an associative array contianing all the fields that are used in the original meta data file
83          *
84          * @var ARRAY
85          */
86         protected $originalFields = array();
87         /**
88          * this will store an associative array contianing all the fields that are used in the new meta data file
89          *
90          * @var ARRAY
91          */
92         protected $newFields = array();
93         /**
94          * this will store an associative array contianing all the fields that are used in the custom meta data file
95          *
96          * @var ARRAY
97          */
98         protected $customFields = array();
99         /**
100          * this will store an associative array contianing all the merged fields 
101          *
102          * @var ARRAY
103          */
104         protected $mergedFields = array();
105         /**
106          * the name of the module to be merged
107          *
108          * @var STRING
109          */
110         protected $module = 'module';
111         /**
112          * the max number of columns for this view
113          *
114          * @var INT
115          */
116         protected $maxCols = 2;
117         /**
118          * If we should use the best match algorithim
119          *
120          * @var BOOLEAN
121          */
122         protected $bestMatch = true;
123         /**
124          * The default panel we place the fields in if we aren't using the best match algorithim
125          *
126          * @var STRING
127          */
128         protected $defaultPanel = 'default';
129         /**
130          * The name of the panels section in the meta data
131          *
132          * @var STRING
133          */
134         protected $panelName = 'panels';
135         /**
136          * The name of the templateMeta data secion in the meta data
137          */
138         protected $templateMetaName = 'templateMeta';
139         /**
140          * The file pointer to log to if set to NULL it will use the GLOBALS['log'] if available and log to debug
141          *
142          * @var FILEPOINTER
143          */
144         protected $fp = NULL;
145         
146         
147         /**
148          * Determines if getFields should analyze panels to determine if it is a MultiPanel
149          *
150          * @var unknown_type
151          */
152         protected $scanForMultiPanel = true;
153         
154         /**
155          * If true then it works as though it's a multipanel
156          *
157          * @var BOOLEAN
158          */
159         protected $isMultiPanel = true;
160         
161         
162         /**
163          * The ids of the panels found in custom metadata fuke
164          * 
165          */
166         protected $customPanelIds = array();
167         
168         
169         /**
170          * The ids of the panels found in original metadata fuke
171          * 
172          */
173         protected $originalPanelIds = array();
174
175
176         /**
177          * The ids of the panels found in original metadata fuke
178          * 
179          */
180         protected $newPanelIds = array();       
181         
182         
183         /**
184          * Special case conversion
185          * 
186          */
187         protected $fieldConversionMapping = array(
188                         'Campaigns' => array('created_by_name'=>'date_entered', 'modified_by_name'=>'date_modified'),
189             'Cases' => array('created_by_name'=>'date_entered', 'modified_by_name'=>'date_modified'),
190                         'Contracts' => array('created_by_name'=>'date_entered', 'modified_by_name'=>'date_modified'),
191                         'Leads' => array('created_by'=>'date_entered'),
192             'Meetings' => array('created_by_name'=>'date_entered', 'modified_by_name'=>'date_modified'),
193                         'ProspectLists' => array('created_by_name'=>'date_entered', 'modified_by_name'=>'date_modified'),
194             'Prospects' => array('created_by_name'=>'date_entered', 'modified_by_name'=>'date_modified'),
195         );
196
197     /**
198      * @var SugarMerge
199      */
200     public $sugarMerge = null;
201
202         /**
203          * Clears out the values of the arrays so that the same object can be utilized
204          *
205          */
206         protected function clear(){
207                 unset($this->newData);
208                 $this->newData = array();
209                 unset($this->customData);
210                 $this->customData = array();
211                 unset($this->originalData);
212                 $this->originalData = array();
213                 unset($this->newFields);
214                 $this->newFields = array();
215                 unset($this->customFields);
216                 $this->customFields = array();
217                 unset($this->originalFields);
218                 $this->originalFields = array();
219                 unset($this->mergedFields);
220                 $this->mergedFields = array();
221                 unset($this->mergeData);
222                 $this->mergeData = array();
223                 $this->defaultPanel = 'default';
224         }
225         
226         /**
227          * Allows the user to choose to use the best match algorithim or not
228          *
229          * @param BOOLEAN $on
230          */
231         public function setBestMatch($on=true){
232                 $this->bestMatch = $on;
233         }
234         
235         
236         /**
237          * Allows users to set the name to use as the default panel in the meta data
238          *
239          * @param STRING $name - name of the default panel
240          */
241         public function setDefaultPanel($name = 'default'){
242                 $this->defaultPanel = $name;
243         }
244         
245         /**
246          * Allows the user to set a filepointer that is already open to log to
247          *
248          * @param FILEPOINTER $fp
249          */
250         public function setLogFilePointer($fp){
251                 $this->fp = $fp;
252         }
253         
254         /**
255          * opens the file with the 'a' parameter and use it to log messages to
256          *
257          * @param STRING $file - path to file we wish to log to
258          */
259         public function setLogFile($file){
260                 $this->fp = fopen($file, 'a');
261         }
262         
263         /**
264          * 
265          */
266         /**
267          * returns true if $val1 and $val2 match otherwise it returns false
268          *
269          * @param MULTI $val1 - a value to compare to val2
270          * @param MULTI $val2 - a value to compare to val1
271          * @return BOOLEAN - if $val1 and $val2 match
272          */
273         protected function areMatchingValues($val1, $val2){
274                 if(!is_array($val1)){
275                         //if val2 is an array and val1 isn't then it isn't a match
276                         if(is_array($val2)){
277                                 return false;
278                         }
279                         //otherwise both are not arrays so we can return a comparison between them
280                         return $val1 == $val2;
281                 }else{
282                         //if val1 is an array and val2 isn't then it isn't a match
283                         if(!is_array($val2)){
284                                 return false;
285                         }
286                 }
287                 foreach($val1 as $k=>$v){
288                         if(!isset($val2[$k]))return false;
289                         if(!$this->areMatchingValues($val1[$k], $val2[$k])){
290                                 return false;
291                         }
292                         unset($val2[$k]);
293                         unset($val1[$k]);
294                 }
295                 //this implies that there are still values left  so the two must not match since we unset any matching values
296                 if(!empty($val2)){
297                         return false;
298                 }
299                 return true;
300         }
301         
302         /**
303          * Recursiveley merges two arrays
304          *
305          * @param ARRAY $gimp - if keys match this arrays values are overriden 
306          * @param ARRAY $dom - if keys match this arrays values will override the others
307          * @return ARRAY $merged - the merges array
308          */
309         function arrayMerge($gimp, $dom) {
310         if(is_array($gimp) && is_array($dom)) {
311                 foreach($dom as $domKey => $domVal) {
312                         if(isset($gimp[$domKey])) {
313                                 if(is_array($domVal)) {
314                                         $gimp[$domKey] = $this->arrayMerge($gimp[$domKey], $dom[$domKey]);
315                                 } else {
316                                         $gimp[$domKey] = $domVal;
317                                 }
318                         } else {
319                                 $gimp[$domKey] = $domVal;
320                         }
321                 }
322         }
323         return $gimp;
324 }
325         
326         /**
327          * Merges the meta data of a single field
328          *
329          * @param ARRAY $orig - the original meta-data for this field
330          * @param ARRAY $new - the new meta-data for this field
331          * @param ARRAY $custom - the custom meta-data for this field
332          * @return ARRAY $merged - the merged meta-data
333          */
334         protected function mergeField($orig, $new, $custom){
335                 $orig_custom = $this->areMatchingValues($orig, $custom);
336                 $new_custom = $this->areMatchingValues($new, $custom);
337                 // if both are true then there is nothing to merge since all three fields match
338                 if(!($orig_custom && $new_custom)){
339                         $this->log('merging field');
340                         $this->log('original meta-data');
341                         $this->log($orig);
342                         $this->log('new meta-data');
343                         $this->log($new);
344                         $this->log('custom meta-data');
345                         $this->log($custom);
346                         $this->log('merged meta-data');
347                         $log = true;
348                 }else{
349                         return $new;
350                 }
351                 //if orignal and custom match always take the new value or if new and custom match
352                 if($orig_custom || $new_custom){
353                         $this->log($new);
354                         return $new;
355                 }
356                 //if original and new match always take the custom
357                 if($this->areMatchingValues($orig, $new)){
358                         $this->log($custom);
359                         return $custom;
360                 }
361                 
362                 if(is_array($custom)) {
363                         //if both new and custom are arrays then at this point new != custom and orig != custom and orig != new  so let's merge the custom and the new and return that
364                         if(is_array($new)){
365                                 $new = $this->arrayMerge($custom, $new);
366                                 $this->log($new);
367                                 return $new;
368                         }else{
369                                 //otherwise we know that new is not an array and custom has been 'customized' so let's keep those customizations.
370                                 $this->log($custom);
371                                 return $custom;
372                         }
373                 }
374                 //default to returning the New version of the field 
375                 $this->log($new);
376                 return $new; 
377         }
378         
379         /**
380          * Merges the fields together and stores them in $this->mergedFields
381          *
382          */
383         protected function mergeFields() {
384                 foreach($this->customFields as $field=>$data) {
385                         //if we have this field in both the new fields and the original fields - it has existed since the last install/upgrade
386                         if(isset($this->newFields[$field]) && isset($this->originalFields[$field])){                            
387                                 //if both the custom field and the original match then we take the location of the custom field since it hasn't moved
388                                 $loc = $this->customFields[$field]['loc'];
389                                 $loc['source'] = 'custom';      
390
391                                 $do_merge = true;
392                                 
393                                 //Address fields present a special problem...
394                                 if(preg_match('/(alt_|primary_|billing_|shipping_)address_street/i', $field, $matches)) {
395                                    $prefix = $matches[1];
396                                    $city = $prefix . 'address_city';
397                                    $postal_code = $prefix . 'address_postalcode';
398                                    $state = $prefix . 'address_state';
399                                    $country = $prefix . 'address_country';
400                                    
401                                    if(isset($this->customFields[$city]) || 
402                                       isset($this->customFields[$postal_code]) || 
403                                       isset($this->customFields[$state]) || 
404                                       isset($this->customFields[$country])) {
405                             $do_merge = false;
406                             $this->mergedFields[$field] = array(
407                                                         'data'=>$this->customFields[$field]['data'], 
408                                                         'loc'=>$loc);
409                                       }
410                                 }                       
411                                 
412                                 if($do_merge) {
413                                         //but we still merge the meta data of the three
414                                         $this->mergedFields[$field] = array(
415                                                 'data'=>$this->mergeField($this->originalFields[$field]['data'], $this->newFields[$field]['data'], $this->customFields[$field]['data']), 
416                                                 'loc'=>$loc);
417                                 }
418                         //if it's not set in the new fields then it was a custom field or an original field so we take the custom fields data and set the location source to custom
419                         } else if(!isset($this->newFields[$field])){
420                                 $this->mergedFields[$field] = $data;
421                                 $this->mergedFields[$field]['loc']['source'] = 'custom';
422                         } else {        
423                                 //otherwise  the field is in both new and custom but not in the orignal so we merge the new and custom data together and take the location from the custom
424                                 $this->mergedFields[$field] = array(
425                                         'data'=>$this->mergeField('', $this->newFields[$field]['data'], $this->customFields[$field]['data']), 
426                                         'loc'=>$this->customFields[$field]['loc']);
427                                 
428                                 $this->mergedFields[$field]['loc']['source'] = 'custom';
429                                 //echo var_export($this->mergedFields[$field], true);
430                         }
431                         
432                         //then we clear out the field from 
433                         unset($this->originalFields[$field]);
434                         unset($this->customFields[$field]);
435                         unset($this->newFields[$field]);
436                 }
437                 
438                 
439                 /**
440                  * These are fields that were removed by the customer
441                  */
442                 foreach($this->originalFields as $field=>$data){
443                         unset($this->originalFields[$field]);
444                         unset($this->newFields[$field]);
445                 }
446                 
447                 /**
448                  * These are fields that were added by sugar
449                  */
450                 $new_field_panel = $this->defaultPanel;
451             foreach($this->customPanelIds as $custom_panel_ids=>$panels) {
452                                 $new_field_panel = $custom_panel_ids;
453                 }               
454                 
455                 foreach($this->newFields as $field=>$data){
456                         $data['loc']['source']= 'new';
457                         $data['loc']['panel'] = $new_field_panel;
458                         $this->mergedFields[$field] = array(
459                                         'data'=>$data['data'], 
460                                         'loc'=>$data['loc']);
461                         unset($this->newFields[$field]);
462                 }
463         }
464         
465         /**
466          * Walks through the merged fields and places them in the appropriate place based on their location parameter as well as the choosen algorithim
467          *
468          * @return ARRAY $panels - the new panels section for the merged file
469          */
470         protected function buildPanels(){
471                 $panels  = array();
472                 
473                 $panel_keys = array_keys($this->customPanelIds);
474                 $this->defaultPanel = end($panel_keys);
475                 
476                 foreach($this->mergedFields as $field_id=>$field){                      
477                         //If this field is in a panel not defined in the custom layout, set it to default panel
478                         if(!isset($this->customPanelIds[$field['loc']['panel']])) {
479                            $field['loc']['panel'] = $this->defaultPanel;
480                         }
481                         
482                         if($field['loc']['source'] == 'new') {
483                                 if($this->bestMatch){
484                                         //for best match as long as the column is filled let's keep walking down till we can fill it
485                                         $row = end(array_keys($this->customData[$this->module][$this->viewDefs][$this->panelName][$field['loc']['panel']]));
486                                         $col = 0;
487                                         while(!empty($panels[$field['loc']['panel']][$row][$col])){
488                                                 $col++;
489                                                 if($col == 2) {
490                                                    $row++;
491                                                    $col = 0;
492                                                 }
493                                         }
494                                         //row should be at a point that there is no field in this location
495                                         $panels[$field['loc']['panel']][$row][$col] = $field['data'];
496                                 }else{
497                                         //so for not best match we place it in the default panel at the first available column for the row
498                                         $row = 0;
499                                         while(!empty($panels[$this->defaultPanel][$row][$field['loc']['col']])){
500                                                 $row++;
501                                         }
502                                         $panels[$field['loc']['panel']][$row][$field['loc']['col']] = $field['data'];
503                                 }                               
504                         } else {
505                                 $panels[$field['loc']['panel']][$field['loc']['row']][$field['loc']['col']] = $field['data'];
506                         }
507                         
508
509                 }
510                 
511                 foreach($panels as $k=>$panel){
512                         foreach($panel as $r=>$row){
513                                         ksort($panels[$k][$r]);
514                         }
515                         ksort($panels[$k]);
516                 }
517                 
518                 return $panels;
519         }
520         
521         /**
522          * Merge the templateMeta entry for the view defs.  Also assume that any changes made in the custom files should
523          * have precedence since they must be changed manually, even over new files that may be provided in the upgarde
524          * patch.
525          *
526          */
527         protected function mergeTemplateMeta()
528         {
529         //this is to handle the situation in Calls/Meetings where we updated the templateMeta and will fail if we don't update this.
530         //long term we should not do this and should provide a way for calls/meetings to update themselves.
531             if( isset($this->customData[$this->module][$this->viewDefs][$this->templateMetaName]) && strcmp(strtolower($this->module), 'calls') != 0 && strcmp(strtolower($this->module), 'meetings') != 0 )
532             {   
533                 $this->newData[$this->module][$this->viewDefs][$this->templateMetaName] = $this->customData[$this->module][$this->viewDefs][$this->templateMetaName];
534             }
535
536         }
537         
538         /**
539          * Sets the panel section for the meta-data after it has been merged
540          *
541          */
542         protected function setPanels(){
543                 $this->newData[$this->module][$this->viewDefs][$this->panelName] = $this->buildPanels();
544                 /*
545                 if(!$this->isMultiPanel) {
546                    $this->newData[$this->module][$this->viewDefs][$this->panelName] = $this->newData[$this->module][$this->viewDefs][$this->panelName][$this->defaultPanel];
547                 }
548         */
549         }
550         
551         /**
552          * Parses out the fields for each files meta data and then calls on mergeFields and setPanels
553          *
554          */
555         protected function mergeMetaData(){
556                 $this->originalFields = $this->getFields($this->originalData[$this->module][$this->viewDefs][$this->panelName]);
557                 $this->originalPanelIds = $this->getPanelIds($this->originalData[$this->module][$this->viewDefs][$this->panelName]);
558                 $this->customFields = $this->getFields($this->customData[$this->module][$this->viewDefs][$this->panelName]);
559                 $this->customPanelIds = $this->getPanelIds($this->customData[$this->module][$this->viewDefs][$this->panelName]);                
560                 $this->newFields = $this->getFields($this->newData[$this->module][$this->viewDefs][$this->panelName]);
561                 //echo var_export($this->newFields, true);
562                 $this->newPanelIds = $this->getPanelIds($this->newData[$this->module][$this->viewDefs][$this->panelName]);
563                 $this->mergeFields();
564                 $this->mergeTemplateMeta();
565                 $this->setPanels();
566         }
567         /**
568          * This takes in a  list of panels and returns an associative array of field names to the meta-data of the field as well as the locations of that field
569          *
570          * @param ARRAY $panels - this is the 'panel' section of the meta-data
571          * @return ARRAY $fields - an associate array of fields and their meta-data as well as their location
572          */
573         protected function getFields(&$panels){
574
575                 $fields = array();
576                 $blanks = 0;
577         $setDefaultPanel = false;
578   
579                 if(count($panels) == 1) {
580                    $arrayKeys = array_keys($panels);
581                    if(!empty($arrayKeys[0])) {
582                           $this->defaultPanel = $arrayKeys[0];
583                       $panels = $panels[$arrayKeys[0]];
584                    } else {
585                           $panels = $panels[''];
586                    }
587                    $setDefaultPanel = true;   
588                 }               
589                 
590                 if($this->scanForMultiPanel){
591                         require_once('include/SugarFields/Parsers/MetaParser.php');                     
592                         if($setDefaultPanel || !MetaParser::hasMultiplePanels($panels)) {
593                            $panels = array($this->defaultPanel=>$panels);
594                            $this->isMultiPanel = false;
595                         }
596                 }
597                 
598                 //echo "---------------------------------------------------------\n";
599                 //echo var_export($panels, true);
600                 
601                 foreach($panels as $panel_id=>$panel){  
602                         foreach($panel as $row_id=>$rows){
603                                 foreach($rows as $col_id=>$col){
604                                         if(empty($col)) {
605                                            $field_name = 'BLANK_' . $blanks;
606                                            $blanks++;
607                                         } else {
608                                                 $field_name = is_array($col) && isset($col['name']) ? $col['name'] : $col;
609                                                 if(is_array($col)){
610                                                         if(!empty($col['name'])) {
611                                                            $field_name = $col['name'];
612                                                         }
613                                                 }else{
614                                                         $field_name = $col;
615                                                 }
616                                         }
617                                         
618                                         if(is_string($field_name)) {
619                         // We need to replace all instances of the fake uploadfile and filename field that has custom code with the real filename field
620                         if(!empty($col['customCode']))
621                         {
622                             if($field_name == 'uploadfile')
623                             {
624                                 $replaceField = false;
625                                 if ( !empty($col['customCode']) ) {
626                                     $replaceField = true;
627                                     unset($col['customCode']);
628                                 }
629
630                                 if( !empty($col['displayParams']) && !empty($col['displayParams']['link']) ) {
631                                     $replaceField = true;
632                                 }
633
634                                 if ( $replaceField ) {
635                                     $field_name = 'filename';
636                                     $col['name'] = 'filename';
637                                 }
638                             } else if ($field_name == 'filename') {
639                                 $col = 'filename';
640                             }
641                         }
642
643                                                 $fields[$field_name] = array('data'=>$col, 'loc'=>array('panel'=>"{$panel_id}", 'row'=>"{$row_id}", 'col'=>"{$col_id}"));
644                                         }
645                                 }
646                         }               
647                 }
648                 
649                 //echo "---------------------------------------------------------\n";
650                 //echo var_export($fields, true);
651                 
652                 return $fields;
653         }
654                 
655                 
656         /**
657          * getPanelIds
658          * 
659          */
660         protected function getPanelIds($panels){
661
662                 $panel_ids = array();
663         $setDefaultPanel = false;
664         
665                 if(count($panels) == 1) {
666                    $arrayKeys = array_keys($panels);
667                    if(!empty($arrayKeys[0])) {
668                           $this->defaulPanel = $arrayKeys[0];
669                       $panels = $panels[$arrayKeys[0]];
670                    } else {
671                           $panels = $panels[''];
672                    }
673                    $setDefaultPanel = true;   
674                 }               
675                 
676                 if($this->scanForMultiPanel){
677                         require_once('include/SugarFields/Parsers/MetaParser.php');                     
678                         if($setDefaultPanel || !MetaParser::hasMultiplePanels($panels)) {
679                            $panels = array($this->defaultPanel=>$panels);
680                            $this->isMultiPanel = false;
681                         }
682                 }
683
684                 foreach($panels as $panel_id=>$panel){  
685                     $panel_ids[$panel_id] = $panel_id;
686                 }
687                                 
688                 return $panel_ids;
689         }       
690         
691         /**
692          * Loads the meta data of the original, new, and custom file into the variables originalData, newData, and customData respectively
693          *
694          * @param STRING $module - name of the module's files that are to be merged
695          * @param STRING $original_file - path to the file that originally shipped with sugar
696          * @param STRING $new_file - path to the new file that is shipping with the patch 
697          * @param STRING $custom_file - path to the custom file
698          */
699         protected function loadData($module, $original_file, $new_file, $custom_file){
700                 $this->module = $module;
701                 $varnmame = $this->varName;
702                 require($original_file);
703                 $this->originalData = $$varnmame;
704                 require($new_file);
705                 $this->newData = $$varnmame;
706                 if(file_exists($custom_file)){
707                         require($custom_file);
708                         $this->customData = $$varnmame;
709                 }else{
710                         $this->customData = $this->originalData;
711                 }       
712         }
713         
714         /**
715          * This will save the merged data to a file
716          *
717          * @param STRING $to - path of the file to save it to 
718          * @return BOOLEAN - success or failure of the save
719          */
720         public function save($to){
721                 return write_array_to_file("viewdefs['$this->module']['$this->viewDefs']", $this->newData[$this->module][$this->viewDefs], $to);
722         }
723         
724         /**
725          * This will return the meta data of the merged file
726          *
727          * @return ARRAY - the meta data of the merged file
728          */
729         public function getData(){
730                 return $this->newData;
731         }
732         
733         /**
734          * public function that will merge meta data from an original sugar file that shipped with the product, a customized file, and a new file shipped with an upgrade
735          *
736          * @param STRING $module - name of the module's files that are to be merged
737          * @param STRING $original_file - path to the file that originally shipped with sugar
738          * @param STRING $new_file - path to the new file that is shipping with the patch 
739          * @param STRING $custom_file - path to the custom file
740          * @param BOOLEAN $save - boolean on if it should save the results to the custom file or not
741          * @return BOOLEAN - if the merged file was saved if false is passed in for the save parameter it always returns true
742          */
743         public function merge($module, $original_file, $new_file, $custom_file=false, $save=true){
744                 $this->clear();
745                 $this->log("\n\n". 'Starting a merge in ' . get_class($this));
746                 $this->log('merging the following files');
747                 $this->log('original file:'  . $original_file);
748                 $this->log('new file:'  . $new_file);
749                 $this->log('custom file:'  . $custom_file);
750                 if(empty($custom_file) && $save){
751                         return true;
752                 }else{
753                         $this->loadData($module, $original_file, $new_file, $custom_file);
754                         $this->mergeMetaData();
755                         if($save && !empty($this->newData) && !empty($custom_file)){
756                                 //backup the file
757                                 copy($custom_file, $custom_file . '.suback.php');
758                                 return $this->save($custom_file);
759                         }
760                 }
761                 if(!$save)return true;
762                 return false;
763         }
764         /**
765          * Logs the given message if the message is not a string it will export it first. If $this->fp is NULL then it will try to log to the $GLOBALS['log'] if it is available
766          *
767          * @param MULTI $message
768          */
769         protected  function log($message){
770                 if(!is_string($message)){
771                         $message = var_export($message, true);
772                 }
773                 if(!empty($this->fp)){
774                         fwrite($this->fp, $message. "\n");
775                 }else{
776                         if(!empty($GLOBALS['log'])){
777                                 $GLOBALS['log']->debug($message . "\n");
778                         }
779                 }
780                 
781         }
782 }
783
784 ?>