# BWD local patch to the vendored Freemius SDK

**Applied:** 2026-07-22 · **Base SDK:** Freemius WordPress SDK 2.13.4 (byte-identical
to upstream `master` @ `fa43eb9` at time of patching) · **Marker after patch:** `2.13.5`

## Why

On PHP 8 + WordPress multisite, activating a Freemius plugin as a **network admin**
took the network opt-in path (`fs_is_network_admin()` → `setup_network_account` →
`_store_account` → `_store_plans`) with `$this->_plans` still `false`. The SDK then
called `count( $this->_plans )` **unguarded**, which is a fatal `TypeError` on PHP 8
(`count(): Argument #1 must be of type Countable|array, bool given`). This took down
admin pages and, on some sites, the front end.

The bug is present in the latest Freemius code — the 2.13.4 tag **and** `master`/
`develop` (verified by diff: our vendored copy is byte-identical to upstream master,
and the crash line is unchanged there). Freemius already guards `$this->_plans` with
`is_array()` in ~5 other places in the same file, but **not** on these lines. There is
no upstream release to update to, so this is patched locally until Freemius ships a fix.

## What changed

`includes/class-freemius.php` — every unguarded `count( $this->_plans )` now short-
circuits on a non-array, matching Freemius's own guard style elsewhere in the file
(`is_array( $this->_plans ) ? count( $this->_plans ) : 0`). Behaviour-preserving: when
`$this->_plans` is an array the result is identical; when it is `false`/`null` the loop
count is `0` instead of fataling. Guarded lines (original numbering): the four
`$len = count( $this->_plans )` loops (incl. `_store_plans`, the crash site ~19872) and
the two arithmetic counts (~12862, ~24072). The three `! is_array( … ) || 0 === count( … )`
short-circuit conditions were already safe and were left untouched.

`start.php` — `$this_sdk_version` nudged `2.13.4` → `2.13.5` so this fixed copy wins the
Freemius newest-wins loader over any unpatched `2.13.4` copy bundled by another plugin on
the same site (Freemius loads exactly one SDK per site).

## Upstream

Report/PR filed with Freemius (`Freemius/wordpress-sdk`). When an official release
contains the guard, **re-vendor the stock SDK verbatim** and delete this file — do not
carry the local patch forward once upstream is fixed.

## Re-applying after a re-vendor (if upstream still unfixed)

Guard every `count( $this->_plans )` that is NOT already inside a
`! is_array( $this->_plans ) || …` short-circuit, and bump `$this_sdk_version` above the
stock value.
