You are here

oa_related.module in Open Atrium Related Content 7.2

File

oa_related.module
View source
<?php

/**
 * @file
 * Code for the Open Atrium Related Content.
 */
include_once 'oa_related.features.inc';
include_once 'oa_related.paragraphs.inc';
include_once 'oa_related.paragraphs.info.inc';
include_once 'oa_related.theme.inc';
define('PARAGRAPH_ADD_MORE_BUNDLE', 'add_more_bundle_');

/**
 * Implements hook_ctools_plugin_directory().
 */
function oa_related_ctools_plugin_directory($owner, $plugin_type) {
  if ($owner == 'ctools' && $plugin_type == 'content_types') {
    return 'plugins/content_types';
  }
}

/**
 * Implements hook_theme().
 */
function oa_related_theme($existing, $type, $theme, $path) {
  $theme = array();
  $path = $path . '/templates';
  $theme['oa_related_files'] = array(
    'template' => 'oa-related-files',
    'variables' => array(),
    'path' => $path,
  );
  $theme['oa_related_ref'] = array(
    'template' => 'oa-related-ref',
    'variables' => array(),
    'path' => $path,
  );
  $theme['oa_related_paragraphs_media_render'] = array(
    'path' => $path,
    'base hook' => 'entity',
    'template' => 'oa-related-paragraphs-media-render',
    'render element' => 'element',
  );
  $theme['oa_related_paragraphs_text_render'] = array(
    'path' => $path,
    'base hook' => 'entity',
    'template' => 'oa-related-paragraphs-text-render',
    'render element' => 'element',
  );
  $theme['oa_related_paragraphs_content_render'] = array(
    'path' => $path,
    'base hook' => 'entity',
    'template' => 'oa-related-paragraphs-content-render',
    'render element' => 'element',
  );
  $theme['oa_related_paragraphs_snippet_render'] = array(
    'path' => $path,
    'base hook' => 'entity',
    'template' => 'oa-related-paragraphs-snippet-render',
    'render element' => 'element',
  );

  // Get all of the paragraph types.
  $bundles = paragraphs_bundle_load();

  // Add all of our paragraph bundles dynamically.
  foreach ($bundles as $machine_name => $bundle) {
    $filename = 'oa-related-paragraphs-' . $machine_name . '-form';
    if (file_exists($path . '/' . $filename . '.tpl.php')) {
      $theme['oa_related_paragraphs_' . $machine_name . '_form'] = array(
        'template' => $filename,
        'render element' => 'element',
        'path' => $path,
      );
    }
  }
  return $theme;
}

/**
 * Implements hook_panels_display_save().
 */
function oa_related_panels_display_save($display) {

  // If a Featured view mode is saved, enable the content type for entityreferences.
  // cache_key has format: panelizer:default:node:%type.%viewmode:default
  if (!empty($display->cache_key)) {
    $parts = explode(':', $display->cache_key);
    if (!empty($parts[2]) && $parts[2] == 'node' && !empty($parts[3])) {
      list($bundle, $viewmode) = explode('.', $parts[3]);
      if ($viewmode == 'featured') {
        _oa_related_enable_related($bundle, _oa_related_has_panelizer_viewmode($bundle, $viewmode));
      }
    }
  }
}

/**
 * Implements hook_node_type_update().
 */
function oa_related_node_type_update($info) {

  // See if this content type has a Featured display mode.
  // If so, enable it for related content.
  _oa_related_enable_related($info->type, _oa_related_has_panelizer_viewmode($info->type, 'featured'));
}

/**
 * Helper function to determine if a given content type has a given panelized view mode
 * @param string $type content type (bundle)
 * @param string $viewmode machine name of view mode
 */
function _oa_related_has_panelizer_viewmode($type, $viewmode) {
  $handler = panelizer_entity_plugin_get_handler('node');
  return !empty($handler->plugin['bundles'][$type]['status']) && !empty($handler->plugin['bundles'][$type]['view modes'][$viewmode]['status']);
}

/**
 * Helper function to enable or disable related content for a given node type.
 * NOTE: This determines if the content type is available via the Related Content Paragraph type
 * It is *not* related to whether oa_related field is added to the content type.
 * See the oa_related_features_template_info() for that.
 * This just modifies the target_bundles for the oa_related_content entityreference.
 * @param string $type content type (bundle)
 * @param bool $value
 */
function _oa_related_enable_related($type, $value = TRUE) {
  $field = field_info_field('field_oa_related_content');

  // Installing site, field doesn't exist, exit out.
  if (!$field) {
    return;
  }

  // If it isn't a group content type then exit
  if (!og_is_group_content_type('node', $type)) {
    return;
  }
  if ($value) {
    $do_update = empty($field['settings']['handler_settings']['target_bundles'][$type]);
    $field['settings']['handler_settings']['target_bundles'][$type] = $type;
  }
  else {
    $do_update = !empty($field['settings']['handler_settings']['target_bundles'][$type]);
    unset($field['settings']['handler_settings']['target_bundles'][$type]);
  }
  if ($do_update) {
    field_update_field($field);
    $message = $value ? t('Enabled !type for related content references.', array(
      '!type' => $type,
    )) : t('Disabled !type for related content references.', array(
      '!type' => $type,
    ));
    if (variable_get('install_task') == 'done') {
      drupal_set_message($message);
    }
  }
}

/**
 * Implements hook_form_FORMID_alter().
 */
function oa_related_form_field_ui_display_overview_form_alter(&$form, &$form_state) {

  // Add Heading option to paragraph field labels.
  if (isset($form['#entity_type']) && $form['#entity_type'] == 'paragraphs_item') {
    foreach ($form['#fields'] as $fieldname) {
      if (isset($form['fields'][$fieldname]['label'])) {
        if (isset($form['fields'][$fieldname]['label']['#options'])) {
          $form['fields'][$fieldname]['label']['#options']['heading'] = t('Heading');
        }
      }
    }
  }
}

/**
 * Implements hook_paragraphs_field_widget_form_alter().
 */
function oa_related_paragraphs_field_widget_form_alter(&$element, &$form_state, &$context) {

  // Set the theme for the widget.
  $element['#theme'] = 'oa_related_paragraphs_' . $element['#bundle'] . '_form';

  // Get the title from pre-rendered markup.
  $bundle_title = trim(str_replace('Paragraph type:', '', $element['paragraph_bundle_title']['info']['#markup']));

  // Set the new title.
  $element['paragraph_bundle_title']['info']['#markup'] = $bundle_title;

  // Rewrite the value of the button.
  $element['actions']['remove_button']['#value'] = t('Remove !title', array(
    '!title' => rtrim(strip_tags($bundle_title)),
  ));
}

/**
 * Helper function to create a new panels pane for a given fieldname.
 *
 * @param $node
 */
function oa_related_default_pane($node, $field_name) {
  $fields = field_info_instances('node', $node->type);
  $instance = $fields[$field_name];
  $field_display = $instance['display']['default'];
  $pane = panels_new_pane('entity_field', 'node:' . $field_name, TRUE);
  $pane->configuration['formatter'] = $field_display['type'];
  $pane->configuration['formatter_settings'] = $field_display['settings'];
  $pane->configuration['label'] = $field_display['label'];
  $pane->configuration['context'] = 'panelizer';
  return $pane;
}

/**
 * Implements hook_panelizer_pre_render_alter().
 *
 * Adds the oa_related field panels pane right after the body field
 */
function oa_related_panelizer_pre_render_alter(&$panelizer, $display, $entity) {
  if (!empty($entity->field_oa_related)) {
    $found = FALSE;
    foreach ($display->content as $index => $panel) {
      if ($panel->type == 'entity_field' && $panel->subtype == 'node:field_oa_related') {
        $found = TRUE;
        break;
      }
    }
    if (!$found) {
      foreach ($display->content as $index => $panel) {
        if ($panel->type == 'entity_field' && $panel->subtype == 'node:body') {

          // found the body field so add a field_oa_related pane right after it
          $pane = oa_related_default_pane($entity, 'field_oa_related');
          $pid = uniqid();
          $pane->pid = $pid;
          $pane->uuid = $pid;

          // set the display panel to the same region as the body field
          $pane->panel = $panel->panel;

          // add new pane to list of available panes
          $panelizer->display->content[$pid] = $pane;

          // finally, insert the pid reference of the new pane into the correct spot
          // within the region right after the body position
          $i = array_search($index, $panelizer->display->panels[$panel->panel]);
          array_splice($panelizer->display->panels[$panel->panel], $i + 1, 0, array(
            $pid,
          ));
          break;
        }
      }
    }
  }
}

/**
 * Return the best section id to create $node in.
 *
 * @param $options array is optional to restrict return values
 */
function oa_related_get_best_section($type, $options = array(), $space_id = NULL) {
  return module_exists('oa_sections') ? oa_sections_get_best_section($type, $options, $space_id) : NULL;
}

/**
 * Implements hook_form_FORM_ID_alter() for node_form.
 *
 * For node/add and node/edit pages
 */
function oa_related_form_node_form_alter(&$form, &$form_state) {
  if (isset($form[OA_SECTION_FIELD])) {
    if (!empty($_GET['render']) && $_GET['render'] == 'references-dialog') {

      // we are in a References Dialog popup form
      $node = $form['#node'];
      $section = oa_related_get_best_section($node->type, $form[OA_SECTION_FIELD][LANGUAGE_NONE]['#options']);
      if (!empty($section)) {
        $form[OA_SECTION_FIELD][LANGUAGE_NONE]['#default_value'] = $section;
      }

      // move Section selection to top of node form so user can confirm it
      $section_field_weight = isset($form['body']['#weight']) ? $form['body']['#weight'] - 0.5 : 0;
      $form[OA_SECTION_FIELD]['#weight'] = $section_field_weight;

      // and move the field out of any field group
      if (isset($form['#group_children'])) {
        unset($form['#group_children'][OA_SECTION_FIELD]);
      }
    }
  }

  // Put the Related Content field right after the Body field on edit forms.
  if (isset($form['field_oa_related']) && isset($form['body'])) {
    $form['field_oa_related']['#weight'] = $form['body']['#weight'] + 0.5;
  }
}

/**
 * Implements hook_features_template_info().
 */
function oa_related_features_template_info() {
  $data =& drupal_static(__FUNCTION__);
  if (empty($data)) {
    $content_types = oa_related_get_content_types();
    $data = array();
    foreach ($content_types as $content_type => $present) {

      // Only have an entry if this will exist or needs to be deleted.
      if ($present || field_info_instance('node', 'field_oa_related', $content_type) && node_type_get_type($content_type)) {
        $data[] = array(
          'plugin' => 'field_instance',
          'template' => 'oa_related_field_default_field_instances_template',
          'deleted' => empty($present),
          'entity_type' => 'node',
          'bundle_type' => $content_type,
          'field' => 'field_oa_related',
        );
      }
    }
  }
  return $data;
}

/**
 * Determine list of content types to add the oa_related field to
 */
function oa_related_get_content_types() {
  $allowed_default = module_invoke_all('oa_related_allowed_default');
  $allowed_default = drupal_map_assoc($allowed_default);
  return array_intersect_key(variable_get('oa_related_allowed_types', $allowed_default), node_type_get_names());
}

/**
 * Template callback for field_topic.
 *
 * Used as a template for other bundles.
 * References to oa_wiki_page will be replaced by features_template.
 */
function oa_related_field_default_field_instances_template() {
  $field_instances = array();
  foreach (paragraphs_bundle_load() as $machine_name => $bundle) {
    $bundles[$machine_name] = $machine_name;
  }

  // Exported field_instance: 'node-oa_wiki_page-field_oa_related'
  $field_instances['node-oa_wiki_page-field_oa_related'] = array(
    'bundle' => 'oa_wiki_page',
    'comment_alter' => 0,
    'default_value' => NULL,
    'deleted' => 0,
    'description' => '',
    'display' => array(
      'default' => array(
        'label' => 'hidden',
        'module' => 'paragraphs',
        'settings' => array(
          'view_mode' => 'full',
        ),
        'type' => 'paragraphs_view',
        'weight' => 1,
      ),
      'featured' => array(
        'label' => 'above',
        'settings' => array(),
        'type' => 'hidden',
        'weight' => 0,
      ),
      'ical' => array(
        'label' => 'above',
        'settings' => array(),
        'type' => 'hidden',
        'weight' => 0,
      ),
      'teaser' => array(
        'label' => 'above',
        'settings' => array(),
        'type' => 'hidden',
        'weight' => 0,
      ),
    ),
    'entity_type' => 'node',
    'field_name' => 'field_oa_related',
    'label' => t('Paragraphs'),
    'required' => 0,
    'settings' => array(
      'add_mode' => 'button',
      'add_mode_instructions' => '',
      'allowed_bundles' => array_intersect_key($bundles, array_filter(variable_get('oa_related_paragraph_bundles', $bundles))),
      'default_edit_mode' => 'open',
      'hide_instructions' => 1,
      'title' => 'Paragraph',
      'title_multiple' => 'Paragraphs',
      'user_register_form' => FALSE,
    ),
    'widget' => array(
      'active' => 0,
      'module' => 'paragraphs',
      'settings' => array(),
      'type' => 'paragraphs_embed',
      'weight' => 4,
    ),
  );
  return $field_instances;
}

/**
 * Implements hook_oa_settings_form().
 */
function oa_related_oa_settings_form(&$form_state) {
  $forms = array();
  $form = array();
  $allowed_default = module_invoke_all('oa_related_allowed_default');
  drupal_map_assoc($allowed_default);
  $types = oa_core_list_content_types(TRUE, TRUE);
  $options = array();
  foreach ($types as $key => $type) {
    $options[$key] = $type->name;
  }
  $default = variable_get('oa_related_allowed_types', $allowed_default);
  $form['oa_related_allowed_types'] = array(
    '#type' => 'checkboxes',
    '#title' => 'Content that can reference other content',
    '#description' => 'Enable which content types should have a Related Content field.',
    '#options' => $options,
    '#default_value' => $default,
  );
  $form_state['build_info']['oa_related_allowed_types'] = $default;

  // Add enabling of oa_related.
  $bundles = array();
  $_bundles = paragraphs_bundle_load();
  foreach ($_bundles as $machine_name => $bundle) {
    $bundles[$machine_name] = $bundle->name;
  }
  $form['oa_related_paragraph_bundles'] = array(
    '#title' => t('Enabled paragraph bundles'),
    '#description' => t('Select which bundles related content field should have.'),
    '#type' => 'checkboxes',
    '#required' => TRUE,
    '#default_value' => array_filter(variable_get('oa_related_paragraph_bundles', array_keys($bundles))),
    '#options' => $bundles,
  );
  $form_state['oa_related_paragraph_bundles'] = $form['oa_related_paragraph_bundles']['#default_value'];
  $forms[] = array(
    'caption' => t('Related Content'),
    'form' => $form,
    'submit' => 'oa_related_settings_submit',
  );
  return $forms;
}

/**
 * Submit handler for oa_related_oa_settings_form
 */
function oa_related_settings_submit($form, &$form_state) {
  $update = FALSE;

  // only revert features template if content types have changed
  if (!empty($form_state['build_info']['oa_related_allowed_types']) && md5(serialize($form_state['build_info']['oa_related_allowed_types'])) != md5(serialize($form_state['values']['oa_related_allowed_types']))) {
    variable_set('oa_related_allowed_types', $form_state['values']['oa_related_allowed_types']);
    $update = TRUE;
  }
  if (isset($form_state['values']['oa_related_paragraph_bundles'])) {
    $filtered = array_filter($form_state['values']['oa_related_paragraph_bundles']);
    variable_set('oa_related_paragraph_bundles', $filtered);
    $form_state['values']['oa_related_paragraph_bundles'] = $filtered;
    $update = $update || $form_state['oa_related_paragraph_bundles'] != $filtered;
  }
  if ($update) {
    features_template_revert();
  }
}

/**
 * Implements hook_preprocess_HOOK().
 *
 * Pre-process theme variables for various paragraph item types.
 */
function oa_related_preprocess_entity(&$vars) {
  if ($vars['entity_type'] == 'paragraphs_item') {
    $field_name = NULL;
    $info = oa_related_get_paragraph_field_info();
    $value = NULL;
    $paragraph_wrapper = entity_metadata_wrapper('paragraphs_item', $vars['paragraphs_item']);
    $vars['oa_related_content'] = '';
    foreach ($info as $field_name => $bundle) {
      foreach ($bundle as $bundle_name => $data) {
        if ($paragraph_wrapper->bundle
          ->value() == $bundle_name) {
          if (isset($paragraph_wrapper->{$field_name})) {
            $value = $paragraph_wrapper->{$field_name}
              ->value();
          }
          if (isset($data['render callback'])) {
            if (is_array($data['render callback'])) {
              foreach ($data['render callback'] as $function) {
                if (function_exists($function)) {

                  // Call the function that will allow pre-processing for this layout selection.
                  $function($vars, $bundle_name, $field_name, $value);

                  // This allows other modules to alter the '$variables' array after we are done with it. If you want to
                  // completely override it then use drupal_alter: "hook_oa_related_field_info_alter()" and
                  // replace the 'render callback'.
                  drupal_alter($function, $vars, $bundle_name, $field_name, $value);
                }
              }
            }
            else {
              $function = $data['render callback'];
              if (function_exists($function)) {

                // Call the function that will allow pre-processing for this layout selection.
                $function($vars, $bundle_name, $field_name, $value);

                // This allows other modules to alter the '$variables' array after we are done with it. If you want to
                // completely override it then use drupal_alter: "hook_oa_related_field_info_alter()" and
                // replace the 'render callback'.
                drupal_alter($function, $vars, $bundle_name, $field_name, $value);
              }
            }
          }
        }
      }
    }
  }
}

/**
 * Implements hook_field_attach_presave().
 */
function oa_related_field_attach_presave($entity_type, $entity) {

  // check paragraph entities that use entityreferences with revisions
  if ($entity_type == 'paragraphs_item') {
    if (isset($entity->field_paragraph_lock_revision)) {
      $lock = field_get_items('paragraphs_item', $entity, 'field_paragraph_lock_revision');

      // only process entities that have the Lock Revision option field
      if (isset($lock)) {
        foreach ($entity as $field_name => $field) {

          // loop through entity looking for fields that have revision info
          if (is_array($field) && isset($field[LANGUAGE_NONE][0]['revision_id'])) {
            if (!empty($lock[0]['value'])) {

              // to lock the revision, get the previously saved revision value
              $original_items = isset($entity->original) ? (array) field_get_items($entity_type, $entity->original, $field_name) : array();
              $revision_id = !empty($field[LANGUAGE_NONE][0]['revision_id']) ? $field[LANGUAGE_NONE][0]['revision_id'] : NULL;
              $revision_id = !empty($original_items[0]['revision_id']) ? $original_items[0]['revision_id'] : $revision_id;
              if ($revision_id) {
                $entity->{$field_name}[LANGUAGE_NONE][0]['revision_id'] = $revision_id;
              }
            }
            else {

              // to unlock the revision, just remove it
              unset($entity->{$field_name}[LANGUAGE_NONE][0]['revision_id']);
            }
          }
        }
      }
    }
  }
}

/**
 * Implements hook_default_search_api_index_alter().
 */
function oa_related_default_search_api_index_alter(&$data) {

  // Generated via Features Override but moved into normal code
  // Adds various paragraph fields to the oa_search index automatically if available
  if (isset($data['database_node_index'])) {
    $data['database_node_index']->options['fields']['field_oa_related'] = array(
      'type' => 'list<integer>',
      'entity_type' => 'paragraphs_item',
    );

    /* WAS: '' */
    $data['database_node_index']->options['fields']['field_oa_related:field_paragraph_text:value'] = array(
      'type' => 'list<text>',
    );

    /* WAS: '' */
    $data['database_node_index']->options['fields']['field_oa_related:snippet_body'] = array(
      'type' => 'list<text>',
    );

    /* WAS: '' */
  }
  if (isset($data['node_index'])) {
    $data['node_index']->options['fields']['field_oa_related'] = array(
      'type' => 'list<integer>',
      'entity_type' => 'paragraphs_item',
    );

    /* WAS: '' */
    $data['node_index']->options['fields']['field_oa_related:field_paragraph_text:value'] = array(
      'type' => 'list<text>',
    );

    /* WAS: '' */
    $data['node_index']->options['fields']['field_oa_related:snippet_body'] = array(
      'type' => 'list<text>',
    );

    /* WAS: '' */
  }
}

/**
 * Implements hook_modules_enabled().
 */
function oa_related_template_modules_enabled($modules) {
  foreach ($modules as $module_name) {
    $node_infos = module_invoke($module_name, 'node_info');
    if (array_intersect_key(oa_related_get_content_types(), $node_infos)) {
      $cache =& drupal_static('features_get_default', array());
      $cache = array();
      features_template_revert('rebuild');
      break;
    }
  }
}

/**
 * Helper function to define allowed values for fields on a paragraph entity used to control the layout.
 *
 * This function is used in place of adding allowed values for those fields in the UI.
 *
 * @param array $field
 *   The field the values will be applied to.
 * @param array $instance
 *   The field instance.
 * @param string $entity_type
 *   The machine name of the paragraph entity.
 * @param object $entity
 *   The paragraphs item entity.
 * @param bool $cacheable
 *
 * @return array
 */
function oa_related_paragraphs_field_allowed_values($field, $instance, $entity_type, $entity, $cacheable) {
  $cache = cache_get(__FUNCTION__ . ':' . $instance['field_name'] . ':' . $instance['bundle'], 'cache_field');
  if (!$cache) {

    // Get information from all modules about this field. The field name does matter, there could be two fields on the
    // same bundle that allow different options.
    $info = oa_related_get_paragraph_field_info();
    $values = array();
    foreach ($info as $field_name => $bundle) {
      if ($field_name == $instance['field_name']) {
        foreach ($bundle as $name => $data) {
          $values = $data['allowed values'];

          // Allow any module to alter these options.
          drupal_alter('oa_related_' . $field_name . '_' . $name . '_values', $values);
        }
      }
    }
    cache_set(__FUNCTION__ . ':' . $instance['field_name'] . ':' . $instance['bundle'], $values, 'cache_field');
    return $values;
  }
  else {
    if (!empty($cache->data)) {
      return $cache->data;
    }
  }
}

/**
 * Helper function used to cache data returned by hook_oa_related_field_info().
 *
 * @return array
 */
function oa_related_get_paragraph_field_info() {
  $info =& drupal_static(__FUNCTION__);
  if (empty($info)) {
    $cache = cache_get(__FUNCTION__);
    if (!$cache) {

      // Get information from all modules about this field. The field name does matter, there could be two fields on the
      // same bundle that allow different options.
      $info = module_invoke_all('oa_related_field_info');
      drupal_alter('oa_related_field_info', $info);
      return $info;
    }
    else {
      if (!empty($cache->data)) {
        return $cache->data;
      }
    }
  }
  return $info;
}

/**
 * Implements hook_oa_related_icons().
 *
 * This is using font-awesome unicode values to return icons for paragraph
 * buttons.
 *
 * @see http://fortawesome.github.io/Font-Awesome/3.2.1/cheatsheet/
 */
function oa_related_oa_related_icons($type) {
  $info = array();
  switch ($type) {
    case 'paragraph_content':
      $info = array(
        'icon' => decode_entities('&#xf08e;'),
      );
      break;
    case 'paragraph_media':
      $info = array(
        'icon' => decode_entities('&#xf03e;'),
      );
      break;
    case 'paragraph_snippet':
      $info = array(
        'icon' => decode_entities('&#xf0c4;'),
      );
      break;
    case 'paragraph_text':
      $info = array(
        'icon' => decode_entities('&#xf0f6;'),
      );
      break;
    default:
      break;
  }
  return $info;
}

Functions

Namesort descending Description
oa_related_ctools_plugin_directory Implements hook_ctools_plugin_directory().
oa_related_default_pane Helper function to create a new panels pane for a given fieldname.
oa_related_default_search_api_index_alter Implements hook_default_search_api_index_alter().
oa_related_features_template_info Implements hook_features_template_info().
oa_related_field_attach_presave Implements hook_field_attach_presave().
oa_related_field_default_field_instances_template Template callback for field_topic.
oa_related_form_field_ui_display_overview_form_alter Implements hook_form_FORMID_alter().
oa_related_form_node_form_alter Implements hook_form_FORM_ID_alter() for node_form.
oa_related_get_best_section Return the best section id to create $node in.
oa_related_get_content_types Determine list of content types to add the oa_related field to
oa_related_get_paragraph_field_info Helper function used to cache data returned by hook_oa_related_field_info().
oa_related_node_type_update Implements hook_node_type_update().
oa_related_oa_related_icons Implements hook_oa_related_icons().
oa_related_oa_settings_form Implements hook_oa_settings_form().
oa_related_panelizer_pre_render_alter Implements hook_panelizer_pre_render_alter().
oa_related_panels_display_save Implements hook_panels_display_save().
oa_related_paragraphs_field_allowed_values Helper function to define allowed values for fields on a paragraph entity used to control the layout.
oa_related_paragraphs_field_widget_form_alter Implements hook_paragraphs_field_widget_form_alter().
oa_related_preprocess_entity Implements hook_preprocess_HOOK().
oa_related_settings_submit Submit handler for oa_related_oa_settings_form
oa_related_template_modules_enabled Implements hook_modules_enabled().
oa_related_theme Implements hook_theme().
_oa_related_enable_related Helper function to enable or disable related content for a given node type. NOTE: This determines if the content type is available via the Related Content Paragraph type It is *not* related to whether oa_related field is added to the content type. See…
_oa_related_has_panelizer_viewmode Helper function to determine if a given content type has a given panelized view mode

Constants