diff --git a/_config/dbargs.yml b/_config/dbargs.yml index 8d84c875..f09ff5b6 100644 --- a/_config/dbargs.yml +++ b/_config/dbargs.yml @@ -2,8 +2,6 @@ Name: graphql-db-args --- # For the DBFieldArgsPlugin, assign each DBField type an args factory -SilverStripe\ORM\FieldType\DBString: - graphql_args: SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBStringArgs SilverStripe\ORM\FieldType\DBText: graphql_args: SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBTextArgs SilverStripe\ORM\FieldType\DBHTMLText: @@ -18,5 +16,3 @@ SilverStripe\ORM\FieldType\DBDecimal: graphql_args: SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBDecimalArgs SilverStripe\ORM\FieldType\DBFloat: graphql_args: SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBFloatArgs -SilverStripe\ORM\FieldType\DBCurrency: - graphql_args: SilverStripe\GraphQL\Schema\DataObject\Plugin\DBFieldArgs\DBCurrencyArgs diff --git a/src/Schema/DataObject/Plugin/DBFieldArgs/DBCurrencyArgs.php b/src/Schema/DataObject/Plugin/DBFieldArgs/DBCurrencyArgs.php deleted file mode 100644 index 1844c9a8..00000000 --- a/src/Schema/DataObject/Plugin/DBFieldArgs/DBCurrencyArgs.php +++ /dev/null @@ -1,29 +0,0 @@ -getValues(), - 'Formatting options for fields that map to DBCurrency data types' - ); - } - - public function getValues(): array - { - return array_merge( - parent::getValues(), - [ - 'WHOLE' => 'Whole', - ] - ); - } -} diff --git a/src/Schema/DataObject/Plugin/DBFieldArgs/DBDecimalArgs.php b/src/Schema/DataObject/Plugin/DBFieldArgs/DBDecimalArgs.php index f5479c9b..ed222a08 100644 --- a/src/Schema/DataObject/Plugin/DBFieldArgs/DBDecimalArgs.php +++ b/src/Schema/DataObject/Plugin/DBFieldArgs/DBDecimalArgs.php @@ -39,7 +39,6 @@ protected function getResolver(): callable public function getValues(): array { return [ - 'NICE' => 'Nice', 'INT' => 'Int', ]; } diff --git a/src/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgsPlugin.php b/src/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgsPlugin.php index 2bf2ca72..07e3e9ca 100644 --- a/src/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgsPlugin.php +++ b/src/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgsPlugin.php @@ -31,11 +31,9 @@ public function getIdentifier(): string public static function updateSchema(Schema $schema): void { $schema - ->addEnum(DBStringArgs::create()->getEnum()) ->addEnum(DBTextArgs::create()->getEnum()) ->addEnum(DBHTMLTextArgs::create()->getEnum()) ->addEnum(DBDecimalArgs::create()->getEnum()) - ->addEnum(DBCurrencyArgs::create()->getEnum()) ->addEnum(DBFloatArgs::create()->getEnum()) ->addEnum(DBDateArgs::create()->getEnum()) ->addEnum(DBDatetimeArgs::create()->getEnum()) diff --git a/src/Schema/DataObject/Plugin/DBFieldArgs/DBStringArgs.php b/src/Schema/DataObject/Plugin/DBFieldArgs/DBStringArgs.php deleted file mode 100644 index 9764cf4e..00000000 --- a/src/Schema/DataObject/Plugin/DBFieldArgs/DBStringArgs.php +++ /dev/null @@ -1,42 +0,0 @@ -getValues(), - 'Formatting options for fields that map to DBString data types' - ); - } - - public function getValues(): array - { - return [ - 'NICE' => 'Nice', - 'INT' => 'Int', - ]; - } - - public function applyToField(ModelField $field): void - { - $field->addArg('format', [ - 'type' => $this->getEnum()->getName(), - 'description' => 'Formatting options for this field', - ])->addResolverAfterware( - $this->getResolver() - ); - } - - protected function getResolver(): callable - { - return [DBFieldArgs::class, 'baseFormatResolver']; - } -} diff --git a/src/Schema/DataObject/Plugin/DBFieldArgs/DBTextArgs.php b/src/Schema/DataObject/Plugin/DBFieldArgs/DBTextArgs.php index 992ad176..84bfb607 100644 --- a/src/Schema/DataObject/Plugin/DBFieldArgs/DBTextArgs.php +++ b/src/Schema/DataObject/Plugin/DBFieldArgs/DBTextArgs.php @@ -8,7 +8,7 @@ use SilverStripe\ORM\FieldType\DBString; use Exception; -class DBTextArgs extends DBStringArgs +class DBTextArgs extends DBFieldArgs { public function getEnum(): Enum { @@ -21,15 +21,12 @@ public function getEnum(): Enum public function getValues(): array { - return array_merge( - parent::getValues(), - [ - 'CONTEXT_SUMMARY' => 'ContextSummary', - 'FIRST_PARAGRAPH' => 'FirstParagraph', - 'LIMIT_SENTENCES' => 'LimitSentences', - 'SUMMARY' => 'Summary', - ] - ); + return [ + 'CONTEXT_SUMMARY' => 'ContextSummary', + 'FIRST_PARAGRAPH' => 'FirstParagraph', + 'LIMIT_SENTENCES' => 'LimitSentences', + 'SUMMARY' => 'Summary', + ]; } public function applyToField(ModelField $field): void @@ -62,13 +59,6 @@ protected function getResolver(): callable */ public static function resolve(DBString $obj, array $args) { - $result = DBFieldArgs::baseFormatResolver($obj, $args); - - // If no referential equality, the parent did something, so we're done. - if ($result !== $obj) { - return $result; - } - $format = $args['format'] ?? null; $limit = $args['limit'] ?? null; @@ -76,9 +66,19 @@ public static function resolve(DBString $obj, array $args) return $obj; } - if ($limit && in_array($format, ['FirstParagraph'])) { + $noArgMethods = ['FirstParagraph']; + + if ($limit && in_array($format, $noArgMethods)) { throw new Exception(sprintf('Arg "limit" is not allowed for format "%s"', $format)); } + + $result = DBFieldArgs::baseFormatResolver($obj, $args); + + // If no referential equality, the parent did something, so we're done. + if ($result !== $obj) { + return $result; + } + if ($format) { $args = $limit === null ? [] : [$limit]; if ($obj->hasMethod($format)) { diff --git a/src/Schema/DataObject/Plugin/DBFieldArgs/DBTimeArgs.php b/src/Schema/DataObject/Plugin/DBFieldArgs/DBTimeArgs.php index 859c204a..6512fb39 100644 --- a/src/Schema/DataObject/Plugin/DBFieldArgs/DBTimeArgs.php +++ b/src/Schema/DataObject/Plugin/DBFieldArgs/DBTimeArgs.php @@ -8,6 +8,7 @@ use SilverStripe\ORM\FieldType\DBDate; use SilverStripe\ORM\FieldType\DBField; use Exception; +use SilverStripe\ORM\FieldType\DBTime; class DBTimeArgs extends DBFieldArgs { @@ -41,12 +42,12 @@ protected function getResolver(): callable } /** - * @param DBDate $obj + * @param DBTime $obj * @param array $args * @return DBField | string * @throws Exception */ - public static function resolve(DBDate $obj, array $args) + public static function resolve(DBTime $obj, array $args) { $format = $args['format'] ?? null; $custom = $args['customFormat'] ?? null; diff --git a/tests/Fake/DataObjectFake.php b/tests/Fake/DataObjectFake.php index 4b4cf6f4..a30da95d 100644 --- a/tests/Fake/DataObjectFake.php +++ b/tests/Fake/DataObjectFake.php @@ -24,6 +24,8 @@ class DataObjectFake extends DataObject implements TestOnly 'MyDate' => 'Datetime', 'MyCurrency' => 'Currency', 'MyText' => 'Text', + 'MyEnum' => "Enum('ONE, TWO')", + 'MyMoney' => 'Money', ]; private static $has_one = [ diff --git a/tests/Schema/DataObject/Plugin/DBFieldArgs/DBDateArgsTest.php b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBDateArgsTest.php new file mode 100644 index 00000000..b0b1ae78 --- /dev/null +++ b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBDateArgsTest.php @@ -0,0 +1,55 @@ +applyToField($field); + $args = $field->getArgs(); + + $this->assertArrayHasKey('format', $args); + $arg = $args['format']; + $this->assertEquals($factory->getEnum()->getName(), $arg->getType()); + + $this->assertArrayHasKey('customFormat', $args); + $arg = $args['customFormat']; + $this->assertEquals('String', $arg->getType()); + } + + public function testResolve() + { + $fake = $this->getMockBuilder(DBDate::class) + ->setMethods(['Nice']) + ->getMock(); + $fake->expects($this->once()) + ->method('Nice'); + + DBDateArgs::resolve($fake, ['format' => 'Nice']); + + $date = DBField::create_field('Date', '123445789'); + $result = DBDateArgs::resolve($date, ['format' => 'FAIL']); + // Referential equality if method not found + $this->assertEquals($result, $date); + + $this->expectExceptionMessage('The "custom" option requires a value for "customFormat"'); + + DBDateArgs::resolve($date, ['format' => 'Custom']); + + $this->expectExceptionMessage('The "customFormat" argument should not be set for formats that are not "custom"'); + + DBDateArgs::resolve($date, ['customFormat' => 'test']); + } +} diff --git a/tests/Schema/DataObject/Plugin/DBFieldArgs/DBDatetimeArgsTest.php b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBDatetimeArgsTest.php new file mode 100644 index 00000000..80a9350b --- /dev/null +++ b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBDatetimeArgsTest.php @@ -0,0 +1,56 @@ +applyToField($field); + $args = $field->getArgs(); + + $this->assertArrayHasKey('format', $args); + $arg = $args['format']; + $this->assertEquals($factory->getEnum()->getName(), $arg->getType()); + + $this->assertArrayHasKey('customFormat', $args); + $arg = $args['customFormat']; + $this->assertEquals('String', $arg->getType()); + } + + public function testResolve() + { + $fake = $this->getMockBuilder(DBDatetime::class) + ->setMethods(['Time']) + ->getMock(); + $fake->expects($this->once()) + ->method('Time'); + + DBDatetimeArgs::resolve($fake, ['format' => 'Time']); + + $date = DBField::create_field('Datetime', '123445789'); + $result = DBDateArgs::resolve($date, ['format' => 'FAIL']); + // Referential equality if method not found + $this->assertEquals($result, $date); + + $this->expectExceptionMessage('The "custom" option requires a value for "customFormat"'); + + DBDateArgs::resolve($date, ['format' => 'Custom']); + + $this->expectExceptionMessage('The "customFormat" argument should not be set for formats that are not "custom"'); + + DBDateArgs::resolve($date, ['customFormat' => 'test']); + } +} diff --git a/tests/Schema/DataObject/Plugin/DBFieldArgs/DBDecimalArgsTest.php b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBDecimalArgsTest.php new file mode 100644 index 00000000..b1c86902 --- /dev/null +++ b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBDecimalArgsTest.php @@ -0,0 +1,25 @@ +applyToField($field); + $args = $field->getArgs(); + + $this->assertArrayHasKey('format', $args); + $arg = $args['format']; + $this->assertEquals($factory->getEnum()->getName(), $arg->getType()); + } +} diff --git a/tests/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgsPluginTest.php b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgsPluginTest.php new file mode 100644 index 00000000..740ec15f --- /dev/null +++ b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgsPluginTest.php @@ -0,0 +1,55 @@ +setFieldAccessor(new FieldAccessor()); + + $field1 = new ModelField('test1', [], $model); + $field1->getMetadata()->set('dataClass', DBText::class); + $field2 = new ModelField('test2', [], $model); + $field2->getMetadata()->set('dataClass', DBDatetime::class); + $field3 = new ModelField('test3', [], $model); + $field3->getMetadata()->set('dataClass', null); + + $type = new ModelType($model, [ + 'fields' => [ + 'test1' => $field1, + 'test2' => $field2, + 'test3' => $field3, + ] + ]); + $plugin = new DBFieldArgsPlugin(); + $plugin->apply($type, new Schema('test')); + + $field = $type->getFieldByName('test1'); + $args = $field->getArgs(); + $this->assertArrayHasKey('format', $args); + $this->assertArrayHasKey('limit', $args); + + $field = $type->getFieldByName('test2'); + $args = $field->getArgs(); + $this->assertArrayHasKey('format', $args); + $this->assertArrayHasKey('customFormat', $args); + + $field = $type->getFieldByName('test3'); + $args = $field->getArgs(); + $this->assertEmpty($args); + } +} diff --git a/tests/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgsTest.php b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgsTest.php new file mode 100644 index 00000000..f7fea636 --- /dev/null +++ b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBFieldArgsTest.php @@ -0,0 +1,29 @@ +getMockBuilder(DBText::class) + ->setMethods(['FirstSentence']) + ->getMock(); + $fake->expects($this->once()) + ->method('FirstSentence'); + + DBFieldArgs::baseFormatResolver($fake, ['format' => 'FirstSentence']); + + $test = DBField::create_field('Text', 'test'); + $result = DBFieldArgs::baseFormatResolver($test, ['format' => 'FAIL']); + + // Referential equality if method not found + $this->assertEquals($result, $test); + } +} diff --git a/tests/Schema/DataObject/Plugin/DBFieldArgs/DBFloatArgsTest.php b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBFloatArgsTest.php new file mode 100644 index 00000000..d8d0552e --- /dev/null +++ b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBFloatArgsTest.php @@ -0,0 +1,25 @@ +applyToField($field); + $args = $field->getArgs(); + + $this->assertArrayHasKey('format', $args); + $arg = $args['format']; + $this->assertEquals($factory->getEnum()->getName(), $arg->getType()); + } +} diff --git a/tests/Schema/DataObject/Plugin/DBFieldArgs/DBHTMLTextArgsTest.php b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBHTMLTextArgsTest.php new file mode 100644 index 00000000..6b56959f --- /dev/null +++ b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBHTMLTextArgsTest.php @@ -0,0 +1,43 @@ +applyToField($field); + $args = $field->getArgs(); + + $this->assertArrayHasKey('format', $args); + $arg = $args['format']; + $this->assertEquals($factory->getEnum()->getName(), $arg->getType()); + + $this->assertArrayHasKey('limit', $args); + $arg = $args['limit']; + $this->assertEquals('Int', $arg->getType()); + } + + public function testResolve() + { + $fake = $this->getMockBuilder(DBHTMLText::class) + ->setMethods(['setProcessShortcodes']) + ->getMock(); + $fake->expects($this->once()) + ->method('setProcessShortcodes'); + + DBHTMLTextArgs::resolve($fake, ['parseShortcodes' => true]); + DBHTMLTextArgs::resolve($fake, []); + } +} diff --git a/tests/Schema/DataObject/Plugin/DBFieldArgs/DBTextArgsTest.php b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBTextArgsTest.php new file mode 100644 index 00000000..63154342 --- /dev/null +++ b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBTextArgsTest.php @@ -0,0 +1,55 @@ +applyToField($field); + $args = $field->getArgs(); + + $this->assertArrayHasKey('format', $args); + $arg = $args['format']; + $this->assertEquals($factory->getEnum()->getName(), $arg->getType()); + + $this->assertArrayHasKey('parseShortcodes', $args); + $arg = $args['parseShortcodes']; + $this->assertEquals('Boolean', $arg->getType()); + } + + public function testResolve() + { + $fake = $this->getMockBuilder(DBText::class) + ->setMethods(['FirstParagraph']) + ->getMock(); + $fake->expects($this->once()) + ->method('FirstParagraph'); + + DBTextArgs::resolve($fake, ['format' => 'FirstParagraph']); + DBTextArgs::resolve($fake, []); + + $this->expectExceptionMessage('Arg "limit" is not allowed for format "FirstParagraph"'); + DBTextArgs::resolve($fake, ['format' => 'FirstParagraph', 'limit' => 5]); + + $fake = $this->getMockBuilder(DBText::class) + ->setMethods(['LimitSentences']) + ->getMock(); + $fake->expects($this->once()) + ->method('LimitSentences') + ->with([5]); + + DBTextArgs::resolve($fake, ['format' => 'LimitSentences', 'limit' => 5]); + } +} diff --git a/tests/Schema/DataObject/Plugin/DBFieldArgs/DBTimeArgsTest.php b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBTimeArgsTest.php new file mode 100644 index 00000000..db24f901 --- /dev/null +++ b/tests/Schema/DataObject/Plugin/DBFieldArgs/DBTimeArgsTest.php @@ -0,0 +1,56 @@ +applyToField($field); + $args = $field->getArgs(); + + $this->assertArrayHasKey('format', $args); + $arg = $args['format']; + $this->assertEquals($factory->getEnum()->getName(), $arg->getType()); + + $this->assertArrayHasKey('customFormat', $args); + $arg = $args['customFormat']; + $this->assertEquals('String', $arg->getType()); + } + + public function testResolve() + { + $fake = $this->getMockBuilder(DBTime::class) + ->setMethods(['Nice']) + ->getMock(); + $fake->expects($this->once()) + ->method('Nice'); + + DBTimeArgs::resolve($fake, ['format' => 'Nice']); + + $time = DBField::create_field('Time', '123445789'); + $result = DBTimeArgs::resolve($time, ['format' => 'FAIL']); + // Referential equality if method not found + $this->assertEquals($result, $time); + + $this->expectExceptionMessage('The "custom" option requires a value for "customFormat"'); + + DBTimeArgs::resolve($time, ['format' => 'Custom']); + + $this->expectExceptionMessage('The "customFormat" argument should not be set for formats that are not "custom"'); + + DBTimeArgs::resolve($time, ['customFormat' => 'test']); + } +} diff --git a/tests/Schema/DataObject/Plugin/DBFieldTypesTest.php b/tests/Schema/DataObject/Plugin/DBFieldTypesTest.php new file mode 100644 index 00000000..bea5f076 --- /dev/null +++ b/tests/Schema/DataObject/Plugin/DBFieldTypesTest.php @@ -0,0 +1,41 @@ +setFieldAccessor(new FieldAccessor()); + + $type = new ModelType($model); + $type->addAllFields(); + + $plugin = new DBFieldTypes(); + $plugin->apply($type, $schema = new Schema('test')); + + $enum = $type->getFieldByName('myEnum'); + $this->assertNotNull($enum); + $this->assertEquals('DataObjectFakemyEnumEnum', $enum->getType()); + $this->assertNotNull($schema->getEnum('DataObjectFakemyEnumEnum')); + + $composite = $type->getFieldByName('myMoney'); + $this->assertNotNull($composite); + $this->assertEquals('DBMoneyComposite', $composite->getType()); + $type = $schema->getType('DBMoneyComposite'); + $this->assertNotNull($type); + $this->assertNotNull($type->getFieldByName('currency')); + $this->assertNotNull($type->getFieldByName('amount')); + } +} diff --git a/tests/Schema/IntegrationTest.php b/tests/Schema/IntegrationTest.php index b2daf541..1fe360f7 100644 --- a/tests/Schema/IntegrationTest.php +++ b/tests/Schema/IntegrationTest.php @@ -999,7 +999,7 @@ public function testDBFieldArgs() $this->assertSchemaHasType($schema, 'DataObjectFake'); $obj = DataObjectFake::create([ 'MyField' => 'This is a varchar field', - 'MyDate' => '2020-29-02 17:00:00', + 'MyDate' => '1582995600', // 29 Feb 2020 17h 'MyCurrency' => '204.75', 'MyText' => 'This is a really long text field. It has a few sentences. Just filling some space now.', ]); @@ -1007,30 +1007,25 @@ public function testDBFieldArgs() $query = <<querySchema($schema, $query); $this->assertSuccess($result); - $node = $result['data']['readOneFakeDataObject'] ?? null; + $node = $result['data']['readOneDataObjectFake'] ?? null; $this->assertEquals('This is a varchar field', $node['myField']); $this->assertEquals('Saturday', $node['date1']); - $this->assertResult('wtf', 1, $node['date2']); - $this->assertResult('17:00:00', 1, $node['date3']); - $this->assertResult('2020', 1, $node['date4']); - $this->assertResult('$204.75', 1, $node['myCurrency']); - $this->assertResult('This is a really long text field. It has a few sentences.', 1, $node['myText - ']); - - + $this->assertEquals('2/29/20, 5:00 PM', $node['date2']); + $this->assertEquals('5:00:00 PM', $node['date3']); + $this->assertEquals('2020', $node['date4']); + $this->assertEquals('This is a really long text field. It has a few sentences.', $node['myText']); } /**