Using process callbacks to modify field data

rhclayto edited this page Apr 27, 2016 · 7 revisions
Clone this wiki locally

This page content is specific to 2.x.

Process callbacks are covered in the Basic field definitions video tutorial. However, this is a more realistic example of how they can be used to enhance field data.

$processCallbacks is defined in class ResourceFieldBase, and described as: "An array of callbacks to perform on the returned value, or an array with the object and method." Note that $accessCallbacks are also defined in that class.

Overview

There are 3 ways to define a callback:

  • String with a function name. Ex: drupal_map_assoc.
  • An array containing an object and a method name of that object. Ex: array($this, 'format').
  • An array containing any of the methods before and an array of parameters to pass to the callback. Ex: array(array($this, 'processing'), array('param1', 2))

Use Case

In this example, I have a field collection named field_images that contains an image field (field_image) and three text fields. As part of my API output, I want to add the path to an image style derivative, instead of just using the main image URL that is stored in the image field. I'm also using the S3FS module to store all of my images in an Amazon S3 bucket, so I need to generate the path to the image on S3.

Callback Definition

To define my callback, I use the process_callbacks key in the field definition array for my field in the publicFields() method in my class:

    class Images__1_0 extends ResourceEntity {

      /**
       * {@inheritdoc}
       */
      protected function publicFields() {
        $public_fields = parent::publicFields();

        $public_fields['image'] = array( 
          'property' => 'field_image',
          'process_callbacks' => array(
            array($this, 'getStyleUrl')
          )
        );

        return $public_fields;
      }

This function call can also be a standard Drupal (or PHP) function:

        $public_fields['image'] = array( 
          'property' => 'field_image',
          'process_callbacks' => array(
            'strip_tags'
          )
        );

which would not require the following step of defining a custom function.

Callback Function

Since I've defined a custom callback function, I now need to create that function. I just do it as another public function in my class.

      /**
       * Adds URL for image style derivative.
       *
       * @param array $image
       *   Loaded image object in array form
       *
       * @return object $image
       *   Image array with additional element added.
       */
      public function getStyleUrl($image) {
        $derivative_uri = image_style_path('blog_list_image', $image['uri']);
        $s3_bucket = variable_get('s3fs_bucket', '');
        $derivative_uri = str_replace('s3://', 'http://' . $s3_bucket . '.s3.amazonaws.com/', $derivative_uri);

        $image['derivative_uri'] = $derivative_uri;
        return $image;
      }

In this case, all I do is use the path of the original image ($image['uri']) to get the path to the derivative image with image_style_path(), and add it to the $image array.

Rendered Output

Then, when including my images element in the URL (see video tutorial 8. Resource composition for details), the included array in the JSON output will look like this:

       {
          "type": "images",
          "id": "38782",
          "attributes": {
            "id": "38782",
            "label": "Featured Image",
            "self": "http://mysite/api/v1.0/images/38782",
            "image": {
              "fid": "87372",
              "uid": "123",
              "filename": "my_image_name.JPG",
              "uri": "s3://images/my_image_name.JPG",
              "filemime": "image/jpeg",
              "filesize": "73289",
              "status": "1",
              "timestamp": "1439997839",
              "rdf_mapping": [

              ],
              "alt": "",
              "title": "",
              "width": "1077",
              "height": "606",
              "derivative_uri": "http://mybucket.s3.amazonaws.com/styles/blog_list_image/s3/images/my_image_name.JPG"
            }
          },