Skip to main content

Working on a decoupled React / Drupal 9 site.

Aim: Adjust the output of curated content for the Work Resources page.  So the icon is displayed with a path.  Enabling React developers to select whether to use the image or icon.

Tools

Drupal 9.4
React  

 

Currently, the JSON output 

{
  "id": "content_reference",
  "title": "Forms",
  "summary": null,
  "columns": "3",
  "cta": {
    "text": "View all",
    "href": "https://www.google.com/"
  },
  "content": [
    {
      "id": "custom_content_tile",
      "title": "Joint mental health commissions and leaders communique",
      "summary": "The mental health commissions and leaders across Australia have come together during the time of the pandemic",
      "link": {
        "text": "Read more",
        "href": "/news/working-together-create-mentally-healthy-and-safe-workplaces"
      },
      "image": {
        "alt": "Test Curated Content two",
        "title": "",
        "href": "https://localhost:8006/sites/default/files/styles/desktop/public/2022-06/Test%20Curated%20Content%20Work%20Resources%202.png?itok=F9TbZoH1",
        "styles": {
          "laptop": {
            "href": "https://localhost:8006/sites/default/files/styles/laptop/public/2022-06/Test%20Curated%20Content%20Work%20Resources%202.png?itok=28KzCLbs",
            "width": 210,
            "height": 196
          },
          "tablet": {
            "href": "https://localhost:8006/sites/default/files/styles/tablet/public/2022-06/Test%20Curated%20Content%20Work%20Resources%202.png?itok=BEH519Q4",
            "width": 210,
            "height": 196
          },
          "mobile": {
            "href": "https://localhost:8006/sites/default/files/styles/mobile/public/2022-06/Test%20Curated%20Content%20Work%20Resources%202.png?itok=ooF3HwDk",
            "width": 210,
            "height": 196
          }
        },
        "width": 210,
        "height": 196
      }
    },
    {
      "id": "custom_content_tile",
      "title": "Joint mental health commissions and leaders communique",
      "summary": "The mental health commissions and leaders across Australia have come together during the time of the pandemic",
      "link": {
        "text": "Read more",
        "href": "https://www.google.com/"
      },
      "image": {
        "alt": "Test Curated Content two",
        "title": "",
        "href": "https://localhost:8006/sites/default/files/styles/desktop/public/2022-06/Test%20Curated%20Content%20Work%20Resources%202_0.png?itok=l19DECi_",
        "styles": {
          "laptop": {
            "href": "https://localhost:8006/sites/default/files/styles/laptop/public/2022-06/Test%20Curated%20Content%20Work%20Resources%202_0.png?itok=nYahgAE1",
            "width": 210,
            "height": 196
          },
          "tablet": {
            "href": "https://localhost:8006/sites/default/files/styles/tablet/public/2022-06/Test%20Curated%20Content%20Work%20Resources%202_0.png?itok=MEQvOPPI",
            "width": 210,
            "height": 196
          },
          "mobile": {
            "href": "https://localhost:8006/sites/default/files/styles/mobile/public/2022-06/Test%20Curated%20Content%20Work%20Resources%202_0.png?itok=vOhvi_b3",
            "width": 210,
            "height": 196
          }
        },
        "width": 210,
        "height": 196
      }
    },
  ]
},

 

Introduction

As the document already exists in the system, I don't want a solution where the content admin can manually set the icon.  Otherwise, all too early they could set conflicting icons.

So moving towards a solution, I'll grab the content href link and lookup the relevant node nid.  This will then enable the correct document type being accessed.

 

Approach to resolution

I'll focus on the link (field_cta) and check if the href element is an internal or external link.  This will be achieved by checking the string /node/###.  Where ### is the node.nid value.  If the nid is not null, then load node and get the node type.  From this node type, the icon path can be generated.

This output has changed by adjusting the two areas of the PHP code.

First through the paragraph tile code:


    use ParagraphTrait;

    /**
     * {@inheritdoc}
     */
    public function process()
    {
        $this->processConfig();

        $this->setData('title', $this->entity->field_title->value);
        $this->setData('summary', $this->entity->field_summary->value);
        $link = $this->helper->getField($this->entity, 'field_cta');
        $this->setData('link', $link);
        $this->setData('image', $this->helper->getFieldImageUrl($this->entity, 'field_image') ?: $this->helper->getFallbackImage());
        // If an internal link, get the type and icon.
        $nid = $this->helper->getNodeNidFromAlias($link['href'], '/node/');
        if (!is_null($nid)) {
            $node = \Drupal\node\Entity\Node::load($nid);
            $this->setData('type', $node->getType());
            $this->setData('icon', $this->helper->getIconFromNode($node));
        }
    }

 

The focus of the above is to extract the node nid from the URL where the URL is an alias.  Through the line

$this->helper->getNodeNidFromAlias($link['href'], '/node/');

Then the icon and its relative path are sourced by a function getIconFromNode()

$this->setData('icon', $this->helper->getIconFromNode($node));

As noted these two functions with the code in full


    /**
     * Load the node nid from the URL alias.
     *
     * @param string $url URL string.
     *
     * @return any
     */
    public function getNodeNidFromAlias($url, $phrase)
    {
        // Default values.
        $nid = null;
        $path = \Drupal::service('path_alias.manager')->getPathByAlias($url);
        $strlen = strlen($phrase);
        if (substr($path, 0, $strlen) === $phrase) {
            $nid = substr($path, $strlen, strlen($path) - $strlen);
        }

        return $nid;
    }

    /**
     * Get the node type.
     *
     * @param any $nid Node nid.
     *
     * @return any
     */
    public function getIconFromNode($node)
    {
        if (is_null($node)) {
            return null;
        }

        return $this->getIcons($node);
    }

 

Subsequently, post the changes above the JSON is now:

{
  "id": "content_reference",
  "title": "Forms",
  "summary": null,
  "columns": "3",
  "cta": {
    "text": "View all",
    "href": "https://www.google.com/"
  },
  "content": [
    {
      "id": "custom_content_tile",
      "title": "Joint mental health commissions and leaders communique",
      "summary": "The mental health commissions and leaders across Australia have come together during the time of the pandemic",
      "link": {
        "text": "Read more",
        "href": "/news/working-together-create-mentally-healthy-and-safe-workplaces"
      },
      "image": {
        "alt": "Test Curated Content two",
        "title": "",
        "href": "https://localhost:8006/sites/default/files/styles/desktop/public/2022-06/Test%20Curated%20Content%20Work%20Resources%202.png?itok=F9TbZoH1",
        "styles": {
          "laptop": {
            "href": "https://localhost:8006/sites/default/files/styles/laptop/public/2022-06/Test%20Curated%20Content%20Work%20Resources%202.png?itok=28KzCLbs",
            "width": 210,
            "height": 196
          },
          "tablet": {
            "href": "https://localhost:8006/sites/default/files/styles/tablet/public/2022-06/Test%20Curated%20Content%20Work%20Resources%202.png?itok=BEH519Q4",
            "width": 210,
            "height": 196
          },
          "mobile": {
            "href": "https://localhost:8006/sites/default/files/styles/mobile/public/2022-06/Test%20Curated%20Content%20Work%20Resources%202.png?itok=ooF3HwDk",
            "width": 210,
            "height": 196
          }
        },
        "width": 210,
        "height": 196
      },
      "type": "news",
      "icon": "sites/default/files/icons/News.svg"
    },
  ]
},

The new elements to the JSON are

      "type": "news",
      "icon": "sites/default/files/icons/News.svg"

 

Note, that the image element remains.  React frontend can use either the icon or image path.

Related articles