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-2012 SugarCRM Inc.
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.
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
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
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.
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.
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 ********************************************************************************/
43 protected $_has_testing_enabled = false;
46 public function __construct() {}
48 public function init() {}
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
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
61 public function fillBean($args=array(), $module=null, $bean=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);
70 throw new Exception("Invalid bean");
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
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
86 public function fillBeans($args=array(), $module=null, $beans=array()) {
88 $args = $this->mapInput($args, $module);
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']);
95 require_once('include/connectors/filters/FilterFactory.php');
96 $filter = FilterFactory::getInstance(get_class($this->_source));
97 $list = $filter->getList($args, $module);
100 $resultSize = count($list);
102 if(count($beans) != $resultSize) {
103 throw new Exception($GLOBALS['app_strings']['ERR_CONNECTOR_FILL_BEANS_SIZE_MISMATCH']);
107 for($x=0; $x < $resultSize; $x++) {
108 $beans[$x] = loadBean($module);
112 $keys = array_keys($beans);
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);
125 $field_defs = $this->getFieldDefs();
126 $map = $this->getMapping();
127 $hasOptions = !empty($map['options']) ? true : false;
129 $options = $map['options'];
130 $optionFields = array();
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];
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;
153 * Obtain a list of items
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.
161 * Given a bean, persist it to a data source
163 * @param SugarBean $bean
165 public function save($bean){}
170 * Returns the configuration Array as definied in the config.php file
172 * @return $config Array of the configuration mappings as defined in config.php
174 public function getConfig(){
175 return $this->_source->getConfig;
179 public function getFieldDefs() {
180 return $this->_source->getFieldDefs();
185 * Used by the Factories to set the config on the corresponding object
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
193 public function setConfig($config){
194 $this->_source->setConfig($config);
200 public function mapInput($inputData, $module){
201 $input_params = array();
202 $map = $this->getMapping();
203 if(empty($map['beans'][$module])) {
204 return $input_params;
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];
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 . '\']';
220 $eval_code .= "= \$val;";
223 $input_params[$arg] = $val;
227 return $input_params;
230 public function mapOutput($bean, $result){
231 if(is_object($bean)) {
232 $map = $this->getMapping();
233 $mapping = $map['beans'][$bean->module_dir];
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']);
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;
248 foreach($result as $key=>$value) {
249 if(isset($bean->field_defs[$key])) {
250 $bean->$key = $value;
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);
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);
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'];
281 $value = SugarArray::staticGet($result, $out_field);
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']);
292 $value = $function($bean, $out_field, $value);
298 public function saveConfig($persister=null) {
299 $this->_source->saveConfig($persister);
302 public function loadConfig($persister=null) {
303 $this->_source->loadConfig($persister);
306 public function setMapping($map=array()) {
307 $this->_source->setMapping($map);
310 public function getMapping() {
311 return $this->_source->getMapping();
314 public function getModuleMapping($module) {
315 $map = $this->getMapping();
316 return !empty($map['beans'][$module]) ? $map['beans'][$module] : array();
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];
331 }elseif(!empty($field_defs[$field])){
332 return $field_defs[$field];
338 public function getSource(){
339 return $this->_source;
342 public function setSource($source){
343 $this->_source = $source;