nodequeue_reference.module in Nodequeue reference 7
Form field type for node queues.
File
nodequeue_reference.moduleView source
<?php
/**
* @file
* Form field type for node queues.
*/
/**
* Implements hook_menu().
*/
function nodequeue_reference_menu() {
$items['nodequeue_reference/autocomplete/%/%/%'] = array(
'page callback' => 'nodequeue_reference_autocomplete',
'page arguments' => array(
2,
3,
4,
),
'access callback' => 'nodequeue_reference_autocomplete_access',
'access arguments' => array(
2,
3,
4,
),
'type' => MENU_CALLBACK,
);
if (module_exists('references_dialog')) {
$items['nodequeue-reference/dialog/redirect'] = array(
'page callback' => 'nodequeue_reference_dialog_redirect_page',
'page arguments' => array(
3,
),
'access callback' => TRUE,
'file' => 'includes/nodequeue_reference.dialog_pages.inc',
'type' => MENU_CALLBACK,
);
}
return $items;
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function nodequeue_reference_form_nodequeue_edit_queue_form_alter(&$form, &$form_state, $form_id) {
if (module_exists('references_dialog') && references_dialog_in_dialog() && references_dialog_close_on_submit()) {
$form['#submit'][] = 'nodequeue_reference_nodequeue_edit_submit';
}
}
/**
* Submit callback for closing the dialog tab.
* If creating a new Nodequeue, we will be directed to the callback for modifing the nodequeue nodes.
* The menu callback will output javascript that will close the dialog, and pass paramenters to the main window.
* Note that the field value will be overriden in the end.
*/
function nodequeue_reference_nodequeue_edit_submit($form, &$form_state) {
$qid = $form_state['values']['qid'];
$is_new = !empty($_GET['nodequeue-new-dialog']);
if ($is_new) {
// If creating a new nodequeue, go to the nodequeue view for adding nodes.
$subqueues = nodequeue_load_subqueues_by_queue($qid);
$keys = array_keys($subqueues);
$sqid = reset($keys);
$_GET['destination'] = "admin/structure/nodequeue/{$qid}/view/{$sqid}" . '?render=references-dialog';
}
else {
$_GET['destination'] = "nodequeue-reference/dialog/redirect/{$qid}" . '?render=references-dialog&references-dialog-close=1';
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function nodequeue_reference_form_nodequeue_arrange_subqueue_form_alter(&$form, &$form_state, $form_id) {
if (module_exists('references_dialog') && references_dialog_in_dialog() && references_dialog_close_on_submit()) {
$form['actions']['submit']['#submit'][] = 'nodequeue_reference_nodequeue_view_submit';
}
}
/**
* Submit callback for modifying nodequeue nodes from the dialog
* The menu callback will output javascript that will close the dialog, and pass paramenters to the main window.
* Note that the field value will be overriden in the end.
*/
function nodequeue_reference_nodequeue_view_submit($form, &$form_state) {
if (references_dialog_in_dialog() && references_dialog_close_on_submit()) {
$qid = $form['nodes']['#queue']['qid'];
$_GET['destination'] = "nodequeue-reference/dialog/redirect/{$qid}" . '?render=references-dialog&references-dialog-close=1';
}
}
/**
* Menu access callback for nodequeue reference autocomplete paths.
*
* Check for both 'edit' and 'view' access in the unlikely event
* a user has edit but not view access.
*/
function nodequeue_reference_autocomplete_access($entity_type, $bundle, $field_name, $entity = NULL, $account = NULL) {
return user_access('access content', $account) && ($field = field_info_field($field_name)) && field_info_instance($entity_type, $field_name, $bundle) && field_access('view', $field, $entity_type, $entity, $account) && field_access('edit', $field, $entity_type, $entity, $account);
}
/**
* Implements hook_field_info().
*/
function nodequeue_reference_field_info() {
return array(
'nodequeue_reference' => array(
'label' => t('Nodequeue reference'),
'description' => t('This field stores a reference to a nodequeue'),
'default_widget' => 'options_select',
'default_formatter' => 'nodequeue_reference_formatter',
'settings' => array(),
),
);
}
/**
* Implements hook_field_widget_info().
*/
function nodequeue_reference_field_widget_info() {
return array(
'nodequeue_reference_autocomplete' => array(
'label' => t('Autocomplete nodequeue field'),
'field types' => array(
'nodequeue_reference',
),
'settings' => array(
'size' => 60,
'autocomplete_path' => 'nodequeue_reference/autocomplete',
'autocomplete_match' => 'contains',
'link' => 0,
),
'property_type' => 'integer',
),
);
}
/**
* Implements hook_field_widget_settings_form().
*/
function nodequeue_reference_field_widget_settings_form($field, $instance) {
$widget = $instance['widget'];
$defaults = field_info_widget_settings($widget['type']);
$settings = array_merge($defaults, $widget['settings']);
$form = array();
if ($widget['type'] == 'nodequeue_reference_autocomplete') {
$form['autocomplete_match'] = array(
'#type' => 'select',
'#title' => t('Autocomplete matching'),
'#default_value' => $settings['autocomplete_match'],
'#options' => array(
'starts_with' => t('Starts with'),
'contains' => t('Contains'),
),
'#description' => t('Select the method used to collect autocomplete suggestions. Note that <em>Contains</em> can cause performance issues on sites with thousands of nodes.'),
);
$form['size'] = array(
'#type' => 'textfield',
'#title' => t('Size of textfield'),
'#default_value' => $settings['size'],
'#element_validate' => array(
'_element_validate_integer_positive',
),
'#required' => TRUE,
);
}
return $form;
}
/**
* Implements hook_field_widget_info_alter().
*/
function nodequeue_reference_field_widget_info_alter(&$info) {
$info['options_select']['field types'][] = 'nodequeue_reference';
$info['options_buttons']['field types'][] = 'nodequeue_reference';
}
/**
* Implements hook_field_is_empty().
*/
function nodequeue_reference_field_is_empty($item, $field) {
return empty($item['qid']);
}
/**
* Implements hook_field_formatter_info().
*/
function nodequeue_reference_field_formatter_info() {
return array(
'nodequeue_reference_default' => array(
'label' => t('Default'),
'field types' => array(
'nodequeue_reference',
),
),
'nodequeue_reference_qid' => array(
'label' => t('Qid Nodequeue'),
'field types' => array(
'nodequeue_reference',
),
),
'nodequeue_list_nodes' => array(
'label' => t('List of nodes'),
'field types' => array(
'nodequeue_reference',
),
),
);
}
/**
* Implements hook_field_formatter_view().
*/
function nodequeue_reference_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
switch ($display['type']) {
case 'nodequeue_reference_default':
foreach ($items as $delta => $item) {
if ($item['qid']) {
$nodequeue = nodequeue_load($item['qid']);
$output = $nodequeue->title;
$element[$delta] = array(
'#markup' => $output,
);
}
}
break;
case 'nodequeue_reference_qid':
foreach ($items as $delta => $item) {
$element[$delta] = array(
'#markup' => $item['qid'],
);
}
break;
case 'nodequeue_list_nodes':
foreach ($items as $delta => $item) {
$result = array();
$queue = nodequeue_load($item['qid']);
$nodes = nodequeue_load_nodes($item['qid'], $queue->reverse, 0, $queue->count);
foreach ($nodes as $node) {
$label = entity_label('node', $node);
$uri = entity_uri('node', $node);
$result[] = l($label, $uri['path'], array(
'attributes' => array(
'class' => array(
'node-link',
),
),
));
}
$element[$delta]['#markup'] = theme('item_list', array(
'items' => $result,
));
}
break;
}
return $element;
}
/**
* Implements hook_field_widget_form().
*/
function nodequeue_reference_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$widget = $instance['widget'];
$defaults = field_info_widget_settings($widget['type']);
$settings = array_merge($defaults, $widget['settings']);
global $user;
switch ($instance['widget']['type']) {
case 'nodequeue_reference_autocomplete':
$element += array(
'#type' => 'textfield',
'#default_value' => isset($items[$delta]['qid']) ? $items[$delta]['qid'] : NULL,
'#autocomplete_path' => $settings['autocomplete_path'] . '/' . $instance['entity_type'] . '/' . $instance['bundle'] . '/' . $field['field_name'],
'#size' => $settings['size'],
'#maxlength' => NULL,
'#element_validate' => array(
'nodequeue_reference_autocomplete_validate',
),
'#value_callback' => 'nodequeue_reference_autocomplete_value',
);
break;
}
return array(
'qid' => $element,
);
}
/**
* Value callback for a nodequeue_reference autocomplete element.
*
* Replace the queue qid with a queue title.
*/
function nodequeue_reference_autocomplete_value($element, $input = FALSE) {
if ($input === FALSE) {
$qid = $element['#default_value'];
if (!empty($qid)) {
$queue = nodequeue_load($qid);
$value = $queue->title;
$value .= ' [qid: ' . $qid . ']';
return $value;
}
}
}
/**
* Validation callback for a nodequeue_reference autocomplete element.
*/
function nodequeue_reference_autocomplete_validate($element, &$form_state, $form) {
$field = field_widget_field($element, $form_state);
$instance = field_widget_instance($element, $form_state);
$value = $element['#value'];
$qid = NULL;
if (!empty($value)) {
// Check whether we have an explicit "[qid:n]" input.
preg_match('/^(?:\\s*|(.*) )?\\[\\s*qid*:\\s*(\\d+)\\s*\\]$/', $value, $matches);
if (!empty($matches)) {
// Explicit qid. Check that the 'title' part matches the actual title for
// the qid.
list(, $title, $qid) = $matches;
if (!empty($title)) {
$real_title = db_select('nodequeue_queue', 'q')
->fields('q', array(
'title',
))
->condition('q.qid', $qid)
->execute()
->fetchField();
if (trim($title) != trim($real_title)) {
form_error($element, t('%name: title mismatch. Please check your selection.', array(
'%name' => $instance['label'],
)));
}
}
}
else {
form_error($element, t('%name: found no valid nodequeue with that title.', array(
'%name' => $instance['label'],
)));
}
}
// Set the element's value as the nodequeue id that was extracted from the entered
// input.
form_set_value($element, $qid, $form_state);
}
/**
* Implements hook_field_widget_error().
*/
function nodequeue_reference_field_widget_error($element, $error, $form, &$form_state) {
form_error($element, $error['message']);
}
/**
* Implements hook_options_list().
*/
function nodequeue_reference_options_list($field, $instance, $entity_type, $entity) {
$result = db_query("SELECT qid, title FROM {nodequeue_queue} ORDER BY title");
$options = array();
foreach ($result as $queue) {
$options[$queue->qid] = $queue->title;
}
return $options;
}
/**
* Menu callback for the autocomplete results.
*/
function nodequeue_reference_autocomplete($entity_type, $bundle, $field_name, $string = '') {
$field = field_info_field($field_name);
$instance = field_info_instance($entity_type, $field_name, $bundle);
$options = array(
'string' => $string,
'match' => $instance['widget']['settings']['autocomplete_match'],
'limit' => 10,
'ids' => array(),
);
$results =& drupal_static(__FUNCTION__, array());
// Create unique id for static cache.
$cid = $field['field_name'] . ':' . $options['match'] . ':' . ($options['string'] !== '' ? $options['string'] : implode('-', $options['ids'])) . ':' . $options['limit'];
if (!isset($results[$cid])) {
$references = FALSE;
$query = db_select('nodequeue_queue', 'q');
$queue_qid_alias = $query
->addField('q', 'qid');
$queue_title_alias = $query
->addField('q', 'title');
if ($options['string'] !== '') {
switch ($options['match']) {
case 'contains':
$query
->condition('title', '%' . $options['string'] . '%', 'LIKE');
break;
case 'starts_with':
$query
->condition('q.title', $options['string'] . '%', 'LIKE');
break;
case 'equals':
default:
// no match type or incorrect match type: use "="
$query
->condition('q.title', $options['string']);
break;
}
}
if ($options['ids']) {
$query
->condition('q.qid', $options['ids'], 'IN');
}
if ($options['limit']) {
$query
->range(0, $options['limit']);
}
$query
->orderBy($queue_title_alias);
$result = $query
->execute()
->fetchAll();
$references = array();
foreach ($result as $queue) {
$references[$queue->qid] = array(
'title' => $queue->title,
'rendered' => check_plain($queue->title),
);
}
// Store the results.
$results[$cid] = !empty($references) ? $references : array();
}
$references = $results[$cid];
$matches = array();
foreach ($references as $id => $row) {
// Markup is fine in autocompletion results (might happen when rendered
// through Views) but we want to remove hyperlinks.
$suggestion = preg_replace('/<a href="([^<]*)">([^<]*)<\\/a>/', '$2', $row['rendered']);
// Add a class wrapper for a few required CSS overrides.
$matches[$row['title'] . " [qid: {$id}]"] = '<div class="reference-autocomplete">' . $suggestion . '</div>';
}
drupal_json_output($matches);
}