Skip to content

fix: repair site_admins after enabling multisite - #2512

Merged
chubes4 merged 2 commits into
mainfrom
fix/multisite-site-admins-seed
Sep 17, 2026
Merged

chubes4 merged 2 commits into
mainfrom
fix/multisite-site-admins-seed

Conversation

@chubes4

@chubes4 chubes4 commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

Fixes #2511.

Problem

Playground's enableMultisite step leaves site_admins as an empty string rather than the array( $admin_login ) core's populate_network() writes. Probed from inside the PHPUnit sandbox:

sitemeta: [
  {"meta_key":"admin_email",   "meta_value":"admin@example.org"},
  {"meta_key":"admin_user_id", "meta_value":"1"},
  {"meta_key":"site_admins",   "meta_value":""}
]
users: ["admin"]

The install only partially succeeds — admin_user_id and admin_email are correct and the user exists.

Why an empty value is worse than a missing one

Core falls back to a sane default only when the option is absent:

return get_site_option( 'site_admins', array( 'admin' ) );

Because the row exists as '', the default never applies. The empty string reaches in_array():

TypeError: in_array(): Argument #2 ($haystack) must be of type array, string given
  at wp-includes/capabilities.php

This fatals is_super_admin(), grant_super_admin(), revoke_super_admin() and every manage_network_* capability check — so any multisite suite touching network capabilities dies inside core rather than failing usefully, which reads as harness breakage.

Fix

A runPHP repair immediately after enableMultisite, mirroring the existing enableMultisite + runPHP pattern already used in site-seed-multisite.ts.

Idempotent and conservative:

  • writes only when the value is not already a non-empty array
  • derives the login from admin_user_id rather than assuming 'admin', falling back to the lowest-ID user
  • single-site recipes unchanged

Tests

tests/playground-multisite-site-admins.test.ts asserts the repair step exists, runs after enableMultisite, guards on is_array, derives from admin_user_id, and that single-site recipes carry no multisite steps.

Existing playground-runtime-multisite and site-seed-multisite suites pass; npm run build clean.

Found via

Extra-Chill/extrachill-network PR #217, which worked around it by setting \$GLOBALS['super_admins'] in the affected test. That workaround can be removed once this ships.

Playground's enableMultisite step leaves site_admins as an empty string
rather than the array( $admin_login ) core's populate_network() writes.
admin_user_id and admin_email come out correct, so the network install only
partially succeeds.

An empty value is worse than a missing one. Core falls back to a sane
default only when the option is absent:

    get_site_option( 'site_admins', array( 'admin' ) )

Because the row exists as '', the default never applies and the empty string
reaches in_array():

    TypeError: in_array(): Argument #2 ($haystack) must be of type array,
    string given (wp-includes/capabilities.php)

That fatals is_super_admin(), grant_super_admin() and every manage_network_*
capability check, so any multisite suite touching network capabilities dies
inside core instead of failing usefully. Observed while getting
Extra-Chill/extrachill-network onto the managed harness; sitemeta showed
admin_user_id=1 and user 'admin' present alongside site_admins=''.

Adds a runPHP repair immediately after enableMultisite, mirroring the
existing enableMultisite + runPHP pattern in site-seed-multisite.ts. It is
idempotent and conservative: writes only when the value is not already a
non-empty array, and derives the login from admin_user_id rather than
assuming 'admin', falling back to the lowest-ID user.

Single-site recipes are unchanged.
The existing deepEqual asserted the exact two-step blueprint and so failed
once the repair step was inserted. Rewritten to assert the contract rather
than the literal array: enableMultisite first, the site_admins repair
immediately after, and caller-supplied steps preserved in order behind
them.
@chubes4
chubes4 merged commit 97baad7 into main Sep 17, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multisite sandbox seeds site_admins as an empty string, fatalling core capability checks

1 participant