1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace LaravelUi5\OData\Exception;
6:
7: use Illuminate\Http\Response;
8: use LaravelUi5\OData\Service\ReadContext;
9:
10: /**
11: * A read was denied by the host's {@see \LaravelUi5\OData\Service\Contracts\ReadAuthorizerInterface}.
12: *
13: * Serializes as a standard OData 403 error envelope (`{"error": {code, message, target, …}}`)
14: * via {@see ProtocolException::toResponse()}. The UI5 v4 model surfaces a failed request's
15: * error body to the message model natively — the reliable carrier for a root-set denial (the
16: * `sap-messages` header is the carrier for the 200-partial case, not this one).
17: */
18: class ForbiddenException extends ProtocolException
19: {
20: protected $httpCode = Response::HTTP_FORBIDDEN;
21:
22: protected $odataCode = 'read_forbidden';
23:
24: protected $message = 'Read access denied';
25:
26: /**
27: * Build a 403 from a {@see ReadContext}'s primary (root) denial, copying its structured
28: * message into the OData error envelope.
29: */
30: public static function fromContext(ReadContext $read): self
31: {
32: $exception = new self();
33: $message = $read->primaryDenial();
34:
35: if ($message !== null) {
36: $exception->code($message->code)->message($message->message);
37:
38: if ($message->target !== '') {
39: $exception->target($message->target);
40: }
41: }
42:
43: return $exception;
44: }
45: }
46: