ExternalAPIFactory::clearCache()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12
Metric Value
cc 3
eloc 7
nc 4
nop 0
dl 0
loc 10
ccs 0
cts 8
cp 0
crap 12
rs 9.4285
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-2013 SugarCRM Inc.
6
7
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
8
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
9
 *
10
 * This program is free software; you can redistribute it and/or modify it under
11
 * the terms of the GNU Affero General Public License version 3 as published by the
12
 * Free Software Foundation with the addition of the following permission added
13
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
14
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
15
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
16
 *
17
 * This program is distributed in the hope that it will be useful, but WITHOUT
18
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
20
 * details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License along with
23
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
24
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25
 * 02110-1301 USA.
26
 *
27
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
28
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
29
 *
30
 * The interactive user interfaces in modified source and object code versions
31
 * of this program must display Appropriate Legal Notices, as required under
32
 * Section 5 of the GNU Affero General Public License version 3.
33
 *
34
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
35
 * these Appropriate Legal Notices must retain the display of the "Powered by
36
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
37
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
38
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
39
 ********************************************************************************/
40
41
42
require_once('include/connectors/utils/ConnectorUtils.php');
43
require_once('include/connectors/sources/SourceFactory.php');
44
/**
45
 * Provides a factory to list, discover and create external API calls
46
 *
47
 * Main features are to list available external API's by supported features, modules and which ones have access for the user.
48
 * @api
49
 */
50
class ExternalAPIFactory
51
{
52
    /**
53
     * Filter the list of APIs, removing disabled ones
54
     * @param array $apiFullList
55
     * @return array Filtered list
56
     */
57 2
    public static function filterAPIList($apiFullList)
58
    {
59 2
        $filteredList = array();
60 2
        foreach($apiFullList as $name => $data) {
61
            if(isset($data['connector'])) {
62
                if(ConnectorUtils::eapmEnabled($data['connector'])) {
63
                     if(isset($data['authMethod']) && $data['authMethod'] == 'oauth'){
64
                        $connector = SourceFactory::getSource($data['connector'], false);
65
                        if(!empty($connector) && $connector->propertyExists('oauth_consumer_key')
66
                            && $connector->isRequiredConfigFieldsSet()) {
67
                                $filteredList[$name] = $data;
68
                        }
69
                     } elseif (isset($data['authMethod']) && $data['authMethod'] == 'oauth2') {
70
                        $connector = SourceFactory::getSource($data['connector'], false);
71
                        if (!empty($connector) && $connector->isRequiredConfigFieldsSet()) {
72
                            $filteredList[$name] = $data;
73
                        }
74
                     }else{
75
                        $filteredList[$name] = $data;
76
                     }
77
                }
78
            }else {
79
                $filteredList[$name] = $data;
80
            }
81
        }
82 2
        return $filteredList;
83
    }
84
85
    /**
86
     * Get the list of available APIs
87
     * @param bool $forceRebuild
88
     * @param bool $ignoreDisabled Should we ignore disabled status?
89
     * @return array
90
     */
91 4
    public static function loadFullAPIList($forceRebuild=false, $ignoreDisabled = false) {
92 4
        if (inDeveloperMode()) {
93
            static $beenHereBefore = false;
94
            if ( !$beenHereBefore ) {
95
                $forceRebuild = true;
96
                $beenHereBefore = true;
97
            }
98
        }
99 4
        $cached=sugar_cached('include/externalAPI.cache.php');
100 4
        if (!$forceRebuild && file_exists($cached) ) {
101
            // Already have a cache file built, no need to rebuild
102 4
            require $cached;
103
104 4
            return $ignoreDisabled?$fullAPIList:self::filterAPIList($fullAPIList);
105
        }
106
107
        $apiFullList = array();
108
        $meetingPasswordList = array();
109
        $needUrlList = array();
110
111
        $baseDirList = array('include/externalAPI/','custom/include/externalAPI/');
112
        foreach ( $baseDirList as $baseDir ) {
113
            $dirList = glob($baseDir.'*',GLOB_ONLYDIR);
114
            foreach($dirList as $dir) {
115
                if ( $dir == $baseDir.'.' || $dir == $baseDir.'..' || $dir == $baseDir.'Base' ) {
116
                    continue;
117
                }
118
119
                $apiName = str_replace($baseDir,'',$dir);
120
                if ( file_exists($dir.'/ExtAPI'.$apiName.'.php') ) {
121
                    $apiFullList[$apiName]['className'] = 'ExtAPI'.$apiName;
122
                    $apiFullList[$apiName]['file'] = $dir.'/'.$apiFullList[$apiName]['className'].'.php';
123
                }
124
                if ( file_exists($dir.'/ExtAPI'.$apiName.'_cstm.php') ) {
125
                    $apiFullList[$apiName]['className'] = 'ExtAPI'.$apiName.'_cstm';
126
                    $apiFullList[$apiName]['file_cstm'] = $dir.'/'.$apiFullList[$apiName]['className'].'.php';
127
                }
128
            }
129
        }
130
131
        $optionList = array('supportedModules','useAuth','requireAuth','supportMeetingPassword','docSearch', 'authMethod', 'oauthFixed','needsUrl','canInvite','sendsInvites','sharingOptions','connector', 'oauthParams','restrictUploadsByExtension');
132
        foreach ( $apiFullList as $apiName => $apiOpts ) {
133
            require_once($apiOpts['file']);
134
            if ( !empty($apiOpts['file_cstm']) ) {
135
                require_once($apiOpts['file_cstm']);
136
            }
137
            $className = $apiOpts['className'];
138
            $apiClass = new $className();
139
            foreach ( $optionList as $opt ) {
140
                if ( isset($apiClass->$opt) ) {
141
                    $apiFullList[$apiName][$opt] = $apiClass->$opt;
142
                }
143
            }
144
145
            // Special handling for the show/hide of the Meeting Password field, we need to create a dropdown for the Sugar Logic code.
146
            if ( isset($apiClass->supportMeetingPassword) && $apiClass->supportMeetingPassword == true ) {
147
                $meetingPasswordList[$apiName] = $apiName;
148
            }
149
150
        }
151
152
        create_cache_directory('/include/');
153
        $cached_tmp = sugar_cached('include/externalAPI.cache-tmp.php');
154
        $fd = fopen($cached_tmp,'w');
155
        fwrite($fd,"<"."?php\n//This file is auto generated by ".basename(__FILE__)."\n\$fullAPIList = ".var_export($apiFullList,true).";\n\n");
156
        fclose($fd);
157
        rename($cached_tmp, $cached);
158
159
        $fd = fopen(sugar_cached('include/externalAPI.cache-tmp.js'),'w');
160
        fwrite($fd,"//This file is auto generated by ".basename(__FILE__)."\nSUGAR.eapm = ".json_encode($apiFullList).";\n\n");
161
        fclose($fd);
162
        rename(sugar_cached('include/externalAPI.cache-tmp.js'),sugar_cached('include/externalAPI.cache.js'));
163
164
165
        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 )) {
166
            // Our meeting password list is different... we need to do something about this.
167
            require_once('modules/Administration/Common.php');
168
            $languages = get_languages();
169
            foreach( $languages as $lang => $langLabel ) {
170
                $contents = return_custom_app_list_strings_file_contents($lang);
171
                $new_contents = replace_or_add_dropdown_type('extapi_meeting_password', $meetingPasswordList, $contents);
172
                save_custom_app_list_strings_contents($new_contents, $lang);
173
            }
174
        }
175
176
        return $ignoreDisabled?$apiFullList:self::filterAPIList($apiFullList);
177
    }
178
179
	/**
180
 	* Clear API cache file
181
 	*/
182
    public static function clearCache() {
183
        $cached=sugar_cached('include/externalAPI.cache.php');
184
        if ( file_exists($cached) ) {
185
            unlink($cached);
186
        }
187
        $cached=sugar_cached('include/externalAPI.cache.js');
188
        if ( file_exists($cached) ) {
189
            unlink($cached);
190
        }
191
    }
192
193
194
    /**
195
     * 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.
196
     * @param string $apiName The name of the requested API ( known API's can be listed by the listAPI() call )
197
     * @param bool $apiName Ignore authentication requirements (optional)
198
     * @return ExternalAPIBase API plugin
199
     */
200
    public static function loadAPI($apiName, $ignoreAuth=false)
201
    {
202
        $apiList = self::loadFullAPIList();
203
        if ( ! isset($apiList[$apiName]) ) {
204
            return false;
205
        }
206
207
        $myApi = $apiList[$apiName];
208
        require_once($myApi['file']);
209
        if ( !empty($myApi['file_cstm']) ) {
210
            require_once($myApi['file_cstm']);
211
        }
212
213
        $apiClassName = $myApi['className'];
214
215
        $apiClass = new $apiClassName();
216
        if ($ignoreAuth) {
217
            return $apiClass;
218
        }
219
220
        if ($myApi['useAuth']) {
221
            $eapmBean = EAPM::getLoginInfo($apiName);
222
223
            if (!isset($eapmBean->application) && $myApi['requireAuth']) {
224
                // We need authentication, and they don't have it, don't load the API
225
                return false;
226
            }
227
        }
228
229
        if ( $myApi['useAuth'] && isset($eapmBean->application) ) {
230
            $apiClass->loadEAPM($eapmBean);
231
        }
232
233
        return $apiClass;
234
    }
235
236
    /**
237
     * 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
238
     * @param string $module Which module name you are searching for, leave blank to find all API's
239
     * @param bool $ignoreAuth Ignore API's demands for authentication (used to get a complete list of modules
240
     * @return API class
241
     */
242 2
    public static function listAPI($module = '', $ignoreAuth = false) {
243 2
        $apiList = self::loadFullAPIList();
244
245 2
        if ( $module == '' && $ignoreAuth == true ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
246
            // Simplest case, return everything.
247 1
            return($apiList);
248
        }
249
250 1
        $apiFinalList = array();
251
252
        // Not such an easy case, we need to limit to specific modules and see if we have authentication (or not)
253 1
        foreach ( $apiList as $apiName => $apiOpts ) {
254
            if ( $module == '' || in_array($module,$apiOpts['supportedModules']) ) {
255
                // This matches the module criteria
256
                if ( $ignoreAuth || !$apiOpts['useAuth'] || !$apiOpts['requireAuth'] ) {
257
                    // Don't need to worry about authentication
258
                    $apiFinalList[$apiName] = $apiOpts;
259
                } else {
260
                    // We need to worry about authentication
261
                    $eapmBean = EAPM::getLoginInfo($apiName);
262
                    if ( isset($eapmBean->application) ) {
263
                        // We have authentication
264
                        $apiFinalList[$apiName] = $apiOpts;
265
                    }
266
                }
267
            }
268
        }
269
270 1
        return $apiFinalList;
271
    }
272
273
    /**
274
     * Get the array of API names available for cetain module
275
     * @param string $moduleName
276
     * @param bool $ignoreAuth Ignore if we have authentication details or not
277
     * @param bool $addEmptyEntry Add empty entry?
278
     * @return array
279
     */
280 2
     public static function getModuleDropDown($moduleName, $ignoreAuth = false, $addEmptyEntry = false) {
281 2
        global $app_list_strings;
282
283 2
        $apiList = self::listAPI($moduleName,$ignoreAuth);
284
285 2
        $apiDropdown = array();
286 2
        if($addEmptyEntry){
287 1
            $apiDropdown[''] = '';
288
        }
289
290 2
        foreach ( $apiList as $apiName => $ignore ) {
291
            $appStringTranslKey = 'eapm_list_' .strtolower($moduleName);
292
            if ( isset($app_list_strings[$appStringTranslKey]) && !empty($app_list_strings[$appStringTranslKey][$apiName]) ) {
293
                $apiDropdown[$apiName] = $app_list_strings[$appStringTranslKey][$apiName];
294
            }
295
            else if ( !empty($app_list_strings['eapm_list'][$apiName]) ) {
296
                $apiDropdown[$apiName] = $app_list_strings['eapm_list'][$apiName];
297
            }
298
            else {
299
                $apiDropdown[$apiName] = $apiName;
300
            }
301
        }
302
303 2
        return $apiDropdown;
304
305
    }
306
}
307