mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
NEW: getByLink plugin allows arrays of links (#2666)
* NEW: getByLink plugin allows arrays of links * Allow configurable resolver * Remove unused exception tag * Refactor to preserve API backward compat * Unit test * Add plugin to readOne * Fix test * add new test
This commit is contained in:
parent
1794eee0ea
commit
f3a76ccf2d
@ -7,3 +7,7 @@ modelConfig:
|
||||
plugins:
|
||||
getByLink:
|
||||
after: filter
|
||||
readOne:
|
||||
plugins:
|
||||
getByLink:
|
||||
after: filter
|
||||
|
@ -12,6 +12,7 @@ use SilverStripe\GraphQL\Schema\Exception\SchemaBuilderException;
|
||||
use SilverStripe\GraphQL\Schema\Field\ModelQuery;
|
||||
use SilverStripe\GraphQL\Schema\Interfaces\ModelQueryPlugin;
|
||||
use SilverStripe\GraphQL\Schema\Schema;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\DataList;
|
||||
|
||||
if (!interface_exists(ModelQueryPlugin::class)) {
|
||||
@ -29,7 +30,18 @@ class LinkablePlugin implements ModelQueryPlugin
|
||||
* @var string
|
||||
* @config
|
||||
*/
|
||||
private static $field_name = 'link';
|
||||
private static $single_field_name = 'link';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @config
|
||||
*/
|
||||
private static $list_field_name = 'links';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $resolver = [__CLASS__, 'applyLinkFilter'];
|
||||
|
||||
/**
|
||||
* @return string
|
||||
@ -43,7 +55,6 @@ class LinkablePlugin implements ModelQueryPlugin
|
||||
* @param ModelQuery $query
|
||||
* @param Schema $schema
|
||||
* @param array $config
|
||||
* @throws SchemaBuilderException
|
||||
*/
|
||||
public function apply(ModelQuery $query, Schema $schema, array $config = []): void
|
||||
{
|
||||
@ -52,43 +63,42 @@ class LinkablePlugin implements ModelQueryPlugin
|
||||
if ($class !== SiteTree::class && !is_subclass_of($class, SiteTree::class)) {
|
||||
return;
|
||||
}
|
||||
Schema::invariant(
|
||||
!$query->isList(),
|
||||
'Plugin %s cannot be applied to queries that return lists. Query "%s" is a list',
|
||||
static::getIdentifier(),
|
||||
$query->getName()
|
||||
$singleFieldName = $this->config()->get('single_field_name');
|
||||
$listFieldName = $this->config()->get('list_field_name');
|
||||
$fieldName = $query->isList() ? $listFieldName : $singleFieldName;
|
||||
$type = $query->isList() ? '[String]' : 'String';
|
||||
$query->addArg($fieldName, $type);
|
||||
$query->addResolverAfterware(
|
||||
$config['resolver'] ?? static::config()->get('resolver')
|
||||
);
|
||||
$fieldName = $this->config()->get('field_name');
|
||||
|
||||
$query->addArg($fieldName, 'String');
|
||||
$query->addResolverAfterware([static::class, 'applyLinkFilter']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $obj
|
||||
* @param array $args
|
||||
* @param array $context
|
||||
* @param ResolveInfo $info
|
||||
* @param callable $done
|
||||
* @return SiteTree|DataList|null
|
||||
* @return callable
|
||||
*/
|
||||
public static function applyLinkFilter(
|
||||
$obj,
|
||||
array $args,
|
||||
array $context,
|
||||
ResolveInfo $info,
|
||||
callable $done
|
||||
) {
|
||||
$fieldName = static::config()->get('field_name');
|
||||
$filterLink = $args['filter'][$fieldName] ?? null;
|
||||
$argLink = $args[$fieldName] ?? null;
|
||||
$filterLink = $filterLink ?: $argLink;
|
||||
|
||||
if ($filterLink) {
|
||||
$done();
|
||||
return SiteTree::get_by_link($filterLink);
|
||||
public static function applyLinkFilter($obj, array $args, array $context, ResolveInfo $info)
|
||||
{
|
||||
$singleFieldName = static::config()->get('single_field_name');
|
||||
$listFieldName = static::config()->get('list_field_name');
|
||||
$filterLink = $args['filter'][$singleFieldName] ?? ($args['filter'][$listFieldName] ?? null);
|
||||
$argLink = $args[$singleFieldName] ?? ($args[$listFieldName] ?? null);
|
||||
$linkData = $filterLink ?: $argLink;
|
||||
if (!$linkData) {
|
||||
return $obj;
|
||||
}
|
||||
// Normalise to an array for both cases. The readOne operation will get
|
||||
// ->first() run on it by the firstResult plugin.
|
||||
$links = is_array($linkData) ? $linkData : [$linkData];
|
||||
|
||||
return $obj;
|
||||
$result = ArrayList::create();
|
||||
|
||||
foreach ($links as $link) {
|
||||
$page = SiteTree::get_by_link($link);
|
||||
if ($page) {
|
||||
$result->push($page);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
112
tests/php/GraphQL/LinkablePluginTest.php
Normal file
112
tests/php/GraphQL/LinkablePluginTest.php
Normal file
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\CMS\Tests\GraphQL;
|
||||
|
||||
use SilverStripe\AssetAdmin\Tests\GraphQL\FakeResolveInfo;
|
||||
use SilverStripe\CMS\GraphQL\LinkablePlugin;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\GraphQL\Schema\DataObject\DataObjectModel;
|
||||
use SilverStripe\GraphQL\Schema\Field\ModelQuery;
|
||||
use SilverStripe\GraphQL\Schema\Schema;
|
||||
use SilverStripe\GraphQL\Schema\SchemaConfig;
|
||||
|
||||
class LinkablePluginTest extends SapphireTest
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (!class_exists(Schema::class)) {
|
||||
$this->markTestSkipped('GraphQL 4 test ' . __CLASS__ . ' skipped');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $list
|
||||
* @dataProvider provideApply
|
||||
*/
|
||||
public function testApply(bool $list)
|
||||
{
|
||||
$query = new ModelQuery(
|
||||
new DataObjectModel(SiteTree::class, new SchemaConfig()),
|
||||
'testQuery'
|
||||
);
|
||||
$query->setType($list ? '[SiteTree]' : 'SiteTree');
|
||||
|
||||
$plugin = new LinkablePlugin();
|
||||
$plugin->apply($query, new Schema('test'));
|
||||
$args = $query->getArgs();
|
||||
$field = $list ? 'links' : 'link';
|
||||
$this->assertArrayHasKey($field, $args);
|
||||
$this->assertEquals($list ? '[String]' : 'String', $args[$field]->getType());
|
||||
}
|
||||
|
||||
public function testResolver()
|
||||
{
|
||||
$page = SiteTree::create([
|
||||
'Title' => 'Test page',
|
||||
'URLSegment' => 'test-page',
|
||||
'ParentID' => 0,
|
||||
]);
|
||||
$page->write();
|
||||
$page->publishRecursive();
|
||||
|
||||
$page = SiteTree::create([
|
||||
'Title' => 'Other test page',
|
||||
'URLSegment' => 'other-test-page',
|
||||
'ParentID' => 0,
|
||||
]);
|
||||
|
||||
$page->write();
|
||||
$page->publishRecursive();
|
||||
|
||||
$result = LinkablePlugin::applyLinkFilter('test', ['link' => 'test-page'], [], new FakeResolveInfo());
|
||||
$this->assertTrue($result->exists());
|
||||
$this->assertEquals('Test page', $result->first()->Title);
|
||||
|
||||
$result = LinkablePlugin::applyLinkFilter('test', ['links' => ['test-page']], [], new FakeResolveInfo());
|
||||
$this->assertTrue($result->exists());
|
||||
$this->assertEquals('Test page', $result->first()->Title);
|
||||
|
||||
$result = LinkablePlugin::applyLinkFilter(
|
||||
'test',
|
||||
['links' => ['test-page', 'other-test-page']],
|
||||
[],
|
||||
new FakeResolveInfo()
|
||||
);
|
||||
$this->assertTrue($result->exists());
|
||||
$this->assertCount(2, $result);
|
||||
$titles = $result->column('Title');
|
||||
$this->assertTrue(in_array('Test page', $titles));
|
||||
$this->assertTrue(in_array('Other test page', $titles));
|
||||
|
||||
$result = LinkablePlugin::applyLinkFilter(
|
||||
'test',
|
||||
['links' => ['test-page', 'fail-page']],
|
||||
[],
|
||||
new FakeResolveInfo()
|
||||
);
|
||||
$this->assertTrue($result->exists());
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('Test page', $result->first()->Title);
|
||||
|
||||
$result = LinkablePlugin::applyLinkFilter('test', ['link' => 'fail-page'], [], new FakeResolveInfo());
|
||||
$this->assertFalse($result->exists());
|
||||
|
||||
$result = LinkablePlugin::applyLinkFilter('test', ['links' => ['fail-page']], [], new FakeResolveInfo());
|
||||
$this->assertFalse($result->exists());
|
||||
|
||||
$result = LinkablePlugin::applyLinkFilter('test', ['notAnArg' => 'fail'], [], new FakeResolveInfo());
|
||||
$this->assertEquals('test', $result);
|
||||
}
|
||||
|
||||
|
||||
public function provideApply()
|
||||
{
|
||||
return [
|
||||
[true],
|
||||
[false],
|
||||
];
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user