Skip to content

Instantly share code, notes, and snippets.

@unclecheese
Last active June 20, 2018 05:10
Show Gist options
  • Save unclecheese/7e03ee197e83a8f1dafeb02ef9d2973c to your computer and use it in GitHub Desktop.
Save unclecheese/7e03ee197e83a8f1dafeb02ef9d2973c to your computer and use it in GitHub Desktop.
<?php
class GridFieldRegistry
{
public function add($identifier, GridField $gridField)
{
if ($identifierIsNotUnique) { throw... }
$this->registry[] = new GridFieldRegistration(
$identifier,
$gridField
);
public function getAll() { return $this->registry; }
}
}
<?php
class ProductsPage extends Page implements GridFieldProvider
{
// The class declares its gridfields and adds them to a registry
public function provideGridFields(GridFieldRegistry $registry)
{
$registry->add(
'FeaturedProducts',
GridField::create(
'FeaturedProducts',
'Featured products',
Product::get()->filter('Featured', true)
)
);
}
// The grid fields are fetched from the registry to build the form
public function getCMSFields()
{
$fields = parent::getCMSFields();
$fields->addFieldToTab(
'Root.FeaturedProducts',
// Helper method. Could be a trait added in the ancestry
$this->getGridField('FeaturedProducts')
);
return $fields;
}
}
<?php
// All dataObjects get exposed to GraphQL
class UniversalScaffolder implements ScaffoldingProvider
{
public function provideGraphQLScaffolding(SchemaScaffolder $scaffolder)
{
foreach(ClassInfo::subclassesFor(DataObject::class) as $dataObjectClass) {
$scaffolder->type($dataObjectClass)
->addAllFields();
->operation(SchemaScaffolder::ALL);
}
}
}
<?php
// GridFields will, at the very least, have special read operations
class GridFieldScaffolder implements ScaffoldingProvider
{
public function __construct(GridFieldRegistry $registry);
public function provideGraphQLScaffolding(SchemaScaffolder $scaffolder)
{
foreach ($this->registry->getAll() as $gridFieldRegistration) {
$gridField = $gridFieldRegistration->getGridField();
$identifier = $gridFieldRegistration->getIdentifier();
$scaffolder->query(
$identifier,
$gridField->getList()->dataClass(), // Warning: assumes DataList
function ($object, array $args, $context, ResolveInfo $info) use ($gridField) {
return $gridField->getList();
}
);
}
}
}
<?php
class LeftAndMain ...
{
// Collects all the providers and loads them into the registry
someInitFunction()
{
$registry = Injector::inst()->get(GridFieldRegistry::class);
foreach(ClassInfo::implementorsOf(GridFieldProvider::class) as $provider) {
$provider->provideGridFields($registry);
}
}
// Send all the GraphQL info to the client config to be loaded into Injector
getClientConfig()
{
foreach(GridFieldRegistry::inst()->getAll() as $gridFieldRegistration) {
$config['gridFieldQueries'][] = [
'context' => $gridFieldRegistration->getInjectorContext(),
'name' => $gridFieldRegistration->getIdentifier(),
'fields' => $gridFieldRegistration->getDisplayedFields()
]
}
}
}
// load the queries into injector
config.gridFieldQueries.forEach(gridFieldQuery => {
const { context, name, fields} = gridFieldQuery;
const query = {
apolloConfig: {
props({ data }) {
return {
gridFieldData: data[name],
}
}
},
templateName: PROBABLY_SOMETHING_CUSTOM,
pagination: true,
params: {},
fields,
};
const queryName = `${name}Query`;
Injector.register(queryName, query);
Injector.transform(
`${name}-graphql`,
(updater) => {
// context is the name of the GridField Injector, e.g.
// GridField.ModelAdmin.EditForm.Products
updater.component(context, injectGraphql(queryName));
}
);
})
@unclecheese
Copy link
Author

unclecheese commented Jun 20, 2018

Notes:

  • Context in FormBuilderLoader follows the pattern [FieldType].[FormIdentifier].[FieldName]. We don't really have enough in a DataObject definition to determine that context. We may need to enhance the way the GridField component creates its context name and/or beef up the way injector can wildcard context, e.g. updater.component(GridField.**.${myGridFieldIdentifier}, injectGraphql(...)) (using a double ** to match any depth).

  • You wouldn't need GridFieldProvider if getCMSFields is deterministic.

  • Thought should be given on how to streamline the 80% use case, which is $myObj->SomeRelationship()

  • Not sure how we would handle the query template. We have to afford customisations for adding params.

  • Maybe the third param of theGridField constructor becomes a closure, and instead of getList(), we have getResolver()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment