-
Notifications
You must be signed in to change notification settings - Fork 21
Increase template controller DI support #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
784715d
Implement native dependency injection for template controllers
8ad3e00
Refine template controller DI and add comprehensive test suite
659057c
Apply phpcs fixes
c4cc725
Optimize DI resolvers and clean up service provider following review
352ad2d
Optimize DI resolvers and clean up service provider following Orbit r…
9e9721a
Refactor DI system to Template Method pattern and consolidate tests
ddcd3de
Refactor DI system to Template Method pattern and consolidate tests
2a261fc
Address final review suggestions for DI refactor
b1a96e1
Merge branch 'feature/template-controller-di' of github.com:Rareloop/…
accad99
Re-add comment
54b92b1
Move core resolvers
6a9a14f
Build controllers with DI
4cdf339
Ensure that Timber context has array access methods
63d2560
Add static class resolution parity for Term and User proxy objects
fbe44c0
Simplify if statements
bff4f3b
Remove unused import
9c27db8
Remove from gitignore
344e757
Remove reflection
d9ee4c7
Revert controller change
16158d5
Remove TimberResponse Bind
f24b6e7
Add `isValidContext` methods
c1a77e4
Remove ControllerTest
be3ebbb
Update Timber import
fbf376c
Change getCoreResolvers visibility
ec23d81
Remove toCollection from PostQuery
1858617
Apply fixes from comments
e1bf2ef
Remove PostTypeResolver
b234850
Remove unused import
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| <?php | ||
|
|
||
| namespace Rareloop\Lumberjack\Exceptions; | ||
|
|
||
| class MismatchedContextException extends UnresolvableContextException | ||
| { | ||
| public static function forIncorrectClass(string $expectedClass, mixed $actualValue): self | ||
| { | ||
| $actualType = is_object($actualValue) ? $actualValue::class : gettype($actualValue); | ||
|
|
||
| return new static( | ||
| "Resolved a WordPress object, but it was of type [{$actualType}] " . | ||
| "instead of the expected [{$expectedClass}]." | ||
| ); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| <?php | ||
|
|
||
| namespace Rareloop\Lumberjack\Exceptions; | ||
|
|
||
| class MissingContextException extends UnresolvableContextException | ||
| { | ||
| public static function forType(string $expectedClass, mixed $actualObject): self | ||
| { | ||
| $actualType = get_debug_type($actualObject); | ||
|
|
||
| return new static( | ||
| "Could not resolve context for typehint [{$expectedClass}]. " . | ||
| "The current WordPress queried object is [{$actualType}]." | ||
| ); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| <?php | ||
|
|
||
| namespace Rareloop\Lumberjack\Exceptions; | ||
|
|
||
| use Exception; | ||
|
|
||
| class UnresolvableContextException extends Exception | ||
| { | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| <?php | ||
|
|
||
| namespace Rareloop\Lumberjack\Http\Resolvers; | ||
|
|
||
| use Illuminate\Support\Arr; | ||
| use Invoker\ParameterResolver\ParameterResolver; | ||
| use Rareloop\Lumberjack\Exceptions\MismatchedContextException; | ||
| use Rareloop\Lumberjack\Exceptions\MissingContextException; | ||
| use ReflectionFunctionAbstract; | ||
|
|
||
| abstract class AbstractContextResolver implements ParameterResolver | ||
| { | ||
| public function getParameters( | ||
| ReflectionFunctionAbstract $reflection, | ||
| array $providedParameters, | ||
| array $resolvedParameters | ||
| ): array { | ||
| foreach ($reflection->getParameters() as $parameter) { | ||
| if (Arr::has($resolvedParameters, $parameter->getPosition())) { | ||
| continue; | ||
| } | ||
|
|
||
| $type = $parameter->getType(); | ||
|
|
||
| if (!$type || $type->isBuiltin()) { | ||
| continue; | ||
| } | ||
|
|
||
| $className = $type->getName(); | ||
|
|
||
| if (!$this->canResolveClass($className)) { | ||
| continue; | ||
| } | ||
|
|
||
| try { | ||
| $context = $this->getContext(); | ||
|
|
||
| if (is_null($context)) { | ||
| throw MissingContextException::forType($className, $context); | ||
| } | ||
|
|
||
| if (!$this->isValidContext($context, $className)) { | ||
| throw MismatchedContextException::forIncorrectClass($className, $context); | ||
| } | ||
|
|
||
| $resolvedObject = $this->resolveObject($className, $context); | ||
|
|
||
| if (!is_null($resolvedObject) && !$resolvedObject instanceof $className) { | ||
| throw MismatchedContextException::forIncorrectClass($className, $resolvedObject); | ||
| } | ||
|
|
||
| $resolvedParameters[$parameter->getPosition()] = $resolvedObject; | ||
| } catch (MissingContextException | MismatchedContextException $e) { | ||
| // If the context is entirely missing or mismatched, we allow null if the typehint supports it | ||
| if (!$parameter->allowsNull()) { | ||
| throw $e; | ||
| } | ||
|
|
||
| $resolvedParameters[$parameter->getPosition()] = null; | ||
| } | ||
| } | ||
|
|
||
| return $resolvedParameters; | ||
| } | ||
|
|
||
| /** | ||
| * Get the raw context object to resolve from (e.g. WP_Post, WP_Term, WP_Query). | ||
| * Defaults to the current WordPress queried object. | ||
| * | ||
| * @return mixed | ||
| */ | ||
| protected function getContext(): mixed | ||
| { | ||
| return get_queried_object(); | ||
| } | ||
|
|
||
| /** | ||
| * Determine if this resolver can handle the given class type-hint. | ||
| * | ||
| * @param string $className | ||
| * @return bool | ||
| */ | ||
| abstract protected function canResolveClass(string $className): bool; | ||
|
|
||
| /** | ||
| * Determine if the current context is valid for this resolver. | ||
| * | ||
| * @param mixed $context | ||
| * @param string $className | ||
| * @return bool | ||
| */ | ||
| abstract protected function isValidContext(mixed $context, string $className): bool; | ||
|
|
||
| /** | ||
| * Build the concrete object instance from the raw context. | ||
| * | ||
| * @param string $className | ||
| * @param mixed $context | ||
| * @return mixed | ||
| */ | ||
| abstract protected function resolveObject(string $className, mixed $context): mixed; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| <?php | ||
|
|
||
| namespace Rareloop\Lumberjack\Http\Resolvers; | ||
|
|
||
| use Rareloop\Lumberjack\Application; | ||
| use Timber\PostQuery as TimberPostQuery; | ||
|
tommitchelmore marked this conversation as resolved.
|
||
| use Timber\PostCollectionInterface; | ||
| use Timber\Timber; | ||
| use WP_Query; | ||
|
|
||
| class PostQueryResolver extends AbstractContextResolver | ||
| { | ||
| public function __construct(protected Application $app) | ||
| { | ||
| } | ||
|
|
||
| protected function canResolveClass(string $className): bool | ||
| { | ||
| return is_a($className, TimberPostQuery::class, true) | ||
| || is_a($className, PostCollectionInterface::class, true); | ||
| } | ||
|
|
||
| protected function isValidContext(mixed $context, string $className): bool | ||
| { | ||
| return is_a($context, WP_Query::class); | ||
| } | ||
|
|
||
| protected function getContext(): mixed | ||
| { | ||
| return $this->app->get(WP_Query::class); | ||
| } | ||
|
|
||
| protected function resolveObject(string $className, mixed $context): mixed | ||
| { | ||
| // If they asked for the interface or the base Timber PostQuery, use the factory | ||
| if ($className === PostCollectionInterface::class || $className === TimberPostQuery::class) { | ||
| return Timber::get_posts($context); | ||
| } | ||
|
|
||
| // If it's a subclass (like Rareloop\Lumberjack\PostQuery), we must instantiate it manually | ||
| // to ensure we get the correct instance type. | ||
| return new $className($context); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <?php | ||
|
|
||
| namespace Rareloop\Lumberjack\Http\Resolvers; | ||
|
|
||
| use Rareloop\Lumberjack\Post; | ||
| use Timber\Post as TimberPost; | ||
| use Timber\Timber; | ||
| use Timber\CoreEntityInterface; | ||
| use WP_Post; | ||
|
|
||
| class PostResolver extends AbstractContextResolver | ||
| { | ||
| protected function canResolveClass(string $className): bool | ||
| { | ||
| return is_a($className, Post::class, true) | ||
| || is_a($className, TimberPost::class, true); | ||
| } | ||
|
|
||
| protected function isValidContext(mixed $context, string $className): bool | ||
| { | ||
| return is_a($context, WP_Post::class) || is_a($context, CoreEntityInterface::class); | ||
| } | ||
|
|
||
| protected function resolveObject(string $className, mixed $context): mixed | ||
| { | ||
| return Timber::get_post($context); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| <?php | ||
|
|
||
| namespace Rareloop\Lumberjack\Http\Resolvers; | ||
|
|
||
| use Rareloop\Lumberjack\Term; | ||
| use Timber\Term as TimberTerm; | ||
| use Timber\Timber; | ||
| use Timber\CoreEntityInterface; | ||
| use WP_Term; | ||
|
|
||
| class TermResolver extends AbstractContextResolver | ||
| { | ||
| protected function canResolveClass(string $className): bool | ||
| { | ||
| return is_a($className, Term::class, true) || is_a($className, TimberTerm::class, true); | ||
| } | ||
|
|
||
| protected function isValidContext(mixed $context, string $className): bool | ||
| { | ||
| return is_a($context, WP_Term::class) || is_a($context, CoreEntityInterface::class); | ||
| } | ||
|
|
||
| protected function resolveObject(string $className, mixed $context): mixed | ||
| { | ||
| return Timber::get_term($context); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| <?php | ||
|
|
||
| namespace Rareloop\Lumberjack\Http\Resolvers; | ||
|
|
||
| use Rareloop\Lumberjack\User; | ||
| use Timber\User as TimberUser; | ||
| use Timber\Timber; | ||
| use Timber\CoreEntityInterface; | ||
| use WP_User; | ||
|
|
||
| class UserResolver extends AbstractContextResolver | ||
| { | ||
| protected function canResolveClass(string $className): bool | ||
| { | ||
| return is_a($className, User::class, true) || is_a($className, TimberUser::class, true); | ||
| } | ||
|
|
||
| protected function isValidContext(mixed $context, string $className): bool | ||
| { | ||
| return is_a($context, WP_User::class) || is_a($context, CoreEntityInterface::class); | ||
| } | ||
|
|
||
| protected function resolveObject(string $className, mixed $context): mixed | ||
| { | ||
| return Timber::get_user($context); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.