yf_htmx class

Fileplugins/htmx/classes/yf_htmx.class.php
Use_class('htmx')

Public properties

A site sets them in its config with $PROJECT_CONF['htmx']['NAME'] = ...;

PropertyDefaultDescription
$EXIT_AFTER_HEADER true
$SEND_HEADERS true
$TOAST_MAX_BODY 500
$TOAST_MAX_COUNT
int
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
$_toasts
array
[] toasts of this response, all sent in one HX-Trigger header by _toast()
$boosted null
$current_url null
$is_hx null
$req
['request' => false, 'boosted' => false, 'target' => '', 'trigger' => '', 'trigger_name' => '', 'current_url' => '', ... (7 items)]
array (
  'request' => false,
  'boosted' => false,
  'target' => '',
  'trigger' => '',
  'trigger_name' => '',
  'current_url' => '',
  'history_restore_request' => false,
)
$sent_headers []
$target null
$trigger null
$trigger_name null

Public methods 17

None without a leading underscore.

Methods starting with _ hooks and helpers; not routable as page actions

_cache

public function _cache($options = null)
    public function _cache($options = null)
    {
        return $this->_api->_cache($options);
    }

_cache_none

public function _cache_none()
    public function _cache_none()
    {
        return $this->_api->_cache(['no-store' => true]);
    }

_error

public function _error()
    public function _error()
    {
        no_graphics(true);
        $this->_api->_error();
    }

_firewall

public function _firewall()
    public function _firewall()
    {
        if ( ! $this->is_hx) {
            $this->_reject();
        }
        return $this->is_hx;
    }

_forbidden

public function _forbidden()
    public function _forbidden()
    {
        no_graphics(true);
        $this->_api->_forbidden();
    }

_get_req

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);
            }
        }
    }

_init

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();
    }

_is_hx

public function _is_hx()
    public function _is_hx()
    {
        $r = (bool) ($_SERVER['HTTP_HX_REQUEST'] ?? null);
        $this->is_hx = $r;
        return $r;
    }

_location

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));
    }

_redirect

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/');
    }

_refresh

public function _refresh()
    public function _refresh()
    {
        no_graphics(true);
        return $this->_finish($this->_header('HX-Refresh: true'));
    }

_reject

public function _reject()
    public function _reject()
    {
        no_graphics(true);
        $this->_api->_reject();
    }

_result

public function _result($r)
    public function _result($r)
    {
        no_graphics(true);
        $this->_robot_none();
        main()->_debug_header();
        echo $r;
        exit;
    }

_robot_none

public function _robot_none()
    public function _robot_none()
    {
        return $this->_api->_robot_none();
    }

_toast

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);
    }