Skip to content

[1.x & 2.x] Admin boolean settings with truthy default values cannot be disabled (Switch component) #4781

Description

@huoxin233

Current Behavior

When an extension registers a boolean setting via the settings registry with a default: true value, it is impossible for the administrator to permanently turn the switch off. Upon saving and refreshing the page, the switch always reverts back to ON.

The Root Cause
This is caused by how JavaScript handles falsy values when initializing setting streams, combined with how PHP casts booleans:

  1. When an admin turns off a <Switch> component, the onchange event passes the boolean false into the setting Stream.
  2. The backend receives false in the JSON payload. The Settings repository casts this to a string for the database, converting false into an empty string "".
  3. On page reload, app.data.settings[key] returns the empty string "".
  4. In AdminPage.tsx (and historically ExtensionPage), the setting stream is initialized using the logical OR operator:
    this.settings[key] = this.settings[key] || Stream(app.data.settings[key] || fallback);
  5. Because "" is a falsy value in JavaScript, "" || fallback completely ignores the saved empty string and evaluates to the fallback value (which is true).

1.x vs 2.x Impact
This logic bug exists in both 1.x and 2.x. However, it is primarily noticeable in 2.x because the 2.x buildSettingComponent was updated to correctly pass the default property into the fallback argument. Now that truthy defaults are respected by the UI, this || bug forces those settings to be permanently on.

Steps to Reproduce

  1. Register an extension setting with type: 'boolean' and default: true.
    e.g. (https://github.com/huoxin233/flarum-ext-filter-rule-manager/blob/7f6531043dabf9b012651f93aba8b3efc8ae0234/js/src/admin/components/RulesetManagerPage.tsx#L248-L254)
{this.buildSettingComponent({
  type: 'boolean',
  setting: 'huoxin-filter.global_evaluate_title',
  label: String(app.translator.trans('huoxin-filter-rule-manager.admin.settings.global_evaluate_title')),
  help: String(app.translator.trans('huoxin-filter-rule-manager.admin.settings.global_evaluate_title_help')),
  default: true,
})}
  1. Go to the admin dashboard and observe the switch is ON.
  2. Toggle the switch to OFF and save changes.
  3. Refresh the page. The switch will be ON again.

Expected Behavior

The switch state should save correctly when OFF.

Screenshots

Extension tested in the video is on commit huoxin233/flarum-ext-filter-rule-manager@db5d5cd

PixPin_2026-06-26_17-45-31.mp4

Environment

  • Flarum version: 2.0.0-rc.4
  • PHP version: 8.3.8

Output of php flarum info

Output of "php flarum info", run this in terminal in your Flarum directory.

Flarum core: 2.0.0-rc.4
PHP version: CLI: 8.3.8, Web: 8.3.8
PHP memory limit: CLI: 512M, Web: 128M
MariaDB version: 10.11.6
Loaded extensions: Core, date, libxml, pcre, hash, json, SPL, session, openssl, random, Reflection, xml, cli_server, bcmath, calendar, curl, ctype, dom, standard, fileinfo, filter, ftp, gd, gettext, gmp, iconv, imap, intl, ldap, mbstring, mysqlnd, mysqli, zlib, pcntl, PDO, pdo_mysql, PDO_ODBC, pdo_pgsql, pdo_sqlite, pgsql, posix, readline, exif, SimpleXML, sockets, soap, sodium, sysvsem, sqlite3, tokenizer, xmlreader, xmlwriter, zip, Phar, Zend OPcache, xdebug
+------------------------------+---------------+------------------------------------------+-------+
| Flarum Extensions | | | |
+------------------------------+---------------+------------------------------------------+-------+
| ID | Version | Commit | Notes |
+------------------------------+---------------+------------------------------------------+-------+
| flarum-flags | v2.0.0-rc.1 | | |
| flarum-approval | v2.0.0-rc.1 | | |
| flarum-suspend | v2.0.0-rc.1 | | |
| flarum-tags | v2.0.0-rc.1 | | |
| flarum-likes | v2.0.0-rc.1 | | |
| fof-default-user-preferences | 2.0.0-beta.2 | | |
| fof-byobu | 2.0.0-beta.11 | | |
| pianotell-flamoji | v2.2.1 | | |
| ianm-log-viewer | 2.0.0-beta.2 | | |
| huoxin-relative-url | 2.x-dev | 9d21286bbca19017285cdd97b466013685fa1354 | |
| huoxin-money-with-history | 2.x-dev | ee1ac54ffb2dc962feb7efa165d87ef701cfee0b | |
| huoxin-filter-rule-manager | 2.x-dev | 8689b9f0d5c0ecd95a2e77a331bad0505a6ff68c | |
| fof-links | 2.0.0-beta.3 | | |
| fof-drafts | dev-main | | |
| flarum-subscriptions | dev-main | | |
| flarum-sticky | v2.0.0-rc.1 | | |
| flarum-statistics | v2.0.0-rc.1 | | |
| flarum-messages | v2.0.0-rc.1 | | |
| flarum-mentions | v2.0.0-rc.1 | | |
| flarum-markdown | v2.0.0-rc.1 | | |
| flarum-lock | v2.0.0-rc.1 | | |
| flarum-lang-english | v2.0.0-rc.1 | | |
| flarum-extension-manager | v2.0.0-rc.1 | | |
| flarum-emoji | v2.0.0-rc.1 | | |
| flarum-bbcode | v2.0.0-rc.1 | | |
| ernestdefoe-calendar | 2.0.3 | | |
+------------------------------+---------------+------------------------------------------+-------+
Base URL: https://xxxxx
Installation path: /home/user/test/public
Queue driver: sync
Session driver: file
Scheduler status: Active
Mail driver: null
Debug mode: ON

Don't forget to turn off debug mode! It should never be turned on in a production system.

Possible Solution

No response

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions