yf_htmx class| File | plugins/htmx/classes/yf_htmx.class.php |
|---|---|
| Use | _class('htmx') |
A site sets them in its config with $PROJECT_CONF['htmx']['NAME'] = ...;
| Property | Default | Description |
|---|---|---|
$EXIT_AFTER_HEADER |
true |
|
$SEND_HEADERS |
true |
|
$TOAST_MAX_BODY |
500 |
|
$TOAST_MAX_COUNTint |
10 |
_toast() limits: header size is limited (often 8 KB in all), so long texts are cut and extra toasts dropped |
$TOAST_MAX_TITLE |
100 |
|
$_api |
null |
|
$_toastsarray |
[] |
toasts of this response, all sent in one HX-Trigger header by _toast() |
$boosted |
null |
|
$current_url |
null |
|
$is_hx |
null |
|
$req |
|
|
$sent_headers |
[] |
|
$target |
null |
|
$trigger |
null |
|
$trigger_name |
null |
None without a leading underscore.
_ hooks and helpers; not routable as page actionspublic function _cache($options = null)
public function _cache($options = null)
{
return $this->_api->_cache($options);
}
public function _cache_none()
public function _cache_none()
{
return $this->_api->_cache(['no-store' => true]);
}
public function _error()
public function _error()
{
no_graphics(true);
$this->_api->_error();
}
public function _firewall()
public function _firewall()
{
if ( ! $this->is_hx) {
$this->_reject();
}
return $this->is_hx;
}
public function _forbidden()
public function _forbidden()
{
no_graphics(true);
$this->_api->_forbidden();
}
public function _get_req()
public function _get_req()
{
foreach ($this->req as $k => &$v) {
$key = 'HTTP_HX_' . strtoupper($k);
if (isset($_SERVER[$key])) {
$v = ($_SERVER[$key] ?? null);
}
}
}
public function _init()
public function _init()
{
$this->_api = _class('api');
$this->_api->JSON_VULNERABILITY_PROTECTION = false;
$this->_is_hx();
$this->target = ($_SERVER['HTTP_HX_TARGET'] ?? null);
$this->boosted = ($_SERVER['HTTP_HX_BOOSTED'] ?? null);
$this->_get_req();
}
public function _is_hx()
public function _is_hx()
{
$r = (bool) ($_SERVER['HTTP_HX_REQUEST'] ?? null);
$this->is_hx = $r;
return $r;
}
public function _location($url)
public function _location($url)
{
no_graphics(true);
if (is_array($url)) {
$url = json_encode($url, true);
}
return $this->_finish($this->_header('HX-Location: ' . $url));
}
public function _redirect($url)
public function _redirect($url)
{
no_graphics(true);
return $this->_finish($this->_header('HX-Redirect: ' . $url));
}
public function _redirect_login()
public function _redirect_login()
{
return $this->_redirect('/login/');
}
public function _refresh()
public function _refresh()
{
no_graphics(true);
return $this->_finish($this->_header('HX-Refresh: true'));
}
public function _reject()
public function _reject()
{
no_graphics(true);
$this->_api->_reject();
}
public function _result($r)
public function _result($r)
{
no_graphics(true);
$this->_robot_none();
main()->_debug_header();
echo $r;
exit;
}
public function _robot_none()
public function _robot_none()
{
return $this->_api->_robot_none();
}
public function _toast($text, $extra = [])
A Bootstrap 5 toast for the page that sent this htmx request: the HX-Trigger event `yf-toast`, shown by the yf_bs5_toasts asset (the page loads it: html()->toast_container() or asset('yf_bs5_toasts')). Text only: the body and title are shown as text, never as HTML. Each call adds a toast to the one HX-Trigger header (it replaces an HX-Trigger header set elsewhere); the response goes on. Headers have size limits: the body is cut at TOAST_MAX_BODY characters, the title at TOAST_MAX_TITLE, and toasts past TOAST_MAX_COUNT in one response are dropped ('' is returned). Options: title, type (success, info, warning, danger / error...), autohide (false keeps it until closed), delay (ms).
public function _toast($text, $extra = [])
{
if (count($this->_toasts) >= $this->TOAST_MAX_COUNT) {
return '';
}
$extra = (array) $extra;
$toast = ['body' => mb_substr((string) $text, 0, $this->TOAST_MAX_BODY)];
strlen((string) ($extra['title'] ?? '')) && $toast['title'] = mb_substr((string) $extra['title'], 0, $this->TOAST_MAX_TITLE);
($extra['type'] ?? null) && $toast['type'] = mb_substr((string) $extra['type'], 0, 20);
isset($extra['autohide']) && $toast['autohide'] = (bool) $extra['autohide'];
isset($extra['delay']) && $toast['delay'] = (int) $extra['delay'];
// json_encode escapes line breaks and non-ASCII, so the header stays one ASCII line
$json = json_encode(['yf-toast' => ['toasts' => array_merge($this->_toasts, [$toast]), 'close' => t('Close')]], JSON_INVALID_UTF8_SUBSTITUTE);
if ($json === false) {
return '';
}
$this->_toasts[] = $toast;
return $this->_header('HX-Trigger: ' . $json);
}
public function _wants_fragment()
Whether to answer with a fragment: an htmx request, but not the history restore htmx sends after a cache miss on Back, which swaps the whole body and so needs the full page.
public function _wants_fragment()
{
return (bool) $this->is_hx && ! ($this->req['history_restore_request'] ?? false);
}