fix: resolve non-existent global function call in ExternalServicesJsonApiResponseFetcher - #216
Conversation
…nApiResponseFetcher Promote ExternalServicesFeedParser::createSecureCurlHandle() to public static, update internal caller to self::, and update ExternalServicesJsonApiResponseFetcher to call ExternalServicesFeedParser::createSecureCurlHandle() — no code duplication. Agent-Logs-Url: https://github.com/EngineScript/EngineScript/sessions/356dcbac-660c-45c0-9f5f-75ce1d21c4b6 Co-authored-by: PDowney <11467177+PDowney@users.noreply.github.com>
…n private method Agent-Logs-Url: https://github.com/EngineScript/EngineScript/sessions/01d555a3-7989-4e50-82d8-938f00024395 Co-authored-by: PDowney <11467177+PDowney@users.noreply.github.com>
Agent-Logs-Url: https://github.com/EngineScript/EngineScript/sessions/abb36eca-8166-4968-a9a3-44fdc50a6a99 Co-authored-by: PDowney <11467177+PDowney@users.noreply.github.com>
…oller Agent-Logs-Url: https://github.com/EngineScript/EngineScript/sessions/abb36eca-8166-4968-a9a3-44fdc50a6a99 Co-authored-by: PDowney <11467177+PDowney@users.noreply.github.com>
Agent-Logs-Url: https://github.com/EngineScript/EngineScript/sessions/abb36eca-8166-4968-a9a3-44fdc50a6a99 Co-authored-by: PDowney <11467177+PDowney@users.noreply.github.com>
…nstructors, typed constants, CurlHandle type, final classes Agent-Logs-Url: https://github.com/EngineScript/EngineScript/sessions/abb36eca-8166-4968-a9a3-44fdc50a6a99 Co-authored-by: PDowney <11467177+PDowney@users.noreply.github.com>
Agent-Logs-Url: https://github.com/EngineScript/EngineScript/sessions/52f701b6-41e9-4d06-915f-c643c2aee61d Co-authored-by: PDowney <11467177+PDowney@users.noreply.github.com>
Updated the changelog to reflect recent changes, including the addition of a dedicated Curl exception class and various refactorings for PHP 8.2–8.4 modernization.
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
|
There was a problem hiding this comment.
Pull request overview
This PR fixes an invalid call to a non-existent global createSecureCurlHandle() by centralizing secure cURL handle creation and reusing it from the JSON API response fetcher, while also modernizing and de-duplicating parts of the external services parsing stack.
Changes:
- Introduced
CurlInitExceptionand switched cURL init failures from generic runtime exceptions to a dedicated exception type. - Centralized secure cURL creation via a shared trait and updated
ExternalServicesJsonApiResponseFetcherto call the correct instance method. - Refactored external-services parsing to reduce duplication (shared nested-path resolver,
ServiceStatusenum), and cleaned up repetitive version parsing inServiceController.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| config/var/www/admin/control-panel/external-services/external-services-api.php | Fixes the non-existent function call by reusing a shared cURL factory; adds shared JSON path resolver and ServiceStatus enum refactors. |
| config/var/www/admin/control-panel/controllers/ServiceController.php | Consolidates repeated version parsing logic into a helper method. |
| config/var/www/admin/control-panel/controllers/ExternalServicesController.php | Adds CurlInitException loading and factors cURL setup into a reusable helper for external requests. |
| config/var/www/admin/control-panel/classes/CurlInitException.php | Adds a dedicated exception type for curl_init() failures. |
| CHANGELOG.md | Documents the refactor/modernisation changes. |
| * HTML-escaped. Returns 'Unknown' when output is null or the pattern | ||
| * does not match. | ||
| * | ||
| * @param string|null $output Raw command output | ||
| * @param string $pattern PCRE pattern with one capture group for the version | ||
| * @return string Sanitized version string or 'Unknown' | ||
| */ | ||
| private function parseVersionOutput(?string $output, string $pattern): string | ||
| { | ||
| if ($output !== null && preg_match($pattern, $output, $matches)) { |
There was a problem hiding this comment.
parseVersionOutput() assumes $output is null or a string, but the SystemCommand::*Version() methods return string|false. If they return false, preg_match() will throw a TypeError (bool given), which is not caught by this controller. Guard with is_string($output) before calling preg_match(), or widen the parameter type to string|false and treat false as Unknown.
| * HTML-escaped. Returns 'Unknown' when output is null or the pattern | |
| * does not match. | |
| * | |
| * @param string|null $output Raw command output | |
| * @param string $pattern PCRE pattern with one capture group for the version | |
| * @return string Sanitized version string or 'Unknown' | |
| */ | |
| private function parseVersionOutput(?string $output, string $pattern): string | |
| { | |
| if ($output !== null && preg_match($pattern, $output, $matches)) { | |
| * HTML-escaped. Returns 'Unknown' when output is null, false, or the | |
| * pattern does not match. | |
| * | |
| * @param string|false|null $output Raw command output | |
| * @param string $pattern PCRE pattern with one capture group for the version | |
| * @return string Sanitized version string or 'Unknown' | |
| */ | |
| private function parseVersionOutput(string|false|null $output, string $pattern): string | |
| { | |
| if (is_string($output) && preg_match($pattern, $output, $matches)) { |
| /** | ||
| * @param string $apiUrl API endpoint URL | ||
| * @return array{data: array, error: ?array} | ||
| */ | ||
| public function fetch(string $apiUrl): array | ||
| { | ||
| // Reuse centralized secure cURL configuration to avoid drift/duplication. | ||
| $curl = createSecureCurlHandle($apiUrl); | ||
| $curl = $this->createSecureCurlHandle($apiUrl); | ||
|
|
||
| $response = curl_exec($curl); | ||
| $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); | ||
| curl_close($curl); | ||
|
|
There was a problem hiding this comment.
ExternalServicesJsonApiResponseFetcher::fetch() now calls createSecureCurlHandle() from SecureCurlHandleTrait, which can throw CurlInitException. That breaks fetch()'s stated contract of always returning an array{data, error} and can bubble exceptions to any future callers. Consider catching CurlInitException inside fetch() and returning FetchError, or update the method’s PHPDoc/contract to document the thrown exception and ensure all callers handle it.



classes/CurlInitException.php—final class CurlInitException extends \RuntimeException {}require_once CurlInitException.phpadded toexternal-services-api.phpandExternalServicesController.phpthrow new \RuntimeExceptionreplaced withthrow new CurlInitException;@throwsdocblocks updatedphp -lOriginal prompt