{{-- Safe action buttons for task-queue directives (expects $ctaLinks iterable of ['label' => string, 'href' => string]). --}} @php $ctaList = collect($ctaLinks ?? []) ->filter(fn ($item) => is_array($item) && is_string($item['href'] ?? null) && is_string($item['label'] ?? null) && $item['href'] !== '' && $item['label'] !== '') ->values(); $appBase = rtrim((string) (config('app.url') ?: 'http://localhost'), '/'); $appHost = parse_url($appBase, PHP_URL_HOST); @endphp @if($ctaList->isNotEmpty())
@foreach($ctaList as $item) @php $rawHref = $item['href']; $label = $item['label']; $resolved = str_starts_with($rawHref, '/') ? url($rawHref) : $rawHref; $host = is_string($resolved) ? parse_url($resolved, PHP_URL_HOST) : null; $resolvedPath = is_string($resolved) ? (string) parse_url($resolved, PHP_URL_PATH) : ''; // Never render a GET anchor to a POST-only invoice action — these cause 405 errors. $isPostOnlyInvoiceEndpoint = (bool) preg_match('#^/invoices/\d+/(approve|pay|submit-payment-request)$#', $resolvedPath); $ok = ! $isPostOnlyInvoiceEndpoint && is_string($resolved) && ( (str_starts_with($resolved, $appBase.'/') || $resolved === $appBase) || ($host !== null && $appHost !== null && strcasecmp((string) $host, (string) $appHost) === 0) ); @endphp @if($ok) {{ $label }} @endif @endforeach
@endif