drupal_get_path('module', 'relevant_content_cck') .'/theme', 'file' => 'relevant_content_cck.theme.inc', 'arguments' => array('element' => NULL, 'type' => 'default'), ); $base = array( 'path' => drupal_get_path('module', 'relevant_content_cck') .'/theme', 'file' => 'relevant_content_cck.theme.inc', 'arguments' => array('element' => NULL), ); $hooks['relevant_content_cck_formatter_default'] = $base; $hooks['relevant_content_cck_formatter_plain'] = $base; $hooks['relevant_content_cck_formatter_teaser'] = $base; $hooks['relevant_content_cck_formatter_full'] = $base; if (module_exists('token')) { $hooks['relevant_content_cck_formatter_token_teaser'] = $base; $hooks['relevant_content_cck_formatter_token_full'] = $base; } return $hooks; } /** * Implementation of hook_field_info(). */ function relevant_content_cck_field_info() { return array( 'relevant_content' => array( 'label' => t('Relevant Content'), 'description' => t('A read only field for listing relevant nodes.'), ), ); } /** * Implementation of hook_field_settings(). */ function relevant_content_cck_field_settings($op, $field) { switch ($op) { case 'form' : $form = array(); $form['multiple'] = $form['required'] = array('#type' => 'value'); $form['relevant_nodetypes'] = array( '#type' => 'checkboxes', '#title' => t('Relevant Node Types'), '#default_value' => is_array($field['relevant_nodetypes']) ? $field['relevant_nodetypes'] : array(), '#options' => node_get_types('names'), '#required' => TRUE, '#description' => t('Select the node types you would like to include in this Relevant Content Field'), ); $vocabs = array(); foreach (taxonomy_get_vocabularies() as $vid => $voc) { $vocabs[$vid] = $voc->name; } // If the vocabularies array is empty, then we should prompt the user to create a vocabulary before they configure the field. if (empty($vocabs)) { // If they have permission to admin taxonomy then configure a link with appropriate destinations/redirections if (user_access('administer taxonomy')) { $link_options = array('query' => array('destination' => $_GET['q'])); $link = l('Create a vocabulary now', 'admin/content/taxonomy/add/vocabulary', $link_options); } // Otherwise, display an error message asking them to get an admin to do it. else { $link = t('You do not have permission to create vocabularies. An administrator must create one for you.'); } // Display the error message on a page on its own - we dont want the user to complete the form as the form itself is incomplete // TODO: Is this OK for usability? drupal_set_message( t('You must define at least one vocabulary before you can continue. !link.', array('!link' => $link)), 'error' ); print theme('page', ''); exit; } $form['relevant_vocabs'] = array( '#type' => 'checkboxes', '#title' => t('Relevant Vocabularies'), '#default_value' => is_array($field['relevant_vocabs']) ? $field['relevant_vocabs'] : array(), '#options' => $vocabs, '#required' => TRUE, '#description' => t('Select the vocabularies you would like to include in this Relevant Content Field. Only terms in the selected vocabularies will be used to find relevant content.'), ); $max_items = (isset($field['relevant_result_limit']) && !empty($field['relevant_result_limit'])) ? $field['relevant_result_limit'] : 5; $form['relevant_result_limit'] = array( '#type' => 'textfield', '#title' => t('Maximum Results'), '#description' => t('Relevant content to display per page. Must be more than 0.'), '#default_value' => $max_items, '#required' => TRUE, ); $form['relevant_header'] = array( '#tree' => TRUE, '#title' => t('Header Text'), '#type' => 'fieldset', '#description' => t('Optionally include some text to appear above the list and below the label (if the label is enabled).'), '#collapsible' => TRUE, '#collapsed' => TRUE, ); $form['relevant_header']['body'] = array( '#type' => 'textarea', '#default_value' => isset($field['relevant_header']['body']) ? $field['relevant_header']['body'] : '', ); $format = isset($field['relevant_header']['format']) ? $field['relevant_header']['format'] : FILTER_FORMAT_DEFAULT; $form['relevant_header']['format'] = filter_form($format, NULL, array('relevant_header', 'format')); $form['relevant_absolute_links'] = array( '#type' => 'checkbox', '#title' => t('Absolute Links'), '#description' => t('If enabled, any outputted links will have absolute URLs. If not enabled (default), URLs will be relative.'), '#default_value' => isset($field['relevant_absolute_links']) ? $field['relevant_absolute_links'] : 0, ); return $form; case 'validate' : if (preg_match('|[^0-9]|', $field['relevant_result_limit']) || $field['relevant_result_limit'] < 1) { form_set_error('relevant_result_limit', t('The result limit should be a whole and positive number')); } break; case 'save' : return array('relevant_nodetypes', 'relevant_vocabs', 'relevant_result_limit', 'relevant_header', 'relevant_absolute_links'); } } /** * Implementation of hook_field(). */ function relevant_content_cck_field($op, &$node, $field, &$items, $teaser, $page) { switch ($op) { case 'load': //Get the terms using the handy term wrapper in the parent module $terms = relevant_content_get_page_terms($node); // If there are no terms, return an empty item set - there will be nothing in common with this. if (empty($terms)) return array($field['field_name'] => array()); // Grab the types & vocabs $types = array_values(array_filter($field['relevant_nodetypes'])); $vocabs = array_values(array_filter($field['relevant_vocabs'])); // Filter the terms from the vocabs associated with this field. foreach ($terms as $tid => $term) { if (in_array($term->vid, $vocabs)) { $terms[$tid] = $tid; } else { unset($terms[$tid]); } } // If there are no terms *after* filtering, return an empty item set - there will be nothing in common with this. if (empty($terms)) return array($field['field_name'] => array()); // Search for items and return the item set. $items = relevant_content_get_nodes($types, $terms, array(), $field['relevant_result_limit']); if (empty($items)) return array($field['field_name'] => array()); // We need the test as the function "relevant_content_get_nodes" returns false on an empty set. Here we need just an array. return array($field['field_name'] => array('items' => $items, 'header' => $field['relevant_header'])); case 'sanitize' : // Apply the filter to the body and store in 'safe' if (!empty($items['header']['body'])) { $items['header']['safe'] = check_markup($items['header']['body'], $items['header']['format'], FALSE); } else { $items['header']['safe'] = ''; } break; } } /** * Implementation of hook_field_formatter_info(). */ function relevant_content_cck_field_formatter_info() { $optional = array(); if (module_exists('token')) { $optional['token_teaser'] = array('multiple values' => CONTENT_HANDLE_MODULE, 'field types' => array('relevant_content'), 'label' => t('Custom Tokens Teaser View')); $optional['token_full'] = array('multiple values' => CONTENT_HANDLE_MODULE, 'field types' => array('relevant_content'), 'label' => t('Custom Tokens Full View')); } return array( 'default' => array('multiple values' => CONTENT_HANDLE_MODULE, 'field types' => array('relevant_content'), 'label' => t('Node Title - Link')), 'plain' => array('multiple values' => CONTENT_HANDLE_MODULE, 'field types' => array('relevant_content'), 'label' => t('Node Title - Plain Text')), 'teaser' => array('multiple values' => CONTENT_HANDLE_MODULE, 'field types' => array('relevant_content'), 'label' => t('Node Teaser')), 'full' => array('multiple values' => CONTENT_HANDLE_MODULE, 'field types' => array('relevant_content'), 'label' => t('Node Full View')), ) + $optional; } /** * Implementation of hook_widget_info(). */ function relevant_content_cck_widget_info() { return array( 'relevant_content_list' => array( 'label' => t('Relevant Nodes (Read Only)'), 'field types' => array('relevant_content'), 'multiple values' => CONTENT_HANDLE_MODULE, 'callbacks' => array( 'default value' => CONTENT_CALLBACK_NONE, ), ), ); } /** * Implementation of hook_elements(). */ function relevant_content_cck_elements() { return array( 'relevant_content_list' => array( '#input' => FALSE, ), ); } /** * Implementation of hook_widget(). */ function relevant_content_cck_widget(&$form, &$form_state, $field, $items, $delta = 0) { return array(); } /** * Implementation of hook_widget_settings(). */ function relevant_content_cck_widget_settings($op, $widget) { // If token isn't installed then dont bother with the form below if (!module_exists('token')) return; switch ($op) { case 'form' : $form = array(); $form['token_settings'] = array( '#type' => 'fieldset', '#title' => t('Token Output Settings'), '#collapsible' => TRUE, '#collapsed' => FALSE, ); $form['token_settings']['token_teaser'] = array( '#type' => 'fieldset', '#title' => t('Tokens for teaser view formatter'), '#tree' => TRUE, ); $form['token_settings']['token_teaser']['body'] = array( '#type' => 'textarea', '#description' => t('Tokens entered in here will be used for the optional token teaser formatter. This allows customized output.'), '#default_value' => $widget['token_teaser']['body'], '#rows' => 4, ); $form['token_settings']['token_teaser']['format'] = filter_form($widget['token_teaser']['format'], NULL, array('token_teaser', 'format')); $form['token_settings']['token_full'] = array( '#type' => 'fieldset', '#title' => t('Tokens for full view formatter'), '#tree' => TRUE, ); $form['token_settings']['token_full']['body'] = array( '#type' => 'textarea', '#description' => t('Tokens entered in here will be used for the optional token full formatter. This allows customized output.'), '#default_value' => $widget['token_full']['body'], '#rows' => 4, ); $form['token_settings']['token_full']['format'] = filter_form($widget['token_full']['format'], NULL, array('token_full', 'format')); $form['token_settings']['token_help'] = array( '#type' => 'fieldset', '#title' => t('Token Help'), '#collapsed' => TRUE, '#collapsible' => TRUE, ); $form['token_settings']['token_help']['view'] = array( '#type' => 'markup', '#value' => theme('token_help'), ); return $form; case 'save' : return array('token_teaser', 'token_full'); } } function relevant_content_cck_preprocess_content_field(&$variables) { // If the field is a relevant content field, we need to add more suggestion types (so we can easily theme all RC fields). // This is necessary so that we can override the default content-field template (which doesn't work correctly for us) if ($variables['field_type'] == 'relevant_content') { $suggestions = array( 'content-field-relevant-content', 'content-field-relevant-content-'. $variables['field_name'], 'content-field-relevant-content-'. $variables['node']->type, 'content-field-relevant-content-'. $variables['field_name'] .'-'. $variables['node']->type, ); $variables['template_files'] = array_merge($variables['template_files'], $suggestions); $variables['field_items'] = $variables['items']['0']['view']; $variables['field_header'] = $variables['items']['header']['safe']; } } function relevant_content_cck_theme_registry_alter(&$theme_registry) { // This seems necessary to allow the theme registry to also search the RC folder for template files. $theme_registry['content_field']['theme paths'][] = drupal_get_path('module', 'relevant_content_cck') .'/theme'; } function relevant_content_cck_content_is_empty() { return FALSE; }