Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7202 from craftcms/feature/graphql-relation-argum…
- Loading branch information
Showing
24 changed files
with
1,029 additions
and
106 deletions.
There are no files selected for viewing
This file contains 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 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 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,24 @@ | ||
<?php | ||
/** | ||
* @link https://craftcms.com/ | ||
* @copyright Copyright (c) Pixel & Tonic, Inc. | ||
* @license https://craftcms.github.io/license/ | ||
*/ | ||
|
||
namespace craft\events; | ||
|
||
use yii\base\Event; | ||
|
||
/** | ||
* RegisterGqlArgumentHandlersEvent class. | ||
* | ||
* @author Pixel & Tonic, Inc. <support@pixelandtonic.com> | ||
* @since 3.6.0 | ||
*/ | ||
class RegisterGqlArgumentHandlersEvent extends Event | ||
{ | ||
/** | ||
* @var array[] List of Argument handler class names. | ||
*/ | ||
public $handlers = []; | ||
} |
This file contains 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,151 @@ | ||
<?php | ||
/** | ||
* @link https://craftcms.com/ | ||
* @copyright Copyright (c) Pixel & Tonic, Inc. | ||
* @license https://craftcms.github.io/license/ | ||
*/ | ||
|
||
namespace craft\gql; | ||
|
||
use Craft; | ||
use craft\base\Component; | ||
use craft\events\DefineGqlTypeFieldsEvent; | ||
use craft\events\RegisterGqlArgumentHandlersEvent; | ||
use craft\gql\base\ArgumentHandlerInterface; | ||
use craft\gql\handlers\RelatedAssets; | ||
use craft\gql\handlers\RelatedCategories; | ||
use craft\gql\handlers\RelatedEntries; | ||
use craft\gql\handlers\RelatedTags; | ||
use craft\gql\handlers\RelatedUsers; | ||
|
||
/** | ||
* Class ArgumentManager | ||
* | ||
* @author Pixel & Tonic, Inc. <support@pixelandtonic.com> | ||
* @since 3.6.0 | ||
*/ | ||
class ArgumentManager extends Component | ||
{ | ||
/** | ||
* @event RegisterGqlArgumentHandlers The event that is triggered when GraphQL argument are being handled. | ||
* | ||
* Plugins can use this event to add, remove or modify arguments on a given GraphQL type. | ||
* | ||
* --- | ||
* ```php | ||
* use craft\events\RegisterGqlArgumentHandlers; | ||
* use craft\gql\ArgumentManager; | ||
* use my/namespace/gql/handlers/RedirectHandler | ||
* use yii\base\Event; | ||
* | ||
* Event::on(ArgumentManager::class, ArgumentManager::EVENT_DEFINE_GQL_ARGUMENT_HANDLERS, function(RegisterGqlArgumentHandlersEvent $event) { | ||
* // Register a handler that works on the `redirect` argument. | ||
* $event->handlers['redirect'] = RedirectHandler::class; | ||
* }; | ||
* }); | ||
* ``` | ||
*/ | ||
const EVENT_DEFINE_GQL_ARGUMENT_HANDLERS = 'defineGqlArgumentHandlers'; | ||
|
||
private $_argumentHandlers = []; | ||
|
||
private $_handlersCreated = false; | ||
|
||
public function init() | ||
{ | ||
$handlers = [ | ||
'relatedToEntries' => RelatedEntries::class, | ||
'relatedToAssets' => RelatedAssets::class, | ||
'relatedToCategories' => RelatedCategories::class, | ||
'relatedToTags' => RelatedTags::class, | ||
'relatedToUsers' => RelatedUsers::class, | ||
]; | ||
|
||
$event= new RegisterGqlArgumentHandlersEvent([ | ||
'handlers' => $handlers | ||
]); | ||
|
||
$this->trigger(self::EVENT_DEFINE_GQL_ARGUMENT_HANDLERS, $event); | ||
|
||
$this->_argumentHandlers = $event->handlers; | ||
} | ||
|
||
/** | ||
* Create all the handlers, if class names were provided. | ||
*/ | ||
protected function createHandlers(): void | ||
{ | ||
if ($this->_handlersCreated) { | ||
return; | ||
} | ||
|
||
foreach ($this->_argumentHandlers as &$handler) { | ||
// Instantiate in place, if a class name is added. | ||
if (is_string($handler)) { | ||
$handler = $this->createHandler($handler); | ||
} | ||
} | ||
|
||
unset($handler); | ||
$this->_handlersCreated = true; | ||
} | ||
|
||
/** | ||
* Set the argument handler for an argument name. | ||
* | ||
* @param string $argumentName | ||
* @param string|ArgumentHandlerInterface $handler | ||
*/ | ||
public function setHandler(string $argumentName, $handler): void | ||
{ | ||
if (is_string($handler)) { | ||
$handler = $this->createHandler($handler); | ||
} | ||
|
||
$this->_argumentHandlers[$argumentName] = $handler; | ||
} | ||
|
||
/** | ||
* Prepare GraphQL arguments according to the registered argument handlers. | ||
* | ||
* @param $arguments | ||
* @return array | ||
* @throws \yii\base\InvalidConfigException | ||
*/ | ||
public function prepareArguments($arguments): array { | ||
$this->createHandlers(); | ||
|
||
// TODO remove in Craft 4.1 | ||
if (isset($arguments['relatedToAll'])) { | ||
Craft::$app->getDeprecator()->log('graphql.arguments.relatedToAll', 'The `relatedToAll` argument has been deprecated. Use the `relatedTo` argument with the `["and", ...ids]` syntax instead.'); | ||
$ids = (array)$arguments['relatedToAll']; | ||
$ids = array_map(function($value) { | ||
return ['element' => $value]; | ||
}, $ids); | ||
$arguments['relatedTo'] = array_merge(['and'], $ids); | ||
unset($arguments['relatedToAll']); | ||
} | ||
|
||
foreach ($this->_argumentHandlers as $argumentName => $handler) { | ||
if (!empty($arguments[$argumentName]) && $handler instanceof ArgumentHandlerInterface) { | ||
$arguments = $handler->handleArgumentCollection($arguments); | ||
} | ||
} | ||
|
||
return $arguments; | ||
} | ||
|
||
/** | ||
* @param string $handler | ||
* @return ArgumentHandlerInterface|string | ||
*/ | ||
protected function createHandler(string $handler) | ||
{ | ||
if (is_a($handler, ArgumentHandlerInterface::class, true)) { | ||
/** @var ArgumentHandlerInterface $handler */ | ||
$handler = new $handler(); | ||
$handler->setArgumentManager($this); | ||
} | ||
return $handler; | ||
} | ||
} |
This file contains 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 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,50 @@ | ||
<?php | ||
/** | ||
* @link https://craftcms.com/ | ||
* @copyright Copyright (c) Pixel & Tonic, Inc. | ||
* @license https://craftcms.github.io/license/ | ||
*/ | ||
|
||
namespace craft\gql\base; | ||
|
||
|
||
use craft\gql\ArgumentManager; | ||
|
||
/** | ||
* Class ArgumentHandler | ||
* | ||
* @author Pixel & Tonic, Inc. <support@pixelandtonic.com> | ||
* @since 3.6.0 | ||
*/ | ||
abstract class ArgumentHandler implements ArgumentHandlerInterface | ||
{ | ||
/** @var ArgumentManager */ | ||
protected $argumentManager; | ||
|
||
/** @var string */ | ||
protected $argumentName; | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function setArgumentManager(ArgumentManager $argumentManager): void { | ||
$this->argumentManager = $argumentManager; | ||
} | ||
|
||
/** | ||
* Handle a single argument value | ||
* @param $argumentValue | ||
* @return mixed | ||
*/ | ||
abstract protected function handleArgument($argumentValue); | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function handleArgumentCollection(array $argumentList = []): array | ||
{ | ||
$argumentList[$this->argumentName] = $this->handleArgument($this->argumentName); | ||
|
||
return $argumentList; | ||
} | ||
} |
This file contains 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,35 @@ | ||
<?php | ||
/** | ||
* @link https://craftcms.com/ | ||
* @copyright Copyright (c) Pixel & Tonic, Inc. | ||
* @license https://craftcms.github.io/license/ | ||
*/ | ||
|
||
namespace craft\gql\base; | ||
|
||
|
||
use craft\gql\ArgumentManager; | ||
|
||
/** | ||
* Class ArgumentHandlerInterface | ||
* | ||
* @author Pixel & Tonic, Inc. <support@pixelandtonic.com> | ||
* @since 3.6.0 | ||
*/ | ||
interface ArgumentHandlerInterface | ||
{ | ||
/** | ||
* Handle an argument collection | ||
* | ||
* @param array $argumentList argument list to be used for the query | ||
* @return mixed | ||
*/ | ||
public function handleArgumentCollection(array $argumentList = []): array; | ||
|
||
/** | ||
* Set the current argument manager. Required for recursive argument preparation. | ||
* | ||
* @param ArgumentManager $argumentManager | ||
*/ | ||
public function setArgumentManager(ArgumentManager $argumentManager): void; | ||
} |
Oops, something went wrong.