diff --git a/docs/Autoloading.md b/docs/Autoloading.md index af8b51c..0b7038d 100644 --- a/docs/Autoloading.md +++ b/docs/Autoloading.md @@ -82,7 +82,7 @@ Environment caching: - Discovery results are cached only in production and staging environments (per `wp_get_environment_type()`). - Cache is stored under the directory you pass to `init_classes()`, in a "class-loader-cache" folder (e.g., `YOUR_PLUGIN_INC . 'class-loader-cache'`). - To refresh: delete that folder; it will be rebuilt automatically. -- Caching is skipped entirely when the constant `VIP_GO_APP_ENVIRONMENT` is defined. +- Caching is skipped entirely when the constant `VIP_GO_APP_ENVIRONMENT` is defined or when `TENUP_FRAMEWORK_DISABLE_CLASS_CACHE` is set to `true`. Use `define( 'TENUP_FRAMEWORK_DISABLE_CLASS_CACHE', true )` in environments that don't support writable file systems. ## Defining a Module ```php diff --git a/docs/Modules-and-Initialization.md b/docs/Modules-and-Initialization.md index 490e85e..e00a34d 100644 --- a/docs/Modules-and-Initialization.md +++ b/docs/Modules-and-Initialization.md @@ -40,6 +40,7 @@ Environment cache behavior - When it’s used: only in `production` and `staging` environment types (`wp_get_environment_type()`). - How to clear: delete the `class-loader-cache` folder; it will be rebuilt on next discovery. - How to disable in development: use `development` or `local` environment types, or define `VIP_GO_APP_ENVIRONMENT` to skip the cache. +- How to disable for hosts that don't support file-based caching: `define( 'TENUP_FRAMEWORK_DISABLE_CLASS_CACHE', true );` to skip caching altogether. Hooks - Action: `tenup_framework_module_init__{slug}` — fires before each module’s `register()` runs. diff --git a/src/ModuleInitialization.php b/src/ModuleInitialization.php index 5c53d4b..0b4d9e3 100644 --- a/src/ModuleInitialization.php +++ b/src/ModuleInitialization.php @@ -70,7 +70,7 @@ public function get_classes( $dir ) { $class_finder->classes(); // If we are in production or staging, cache the class loader to improve performance. - if ( ! defined( 'VIP_GO_APP_ENVIRONMENT' ) && in_array( wp_get_environment_type(), [ 'production', 'staging' ], true ) ) { + if ( $this->should_use_cache() ) { $class_finder->withCache( __NAMESPACE__, new FileDiscoverCacheDriver( $dir . '/class-loader-cache' ) @@ -83,6 +83,27 @@ public function get_classes( $dir ) { return $classes; } + /** + * Should we set up and use the class cache? + * + * @return bool + */ + protected function should_use_cache(): bool { + if ( defined( 'VIP_GO_APP_ENVIRONMENT' ) ) { + return false; + } + + if ( ! in_array( wp_get_environment_type(), [ 'production', 'staging' ], true ) ) { + return false; + } + + if ( defined( 'TENUP_FRAMEWORK_DISABLE_CLASS_CACHE' ) && true === TENUP_FRAMEWORK_DISABLE_CLASS_CACHE ) { + return false; + } + + return true; + } + /** * Check if the directory exists. * diff --git a/tests/ModuleInitializationTest.php b/tests/ModuleInitializationTest.php index ccf13db..2984b67 100644 --- a/tests/ModuleInitializationTest.php +++ b/tests/ModuleInitializationTest.php @@ -10,6 +10,7 @@ namespace TenupFrameworkTests; use PHPUnit\Framework\TestCase; +use function Brain\Monkey\Functions\stubs; /** * Test Class @@ -147,4 +148,75 @@ public function testIsClassFullyLoadable() { $this->assertInstanceOf( 'ReflectionClass', $module_init->get_fully_loadable_class( '\TenupFrameworkTestClasses\Loadable\ChildClass' ) ); $this->assertFalse( $module_init->get_fully_loadable_class( '\TenupFrameworkTestClasses\Loadable\InvalidChildClass' ) ); } + + + /** + * Ensure it returns false if VIP_GO_APP_ENVIRONMENT is defined. + * + * @return void + */ + public function test_should_use_cache_returns_false_when_vip_env_is_defined() { + define( 'VIP_GO_APP_ENVIRONMENT', true ); + $module_init = \TenupFramework\ModuleInitialization::instance(); + $reflection = new \ReflectionClass( $module_init ); + $method = $reflection->getMethod( 'should_use_cache' ); + $method->setAccessible( true ); + + $this->assertFalse( $method->invoke( $module_init ) ); + } + + /** + * Ensure it returns false in non-production or staging environments. + * + * @return void + */ + public function test_should_use_cache_returns_false_in_non_production_or_staging_env() { + stubs( + [ + 'wp_get_environment_type' => 'development', + ] + ); + + $module_init = \TenupFramework\ModuleInitialization::instance(); + $reflection = new \ReflectionClass( $module_init ); + $method = $reflection->getMethod( 'should_use_cache' ); + $method->setAccessible( true ); + + $this->assertFalse( $method->invoke( $module_init ) ); + } + + /** + * Ensure it returns false when TENUP_FRAMEWORK_DISABLE_CLASS_CACHE is defined. + * + * @return void + */ + public function test_should_use_cache_returns_false_when_disable_class_cache_is_defined() { + define( 'TENUP_FRAMEWORK_DISABLE_CLASS_CACHE', true ); + $module_init = \TenupFramework\ModuleInitialization::instance(); + $reflection = new \ReflectionClass( $module_init ); + $method = $reflection->getMethod( 'should_use_cache' ); + $method->setAccessible( true ); + + $this->assertFalse( $method->invoke( $module_init ) ); + } + + /** + * Ensure it returns true under default conditions. + * + * @return void + */ + public function test_should_use_cache_returns_true_under_default_conditions() { + stubs( + [ + 'wp_get_environment_type' => 'production', + ] + ); + + $module_init = \TenupFramework\ModuleInitialization::instance(); + $reflection = new \ReflectionClass( $module_init ); + $method = $reflection->getMethod( 'should_use_cache' ); + $method->setAccessible( true ); + + $this->assertTrue( $method->invoke( $module_init ) ); + } }