alxarafe /
alixar
| 1 | <?php |
||
| 2 | |||
| 3 | /* Copyright (C) 2015 Jean-François Ferry <[email protected]> |
||
| 4 | * Copyright (C) 2016 Laurent Destailleur <[email protected]> |
||
| 5 | * Copyright (C) 2017 Regis Houssin <[email protected]> |
||
| 6 | * Copyright (C) 2021 Alexis LAURIER <[email protected]> |
||
| 7 | * Copyright (C) 2024 MDW <[email protected]> |
||
| 8 | * Copyright (C) 2024 Rafael San José <[email protected]> |
||
| 9 | * |
||
| 10 | * This program is free software; you can redistribute it and/or modify |
||
| 11 | * it under the terms of the GNU General Public License as published by |
||
| 12 | * the Free Software Foundation; either version 3 of the License, or |
||
| 13 | * (at your option) any later version. |
||
| 14 | * |
||
| 15 | * This program is distributed in the hope that it will be useful, |
||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 18 | * GNU General Public License for more details. |
||
| 19 | * |
||
| 20 | * You should have received a copy of the GNU General Public License |
||
| 21 | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
||
| 22 | */ |
||
| 23 | |||
| 24 | use Dolibarr\Code\Api\Classes\DolibarrApiAccess; |
||
| 25 | use Dolibarr\Core\Base\DolibarrApi; |
||
| 26 | use Luracast\Restler\Format\UploadFormat; |
||
| 27 | |||
| 28 | $api_route = $_GET['api_route'] ?? ''; |
||
| 29 | unset($_GET['api_route']); |
||
| 30 | $_SERVER['SCRIPT_NAME'] = '/api/index.php'; |
||
| 31 | |||
| 32 | if (!defined('NOCSRFCHECK')) { |
||
| 33 | define('NOCSRFCHECK', '1'); // Do not check anti CSRF attack test |
||
| 34 | } |
||
| 35 | if (!defined('NOTOKENRENEWAL')) { |
||
| 36 | define('NOTOKENRENEWAL', '1'); // Do not check anti POST attack test |
||
| 37 | } |
||
| 38 | if (!defined('NOREQUIREMENU')) { |
||
| 39 | define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu |
||
| 40 | } |
||
| 41 | if (!defined('NOREQUIREHTML')) { |
||
| 42 | define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php |
||
| 43 | } |
||
| 44 | if (!defined('NOREQUIREAJAX')) { |
||
| 45 | define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library |
||
| 46 | } |
||
| 47 | if (!defined("NOLOGIN")) { |
||
| 48 | define("NOLOGIN", '1'); // If this page is public (can be called outside logged session) |
||
| 49 | } |
||
| 50 | if (!defined("NOSESSION")) { |
||
| 51 | define("NOSESSION", '1'); |
||
| 52 | } |
||
| 53 | if (!defined("NODEFAULTVALUES")) { |
||
| 54 | define("NODEFAULTVALUES", '1'); |
||
| 55 | } |
||
| 56 | |||
| 57 | // Force entity if a value is provided into HTTP header. Otherwise, will use the entity of user of token used. |
||
| 58 | if (!empty($_SERVER['HTTP_DOLAPIENTITY'])) { |
||
| 59 | define("DOLENTITY", (int)$_SERVER['HTTP_DOLAPIENTITY']); |
||
| 60 | } |
||
| 61 | |||
| 62 | // Response for preflight requests (used by browser when into a CORS context) |
||
| 63 | if (!empty($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'OPTIONS' && !empty($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) { |
||
| 64 | header('Access-Control-Allow-Origin: *'); |
||
| 65 | header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE'); |
||
| 66 | header('Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY'); |
||
| 67 | http_response_code(204); |
||
| 68 | exit; |
||
| 69 | } |
||
| 70 | |||
| 71 | // When we request url to get the json file, we accept Cross site so we can include the descriptor into an external tool. |
||
| 72 | if (str_contains($_SERVER["PHP_SELF"], '/explorer/swagger.json')) { |
||
| 73 | header('Access-Control-Allow-Origin: *'); |
||
| 74 | header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE'); |
||
| 75 | header('Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY'); |
||
| 76 | } |
||
| 77 | |||
| 78 | // When we request url to get an API, we accept Cross site so we can make js API call inside another website |
||
| 79 | if (str_contains($_SERVER["PHP_SELF"], '/api/index.php')) { |
||
| 80 | header('Access-Control-Allow-Origin: *'); |
||
| 81 | header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE'); |
||
| 82 | header('Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY'); |
||
| 83 | } |
||
| 84 | header('X-Frame-Options: SAMEORIGIN'); |
||
| 85 | |||
| 86 | $res = 0; |
||
| 87 | $res = include constant('DOL_DOCUMENT_ROOT') . "/main.inc.php"; |
||
| 88 | if (!$res) { |
||
| 89 | die("Include of main fails"); |
||
| 90 | } |
||
| 91 | |||
| 92 | require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/functions2.lib.php'; |
||
| 93 | |||
| 94 | $url = $_SERVER['PHP_SELF']; |
||
| 95 | if (str_ends_with($_SERVER['PHP_SELF'], 'api/index.php')) { |
||
| 96 | $additionalPath = !empty($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : ($_SERVER['ORIG_PATH_INFO'] ?? ''); |
||
| 97 | $url = $_SERVER['PHP_SELF'] . $additionalPath; |
||
| 98 | } |
||
| 99 | |||
| 100 | // Fix for some NGINX setups (this should not be required even with NGINX, however setup of NGINX are often mysterious and this may help is such cases) |
||
| 101 | if (getDolGlobalString('MAIN_NGINX_FIX')) { |
||
| 102 | $url = (isset($_SERVER['SCRIPT_URI']) && $_SERVER["SCRIPT_URI"] !== null) ? $_SERVER["SCRIPT_URI"] : $_SERVER['PHP_SELF']; |
||
| 103 | } |
||
| 104 | |||
| 105 | // Enable and test if module Api is enabled |
||
| 106 | if (!isModEnabled('api')) { |
||
| 107 | $langs->load("admin"); |
||
| 108 | dol_syslog("Call of Dolibarr API interfaces with module API REST are disabled"); |
||
| 109 | print $langs->trans("WarningModuleNotActive", 'Api') . '.<br><br>'; |
||
| 110 | print $langs->trans("ToActivateModule"); |
||
| 111 | //session_destroy(); |
||
| 112 | exit(0); |
||
| 113 | } |
||
| 114 | |||
| 115 | // Test if explorer is not disabled |
||
| 116 | if (str_contains($url, 'api/index.php/explorer') && getDolGlobalString('API_EXPLORER_DISABLED')) { |
||
| 117 | $langs->load("admin"); |
||
| 118 | dol_syslog("Call Dolibarr API interfaces with module API REST disabled"); |
||
| 119 | print $langs->trans("WarningAPIExplorerDisabled") . '.<br><br>'; |
||
| 120 | //session_destroy(); |
||
| 121 | exit(0); |
||
| 122 | } |
||
| 123 | |||
| 124 | // This 2 lines are useful only if we want to exclude some Urls from the explorer |
||
| 125 | //use Luracast\Restler\Explorer; |
||
| 126 | //Explorer::$excludedPaths = array('/categories'); |
||
| 127 | |||
| 128 | |||
| 129 | // Analyze URLs |
||
| 130 | // index.php/explorer do a redirect to index.php/explorer/ |
||
| 131 | // index.php/explorer/ called by swagger to build explorer page index.php/explorer/index.html |
||
| 132 | // index.php/explorer/.../....png|.css|.js called by swagger for resources to build explorer page |
||
| 133 | // index.php/explorer/resources.json called by swagger to get list of all services |
||
| 134 | // index.php/explorer/resources.json/xxx called by swagger to get detail of services xxx |
||
| 135 | // index.php/xxx called by any REST client to run API |
||
| 136 | |||
| 137 | $reg = array(); |
||
| 138 | preg_match('/index\.php\/([^\/]+)(.*)$/', $url, $reg); |
||
| 139 | // .../index.php/categories?sortfield=t.rowid&sortorder=ASC |
||
| 140 | |||
| 141 | $hookmanager->initHooks(array('api')); |
||
| 142 | |||
| 143 | // When in production mode, a file api/temp/routes.php is created with the API available of current call. |
||
| 144 | // But, if we set $refreshcache to false, so it may have only one API in the routes.php file if we make a call for one API without |
||
| 145 | // using the explorer. And when we make another call for another API, the API is not into the api/temp/routes.php and a 404 is returned. |
||
| 146 | // So we force refresh to each call. |
||
| 147 | $refreshcache = (getDolGlobalString('API_PRODUCTION_DO_NOT_ALWAYS_REFRESH_CACHE') ? false : true); |
||
| 148 | if (!empty($reg[1]) && $reg[1] == 'explorer' && ($reg[2] == '/swagger.json' || $reg[2] == '/swagger.json/root' || $reg[2] == '/resources.json' || $reg[2] == '/resources.json/root')) { |
||
| 149 | $refreshcache = true; |
||
| 150 | if (!is_dir($conf->api->dir_temp)) { |
||
| 151 | mkdir($conf->api->dir_temp); |
||
| 152 | } |
||
| 153 | if (!is_writable($conf->api->dir_temp)) { |
||
| 154 | print 'Erreur temp dir api/temp (' . $conf->api->dir_temp . ') not writable'; |
||
| 155 | header('HTTP/1.1 500 temp dir api/temp not writable'); |
||
| 156 | exit(0); |
||
| 157 | } |
||
| 158 | } |
||
| 159 | |||
| 160 | $api = new DolibarrApi($db, '', $refreshcache); |
||
| 161 | // var_dump($api->r->apiVersionMap); |
||
| 162 | |||
| 163 | // If MAIN_API_DEBUG is set to 1, we save logs into file "dolibarr_api.log" |
||
| 164 | if (getDolGlobalString('MAIN_API_DEBUG')) { |
||
| 165 | $r = $api->r; |
||
| 166 | $r->onCall(function () use ($r) { |
||
| 167 | // Don't log Luracast Restler Explorer resources calls |
||
| 168 | //if (!preg_match('/^explorer/', $r->url)) { |
||
| 169 | // 'method' => $api->r->requestMethod, |
||
| 170 | // 'url' => $api->r->url, |
||
| 171 | // 'route' => $api->r->apiMethodInfo->className.'::'.$api->r->apiMethodInfo->methodName, |
||
| 172 | // 'version' => $api->r->getRequestedApiVersion(), |
||
| 173 | // 'data' => $api->r->getRequestData(), |
||
| 174 | //dol_syslog("Debug API input ".var_export($r, true), LOG_DEBUG, 0, '_api'); |
||
| 175 | dol_syslog("Debug API url " . var_export($r->url, true), LOG_DEBUG, 0, '_api'); |
||
| 176 | dol_syslog("Debug API input " . var_export($r->getRequestData(), true), LOG_DEBUG, 0, '_api'); |
||
| 177 | //} |
||
| 178 | }); |
||
| 179 | } |
||
| 180 | |||
| 181 | // Enable the Restler API Explorer. |
||
| 182 | // See https://github.com/Luracast/Restler-API-Explorer for more info. |
||
| 183 | $api->r->addAPIClass('Luracast\\Restler\\Explorer'); |
||
| 184 | $api->r->addAPIClass('Luracast\\Restler\\Explorer\\v1\\Explorer'); |
||
| 185 | $api->r->addAPIClass('Luracast\\Restler\\Explorer\\v2\\Explorer'); |
||
| 186 | |||
| 187 | $api->r->setSupportedFormats('JsonFormat', 'XmlFormat', 'UploadFormat'); // 'YamlFormat' |
||
| 188 | $api->r->addAuthenticationClass('Dolibarr\\Code\\Api\\Classes\\DolibarrApiAccess', ''); |
||
| 189 | |||
| 190 | // Define accepted mime types |
||
| 191 | UploadFormat::$allowedMimeTypes = array('image/jpeg', 'image/png', 'text/plain', 'application/octet-stream'); |
||
| 192 | |||
| 193 | // Restrict API to some IPs |
||
| 194 | if (getDolGlobalString('API_RESTRICT_ON_IP')) { |
||
| 195 | $allowedip = explode(' ', getDolGlobalString('API_RESTRICT_ON_IP')); |
||
| 196 | $ipremote = getUserRemoteIP(); |
||
| 197 | if (!in_array($ipremote, $allowedip)) { |
||
| 198 | dol_syslog('Remote ip is ' . $ipremote . ', not into list ' . getDolGlobalString('API_RESTRICT_ON_IP')); |
||
| 199 | print 'APIs are not allowed from the IP ' . $ipremote; |
||
| 200 | header('HTTP/1.1 503 API not allowed from your IP ' . $ipremote); |
||
| 201 | //session_destroy(); |
||
| 202 | exit(0); |
||
| 203 | } |
||
| 204 | } |
||
| 205 | |||
| 206 | // Call Explorer file for all APIs definitions (this part is slow) |
||
| 207 | if (!empty($reg[1]) && $reg[1] == 'explorer' && ($reg[2] == '/swagger.json' || $reg[2] == '/swagger.json/' || $reg[2] == '/swagger.json/root' || $reg[2] == '/resources.json/' || $reg[2] == '/resources.json' || $reg[2] == '/resources.json/root')) { |
||
| 208 | // Scan all API files to load them |
||
| 209 | $listofapis = DolibarrApi::getModules(); |
||
| 210 | foreach ($listofapis as $apiname => $classname) { |
||
| 211 | new $classname(); |
||
| 212 | $api->r->addAPIClass($classname); |
||
| 213 | } |
||
| 214 | } |
||
| 215 | |||
| 216 | |||
| 217 | // Call one APIs or one definition of an API |
||
| 218 | $regbis = array(); |
||
| 219 | if (!empty($reg[1]) && ($reg[1] != 'explorer' || ($reg[2] != '/swagger.json' && $reg[2] != '/resources.json' && preg_match('/^\/(swagger|resources)\.json\/(.+)$/', $reg[2], $regbis) && $regbis[2] != 'root'))) { |
||
| 220 | $moduleobject = $reg[1]; |
||
| 221 | if ($moduleobject == 'explorer') { // If we call page to explore details of a service |
||
| 222 | $moduleobject = $regbis[2]; |
||
| 223 | } |
||
| 224 | |||
| 225 | $moduleobject = strtolower($moduleobject); |
||
| 226 | $moduledirforclass = getModuleDirForApiClass($moduleobject); |
||
| 227 | |||
| 228 | // Load a dedicated API file |
||
| 229 | dol_syslog("Load a dedicated API file moduleobject=" . $moduleobject . " moduledirforclass=" . $moduledirforclass); |
||
| 230 | |||
| 231 | $tmpmodule = $moduleobject; |
||
| 232 | if ($tmpmodule != 'api') { |
||
| 233 | $tmpmodule = preg_replace('/api$/i', '', $tmpmodule); |
||
| 234 | } |
||
| 235 | $classfile = str_replace('_', '', $tmpmodule); |
||
| 236 | |||
| 237 | // Special cases that does not match name rules conventions |
||
| 238 | if ($moduleobject == 'supplierproposals') { |
||
| 239 | $classfile = 'supplier_proposals'; |
||
| 240 | } |
||
| 241 | if ($moduleobject == 'supplierorders') { |
||
| 242 | $classfile = 'supplier_orders'; |
||
| 243 | } |
||
| 244 | if ($moduleobject == 'supplierinvoices') { |
||
| 245 | $classfile = 'supplier_invoices'; |
||
| 246 | } |
||
| 247 | if ($moduleobject == 'ficheinter') { |
||
| 248 | $classfile = 'interventions'; |
||
| 249 | } |
||
| 250 | if ($moduleobject == 'interventions') { |
||
| 251 | $classfile = 'interventions'; |
||
| 252 | } |
||
| 253 | |||
| 254 | $filename = '/' . $moduledirforclass . '/class/api_' . $classfile . '.class.php'; |
||
| 255 | $dir_part_file = dol_buildpath($filename, 0, 2); |
||
| 256 | |||
| 257 | $classname = ucwords($moduleobject); |
||
| 258 | $modulename = ucwords($moduledirforclass); |
||
| 259 | |||
| 260 | // Test rules on endpoints. For example: |
||
| 261 | // $conf->global->API_ENDPOINT_RULES = 'endpoint1:1,endpoint2:1,...' |
||
| 262 | if (getDolGlobalString('API_ENDPOINT_RULES')) { |
||
| 263 | $listofendpoints = explode(',', getDolGlobalString('API_ENDPOINT_RULES')); |
||
| 264 | $endpointisallowed = false; |
||
| 265 | |||
| 266 | foreach ($listofendpoints as $endpointrule) { |
||
| 267 | $tmparray = explode(':', $endpointrule); |
||
| 268 | if (($classfile == $tmparray[0] || $classfile . 'api' == $tmparray[0]) && $tmparray[1] == 1) { |
||
| 269 | $endpointisallowed = true; |
||
| 270 | break; |
||
| 271 | } |
||
| 272 | } |
||
| 273 | |||
| 274 | if (!$endpointisallowed) { |
||
| 275 | dol_syslog('The API with endpoint /' . $classfile . ' is forbidden by config API_ENDPOINT_RULES', LOG_WARNING); |
||
| 276 | print 'The API with endpoint /' . $classfile . ' is forbidden by config API_ENDPOINT_RULES'; |
||
| 277 | header('HTTP/1.1 501 API is forbidden by API_ENDPOINT_RULES'); |
||
| 278 | //session_destroy(); |
||
| 279 | exit(0); |
||
| 280 | } |
||
| 281 | } |
||
| 282 | |||
| 283 | dol_syslog('Search api file /' . $moduledirforclass . '/class/api_' . $classfile . '.class.php => dir_part_file=' . $dir_part_file . ', classname=' . $classname); |
||
| 284 | |||
| 285 | $namespace = DolibarrApi::getModuleNamespace($modulename, $classname); |
||
| 286 | $class = new $namespace(); |
||
| 287 | if (!isset($class)) { |
||
| 288 | dol_syslog('Failed to make include_once ' . $dir_part_file, LOG_WARNING); |
||
| 289 | print 'API not found (failed to include API file)'; |
||
| 290 | header('HTTP/1.1 501 API not found (failed to include API file)'); |
||
| 291 | //session_destroy(); |
||
| 292 | exit(0); |
||
| 293 | } |
||
| 294 | |||
| 295 | $api->r->addAPIClass($namespace); |
||
| 296 | } |
||
| 297 | |||
| 298 | // We do not want that restler outputs data if we use native compression (default behaviour) but we want to have it returned into a string. |
||
| 299 | // If API_DISABLE_COMPRESSION is set, returnResponse is false => It use default handling so output result directly. |
||
| 300 | $usecompression = (!getDolGlobalString('API_DISABLE_COMPRESSION') && !empty($_SERVER['HTTP_ACCEPT_ENCODING'])); |
||
| 301 | $foundonealgorithm = 0; |
||
| 302 | if ($usecompression) { |
||
| 303 | if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'br') !== false && function_exists('brotli_compress')) { |
||
| 304 | $foundonealgorithm++; |
||
| 305 | } |
||
| 306 | if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'bz') !== false && function_exists('bzcompress')) { |
||
| 307 | $foundonealgorithm++; |
||
| 308 | } |
||
| 309 | if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && function_exists('gzencode')) { |
||
| 310 | $foundonealgorithm++; |
||
| 311 | } |
||
| 312 | if (!$foundonealgorithm) { |
||
| 313 | $usecompression = false; |
||
| 314 | } |
||
| 315 | } |
||
| 316 | |||
| 317 | //dol_syslog('We found some compression algorithm: '.$foundonealgorithm.' -> usecompression='.$usecompression, LOG_DEBUG); |
||
| 318 | |||
| 319 | Luracast\Restler\Defaults::$returnResponse = $usecompression; |
||
| 320 | |||
| 321 | // Call API (we suppose we found it). |
||
| 322 | // The handle will use the file api/temp/routes.php to get data to run the API. If the file exists and the entry for API is not found, it will return 404. |
||
| 323 | $responsedata = $api->r->handle(); |
||
|
0 ignored issues
–
show
|
|||
| 324 | |||
| 325 | if (Luracast\Restler\Defaults::$returnResponse) { |
||
| 326 | // We try to compress the data received data |
||
| 327 | if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'br') !== false && function_exists('brotli_compress') && defined('BROTLI_TEXT')) { |
||
| 328 | header('Content-Encoding: br'); |
||
| 329 | $result = brotli_compress($responsedata, 11, constant('BROTLI_TEXT')); |
||
| 330 | } elseif (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'bz') !== false && function_exists('bzcompress')) { |
||
| 331 | header('Content-Encoding: bz'); |
||
| 332 | $result = bzcompress($responsedata, 9); |
||
| 333 | } elseif (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && function_exists('gzencode')) { |
||
| 334 | header('Content-Encoding: gzip'); |
||
| 335 | $result = gzencode($responsedata, 9); |
||
| 336 | } else { |
||
| 337 | header('Content-Encoding: text/html'); |
||
| 338 | print "No compression method found. Try to disable compression by adding API_DISABLE_COMPRESSION=1"; |
||
| 339 | exit(0); |
||
| 340 | } |
||
| 341 | |||
| 342 | // Restler did not output data yet, we return it now |
||
| 343 | echo $result; |
||
| 344 | } |
||
| 345 | |||
| 346 | if (getDolGlobalInt("API_ENABLE_COUNT_CALLS") && $api->r->responseCode == 200) { |
||
| 347 | $error = 0; |
||
| 348 | $db->begin(); |
||
| 349 | $userid = DolibarrApiAccess::$user->id; |
||
| 350 | |||
| 351 | $sql = "SELECT up.value"; |
||
| 352 | $sql .= " FROM " . MAIN_DB_PREFIX . "user_param as up"; |
||
| 353 | $sql .= " WHERE up.param = 'API_COUNT_CALL'"; |
||
| 354 | $sql .= " AND up.fk_user = " . ((int)$userid); |
||
| 355 | $sql .= " AND up.entity = " . ((int)$conf->entity); |
||
| 356 | |||
| 357 | $result = $db->query($sql); |
||
| 358 | if ($result) { |
||
| 359 | $updateapi = false; |
||
| 360 | $nbrows = $db->num_rows($result); |
||
| 361 | if ($nbrows == 0) { |
||
| 362 | $sql2 = "INSERT INTO " . MAIN_DB_PREFIX . "user_param"; |
||
| 363 | $sql2 .= " (fk_user, entity, param, value)"; |
||
| 364 | $sql2 .= " VALUES (" . ((int)$userid) . ", " . ((int)$conf->entity) . ", 'API_COUNT_CALL', 1)"; |
||
| 365 | } else { |
||
| 366 | $updateapi = true; |
||
| 367 | $sql2 = "UPDATE " . MAIN_DB_PREFIX . "user_param as up"; |
||
| 368 | $sql2 .= " SET up.value = up.value + 1"; |
||
| 369 | $sql2 .= " WHERE up.param = 'API_COUNT_CALL'"; |
||
| 370 | $sql2 .= " AND up.fk_user = " . ((int)$userid); |
||
| 371 | $sql2 .= " AND up.entity = " . ((int)$conf->entity); |
||
| 372 | } |
||
| 373 | |||
| 374 | $result2 = $db->query($sql2); |
||
| 375 | if (!$result2) { |
||
| 376 | $modeapicall = $updateapi ? 'updating' : 'inserting'; |
||
| 377 | dol_syslog('Error while ' . $modeapicall . ' API_COUNT_CALL for user ' . $userid, LOG_ERR); |
||
| 378 | $error++; |
||
| 379 | } |
||
| 380 | } else { |
||
| 381 | dol_syslog('Error on select API_COUNT_CALL for user ' . $userid, LOG_ERR); |
||
| 382 | $error++; |
||
| 383 | } |
||
| 384 | |||
| 385 | if ($error) { |
||
| 386 | $db->rollback(); |
||
| 387 | } else { |
||
| 388 | $db->commit(); |
||
| 389 | } |
||
| 390 | } |
||
| 391 | |||
| 392 | // Call API termination method |
||
| 393 | $apiMethodInfo = &$api->r->apiMethodInfo; |
||
| 394 | $terminateCall = '_terminate_' . $apiMethodInfo->methodName . '_' . $api->r->responseFormat->getExtension(); |
||
| 395 | if (method_exists($apiMethodInfo->className, $terminateCall)) { |
||
| 396 | // Now flush output buffers so that response data is sent to the client even if we still have action to do in a termination method. |
||
| 397 | ob_end_flush(); |
||
| 398 | |||
| 399 | // If you're using PHP-FPM, this function will allow you to send the response and then continue processing |
||
| 400 | if (function_exists('fastcgi_finish_request')) { |
||
| 401 | fastcgi_finish_request(); |
||
| 402 | } |
||
| 403 | |||
| 404 | // Call a termination method. Warning: This method can do I/O, sync but must not make output. |
||
| 405 | call_user_func(array(Luracast\Restler\Scope::get($apiMethodInfo->className), $terminateCall), $responsedata); |
||
| 406 | } |
||
| 407 | |||
| 408 | //session_destroy(); |
||
| 409 |
This check looks for function or method calls that always return null and whose return value is assigned to a variable.
The method
getObject()can return nothing but null, so it makes no sense to assign that value to a variable.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.