CoolCMS API

ApiBridge
in package

Bridge for internal (in-process presenter) and external (HTTP) API calls.

Usage (config.neon):

services:
    apiBridge:
        factory: ApiBridge(%apiBridge%)

Parameters under apiBridge: defaultCallType (internal|external), baseUrl, timeout, sslVerify, maxRedirects, headers.

Table of Contents

Constants

EXTERNAL_CALL  : mixed = 'external'
INTERNAL_CALL  : mixed = 'internal'
PARAM_SOURCE  : mixed = '_callSource'
Payload control key: which call branch the call comes from (`front` or `admin`).
PARAM_USE_CACHE  : mixed = 'useCache'
Payload control key: whether the query may be read from the query cache.
SOURCE_ADMIN  : mixed = 'admin'
SOURCE_FRONT  : mixed = 'front'

Properties

$authStorage  : AuthSessionStorage|null
$baseUrl  : string
$callType  : string
$defaultHeaders  : array<string, mixed>
$fieldAudienceContext  : FieldAudienceContext|null
$httpClient  : Client
$httpRequest  : IRequest
$internalAuthToken  : string|null
$internalCallContext  : InternalCallContext|null
$jwtManager  : JwtManager|null
$personalDataPolicy  : PersonalDataPolicy|null
$presenterFactory  : IPresenterFactory
$queryCacheContext  : QueryCacheContext|null
$timeout  : int

Methods

__construct()  : mixed
call()  : mixed
Calls the API module in-process without HTTP, or externally over HTTP.
delete()  : mixed
Performs a DELETE request.
get()  : mixed
Performs a GET request.
hasInternalAuth()  : bool
Returns whether an internal call carries an identity (token from the setter or the session).
inheritAuth()  : self
Takes over the authorization from the current HTTP request.
post()  : mixed
Performs a POST request.
proxy()  : mixed
Calls the endpoint with parameters taken from the current HTTP request (proxy).
put()  : mixed
Performs a PUT request.
setAuthToken()  : self
Sets the authorization token for external calls.
setBaseUrl()  : self
Sets the base URL for external calls.
setCallType()  : self
Sets the call type for all following calls.
setHeader()  : self
Adds or overrides an HTTP header for external calls.
setInternalAuthToken()  : self
Sets the token used to authorize internal calls, overriding the one taken from the `front.auth` session. `null` restores the default.
externalCall()  : mixed
Performs an external HTTP call to the API using Guzzle.
extractParamsFromRequest()  : array<string|int, mixed>
Converts parameters of the incoming HTTP request into the format of an internal call.
internalCall()  : mixed
propagateAuthToPresenter()  : void
Propagates the JWT to the presenter for an internal call.
propagateQueryCachePolicy()  : void
Passes the query cache policy of this call to the presenter ({@see PARAM_USE_CACHE}).
reportFailureEnvelope()  : void
Logs a failed response envelope; every Api layer response passes through here.
resolveFailSoftCaller()  : string
Returns the first stack frame outside the transport and the generic Front/Admin repositories, i.e. the module code that asked for the data.
resolveInternalAuthToken()  : string|null
Returns the token for internal calls; the explicit setter wins over the session token.
resolveQueryCachePolicy()  : bool
Resolves the cache policy of this call; the order is binding.

Constants

EXTERNAL_CALL

public mixed EXTERNAL_CALL = 'external'

INTERNAL_CALL

public mixed INTERNAL_CALL = 'internal'

PARAM_SOURCE

Payload control key: which call branch the call comes from (`front` or `admin`).

public mixed PARAM_SOURCE = '_callSource'

Same path as PARAM_USE_CACHE: call() strips it from the arguments and internalCall() hands it to the presenter via setApiCallSource(). The base ApiRepository of Front and Admin sets it through the shared repository SaveTrait.

IMPORTANT: three safeguards.

  1. It cannot be injected from outside: proxy() drops it from HTTP parameters and the external incoming path has no source for it.
  2. Missing means null ("unknown"), and notification producers notify on null, so a forgotten path never stays silent.
  3. It is a branch marker, not a permission; RBAC decides access, never this value.

IMPORTANT: the name must not collide with a parameter of any internalAction*(), because call() always strips the key. With the former name source, the stock Api endpoints (stock-reservation/release, stock-document/receive) never received their own source parameter from the admin.

PARAM_USE_CACHE

Payload control key: whether the query may be read from the query cache.

public mixed PARAM_USE_CACHE = 'useCache'

The repository puts it into the parameter array like any other key, but call() strips it and passes it to the presenter outside the arguments (BasePresenter::setQueryCacheEnabled()).

It is not a named parameter of internalAction*() because internalCall() spreads the array as named arguments, so a key the target method does not declare ends in Error: Unknown named parameter $useCache. The internalAction*() signature is not uniform (some presenters have their own), so every future method would have to know the cache parameter and a missing one would fail only at runtime, invisible to PHPStan. Outside the arguments, a presenter that knows nothing about the cache simply sets nothing.

IMPORTANT: the external HTTP path drops the key (see call()); the cache switch must never be in the hands of an outside caller.

SOURCE_ADMIN

public mixed SOURCE_ADMIN = 'admin'

SOURCE_FRONT

public mixed SOURCE_FRONT = 'front'

Properties

$callType

private string $callType = self::INTERNAL_CALL

$defaultHeaders

private array<string, mixed> $defaultHeaders

$httpRequest read-only

private IRequest $httpRequest

$internalAuthToken

private string|null $internalAuthToken = null

$presenterFactory read-only

private IPresenterFactory $presenterFactory

Methods

__construct()

public __construct(IPresenterFactory $presenterFactory, IRequest $httpRequest[, AuthSessionStorage|null $authStorage = null ][, JwtManager|null $jwtManager = null ][, array<string, mixed> $config = [] ][, Client|null $httpClient = null ][, FieldAudienceContext|null $fieldAudienceContext = null ][, QueryCacheContext|null $queryCacheContext = null ][, PersonalDataPolicy|null $personalDataPolicy = null ][, InternalCallContext|null $internalCallContext = null ]) : mixed
Parameters
$presenterFactory : IPresenterFactory
$httpRequest : IRequest
$authStorage : AuthSessionStorage|null = null
$jwtManager : JwtManager|null = null
$config : array<string, mixed> = []
$httpClient : Client|null = null
$fieldAudienceContext : FieldAudienceContext|null = null
$queryCacheContext : QueryCacheContext|null = null
$personalDataPolicy : PersonalDataPolicy|null = null
$internalCallContext : InternalCallContext|null = null

call()

Calls the API module in-process without HTTP, or externally over HTTP.

public call(string $endpoint[, array<string, mixed> $params = [] ][, string|null $callType = null ][, string $method = 'GET' ]) : mixed
Parameters
$endpoint : string

format api/section/presenter/action

$params : array<string, mixed> = []

parameters passed to the API method; the PARAM_USE_CACHE key is a control key and is not passed as an action argument

$callType : string|null = null

call type (internal/external)

$method : string = 'GET'

HTTP method for external calls

Tags
throws
InvalidArgumentException

when the endpoint is invalid

RuntimeException

when the presenter method does not exist or on an HTTP error

Return values
mixed —

data returned from the API

delete()

Performs a DELETE request.

public delete(string $endpoint[, array<string, mixed> $params = [] ][, string|null $callType = null ]) : mixed
Parameters
$endpoint : string
$params : array<string, mixed> = []
$callType : string|null = null

get()

Performs a GET request.

public get(string $endpoint[, array<string, mixed> $params = [] ][, string|null $callType = null ]) : mixed
Parameters
$endpoint : string
$params : array<string, mixed> = []
$callType : string|null = null

hasInternalAuth()

Returns whether an internal call carries an identity (token from the setter or the session).

public hasInternalAuth() : bool

False means the call runs as a guest, so the caller can skip an admin-only read before RBAC rejects it and writes deny and fail-soft lines to auth.log.

Return values
bool

inheritAuth()

Takes over the authorization from the current HTTP request.

public inheritAuth() : self
Return values
self

post()

Performs a POST request.

public post(string $endpoint[, array<string, mixed> $params = [] ][, string|null $callType = null ]) : mixed
Parameters
$endpoint : string
$params : array<string, mixed> = []
$callType : string|null = null

proxy()

Calls the endpoint with parameters taken from the current HTTP request (proxy).

public proxy(string $endpoint[, string|null $callType = null ]) : mixed
Parameters
$endpoint : string
$callType : string|null = null

put()

Performs a PUT request.

public put(string $endpoint[, array<string, mixed> $params = [] ][, string|null $callType = null ]) : mixed
Parameters
$endpoint : string
$params : array<string, mixed> = []
$callType : string|null = null

setAuthToken()

Sets the authorization token for external calls.

public setAuthToken(string $token) : self
Parameters
$token : string
Return values
self

setBaseUrl()

Sets the base URL for external calls.

public setBaseUrl(string $baseUrl) : self
Parameters
$baseUrl : string
Return values
self

setCallType()

Sets the call type for all following calls.

public setCallType(string $callType) : self
Parameters
$callType : string
Return values
self

setHeader()

Adds or overrides an HTTP header for external calls.

public setHeader(string $name, string $value) : self
Parameters
$name : string
$value : string
Return values
self

setInternalAuthToken()

Sets the token used to authorize internal calls, overriding the one taken from the `front.auth` session. `null` restores the default.

public setInternalAuthToken(string|null $token) : self
Parameters
$token : string|null
Return values
self

externalCall()

Performs an external HTTP call to the API using Guzzle.

private externalCall(string $endpoint[, array<string, mixed> $params = [] ][, string $method = 'GET' ]) : mixed
Parameters
$endpoint : string

API endpoint

$params : array<string, mixed> = []

request parameters

$method : string = 'GET'

HTTP method

Tags
throws
RuntimeException

on an HTTP error

Return values
mixed —

API response; a non-JSON body is returned raw

extractParamsFromRequest()

Converts parameters of the incoming HTTP request into the format of an internal call.

private extractParamsFromRequest() : array<string|int, mixed>
Return values
array<string|int, mixed>

internalCall()

private internalCall(string $endpoint[, array<string, mixed> $params = [] ][, bool $useCache = true ][, string|null $source = null ]) : mixed
Parameters
$endpoint : string
$params : array<string, mixed> = []
$useCache : bool = true
$source : string|null = null

propagateAuthToPresenter()

Propagates the JWT to the presenter for an internal call.

private propagateAuthToPresenter(IPresenter $presenter, string $presenterName, string $action) : void

Takes the token from the front.auth session (or the explicit setInternalAuthToken()), verifies signature and expiry through JwtManager and pre-populates the payload on the presenter via JwtAuthTrait; failures go to the auth log channel. Does nothing for a presenter without the trait, without a token or with an invalid one (downstream code then sees a null payload).

Parameters
$presenter : IPresenter
$presenterName : string
$action : string

propagateQueryCachePolicy()

Passes the query cache policy of this call to the presenter ({@see PARAM_USE_CACHE}).

private propagateQueryCachePolicy(IPresenter $presenter, bool $useCache) : void

Same pattern as propagateAuthToPresenter(): outside the arguments, via a setter, best effort. A presenter outside the Api stack has no setter and nothing happens. It is set always, even for true, so a presenter that stops being new per call never keeps a stale flag.

Parameters
$presenter : IPresenter
$useCache : bool

reportFailureEnvelope()

Logs a failed response envelope; every Api layer response passes through here.

private reportFailureEnvelope(mixed $response, string $endpoint, string $callType) : void

IMPORTANT: the response is deliberately not rewritten. The bridge serves two incompatible contracts. Read repositories (find, findBy, findAll) treat the envelope as a defect and FailSoftReadTrait turns it into []. Write callers (SaveTrait, DeleteTrait, TreeTrait, RegisterEventTrait, ...) need the envelope as the result; many places read ['success']. Dropping it would lose the error messages and some of those places (return $result['success']; without ??) would fail fatally. The decision "this should have been data" belongs one layer up where the contract is known; here the failure is only no longer hidden (otherwise it is an empty page with no log line).

Parameters
$response : mixed
$endpoint : string
$callType : string

resolveFailSoftCaller()

Returns the first stack frame outside the transport and the generic Front/Admin repositories, i.e. the module code that asked for the data.

private static resolveFailSoftCaller() : string

Same principle as ApiPermissionGuardTrait::resolveCallerFrame().

Return values
string

resolveInternalAuthToken()

Returns the token for internal calls; the explicit setter wins over the session token.

private resolveInternalAuthToken() : string|null
Return values
string|null

resolveQueryCachePolicy()

Resolves the cache policy of this call; the order is binding.

private resolveQueryCachePolicy(mixed $requested) : bool
  1. The caller's opinion (PARAM_USE_CACHE in the payload) is the most specific and wins.
  2. The request context (QueryCacheContext): admin disables it in startup(), so it also covers reads through front managers that run in an admin request (AssetManager, ThemeManager, UserManager, ...).
  3. Default true for front and external calls.

null in the payload means "no opinion", not "disable", hence ?? instead of a (bool) cast.

Parameters
$requested : mixed
Return values
bool
On this page

Search results