Skip to main content

Drupal

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
info

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.

info

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

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
},
};
};