Repository navigation
Framework: Store one Factory instance per subclass - #624
jonathanbossenger merged 3 commits into
Conversation
`Framework\Factory::get_instance()` stored the instance in `self::$instance` on the abstract base class, so every factory subclass returned whichever factory was created first. Store instances in a `static::$instances` map keyed by `static::class`, fix the `get_instance()` return type in the docblock, and add unit tests. Fixes WordPress#613.
|
@huzaifaalmesbah I wanted to check in to see what you thought of the suggestions. If you feel comfortable to leave them as is, just comment here. Thanks |
|
Thanks for checking in, @jonathanbossenger! I can't see any review comments or suggestions on this PR on my side. Could they still be in a pending review that wasn't submitted? Or did you mean the suggestion on #627? I've added that one now. Happy to look at any suggestions for this PR once I can see them. |
| if ( ! isset( static::$instances[ static::class ] ) ) { | ||
| static::$instances[ static::class ] = new static(); | ||
| } | ||
|
|
||
| return self::$instance; | ||
| return static::$instances[ static::class ]; |
There was a problem hiding this comment.
Optional: What do you think about using self::$instances here (and on the next two lines) instead of static::$instances? The array key would still be static::class.
The fix works as written. The difference only shows up if a subclass ever declares its own $instances property. With static::, that subclass would then store its instance in its own separate array, not in the shared one on Factory. With self::, all instances always live in one array on the base class, whatever the subclasses do.
if ( ! isset( self::$instances[ static::class ] ) ) {
self::$instances[ static::class ] = new static();
}
return self::$instances[ static::class ];There was a problem hiding this comment.
Good point, done in 5a9df29. All instances now live in self::$instances on Factory, still keyed by static::class.
|
@huzaifaalmesbah I am so sorry; they were indeed sitting in draft. I've submitted them now. The PR is approved, and the comments are optional, so let me know if you think they are worth updating or not, and then we'll can get this merged. |
Use self::$instances so every instance stays in the one array on Factory, even if a subclass declares its own $instances property. Also check Factory\Subscription in the singleton test.
|
Thanks @jonathanbossenger, no worries! I applied both suggestions in 5a9df29. Tests: 66 tests, 0 failures on single site and multisite. PHPCS is clean. Ready to merge from my side. |
What?
Fixes
Framework\Factory::get_instance()so each factory subclass gets its own instance instead of all subclasses sharing one.Closes #613. Part of #302.
Why?
get_instance()stored the instance inself::$instanceon the abstract base class. Whichever factory was called first set that property, and every other factory then got the same object back:A notification query loads both models (
messages JOIN queue), so callingmake()on the wrong factory would produce the wrong model. Nothing callsget_instance()on the factories yet, but this blocks #307.How?
protected static $instance = nullwithprotected static $instances = array(), keyed bystatic::class, so each subclass stores and returns its own instance.get_instance()docblock, which said it returnsModel. It returns the factory (static).tests/phpunit/tests/framework/test-factory.php, which checks that:get_instance()returns an instance of that factory's classMessage,NotificationandSubscriptionnever return the same objectTesting Instructions
npx wp-env startnpx wp-env run tests-cli --env-cwd=wp-content/plugins/wp-feature-notifications vendor/bin/phpunitnpx wp-env run tests-cli --env-cwd=wp-content/plugins/wp-feature-notifications env WP_MULTISITE=1 vendor/bin/phpunitnpx wp-env run tests-cli --env-cwd=wp-content/plugins/wp-feature-notifications vendor/bin/phpunit --filter Test_Framework_FactoryLocal results: 65 tests, 0 failures on single site and multisite (the 24 skipped are the existing REST controller placeholder tests).
composer lintis clean.Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: Drafting the fix and unit tests. I chose the approach from the issue, reviewed every change, and verified it locally with PHPUnit (single site and multisite) and PHPCS.