fix(wpmc 1.0.1): guard ACF helpers with did_action('acf/init')

Add private Helpers::acf_ready() that checks did_action('acf/init') > 0,
then guard the five ACF-dependent methods (alt_get_field, index_town_alt_page_id,
main_town_slug, page_unic_swap, is_routable_path) so they return safe defaults
(null/true) before ACF initialises. Fixes the acf_get_value "called too early"
notice triggered when home_url filter fires before acf/init.

Update existing tests in HelpersTest, LinkFilterTest, RedirectTest, RouterTest
to stub did_action => 1 where ACF-ready behaviour is expected. Add four new
guard tests covering before/after acf/init for main_town_slug and is_routable_path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Vladimir Bryzgalov
2026-05-17 17:01:19 +05:00
parent 949fb19e95
commit 82d2345d12
5 changed files with 105 additions and 0 deletions
+69
View File
@@ -133,6 +133,7 @@ final class HelpersTest extends TestCase
public function test_alt_get_field_applies_do_shortcode_to_string_values(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
// expect() must come before when('function_exists') so Brain Monkey's
// FunctionStub::__construct can eval-define get_field() before the shim
// fakes function_exists('get_field') === true.
@@ -153,6 +154,7 @@ final class HelpersTest extends TestCase
public function test_alt_get_field_returns_arrays_as_is(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
// expect() before when('function_exists') to avoid FunctionStub seeing
// the shim and skipping the eval-declaration of get_field.
// do_shortcode is intentionally NOT registered: if the implementation
@@ -167,6 +169,7 @@ final class HelpersTest extends TestCase
public function test_alt_get_field_post_id_filter_overrides_caller_id(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('get_field')
->once()
->with('title', 99, true)
@@ -207,13 +210,27 @@ final class HelpersTest extends TestCase
self::assertTrue(function_exists('wpmc_get_term_by_slug'));
self::assertTrue(function_exists('wpmc_alt_get_field'));
self::assertTrue(function_exists('wpmc_remove_domain_link'));
self::assertTrue(function_exists('wpmc_main_town_slug'));
// remove_domain_link is pure (no WP function dependencies) — exercise the proxy.
self::assertSame('/foo/', wpmc_remove_domain_link('https://site.com/foo/'));
}
public function test_wpmc_main_town_slug_delegates_to_helpers(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('get_field')
->once()
->with('main_town_slug', 'option')
->andReturn('spb');
require_once dirname(__DIR__) . '/includes/wpmc-functions.php';
self::assertSame('spb', wpmc_main_town_slug());
}
public function test_main_town_slug_reads_option_via_acf(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('get_field')
->once()
->with('main_town_slug', 'option')
@@ -224,6 +241,7 @@ final class HelpersTest extends TestCase
public function test_main_town_slug_returns_null_when_option_empty(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('get_field')
->once()
->with('main_town_slug', 'option')
@@ -234,6 +252,7 @@ final class HelpersTest extends TestCase
public function test_is_routable_path_returns_true_when_no_exclusions(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('get_field')
->once()
->with('page_no_rep', 'option')
@@ -244,6 +263,7 @@ final class HelpersTest extends TestCase
public function test_is_routable_path_returns_false_when_path_matches_exclusion(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('get_field')
->once()
->with('page_no_rep', 'option')
@@ -257,6 +277,7 @@ final class HelpersTest extends TestCase
public function test_is_routable_path_uses_request_uri_when_path_null(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
$_SERVER['REQUEST_URI'] = '/terms/';
\Brain\Monkey\Functions\expect('get_field')
->once()
@@ -268,6 +289,7 @@ final class HelpersTest extends TestCase
public function test_page_unic_swap_returns_clone_id_when_row_matches(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
$term = new \WP_Term();
$term->term_id = 11;
$term->slug = 'tyumen';
@@ -285,6 +307,7 @@ final class HelpersTest extends TestCase
public function test_page_unic_swap_returns_null_when_no_row_matches(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
$term = new \WP_Term();
$term->term_id = 11;
$term->slug = 'tyumen';
@@ -298,6 +321,7 @@ final class HelpersTest extends TestCase
public function test_page_unic_swap_caches_within_request(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
$term = new \WP_Term();
$term->term_id = 11;
\Brain\Monkey\Functions\when('get_term_by')->justReturn($term);
@@ -314,6 +338,7 @@ final class HelpersTest extends TestCase
public function test_index_town_alt_page_id_returns_int_when_option_set(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('get_field')
->once()
->with('index_town_alt', 'option')
@@ -324,6 +349,7 @@ final class HelpersTest extends TestCase
public function test_index_town_alt_page_id_returns_null_when_zero(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('get_field')
->once()
->with('index_town_alt', 'option')
@@ -334,6 +360,7 @@ final class HelpersTest extends TestCase
public function test_reset_cache_clears_page_unic_cache(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
$term = new \WP_Term();
$term->term_id = 11;
\Brain\Monkey\Functions\when('get_term_by')->justReturn($term);
@@ -348,6 +375,48 @@ final class HelpersTest extends TestCase
self::assertTrue(true);
}
public function test_main_town_slug_returns_null_before_acf_init(): void
{
\Brain\Monkey\Functions\expect('did_action')
->with('acf/init')
->andReturn(0);
// get_field should NOT be called — no expectation means Brain Monkey throws if it is.
self::assertNull(Helpers::main_town_slug());
}
public function test_main_town_slug_calls_get_field_after_acf_init(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('get_field')
->once()
->with('main_town_slug', 'option')
->andReturn('spb');
self::assertSame('spb', Helpers::main_town_slug());
}
public function test_is_routable_path_returns_true_before_acf_init(): void
{
\Brain\Monkey\Functions\expect('did_action')
->with('acf/init')
->andReturn(0);
// get_field should NOT be called.
self::assertTrue(Helpers::is_routable_path('/some/path/'));
}
public function test_is_routable_path_checks_exclusions_after_acf_init(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('get_field')
->once()
->with('page_no_rep', 'option')
->andReturn([['link' => '/excluded/']]);
self::assertFalse(Helpers::is_routable_path('/excluded/page/'));
}
public function test_is_bypassed_returns_false_by_default(): void
{
self::assertFalse(Helpers::is_bypassed());
+3
View File
@@ -44,6 +44,7 @@ final class LinkFilterTest extends TestCase
{
$_SERVER['REQUEST_URI'] = '/' . $town_slug . '/';
$_SERVER['HTTP_HOST'] = $host;
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\when('get_terms')->justReturn([11 => $town_slug]);
\Brain\Monkey\Functions\when('get_field')->alias(function ($name) use ($main) {
if ($name === 'main_town_slug') return $main;
@@ -62,6 +63,7 @@ final class LinkFilterTest extends TestCase
{
$_SERVER['REQUEST_URI'] = '/random/';
$_SERVER['HTTP_HOST'] = 'site.com';
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\when('get_terms')->justReturn([10 => 'spb']);
\Brain\Monkey\Functions\when('get_field')->justReturn(false);
@@ -129,6 +131,7 @@ final class LinkFilterTest extends TestCase
{
$_SERVER['REQUEST_URI'] = '/tyumen/';
$_SERVER['HTTP_HOST'] = 'site.com';
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\when('get_terms')->justReturn([11 => 'tyumen']);
\Brain\Monkey\Functions\when('get_field')->alias(function ($name) {
if ($name === 'main_town_slug') return 'spb';
+4
View File
@@ -20,6 +20,7 @@ final class RedirectTest extends TestCase
public function test_handle_skips_when_current_town_equals_main(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('wp_safe_redirect')->never();
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/spb/about/';
@@ -36,6 +37,7 @@ final class RedirectTest extends TestCase
public function test_handle_skips_when_post_not_set(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('wp_safe_redirect')->never();
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/about/';
@@ -53,6 +55,7 @@ final class RedirectTest extends TestCase
public function test_handle_skips_when_url_already_has_town_prefix(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('wp_safe_redirect')->never();
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/tyumen/about/';
@@ -70,6 +73,7 @@ final class RedirectTest extends TestCase
public function test_handle_redirects_when_post_is_page_unic_clone_without_prefix(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/about/';
\Brain\Monkey\Functions\when('get_terms')->justReturn([11 => 'tyumen']);
+9
View File
@@ -48,6 +48,7 @@ final class RouterTest extends TestCase
public function test_route_skips_when_current_town_is_null(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('url_to_postid')->never();
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/something-not-a-city/';
@@ -61,6 +62,7 @@ final class RouterTest extends TestCase
public function test_route_skips_when_current_town_equals_main_town(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('url_to_postid')->never();
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/spb/';
@@ -77,6 +79,7 @@ final class RouterTest extends TestCase
public function test_route_skips_when_path_not_routable(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('url_to_postid')->never();
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/tyumen/privacy/';
@@ -94,6 +97,7 @@ final class RouterTest extends TestCase
public function test_route_uses_main_page_alt_term_meta_for_root_url(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/tyumen/';
\Brain\Monkey\Functions\when('get_terms')->justReturn([11 => 'tyumen']);
@@ -123,6 +127,7 @@ final class RouterTest extends TestCase
public function test_route_falls_back_to_index_town_alt_option(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/tyumen/';
\Brain\Monkey\Functions\when('get_terms')->justReturn([11 => 'tyumen']);
@@ -148,6 +153,7 @@ final class RouterTest extends TestCase
public function test_route_does_not_install_query_when_neither_main_nor_fallback_set(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('get_post')->never();
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/tyumen/';
@@ -169,6 +175,7 @@ final class RouterTest extends TestCase
public function test_route_resolves_internal_page_via_url_to_postid(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/tyumen/about/';
\Brain\Monkey\Functions\when('get_terms')->justReturn([11 => 'tyumen']);
@@ -193,6 +200,7 @@ final class RouterTest extends TestCase
public function test_route_applies_page_unic_swap_when_clone_exists(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/tyumen/about/';
\Brain\Monkey\Functions\when('get_terms')->justReturn([11 => 'tyumen']);
@@ -220,6 +228,7 @@ final class RouterTest extends TestCase
public function test_route_does_not_install_query_when_url_to_postid_returns_zero(): void
{
\Brain\Monkey\Functions\stubs(['did_action' => 1]);
\Brain\Monkey\Functions\expect('get_post')->never();
\Brain\Monkey\Functions\when('is_admin')->justReturn(false);
$_SERVER['REQUEST_URI'] = '/tyumen/unknown/';