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