]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/connectors/component.php
Release 6.4.0
[Github/sugarcrm.git] / include / connectors / component.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  * Connector component
40  * @api
41  */
42 class component{
43         protected $_has_testing_enabled = false;
44         protected $_source;
45
46         public function __construct() {}
47
48         public function init() {}
49
50         /**
51          * fillBean
52          * This function wraps the call to getItem, but takes an additional SugarBean argument
53          * and loads the SugarBean's fields with the results as defined in the connector
54          * loadBean configuration mapping
55          *
56          * @param $args Array of arguments to pass into getItem
57          * @param $module String value of the module to map bean to
58          * @param $bean SugarBean instance to load values into
59          * @throws Exception Thrown if results could not be loaded into bean
60          */
61         public function fillBean($args=array(), $module=null, $bean=null) {
62             $result = null;
63                 if(is_object($bean)) {
64                    $args = $this->mapInput($args, $module);
65                $item = $this->_source->getItem($args, $module);
66                $result = $this->mapOutput($bean, $item);
67             } else if(!empty($module) && ($bean = loadBean($module))) {
68                return $this->fillBean($args, $module, $bean);
69             } else {
70                throw new Exception("Invalid bean");
71             }
72             return $result;
73         }
74
75         /**
76          * fillBeans
77          * This function wraps the call to getList, but takes an additional Array argument
78          * and loads the SugarBean's fields with the results as defined in the connector
79          * loadBean configuration mapping
80          *
81          * @param $args Array of arguments to pass into getItem
82          * @param $module String value of the module to map bean to
83          * @param $bean Array to load SugarBean intances into
84          * @throws Exception Thrown if errors are found
85          */
86         public function fillBeans($args=array(), $module=null, $beans=array()) {
87                 $results = array();
88                 $args = $this->mapInput($args, $module);
89                 if(empty($args)) {
90                    $GLOBALS['log']->fatal($GLOBALS['app_strings']['ERR_MISSING_MAPPING_ENTRY_FORM_MODULE']);
91                    throw new Exception($GLOBALS['app_strings']['ERR_MISSING_MAPPING_ENTRY_FORM_MODULE']);
92                 }
93
94
95                 require_once('include/connectors/filters/FilterFactory.php');
96                 $filter = FilterFactory::getInstance(get_class($this->_source));
97                 $list = $filter->getList($args, $module);
98
99                 if(!empty($list)) {
100                         $resultSize = count($list);
101                         if(!empty($beans)) {
102                            if(count($beans) != $resultSize) {
103                                   throw new Exception($GLOBALS['app_strings']['ERR_CONNECTOR_FILL_BEANS_SIZE_MISMATCH']);
104                            }
105                         } else {
106
107                            for($x=0; $x < $resultSize; $x++) {
108                                    $beans[$x] = loadBean($module);
109                            }
110                         }
111
112                     $keys = array_keys($beans);
113                         $count = 0;
114                         foreach($list as $entry) {
115                                    //Change the result keys to lower case.  This has important ramifications.
116                                    //This was done because the listviewdefs.php files may not know the proper casing
117                                    //of the fields to display.  We change the keys to lowercase so that the values
118                                    //may be mapped to the beans without having to rely on the proper string casing
119                                    //in the listviewdefs.php files.
120                                    $entry = array_change_key_case($entry, CASE_LOWER);
121                                    $results[] = $this->mapOutput($beans[$keys[$count]], $entry);
122                                    $count++;
123                         }
124
125                         $field_defs = $this->getFieldDefs();
126                     $map = $this->getMapping();
127                         $hasOptions = !empty($map['options']) ? true : false;
128                         if($hasOptions) {
129                            $options = $map['options'];
130                            $optionFields = array();
131
132                            foreach($field_defs as $name=>$field) {
133                                        if(!empty($field['options']) && !empty($map['options'][$field['options']]) && !empty($map['beans'][$module][$name])) {
134                                           $optionFields[$name] = $map['beans'][$module][$name];
135                                        }
136                            }
137
138                            foreach($results as $key=>$bean) {
139                                    foreach($optionFields as $sourceField=>$sugarField) {
140                                                $options_map = $options[$field_defs[$sourceField]['options']];
141                                                $results[$key]->$sugarField =  !empty($options_map[$results[$key]->$sugarField]) ? $options_map[$results[$key]->$sugarField] : $results[$key]->$sugarField;
142                                    }
143                            } //foreach
144                         }
145                 }
146
147                 return $results;
148         }
149
150
151
152         /**
153          * Obtain a list of items
154          *
155          * @param string $module ideally this method should return a list of beans of type $module.
156          * @param Mixed $args this represents the 'query' on the data source.
157          */
158
159
160         /**
161          * Given a bean, persist it to a data source
162          *
163          * @param SugarBean $bean
164          */
165         public function save($bean){}
166
167
168         /**
169          * getConfig
170          * Returns the configuration Array as definied in the config.php file
171          *
172          * @return $config Array of the configuration mappings as defined in config.php
173          */
174         public function getConfig(){
175                 return $this->_source->getConfig;
176         }
177
178
179         public function getFieldDefs() {
180                 return $this->_source->getFieldDefs();
181         }
182
183         /**
184          * setConfig
185          * Used by the Factories to set the config on the corresponding object
186          *
187          * @param array $config this file will be specified in config file corresponding to the wrapper or data source we are
188          * using. The name would be something like hoovers.php if we are using the hoovers data source or hoovers wrapper
189          * and it would exist in the same directory as the connector and/or wrapper.
190          * Note that the confing specified at the connector level takes precendence over the config specified at the wrapper level.
191          * This logic is performed in ConnectorFactory.php
192          */
193         public function setConfig($config){
194                 $this->_source->setConfig($config);
195         }
196
197         /**
198          * mapInput
199          */
200         public function mapInput($inputData, $module){
201                 $input_params = array();
202                 $map = $this->getMapping();
203                 if(empty($map['beans'][$module])) {
204                    return $input_params;
205                 }
206                 $mapping = array_flip($map['beans'][$module]);
207                 $field_defs = $this->getFieldDefs();
208                 foreach($inputData as $arg=>$val){
209                         if(!empty($mapping[$arg]) || !empty($field_defs[$arg])) {
210                                 if(!empty($mapping[$arg])){
211                                         $arg = $mapping[$arg];
212                                 }
213                                 if(!empty($field_defs[$arg]['input'])){
214                                         $in_field = $field_defs[$arg]['input'];
215                                         $temp = explode('.', $in_field);
216                                         $eval_code = "\$input_params";
217                                         foreach($temp as $arr_key) {
218                                                 $eval_code .= '[\'' . $arr_key . '\']';
219                                         }
220                                         $eval_code .= "= \$val;";
221                                         eval($eval_code);
222                                 } else {
223                                         $input_params[$arg] = $val;
224                                 }
225                         } //if
226                 } //foreach
227                 return $input_params;
228         }
229
230         public function mapOutput($bean, $result){
231                 if(is_object($bean)) {
232                         $map = $this->getMapping();
233                         $mapping = $map['beans'][$bean->module_dir];
234
235                     //Check for situation where nothing was mapped or the only field mapped was id
236                         if(empty($mapping) || (count($mapping) == 1 && isset($mapping['id']))) {
237                            $GLOBALS['log']->error($GLOBALS['mod_strings']['ERROR_NO_DISPLAYABLE_MAPPED_FIELDS']);
238                            throw new Exception($GLOBALS['mod_strings']['ERROR_NO_DISPLAYABLE_MAPPED_FIELDS']);
239                         }
240
241                         $mapped = array();
242                         if(!empty($mapping)) {
243                                 foreach($mapping as $source_field => $sugar_field){
244                                         $bean->$sugar_field = $this->getFieldValue($bean, $result, $source_field);
245                                         $mapped[$source_field] = $bean->$sugar_field;
246                                 }
247                         } else {
248                                 foreach($result as $key=>$value) {
249                                         if(isset($bean->field_defs[$key])) {
250                                            $bean->$key = $value;
251                                         }
252                                 }
253                         }
254
255                         //set the data_source_id field which contain the unique id for the source
256                         $source_field = 'id';
257                         $bean->data_source_id = $this->getFieldValue($bean, $result, $source_field);
258
259                         //now let's check for any fields that have not been mapped which may be required
260                         $required_fields = $this->_source->getFieldsWithParams('required', true);
261                         if(!empty($required_fields)){
262                                 foreach($required_fields as $key => $def){
263                                         if(empty($mapped[$key])){
264                                                 $bean->$key = $this->getFieldValue($bean, $result, $key);
265                                         }
266                                 }
267                         }
268
269                         return $bean;
270                 }
271                 return $bean;
272         }
273
274         private function getFieldValue($bean, $result, $source_field){
275                 $def = $this->getModuleFieldDef($bean->module_dir, $source_field);
276                 $out_field = $source_field;
277                 if(!empty($def['output'])){
278                         $out_field = $def['output'];
279                 }
280
281                 $value = SugarArray::staticGet($result, $out_field);
282
283                 if(is_array($def)){
284                         if(!empty($def['function'])){
285                                 $function = $def['function'];
286                                 if(is_array($function) && isset($function['name'])){
287                                         $function = $def['function']['name'];
288                                         if(!empty($def['function']['include'])){
289                                                 require_once($def['function']['include']);
290                                         }
291                                  }
292                                  $value = $function($bean, $out_field, $value);
293                          }
294                  }
295                  return $value;
296         }
297
298         public function saveConfig($persister=null) {
299                 $this->_source->saveConfig($persister);
300         }
301
302         public function loadConfig($persister=null) {
303                 $this->_source->loadConfig($persister);
304         }
305
306         public function setMapping($map=array()) {
307                 $this->_source->setMapping($map);
308         }
309
310         public function getMapping() {
311                 return $this->_source->getMapping();
312         }
313
314         public function getModuleMapping($module) {
315                 $map = $this->getMapping();
316                 return !empty($map['beans'][$module]) ? $map['beans'][$module] : array();
317         }
318
319         public function getModuleFieldDef($module, $field){
320                 $map = $this->getMapping();
321                 $field_defs = $this->getFieldDefs();
322                 if(!empty($map['beans'][$module][$field])){
323                         $source_field = $field;
324                         if(!empty($field_defs[$source_field])){
325                                 return $field_defs[$source_field];
326                         }elseif(!empty($field_defs[$field])){
327                                 return $field_defs[$field];
328                         }else{
329                                 return $field;
330                         }
331                 }elseif(!empty($field_defs[$field])){
332                                 return $field_defs[$field];
333                 }else{
334                                 return $field;
335                 }
336         }
337
338         public function getSource(){
339                 return $this->_source;
340         }
341
342         public function setSource($source){
343                 $this->_source = $source;
344         }
345 }
346 ?>