Drupal CMS plugin
Plugin for Gesso CMS Provider
Requirements
- Create or update your
.env
- Add an entry for your Drupal URL
NEXT_PUBLIC_DRUPAL_URL=https://mydrupal.com
Your graphql endpoint is required to be accessible at /graphql
.
Registering hooks
Within your src/
directory create a drupal.ts
file. In that file register the Drupal plugins with the CMS Provider.
NEXT_PUBLIC_DRUPAL_URL should be pointing to some instance of drupal ie: http://drupal10.lndo.site
import { cms as GessoCms } from '@acromedia/gesso-cms';
import plugins from '@acromedia/gesso-drupal';
const config = {
drupalUrl: process.env.NEXT_PUBLIC_DRUPAL_URL,
};
export const cms = GessoCms(plugins, config);
Customizing the response data
Gesso's Drupal provider plugin includes default GraphQL query fragments that are used to construct the queries used by hooks for retrieving data from Drupal. This is useful when you have custom content types or have altered default content types and need to query that data via Provider hooks.
See here for a full list of the default query fragments
For example the default fragment for NodeArticle
:
import { gql } from 'graphql-request';
export const NodePage = gql`
fragment NodePage on Entity {
... on NodePage {
id
uuid
title: label
status
type: typeRawField {
value: getString
}
fieldComponents: fieldComponentsRawField {
entityReferences
}
referencedEntities {
id
label
...Tags
entityTypeId
}
}
}
`;
If your project requires querying additional fields you will need to override the default queries. This can be achieved by passing the query overrides into the provider config when registering the hooks.
import { cms as GessoCms } from '@acromedia/gesso-cms';
import plugins from '@acromedia/gesso-drupal';
const config = {
drupalUrl: process.env.NEXT_PUBLIC_DRUPAL_URL,
queries: {
'TYPE': {
'FRAGMENT_NAME': myFragment
}
}
};
export const cms = GessoCms(plugins, config);
In the above examples TYPE
should be replaced with the cooresponding value for the specific type you are trying to create/update a fragment for.
This value matches the name of the directory holding the fragments. When looking at the queries directory here
this value would be one of the following types.
Types
Types are used to group common fragments that should be included together.
- Menu
- Nodes
- Path
- Redirects
- Routes
- Tags
- User
- WithReferences
Overriding Default Queries
So if we want to override the default fields for NodePage
and add a custom field we might have something like:
import { cms as GessoCms } from '@acromedia/gesso-cms';
import plugins from '@acromedia/gesso-drupal';
import { gql } from 'graphql-request';
export const customNodePage = gql`
fragment NodePage on Entity {
... on NodePage {
id
uuid
title: label
status
type: typeRawField {
value: getString
}
fieldComponents: fieldComponentsRawField {
entityReferences
}
referencedEntities {
id
label
...Tags
entityTypeId
}
// Add additional fields.
customField
}
}
`;
const config = {
drupalUrl: process.env.NEXT_PUBLIC_DRUPAL_URL,
queries: {
'NODES': {
'NodePage': customNodePage
}
}
};
export const cms = GessoCms(plugins, config);
Registering New Queries
You can also register net new query fragments that will be included in Nodes
queries aswell.
Simply create a fragment for a new node type and register it with the Nodes
type.
Say we have a content type called Instructions
our new fragment might look something like this..
export const customNodeInstruction = gql`
fragment NodeInstruction on Entity {
... on NodeInstruction {
title: label
status
type: typeRawField {
value: getString
}
fieldComponents: fieldComponentsRawField {
entityReferences
}
customField
}
}
`;
const config = {
drupalUrl: process.env.NEXT_PUBLIC_DRUPAL_URL,
queries: {
'NODES': {
'NodeInstruction': customNodeInstruction
}
}
};
Enabling Webforms integration
via Commerce useForm/getForm
The Commerce Provider exposes useForm/getForm
in order to use these with drupal you will need to configure Webforms.
- Install/Enable
Webform, Webform UI, Webform REST
- Configure REST endpoints for Webforms, go to
admin/config/services/rest
- Webform Fields
/webform_rest/{webform_id}/fields
:GET
- Webform Submit
/webform_rest/submit
:POST
- Webform Fields
With both those endpoints enabled we will be able to get form data using the Form methods.
Rendering Forms
Using ComponentFactory we can easily render Drupal Webforms on a decoupled frontend.
import { ComponentFactoryData } from '@acromedia/gesso';
import { GetStaticProps } from 'next';
import ComponentFactory from '../components/ComponentFactory';
import { cms } from '../drupal';
import { Form } from '@acromedia/gesso-cms';
import { Response } from '@acromedia/gesso-core';
const { getForm } = cms;
interface Props {
payload?: ComponentFactoryData;
error?: Error;
state: string;
}
const ContactForm = ({ payload }: Props) => {
if (!payload) {
return null;
}
// Pass the data directly from the getForm response.
// NOTE: ComponentFactory data prop expects an array.
// So to work around this wrap payload in an array.
return <ComponentFactory data={[payload]} />;
};
export default ContactForm;
export const getStaticProps: GetStaticProps = async () => {
// Load the form data.
const res = await getForm('contact');
// This is a hack to remove instances of undefined from the response.
const formResponse = JSON.parse(JSON.stringify(res)) as Response<
Form | undefined
>;
return {
props: {
...formResponse, // Pass the form data to the component
},
};
};