]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/ModuleBuilder/parsers/views/ListLayoutMetaDataParser.php
Release 6.4.0
[Github/sugarcrm.git] / modules / ModuleBuilder / parsers / views / ListLayoutMetaDataParser.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-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 require_once 'modules/ModuleBuilder/parsers/views/AbstractMetaDataParser.php' ;
40 require_once 'modules/ModuleBuilder/parsers/views/MetaDataParserInterface.php' ;
41
42 class ListLayoutMetaDataParser extends AbstractMetaDataParser implements MetaDataParserInterface
43 {
44
45     // Columns is used by the view to construct the listview - each column is built by calling the named function
46     public $columns = array ( 'LBL_DEFAULT' => 'getDefaultFields' , 'LBL_AVAILABLE' => 'getAdditionalFields' , 'LBL_HIDDEN' => 'getAvailableFields' ) ;
47     protected $labelIdentifier = 'label' ; // labels in the listviewdefs.php are tagged 'label' =>
48     protected $allowParent = false;
49
50     /*
51      * Simple function for array_udiff_assoc function call in getAvailableFields()
52      */
53     static function getArrayDiff ($one , $two)
54     {
55         $retArray = array();
56         foreach($one as $key => $value)
57         {
58             if (!isset($two[$key]))
59             {
60                 $retArray[$key] = $value;
61             }
62         }
63         return $retArray;
64     }
65
66     /*
67      * Constructor
68      * @param string view          The view type, that is, editview, searchview etc
69      * @param string moduleName     The name of the module to which this listview belongs
70      * @param string packageName    If not empty, the name of the package to which this listview belongs
71      */
72     function __construct ($view , $moduleName , $packageName = '')
73     {
74         $GLOBALS [ 'log' ]->debug ( get_class ( $this ) . ": __construct()" ) ;
75
76         // BEGIN ASSERTIONS
77         $views = array ( MB_LISTVIEW, MB_DASHLET, MB_DASHLETSEARCH, MB_POPUPLIST, MB_POPUPSEARCH ) ;
78         if (! in_array ( $view , $views ) )
79         {
80             sugar_die ( "ListLayoutMetaDataParser: View $view is not supported" ) ;
81         }
82         // END ASSERTIONS
83
84         if (empty ( $packageName ))
85         {
86             require_once 'modules/ModuleBuilder/parsers/views/DeployedMetaDataImplementation.php' ;
87             $this->implementation = new DeployedMetaDataImplementation ( $view, $moduleName ) ;
88         } else
89         {
90             require_once 'modules/ModuleBuilder/parsers/views/UndeployedMetaDataImplementation.php' ;
91             $this->implementation = new UndeployedMetaDataImplementation ( $view, $moduleName, $packageName ) ;
92         }
93         $this->view = $view;
94
95         $this->_fielddefs = $this->implementation->getFielddefs () ;
96         $this->_standardizeFieldLabels( $this->_fielddefs );
97         $this->_viewdefs = array_change_key_case ( $this->implementation->getViewdefs () ) ; // force to lower case so don't have problems with case mismatches later
98
99     }
100
101     /*
102      * Deploy the layout
103      * @param boolean $populate If true (default), then update the layout first with new layout information from the $_REQUEST array
104      */
105     function handleSave ($populate = true)
106     {
107         if ($populate)
108             $this->_populateFromRequest () ;
109         $this->implementation->deploy ( array_change_key_case ( $this->_viewdefs, CASE_UPPER ) ) ; // force the field names back to upper case so the list view will work correctly
110     }
111
112     function getLayout ()
113     {
114         return $this->_viewdefs ;
115     }
116
117     /**
118      * Return a list of the default fields for a listview
119      * @return array    List of default fields as an array, where key = value = <field name>
120      */
121     function getDefaultFields ()
122     {
123         $defaultFields = array ( ) ;
124         foreach ( $this->_viewdefs as $key => $def )
125         {
126             // add in the default fields from the listviewdefs but hide fields disabled in the listviewdefs.
127             if (! empty ( $def [ 'default' ] ) && (!isset($def['enabled']) || $def['enabled'] != false)
128                 && (!isset($def [ 'studio' ]) || ($def [ 'studio' ] !== false && $def [ 'studio' ] != "false")))
129             {
130                 if (isset($this->_fielddefs [ $key ] )) {
131                                         $defaultFields [ $key ] = self::_trimFieldDefs ( $this->_fielddefs [ $key ] ) ;
132                                         if (!empty($def['label']))
133                                            $defaultFields [ $key ]['label'] = $def['label'];
134                 }
135                                 else {
136                                         $defaultFields [ $key ] = $def;
137                                 }
138             }
139         }
140
141         return $defaultFields ;
142     }
143
144     /**
145      * Returns additional fields available for users to create fields
146       @return array    List of additional fields as an array, where key = value = <field name>
147      */
148     function getAdditionalFields ()
149     {
150         $additionalFields = array ( ) ;
151         foreach ( $this->_viewdefs as $key => $def )
152         {
153                 //#25322 
154                 if(strtolower ( $key ) == 'email_opt_out'){
155                         continue;
156                 }
157                 
158             if (empty ( $def [ 'default' ] ))
159             {
160                 if (isset($this->_fielddefs [ $key ] ))
161                                         $additionalFields [ $key ] = self::_trimFieldDefs ( $this->_fielddefs [ $key ] ) ;
162                                 else
163                                         $additionalFields [ $key ] = $def;
164             }
165         }
166         return $additionalFields ;
167     }
168
169     /**
170      * Returns unused fields that are available for use in either default or additional list views
171      * @return array    List of available fields as an array, where key = value = <field name>
172      */
173     function getAvailableFields ()
174     {
175         $availableFields = array ( ) ;
176         // Select available fields from the field definitions - don't need to worry about checking if ok to include as the Implementation has done that already in its constructor
177         foreach ( $this->_fielddefs as $key => $def )
178         {
179             if ($this->isValidField($key, $def) && !isset($this->_viewdefs[$key]))
180                     $availableFields [ $key ] = self::_trimFieldDefs( $this->_fielddefs [ $key ] ) ;
181         }
182         $origDefs = $this->getOriginalViewDefs();
183         foreach($origDefs as $key => $def)
184         {
185                 if (!isset($this->_viewdefs[$key]) || 
186                         (isset($this->_viewdefs[$key]['enabled']) && $this->_viewdefs[$key]['enabled'] == false))
187                 $availableFields [ $key ] = $def;
188         }
189
190         return $availableFields;
191     }
192
193     public function isValidField($key, $def)
194     {
195         if (isset($def['studio']))
196         {
197             if (is_array($def['studio']))
198             {
199                 $view = !empty($_REQUEST['view']) ? $_REQUEST['view'] : $this->view;
200                 
201                 // fix for removing email1 field from studio popup searchview - bug 42902
202                 if($view == 'popupsearch' && $key == 'email1')
203                 {       
204                         return false;
205                 } //end bug 42902
206            
207                 if (!empty($view) && isset($def['studio'][$view]) && ($def['studio'][$view] !== false && (string)$def['studio'][$view] != 'false' && (string)$def['studio'][$view] != 'hidden'))
208                 {
209                                         return true;
210                 }
211
212                 if (isset($def['studio']['listview']) && ($def['studio']['listview'] !== false && (string)$def['studio']['listview'] != 'false' && (string)$def['studio']['listview'] != 'hidden'))
213                 {
214                                         return true;
215                 }
216                 
217                 if (isset($def ['studio']['visible']))
218                 {
219                     return $def['studio']['visible'];
220                 }
221             } else if(is_string($def['studio'])) {
222                 return $def['studio'] != 'false' && $def['studio'] != 'hidden';
223             } else if(is_bool($def['studio'])) {
224                 return $def['studio'];
225             }
226
227         }
228         
229         //Bug 32520. We need to dissalow currency_id fields on list views. 
230         //This should be removed once array based studio definitions are in.
231         if (isset($def['type']) && $def['type'] == "id" && $def['name'] == 'currency_id')
232         {
233            return false;
234         }
235         
236         //Check fields types
237         if (isset($def['dbType']) && $def['dbType'] == "id")
238         {
239             return false;
240         }
241         
242         if (isset($def['type']))
243         {
244             if ($def['type'] == 'html' || ($def['type'] == 'parent' && !$this->allowParent) 
245              || $def['type'] == "id" || $def['type'] == "link" || $def['type'] == 'image')
246                 return false;
247         }
248
249         //hide currency_id, deleted, and _name fields by key-name
250         if(strcmp ( $key, 'deleted' ) == 0 ) {
251             return false;
252         }
253
254         //if all the tests failed, the field is probably ok
255         return true;
256     }
257
258     protected function _populateFromRequest ()
259     {
260         $GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->populateFromRequest() - fielddefs = ".print_r($this->_fielddefs, true));
261         // Transfer across any reserved fields, that is, any where studio !== true, which are not editable but must be preserved
262         $newViewdefs = array ( ) ;
263         $rejectTypes = array ( 'html'=>'html', 'text'=>'text', 'encrypt'=>'encrypt' ) ;
264
265         $originalViewDefs = $this->getOriginalViewDefs();
266
267         foreach ( $this->_viewdefs as $key => $def )
268         {
269             //If the field is on the layout, but studio disabled, put it back on the layout at the front
270                 if (isset ($def['studio']) && (
271                         (is_array($def['studio']) && isset($def['studio']['listview']) && 
272                         ($def['studio']['listview'] === false || strtolower($def['studio']['listview']) == 'false' 
273                         || strtolower($def['studio']['listview']) == 'required')
274                 )
275                         || (!is_array($def['studio']) && 
276                                 ($def [ 'studio' ] === false || strtolower($def['studio']) == 'false' || strtolower($def['studio']) == 'required'))
277                         ))
278                 {
279                 $newViewdefs [ $key ] = $def ;
280                 }
281         }
282         // only take items from group_0 for searchviews (basic_search or advanced_search) and subpanels (which both are missing the Available column) - take group_0, _1 and _2 for all other list views
283         $lastGroup = (isset ( $this->columns [ 'LBL_AVAILABLE' ] )) ? 2 : 1 ;
284
285         for ( $i = 0 ; isset ( $_POST [ 'group_' . $i ] ) && $i < $lastGroup ; $i ++ )
286         {
287             foreach ( $_POST [ 'group_' . $i ] as $fieldname )
288             {
289                 $fieldname = strtolower ( $fieldname ) ;
290                 //Check if the field was previously on the layout
291                 if (isset ($this->_viewdefs[$fieldname])) {
292                         $newViewdefs [ $fieldname ] = $this->_viewdefs[$fieldname];
293                    // print_r($this->_viewdefs[ $fieldname ]);
294                                 }
295                 //Next check if the original view def contained it
296                 else if (isset($originalViewDefs[ $fieldname ]))
297                 {
298                         $newViewdefs [ $fieldname ] =  $originalViewDefs[ $fieldname ];
299                 }
300                 //create a definition from the fielddefs
301                 else
302                 {
303                         // if we don't have a valid fieldname then just ignore it and move on...
304                                         if ( ! isset ( $this->_fielddefs [ $fieldname ] ) )
305                                                 continue ;
306
307                         $newViewdefs [ $fieldname ] = $this->_trimFieldDefs($this->_fielddefs [ $fieldname ]) ;
308                     // sorting fields of certain types will cause a database engine problems
309                         if ( isset($this->_fielddefs[$fieldname]['type']) &&
310                                         isset ( $rejectTypes [ $this->_fielddefs [ $fieldname ] [ 'type' ] ] ))
311                         {
312                             $newViewdefs [ $fieldname ] [ 'sortable' ] = false ;
313                         }
314
315                         // Bug 23728 - Make adding a currency type field default to setting the 'currency_format' to true
316                         if (isset ( $this->_fielddefs [ $fieldname ] [ 'type' ]) && $this->_fielddefs [ $fieldname ] [ 'type' ] == 'currency')
317                         {
318                             $newViewdefs [ $fieldname ] [ 'currency_format' ] = true;
319                         }
320                 }
321                 if (isset($newViewdefs [ $fieldname ]['enabled']))
322                                 $newViewdefs [ $fieldname ]['enabled'] = true;
323
324                 if (isset ( $_REQUEST [ strtolower ( $fieldname ) . 'width' ] ))
325                 {
326                     $width = substr ( $_REQUEST [ $fieldname . 'width' ], 6, 3 ) ;
327                     if (strpos ( $width, "%" ) != false)
328                     {
329                         $width = substr ( $width, 0, 2 ) ;
330                     }
331                                         if (!($width < 101 && $width > 0))
332                     {
333                         $width = 10;
334                     }
335                     $newViewdefs [ $fieldname ] [ 'width' ] = $width."%" ;
336                 } else if (isset ( $this->_viewdefs [ $fieldname ] [ 'width' ] ))
337                 {
338                     $newViewdefs [ $fieldname ] [ 'width' ] = $this->_viewdefs [ $fieldname ] [ 'width' ] ;
339                 }
340                 else {
341                         $newViewdefs [ $fieldname ] [ 'width' ] = "10%";
342                 }
343
344                 $newViewdefs [ $fieldname ] [ 'default' ] = ($i == 0) ;
345             }
346         }
347         $this->_viewdefs = $newViewdefs ;
348
349     }
350
351     /*
352      * Remove all instances of a field from the layout
353      * @param string $fieldName Name of the field to remove
354      * @return boolean True if the field was removed; false otherwise
355      */
356     function removeField ($fieldName)
357     {
358         if (isset ( $this->_viewdefs [ $fieldName ] ))
359         {
360             unset( $this->_viewdefs [ $fieldName ] )  ;
361             return true ;
362         }
363         return false ;
364     }
365
366     function getOriginalViewDefs() {
367         $defs = $this->implementation->getOriginalViewdefs ();
368         $out = array();
369         foreach ($defs as $field => $def)
370         {
371                 $out[strtolower($field)] = $def;
372         }
373
374         return $out;
375     }
376
377    static function _trimFieldDefs ( $def )
378         {
379                 if ( isset ( $def [ 'vname' ] ) )
380                         $def [ 'label' ] = $def [ 'vname' ] ;
381                 return array_intersect_key ( $def , array ( 'type' => true, 'studio' => true , 'label' => true , 'width' => true , 'sortable' => true , 'related_fields' => true , 'default' => true , 'link' => true , 'align' => true , 'orderBy' => true ,'hideLabel' => true, 'customLable' => true , 'currency_format' => true ) ) ;
382         }
383
384 }