Docs: Upgrading from 1.17

Upgrading from 1.17

A checklist for a theme forked before Tilspire 1.18.0 — five habits that now cost something, four worth replacing, and the Template API call to use for each.

Most of Tilspire 1.18.0 is additive: a theme that changes nothing keeps working, and is simply floored on every contract it does not claim. Five habits now cost something, and four more are worth replacing. If your theme was forked earlier than 1.17.0, read the 1.17 and older notes as well; each release lists only what changed since the one below it.

Five habits that now cost something #

  • It versions a URL with CMS_VERSION or a number of its own. CSS edited between releases is served stale to returning visitors for up to a week. Use $this->assetVersion($path).
  • It writes the panel's address (/adm). The link breaks once the operator moves the panel, and shows a member where it is. Use $this->panelLink().
  • It writes /forums or /blog. After a rename the link works only through a 301. Use $this->section('forums').
  • It draws its own comment or ticket form with only the v2 box from form.captcha. Under reCAPTCHA v3 or Turnstile its posts are refused, and Health warns. Use $this->captchaBox('comment'), or the ticket form's name.
  • It ships its own views/auth-login.php or views/auth-forgot.php. The form is held to the sign-in throttle alone, and Health warns. Use $this->captchaBox('signin') or ('password_reset').

Four habits worth replacing #

These break nothing.

  • Gating on maintenance mode in the header, or testing isStaff(), a role or a permission. Core settles maintenance first. Use site()['maintenance'] for a staff banner, and may() or action() for a control.
  • Reading the analytics id or the custom head code from the settings table. Use $this->headExtras().
  • Loading a third-party script with a plain <script src>. Use $this->heldScript('statistics', $src), so cookie consent can hold it.
  • Printing a search box unconditionally, or naming a core class such as ContentModel::LIST_TYPES. Use $this->searchEnabled(), and $this::FIELD_LIST_TYPES and the other constants.

A theme that draws no cookie banner or settings link gets core's while consent is on (contracts 10 and 11).

Checklist #

Work down it once, search your theme's folder for each pattern, and change what you find.

  1. Cache-busting. Search for CMS_VERSION and for any ?v= with a number of your own. Replace each with the file's own stamp. Note that asset() returns an address without a version stamp, so add it yourself:
    <link rel="stylesheet" href="<?= $esc($this->asset('main.css') . '?v=' . $this->assetVersion('main.css')) ?>">
    assetVersion() changes whenever the file's modification time or size does, and falls back to CMS_VERSION for a file that does not exist.
  2. Panel link. Search for /adm. Draw the link only when panelLink() returns an address:
    <?php if (($panel = $this->panelLink()) !== null): ?><a href="<?= $esc($panel) ?>">Control panel</a><?php endif; ?>
  3. Section addresses. Search for /forums and /blog. Replace each with section() and test for null:
    <?php if ($forums = $this->section('forums')): ?><a href="<?= $forums['url'] ?>"><?= $forums['title'] ?></a><?php endif; ?>
  4. Captcha on your own forms. In every comment or ticket form you draw, and in your own views/auth-login.php and views/auth-forgot.php, add <?php $this->captchaBox('comment'); ?> (or signin, password_reset, new_ticket, reply_ticket) inside the form, before the submit button.
  5. Sign-up forms. If you ship views/auth-register.php, or any form that posts to /account/register, call <?php $this->signupChecks(); ?> inside it, before the submit button.
  6. Rules in templates. Search for isStaff(), role numbers and permission tests used to show or hide a control. Replace them with may() or action(). Remove any maintenance gate in your header and draw a banner from site()['maintenance'] if you want one.
  7. Head extras. Replace settings-table reads for the analytics id and the custom head code with headExtras().
  8. Third-party scripts. Route each through heldScript(), with the loader in a file of your theme. Anything written as a plain <script src> is not held by cookie consent, and Health says so.
  9. Search. Wrap any search box or link in searchEnabled(), so a site with search off shows no form that lands on a 404.
  10. Constants. Replace named core classes (ContentModel::LIST_TYPES) with $this::FIELD_LIST_TYPES and the other constants on $this.
  11. Consent. Decide whether to use core's banner and "Cookie settings" link or draw your own. To keep core's, place <?= $this->consentBanner() ?> right after <body> and <?= $this->consentLink('footer-link') ?> in the footer; to draw your own, call each without printing it, and build the markup as the Sign-in, forms and consent page describes.
  12. Check. Load the site as a guest and as a signed-in member, with consent on and off, and with search and each module on and off. Then check the Health page for warnings about your theme.

The calls named above are described on these pages: panelLink on Site, visitor and request; assetVersion and headExtras on Head, assets and views; action, actions, may, section and searchEnabled on Actions and sections; the consent, captcha and sign-in calls on Sign-in, forms and consent.