]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/connectors/sources/default/source.php
Release 6.5.0
[Github/sugarcrm.git] / include / connectors / sources / default / source.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-2012 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  * source is the parent class of any source object.
41  * @api
42  */
43 abstract class source{
44         /**
45          * The name of an wrapper to use if the class wants to provide an override
46          */
47         public $wrapperName;
48         protected $_config;
49         protected $_mapping;
50         protected $_field_defs;
51
52     /**
53      * @var bool enable_in_wizard Boolean value marking whether or not the connector may appear in the wizard (Get Data) views
54      */
55     protected $_enable_in_wizard = true;
56
57     /**
58      * @var bool enable_in_hover Boolean value marking whether or not a hover link could be applied to the connector
59      */
60         protected $_enable_in_hover = false;
61
62     /**
63      * @var bool enable_in_admin_mapping Boolean value marking whether or not this connector should be shown in the Modify Mapping view
64      */
65     protected $_enable_in_admin_mapping = true;
66
67     /**
68      * @var bool enable_in_admin_properties Boolean value marking whether or not this connector should appear in the Set Connector Properties view
69      */
70     protected $_enable_in_admin_properties = true;
71
72     /**
73      * @var bool enable_in_admin_display Boolean value marking whether or not this connector should appear in the Enable Connectors view
74      */
75     protected $_enable_in_admin_display = true;
76
77     /**
78      * @var bool enable_in_admin_search Boolean value marking whether or not this connector should appear in the Manage Connector Search view
79      */
80     protected $_enable_in_admin_search = true;
81
82     /**
83      * @var bool has_testing_enabled Boolean value marking whether or not the connector should display the test button in administration view
84      */
85         protected $_has_testing_enabled = false;
86
87         protected $_required_config_fields = array();
88         protected $_required_config_fields_for_button = array();
89         protected $config_decrypted = false;
90
91     /**
92      * The ExternalAPI Base that instantiated this connector.
93      * @var _eapm
94      */
95     protected $_eapm = null;
96
97         public function __construct(){
98                 $this->loadConfig();
99                 $this->loadMapping();
100                 $this->loadVardefs();
101         }
102
103         public function init(){}
104
105         //////// CALLED FROM component.php ///////
106         public function loadMapping() {
107                 $mapping = array();
108                 $dir = str_replace('_','/',get_class($this));
109                 if(file_exists("custom/modules/Connectors/connectors/sources/{$dir}/mapping.php")) {
110                         require("custom/modules/Connectors/connectors/sources/{$dir}/mapping.php");
111                 } else if(file_exists("modules/Connectors/connectors/sources/{$dir}/mapping.php")){
112                         require("modules/Connectors/connectors/sources/{$dir}/mapping.php");
113                 }
114             $this->_mapping = $mapping;
115         }
116
117     public function saveMappingHook($mapping) {
118         // Most classes don't care that the mapping has changed, but this is here if they do.
119         return;
120     }
121
122     /**
123      * Load source's vardef file
124      */
125         public function loadVardefs() {
126                 $class = get_class($this);
127                 $dir = str_replace('_','/',$class);
128                 if(file_exists("custom/modules/Connectors/connectors/sources/{$dir}/vardefs.php")) {
129                         require("custom/modules/Connectors/connectors/sources/{$dir}/vardefs.php");
130                 } else if(file_exists("modules/Connectors/connectors/sources/{$dir}/vardefs.php")){
131                         require("modules/Connectors/connectors/sources/{$dir}/vardefs.php");
132                 }
133
134                 $this->_field_defs = !empty($dictionary[$class]['fields']) ? $dictionary[$class]['fields'] : array();
135         }
136
137         /**
138          * Given a parameter in a vardef field, return the list of fields that match the param and value
139          *
140          * @param string $param_name
141          * @param string $param_value
142          * @return array
143          */
144         public function getFieldsWithParams($param_name, $param_value)
145         {
146                 if(empty($this->_field_defs)){
147                         $this->loadVardefs();
148                 }
149                 $fields_with_param = array();
150                 foreach($this->_field_defs as $key => $def){
151                         if(!empty($def[$param_name]) && ($def[$param_name] == $param_value)){
152                                 $fields_with_param[$key] = $def;
153                         }
154                 }
155                 return $fields_with_param;
156         }
157
158         /**
159          * Save source's config to custom directory
160          */
161         public function saveConfig()
162         {
163                 $config_str = "<?php\n/***CONNECTOR SOURCE***/\n";
164
165         // Handle encryption
166         if(!empty($this->_config['encrypt_properties']) && is_array($this->_config['encrypt_properties']) && !empty($this->_config['properties'])){
167             require_once('include/utils/encryption_utils.php');
168             foreach($this->_config['encrypt_properties'] as $name) {
169                 if(!empty($this->_config['properties'][$name])) {
170                     $this->_config['properties'][$name] = blowfishEncode(blowfishGetKey('encrypt_field'),$this->_config['properties'][$name]);
171                 }
172             }
173         }
174
175
176                 foreach($this->_config as $key => $val) {
177                         if(!empty($val)){
178                                 $config_str .= override_value_to_string_recursive2('config', $key, $val, false);
179                         }
180                 }
181                 $dir = str_replace('_', '/', get_class($this));
182
183             if(!file_exists("custom/modules/Connectors/connectors/sources/{$dir}")) {
184                mkdir_recursive("custom/modules/Connectors/connectors/sources/{$dir}");
185             }
186             file_put_contents("custom/modules/Connectors/connectors/sources/{$dir}/config.php", $config_str);
187         }
188
189         /**
190          * Initialize config - decrypt encrypted fields
191          */
192         public function initConfig()
193         {
194         if($this->config_decrypted) return;
195         // Handle decryption
196         require_once('include/utils/encryption_utils.php');
197         if(!empty($this->_config['encrypt_properties']) && is_array($this->_config['encrypt_properties']) && !empty($this->_config['properties'])){
198             foreach($this->_config['encrypt_properties'] as $name) {
199                 if(!empty($this->_config['properties'][$name])) {
200                     $this->_config['properties'][$name] = blowfishDecode(blowfishGetKey('encrypt_field'),$this->_config['properties'][$name]);
201                 }
202             }
203         }
204         $this->config_decrypted = true;
205         }
206
207         /**
208          * Load config.php for this source
209          */
210         public function loadConfig()
211         {
212                 $config = array();
213                 $dir = str_replace('_','/',get_class($this));
214                 if(file_exists("modules/Connectors/connectors/sources/{$dir}/config.php")){
215                         require("modules/Connectors/connectors/sources/{$dir}/config.php");
216                 }
217                 if(file_exists("custom/modules/Connectors/connectors/sources/{$dir}/config.php")) {
218                         require("custom/modules/Connectors/connectors/sources/{$dir}/config.php");
219                 }
220                 $this->_config = $config;
221
222                 //If there are no required config fields specified, we will default them to all be required
223                 if(empty($this->_required_config_fields)) {
224                    foreach($this->_config['properties'] as $id=>$value) {
225                           $this->_required_config_fields[] = $id;
226                    }
227                 }
228         }
229
230     // Helper function for the settings panels
231     /**
232      * Filter which modules are allowed to connect
233      * @param array $moduleList
234      * @return array Allowed modules
235      */
236     public function filterAllowedModules( $moduleList )
237     {
238         // Most modules can connect to everything, no further filtering necessary
239         return $moduleList;
240     }
241
242         ////////////// GETTERS and SETTERS ////////////////////
243         public function getMapping()
244         {
245                 return $this->_mapping;
246         }
247
248         public function getOriginalMapping() {
249                 $mapping = array();
250                 $dir = str_replace('_','/',get_class($this));
251                 if(file_exists("modules/Connectors/connectors/sources/{$dir}/mapping.php")) {
252                         require("modules/Connectors/connectors/sources/{$dir}/mapping.php");
253                 } else if(file_exists("custom/modules/Connectors/connectors/sources/{$dir}/mapping.php")){
254                         require("custom/modules/Connectors/connectors/sources/{$dir}/mapping.php");
255                 }
256                 return $mapping;
257         }
258
259         public function setMapping($mapping)
260         {
261                 $this->_mapping = $mapping;
262         }
263
264         public function getFieldDefs()
265         {
266                 return $this->_field_defs;
267         }
268
269         public function getConfig()
270         {
271             if(!$this->config_decrypted) $this->initConfig();
272                 return $this->_config;
273         }
274
275         public function setConfig($config)
276         {
277                 $this->_config = $config;
278                 $this->config_decrypted = true; // Don't decrypt external configs
279         }
280
281     public function setEAPM(ExternalAPIBase $eapm)
282     {
283         $this->_eapm = $eapm;
284     }
285
286     public function getEAPM()
287     {
288         return $this->_eapm;
289     }
290
291     public function setProperties($properties=array())
292     {
293                 if(!empty($this->_config) && isset($this->_config['properties'])) {
294                    $this->_config['properties'] = $properties;
295                    $this->config_decrypted = true; // Don't decrypt external configs
296                 }
297         }
298
299         public function getProperties()
300         {
301                 if(!empty($this->_config) && isset($this->_config['properties'])) {
302                    if(!$this->config_decrypted) $this->initConfig();
303                    return $this->_config['properties'];
304                 }
305                 return array();
306         }
307
308         /**
309          * Check if certain property contains non-empty value
310          * @param string $name
311          * @return bool
312          */
313         public function propertyExists($name)
314         {
315             return !empty($this->_config['properties'][$name]);
316         }
317
318         public function getProperty($name)
319         {
320             if(!empty($this->_config) && isset($this->_config['properties'][$name])) {
321                 // check if we're asking for encrypted property and we didn't decrypt yet
322                 if(!$this->config_decrypted && !empty($this->_config['encrypt_properties']) && in_array($name, $this->_config['encrypt_properties']) && !empty($this->_config['properties'][$name])) {
323                     $this->initConfig();
324                 }
325                 return $this->_config['properties'][$name];
326                 } else {
327                         return '';
328                 }
329         }
330
331         /**
332          * hasTestingEnabled
333          * This method is used to indicate whether or not a data source has testing enabled so that
334          * the administration interface may call the test method on the data source instance
335          *
336          * @return enabled boolean value indicating whether or not testing is enabled
337          */
338         public function hasTestingEnabled() {
339                 return $this->_has_testing_enabled;
340         }
341
342         /**
343          * test
344          * This method is called from the administration interface to run a test of the service
345          * It is up to subclasses to implement a test and set _has_testing_enabled to true so that
346          * a test button is rendered in the administration interface
347          *
348          * @return result boolean result of the test function
349          */
350     public function test() {
351         return false;
352     }
353
354
355     /**
356      * isEnabledInWizard
357      * This method indicates whether or not the connector should be enabled in the wizard
358      * Connectors that do not support the getList/getItem methods via API calls should
359      * set the protected class variable _enable_in_wizard to false.
360      *
361      * @return $enabled boolean variable indicating whether or not the connector is enabled for the wizard
362      */
363     public function isEnabledInWizard() {
364         return $this->_enable_in_wizard;
365     }
366
367
368     /**
369      * isEnabledInHover
370      * This method indicates whether or not the connector should be enabled for the hover links
371      * Connectors that do not provide a formatter implementation should not
372      * set the protected class variable _enable_in_hover to true.
373      *
374      * @return $enabled boolean variable indicating whether or not the connector is enabled for the hover links
375      *
376      */
377     public function isEnabledInHover() {
378         return $this->_enable_in_hover;
379     }
380
381     /**
382      * isEnabledInAdminProperties
383      * This method indicates whether or not the connector should be shown in the Set Connector Properties view.
384      * The Admin views call each source's isEnabledInAdminProperties method to verify whether or not the connector should be
385      * displayed.  Connectors that do not have any administrative properties should set the protected class variable
386      * _enable_in_admin_properties to false.
387      *
388      * @return boolean value indicating whether or not the connector is enabled for admin views
389      */
390     public function isEnabledInAdminProperties()
391     {
392         return $this->_enable_in_admin_properties;
393     }
394
395     /**
396      * isEnabledInAdminMapping
397      * This method indicates whether or not the connector should be shown in the Map Connector Fields view.
398      * The Admin views call each source's isEnabledInAdminMapping method to verify whether or not the connector should be
399      * displayed.  Connectors that do not have any administrative mapping properties should set the protected class variable
400      * _enable_in_admin_mapping to false.
401      *
402      * @return boolean value indicating whether or not the connector is enabled for admin views
403      */
404     public function isEnabledInAdminMapping()
405     {
406         return $this->_enable_in_admin_mapping;
407     }
408
409     /**
410      * isEnabledInAdminDisplay
411      * This method indicates whether or not the connector should be shown in the Enable Connectors view.
412      * The Admin views call each source's isEnabledInAdminDisplay method to verify whether or not the connector should be
413      * displayed.  Connectors that do not have any administrative display settings should set the protected class variable
414      * _enable_in_admin_display to false.
415      *
416      * @return boolean value indicating whether or not the connector is enabled for admin views
417      */
418     public function isEnabledInAdminDisplay()
419     {
420         return $this->_enable_in_admin_display;
421     }
422
423     /**
424      * isEnabledInAdminSearch
425      * This method indicates whether or not the connector should be shown in the Manage Connectors Search view.
426      * The Admin views call each source's isEnabledInAdminSearch method to verify whether or not the connector should be
427      * displayed.  Connectors that do not have any administrative search settings should set the protected class variable
428      * _enable_in_admin_search to false.
429      *
430      * @return boolean value indicating whether or not the connector is enabled for admin views
431      */
432     public function isEnabledInAdminSearch()
433     {
434         return $this->_enable_in_admin_search;
435     }
436
437     /**
438      * getRequiredConfigFields
439      * This method returns an Array of the configuration keys that are required for the Connector.
440      * Subclasses should set the class variable _required_config_fields to
441      * return an Array of keys as specified in the Connector's config.php that are required.
442      *
443      * @return $fields Array of Connector config fields that are required
444      */
445     public function getRequiredConfigFields() {
446         return $this->_required_config_fields;
447     }
448
449
450     /**
451      * isRequiredConfigFieldsSet
452      * This method checks the configuration parameters against the required config fields
453      * to see if they are set
454      *
455      * @return $set boolean value indicating whether or not the required config fields are set
456      */
457     public function isRequiredConfigFieldsSet() {
458         //Check if required fields are set
459                 foreach($this->_required_config_fields as $field) {
460                 if(empty($this->_config['properties'][$field])) {
461                    return false;
462                 }
463                 }
464         return true;
465     }
466
467
468     /**
469      * getRequiredConfigFieldsForButton
470      * This method returns an Array of the configuration keys that are required before the
471      * "Get Data" button will include the Connector.  We use it as a subset of the
472      * $this->_required_config_fields Array.
473      *
474      * @return $fields Array of Connector config fields that are required to be set for the "Get Data" button to appear
475      */
476     public function getRequiredConfigFieldsForButton() {
477         return $this->_required_config_fields_for_button;
478     }
479
480
481     /**
482      * isRequiredConfigFieldsForButtonSet
483      * This method checks the configuration parameters against the required config fields
484      * for the "Get Button" to see if they are set
485      *
486      * @return $set boolean value indicating whether or not the required config fields are set
487      */
488     public function isRequiredConfigFieldsForButtonSet() {
489         //Check if required fields for button are set
490                 foreach($this->_required_config_fields_for_button as $field) {
491                 if(empty($this->_config['properties'][$field])) {
492                    return false;
493                 }
494                 }
495         return true;
496     }
497
498
499     /**
500      * Allow data sources to log information
501      *
502      * @param string $log_data
503      */
504     protected function log($log_data){
505         $name = get_class($this);
506         $property_name = $this->getProperty('name');
507         if(!empty($property_name)){
508                 $name = $property_name;
509         }
510         $GLOBALS['log']->info($name. ': '.$log_data);
511     }
512
513         /**
514          * getItem
515          * Returns an array containing a key/value pair(s) of a connector record. To be overridden by the implementation
516          * source.
517          *
518          * @param $args Array of arguments to search/filter by
519          * @param $module String optional value of the module that the connector framework is attempting to map to
520          * @return Array of key/value pair(s) of connector record; empty Array if no results are found
521          */
522         public abstract function getItem($args=array(), $module=null);
523
524
525         /**
526          * getList
527          * Returns a nested array containing a key/value pair(s) of a connector record. To be overridden by the
528          * implementation source.
529          *
530          * @param $args Array of arguments to search/filter by
531          * @param $module String optional value of the module that the connector framework is attempting to map to
532          * @return Array of key/value pair(s) of connector record; empty Array if no results are found
533          */
534         public abstract function getList($args=array(), $module=null);
535
536     /**
537          * Default destructor
538          *
539          */
540         public function __destruct(){
541          // Bug # 47233 - This desctructor was originally removed by bug # 44533.
542          // We have to add this destructor back in
543          // because there are customers who upgrade from 61x to 623
544          // who have the Jigsaw connector enabled, and the jigsaw connector
545          // makes a call to this destructor.
546
547      }
548 }