]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/externalAPI/ExternalAPIFactory.php
Release 6.2.3
[Github/sugarcrm.git] / include / externalAPI / ExternalAPIFactory.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('include/connectors/utils/ConnectorUtils.php');
40 require_once('include/connectors/sources/SourceFactory.php');
41 /**
42  * Provides a factory to list, discover and create external API calls
43  *
44  * Main features are to list available external API's by supported features, modules and which ones have access for the user.
45  **/
46 class ExternalAPIFactory
47 {
48     /**
49      * Filter the list of APIs, removing disabled ones
50      * @param array $apiFullList
51      * @return array Filtered list
52      */
53     public static function filterAPIList($apiFullList)
54     {
55         $filteredList = array();
56         foreach($apiFullList as $name => $data) {
57             if(isset($data['connector'])) {
58                 if(ConnectorUtils::eapmEnabled($data['connector'])) {
59                      if(isset($data['authMethod']) && $data['authMethod'] == 'oauth'){
60                         $connector = SourceFactory::getSource($data['connector'], false);
61                         if(!empty($connector) && $connector->propertyExists('oauth_consumer_key')
62                             && $connector->propertyExists('oauth_consumer_secret')) {
63                                 $filteredList[$name] = $data;
64                         }
65                      }else{
66                         $filteredList[$name] = $data;
67                      }
68                 }
69             }else {
70                 $filteredList[$name] = $data;
71             }
72         }
73         return $filteredList;
74     }
75
76     /**
77      * Get the list of available APIs
78      * @param bool $forceRebuild
79      * @param bool $ignoreDisabled Should we ignore disabled status?
80      * @return array
81      */
82     public static function loadFullAPIList($forceRebuild=false, $ignoreDisabled = false) {
83         if ( isset($GLOBALS['sugar_config']['developer_mode']) && $GLOBALS['sugar_config']['developer_mode'] ) {
84             static $beenHereBefore = false;
85             if ( !$beenHereBefore ) {
86                 $forceRebuild = true;
87                 $beenHereBefore = true;
88             }
89         }
90         if (!$forceRebuild && file_exists('cache/include/externalAPI.cache.php') ) {
91             // Already have a cache file built, no need to rebuild
92             require('cache/include/externalAPI.cache.php');
93
94             return $ignoreDisabled?$fullAPIList:self::filterAPIList($fullAPIList);
95         }
96
97         $apiFullList = array();
98         $meetingPasswordList = array();
99         $needUrlList = array();
100
101         $baseDirList = array('include/externalAPI/','custom/include/externalAPI');
102         foreach ( $baseDirList as $baseDir ) {
103             $dirList = glob($baseDir.'*',GLOB_ONLYDIR);
104             foreach($dirList as $dir) {
105                 if ( $dir == $baseDir.'.' || $dir == $baseDir.'..' || $dir == $baseDir.'Base' ) {
106                     continue;
107                 }
108
109                 $apiName = str_replace($baseDir,'',$dir);
110                 if ( file_exists($dir.'/ExtAPI'.$apiName.'.php') ) {
111                     $apiFullList[$apiName]['className'] = 'ExtAPI'.$apiName;
112                     $apiFullList[$apiName]['file'] = $dir.'/'.$apiFullList[$apiName]['className'].'.php';
113                 }
114                 if ( file_exists($dir.'/ExtAPI'.$apiName.'_cstm.php') ) {
115                     $apiFullList[$apiName]['className'] = 'ExtAPI'.$apiName.'_cstm';
116                     $apiFullList[$apiName]['file_cstm'] = $dir.'/'.$apiFullList[$apiName]['className'].'.php';
117                 }
118             }
119         }
120
121         $optionList = array('supportedModules','useAuth','requireAuth','supportMeetingPassword','docSearch', 'authMethod', 'oauthFixed','needsUrl','canInvite','sendsInvites','sharingOptions','connector', 'oauthParams','restrictUploadsByExtension');
122         foreach ( $apiFullList as $apiName => $apiOpts ) {
123             require_once($apiOpts['file']);
124             if ( !empty($apiOpts['file_cstm']) ) {
125                 require_once($apiOpts['file_cstm']);
126             }
127             $className = $apiOpts['className'];
128             $apiClass = new $className();
129             foreach ( $optionList as $opt ) {
130                 if ( isset($apiClass->$opt) ) {
131                     $apiFullList[$apiName][$opt] = $apiClass->$opt;
132                 }
133             }
134
135             // Special handling for the show/hide of the Meeting Password field, we need to create a dropdown for the Sugar Logic code.
136             if ( isset($apiClass->supportMeetingPassword) && $apiClass->supportMeetingPassword == true ) {
137                 $meetingPasswordList[$apiName] = $apiName;
138             }
139
140         }
141
142         create_cache_directory('/include/');
143         $fd = fopen('cache/include/externalAPI.cache-tmp.php','w');
144         fwrite($fd,"<"."?php\n//This file is auto generated by ".__FILE__."\n\$fullAPIList = ".var_export($apiFullList,true).";\n\n");
145         fclose($fd);
146         rename('cache/include/externalAPI.cache-tmp.php','cache/include/externalAPI.cache.php');
147
148         $fd = fopen('cache/include/externalAPI.cache-tmp.js','w');
149         fwrite($fd,"//This file is auto generated by ".__FILE__."\nSUGAR.eapm = ".json_encode($apiFullList).";\n\n");
150         fclose($fd);
151         rename('cache/include/externalAPI.cache-tmp.js','cache/include/externalAPI.cache.js');
152
153
154         if (!isset($GLOBALS['app_list_strings']['extapi_meeting_password']) || (is_array($GLOBALS['app_list_strings']['extapi_meeting_password']) && count(array_diff($meetingPasswordList,$GLOBALS['app_list_strings']['extapi_meeting_password'])) != 0 )) {
155             // Our meeting password list is different... we need to do something about this.
156             require_once('modules/Administration/Common.php');
157             $languages = get_languages();
158             foreach( $languages as $lang => $langLabel ) {
159                 $contents = return_custom_app_list_strings_file_contents($lang);
160                 $new_contents = replace_or_add_dropdown_type('extapi_meeting_password', $meetingPasswordList, $contents);
161                 save_custom_app_list_strings_contents($new_contents, $lang);
162             }
163         }
164
165         return $ignoreDisabled?$apiFullList:self::filterAPIList($apiFullList);
166     }
167
168         /**
169         * Clear API cache file
170         */
171     public static function clearCache() {
172         if ( file_exists('cache/include/externalAPI.cache.php') ) {
173             unlink('cache/include/externalAPI.cache.php');
174         }
175         if ( file_exists('cache/include/externalAPI.cache.js') ) {
176             unlink('cache/include/externalAPI.cache.js');
177         }
178     }
179
180
181     /**
182      * This will hand back an initialized class for the requested external API, it will also load in the external API password information into the bean.
183      * @param string $apiName The name of the requested API ( known API's can be listed by the listAPI() call )
184      * @param bool $apiName Ignore authentication requirements (optional)
185      * @return ExternalAPIBase API plugin
186      */
187     public static function loadAPI($apiName, $ignoreAuth=false)
188     {
189         $apiList = self::loadFullAPIList();
190         if ( ! isset($apiList[$apiName]) ) {
191             return false;
192         }
193
194         $myApi = $apiList[$apiName];
195         require_once($myApi['file']);
196         if ( !empty($myApi['file_cstm']) ) {
197             require_once($myApi['file_cstm']);
198         }
199
200         $apiClassName = $myApi['className'];
201
202         $apiClass = new $apiClassName();
203         if ($ignoreAuth) {
204             return $apiClass;
205         }
206
207         if ($myApi['useAuth']) {
208             $eapmBean = EAPM::getLoginInfo($apiName);
209
210             if (!isset($eapmBean->application) && $myApi['requireAuth']) {
211                 // We need authentication, and they don't have it, don't load the API
212                 return false;
213             }
214         }
215
216         if ( $myApi['useAuth'] && isset($eapmBean->application) ) {
217             $apiClass->loadEAPM($eapmBean);
218         }
219
220         return $apiClass;
221     }
222
223     /**
224      * Lists the available API's for a module or all modules, and possibly ignoring if the user has auth information for that API even if it is required
225      * @param string $module Which module name you are searching for, leave blank to find all API's
226      * @param bool $ignoreAuth Ignore API's demands for authentication (used to get a complete list of modules
227      * @return API class
228      */
229     public static function listAPI($module = '', $ignoreAuth = false) {
230         $apiList = self::loadFullAPIList();
231
232         if ( $module == '' && $ignoreAuth == true ) {
233             // Simplest case, return everything.
234             return($apiList);
235         }
236
237         $apiFinalList = array();
238
239         // Not such an easy case, we need to limit to specific modules and see if we have authentication (or not)
240         foreach ( $apiList as $apiName => $apiOpts ) {
241             if ( $module == '' || in_array($module,$apiOpts['supportedModules']) ) {
242                 // This matches the module criteria
243                 if ( $ignoreAuth || !$apiOpts['useAuth'] || !$apiOpts['requireAuth'] ) {
244                     // Don't need to worry about authentication
245                     $apiFinalList[$apiName] = $apiOpts;
246                 } else {
247                     // We need to worry about authentication
248                     $eapmBean = EAPM::getLoginInfo($apiName);
249                     if ( isset($eapmBean->application) ) {
250                         // We have authentication
251                         $apiFinalList[$apiName] = $apiOpts;
252                     }
253                 }
254             }
255         }
256
257         return $apiFinalList;
258     }
259
260     /**
261      * Get the array of API names available for cetain module
262      * @param string $moduleName
263      * @param bool $ignoreAuth Ignore if we have authentication details or not
264      * @param bool $addEmptyEntry Add empty entry?
265      */
266      public static function getModuleDropDown($moduleName, $ignoreAuth = false, $addEmptyEntry = false) {
267         global $app_list_strings;
268
269         $apiList = self::listAPI($moduleName,$ignoreAuth);
270
271         $apiDropdown = array();
272         if($addEmptyEntry){
273             $apiDropdown[''] = '';
274         }
275
276         foreach ( $apiList as $apiName => $ignore ) {
277
278             if ( !empty($app_list_strings['eapm_list'][$apiName]) ) {
279                 $apiDropdown[$apiName] = $app_list_strings['eapm_list'][$apiName];
280             } else {
281                 $apiDropdown[$apiName] = $apiName;
282             }
283         }
284
285         return $apiDropdown;
286
287     }
288 }