Files
ladill-woo-manager/app/Services/Woo/PluginClient.php
T
isaaccladandCursor 1e97f129e9
Deploy Ladill Woo Manager / deploy (push) Successful in 1m4s
Handle Woo plugin connection timeouts without 500 errors.
Treat unreachable WordPress stores as unavailable during integrations refresh instead of throwing when the site times out.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-08 11:02:06 +00:00

136 lines
4.3 KiB
PHP

<?php
namespace App\Services\Woo;
use App\Models\WooStore;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Client\Response;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class PluginClient
{
/** @return array<string, mixed>|null */
public function get(WooStore $store, string $path, array $query = []): ?array
{
return $this->request($store, 'GET', $path, $query);
}
/** @param array<string, mixed> $payload */
public function post(WooStore $store, string $path, array $payload = []): ?array
{
return $this->request($store, 'POST', $path, $payload);
}
/** @param array<string, mixed> $payload */
public function put(WooStore $store, string $path, array $payload = []): ?array
{
return $this->request($store, 'PUT', $path, $payload);
}
public function delete(WooStore $store, string $path): bool
{
try {
return $this->raw($store, 'DELETE', $path)->successful();
} catch (ConnectionException $e) {
$this->logConnectionFailure($store, 'DELETE', $path, $e);
return false;
}
}
/** @return array<string, mixed>|null */
public function uploadMedia(WooStore $store, UploadedFile $file, string $alt = ''): ?array
{
$site = rtrim((string) $store->site_url, '/');
$url = $site.'/wp-json/ladill-woo/v1/media';
try {
$response = Http::acceptJson()
->timeout(60)
->withHeaders(['X-Ladill-Store' => $store->public_id])
->attach(
'file',
file_get_contents($file->getRealPath()) ?: '',
$file->getClientOriginalName() ?: 'upload.jpg',
)
->post($url, array_filter(['alt' => $alt !== '' ? $alt : null]));
} catch (ConnectionException $e) {
$this->logConnectionFailure($store, 'POST', 'media', $e);
return null;
}
if (! $response->successful()) {
Log::warning('Woo plugin media upload failed', [
'store_id' => $store->id,
'status' => $response->status(),
]);
return null;
}
/** @var array<string, mixed>|null $json */
$json = $response->json();
return is_array($json) ? $json : null;
}
/** @return array<string, mixed>|null */
private function request(WooStore $store, string $method, string $path, array $data = []): ?array
{
try {
$response = $this->raw($store, $method, $path, $data);
} catch (ConnectionException $e) {
$this->logConnectionFailure($store, $method, $path, $e);
return null;
}
if (! $response->successful()) {
Log::warning('Woo plugin API request failed', [
'store_id' => $store->id,
'method' => $method,
'path' => $path,
'status' => $response->status(),
]);
return null;
}
/** @var array<string, mixed>|null $json */
$json = $response->json();
return is_array($json) ? $json : null;
}
private function raw(WooStore $store, string $method, string $path, array $data = []): Response
{
$site = rtrim((string) $store->site_url, '/');
$url = $site.'/wp-json/ladill-woo/v1/'.ltrim($path, '/');
$pending = Http::acceptJson()
->timeout(20)
->withHeaders(['X-Ladill-Store' => $store->public_id]);
return match (strtoupper($method)) {
'GET' => $pending->get($url, $data),
'POST' => $pending->asJson()->post($url, $data),
'PUT' => $pending->asJson()->put($url, $data),
'DELETE' => $pending->delete($url, $data),
default => throw new \InvalidArgumentException("Unsupported method: {$method}"),
};
}
private function logConnectionFailure(WooStore $store, string $method, string $path, ConnectionException $e): void
{
Log::warning('Woo plugin API connection failed', [
'store_id' => $store->id,
'method' => $method,
'path' => $path,
'message' => $e->getMessage(),
]);
}
}