Commit 70c91e33 authored by Steven Wittens's avatar Steven Wittens
Browse files

#56457: hook_search() form API conversion

parent d498d4c1
......@@ -731,94 +731,6 @@ function node_search($op = 'search', $keys = null) {
'snippet' => search_excerpt($keys, $node->body));
}
return $results;
case 'form':
$form = array();
// Keyword boxes
$form['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced search'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#attributes' => array('class' => 'search-advanced'),
);
$form['advanced']['keywords'] = array(
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
);
$form['advanced']['keywords']['or'] = array(
'#type' => 'textfield',
'#title' => t('Containing any of the words'),
'#size' => 30,
'#maxlength' => 255,
);
$form['advanced']['keywords']['phrase'] = array(
'#type' => 'textfield',
'#title' => t('Containing the phrase'),
'#size' => 30,
'#maxlength' => 255,
);
$form['advanced']['keywords']['negative'] = array(
'#type' => 'textfield',
'#title' => t('Containing none of the words'),
'#size' => 30,
'#maxlength' => 255,
);
// Taxonomy box
if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) {
$form['advanced']['category'] = array(
'#type' => 'select',
'#title' => t('Only in the category(s)'),
'#prefix' => '<div class="criterion">',
'#size' => 10,
'#suffix' => '</div>',
'#options' => $taxonomy,
'#multiple' => TRUE,
);
}
// Node types
$types = node_get_types();
$form['advanced']['type'] = array(
'#type' => 'checkboxes',
'#title' => t('Only of the type(s)'),
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
'#options' => $types,
);
$form['advanced']['submit'] = array(
'#type' => 'submit',
'#value' => t('Advanced search'),
'#prefix' => '<div class="action">',
'#suffix' => '</div><br clear="all" />',
);
return $form;
case 'post':
// Insert extra restrictions into the search keywords string.
$edit = &$_POST['edit'];
if (isset($edit['type']) && is_array($edit['type'])) {
$keys = search_query_insert($keys, 'type', implode(',', array_keys($edit['type'])));
}
if (isset($edit['category']) && is_array($edit['category'])) {
$keys = search_query_insert($keys, 'category', implode(',', $edit['category']));
}
if ($edit['or'] != '') {
if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' '. $edit['or'], $matches)) {
$keys = $keys .' '. implode(' OR ', $matches[1]);
}
}
if ($edit['negative'] != '') {
if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' '. $edit['negative'], $matches)) {
$keys = $keys .' -'. implode(' -', $matches[1]);
}
}
if ($edit['phrase'] != '') {
$keys .= ' "'. str_replace('"', ' ', $edit['phrase']) .'"';
}
return trim($keys);
}
}
......@@ -2163,14 +2075,126 @@ function node_update_index() {
}
}
/**
* Implementation of hook_form_alter().
*/
function node_form_alter($form_id, &$form) {
// Node publishing options
if (isset($form['type']) && $form['type']['#value'] .'_node_settings' == $form_id) {
$form['workflow']['node_options_'. $form['type']['#value']] = array(
'#type' => 'checkboxes', '#title' => t('Default options'), '#default_value' => variable_get('node_options_'. $form['type']['#value'], array('status', 'promote')),
'#options' => array('status' => t('Published'), 'moderate' => t('In moderation queue'), 'promote' => t('Promoted to front page'), 'sticky' => t('Sticky at top of lists'), 'revision' => t('Create new revision')),
$form['workflow']['node_options_'. $form['type']['#value']] = array('#type' => 'checkboxes',
'#title' => t('Default options'),
'#default_value' => variable_get('node_options_'. $form['type']['#value'], array('status', 'promote')),
'#options' => array(
'status' => t('Published'),
'moderate' => t('In moderation queue'),
'promote' => t('Promoted to front page'),
'sticky' => t('Sticky at top of lists'),
'revision' => t('Create new revision'),
),
'#description' => t('Users with the <em>administer nodes</em> permission will be able to override these options.'),
);
}
// Advanced node search form
elseif ($form_id == 'search_form' && arg(1) == 'node') {
// Keyword boxes:
$form['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced search'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#attributes' => array('class' => 'search-advanced'),
);
$form['advanced']['keywords'] = array(
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
);
$form['advanced']['keywords']['or'] = array(
'#type' => 'textfield',
'#title' => t('Containing any of the words'),
'#size' => 30,
'#maxlength' => 255,
);
$form['advanced']['keywords']['phrase'] = array(
'#type' => 'textfield',
'#title' => t('Containing the phrase'),
'#size' => 30,
'#maxlength' => 255,
);
$form['advanced']['keywords']['negative'] = array(
'#type' => 'textfield',
'#title' => t('Containing none of the words'),
'#size' => 30,
'#maxlength' => 255,
);
// Taxonomy box:
if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) {
$form['advanced']['category'] = array(
'#type' => 'select',
'#title' => t('Only in the category(s)'),
'#prefix' => '<div class="criterion">',
'#size' => 10,
'#suffix' => '</div>',
'#options' => $taxonomy,
'#multiple' => TRUE,
);
}
// Node types:
$types = node_get_types();
$form['advanced']['type'] = array(
'#type' => 'checkboxes',
'#title' => t('Only of the type(s)'),
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
'#options' => $types,
);
$form['advanced']['submit'] = array(
'#type' => 'submit',
'#value' => t('Advanced search'),
'#prefix' => '<div class="action">',
'#suffix' => '</div><br clear="all" />',
);
$form['#validate']['node_search_validate'] = array();
}
}
/**
* Form API callback for the search form. Registered in node_form_alter().
*/
function node_search_validate($form_id, $form_values) {
// Initialise using any existing basic search keywords.
$keys = $form_values['processed_keys']['#ref'];
// Insert extra restrictions into the search keywords string.
if (isset($form_values['type']) && is_array($form_values['type'])) {
// Retrieve selected types - Forms API sets the value of unselected checkboxes to 0.
$form_values['type'] = array_filter($form_values['type']);
if (count($form_values['type'])) {
$keys = search_query_insert($keys, 'type', implode(',', array_keys($form_values['type'])));
}
}
if (isset($form_values['category']) && is_array($form_values['category'])) {
$keys = search_query_insert($keys, 'category', implode(',', $form_values['category']));
}
if ($form_values['or'] != '') {
if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' '. $form_values['or'], $matches)) {
$keys .= ' '. implode(' OR ', $matches[1]);
}
}
if ($form_values['negative'] != '') {
if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' '. $form_values['negative'], $matches)) {
$keys .= ' -'. implode(' -', $matches[1]);
}
}
if ($form_values['phrase'] != '') {
$keys .= ' "'. str_replace('"', ' ', $form_values['phrase']) .'"';
}
if (!empty($keys)) {
$form_values['processed_keys']['#ref'] = trim($keys);
}
}
/**
......
......@@ -731,94 +731,6 @@ function node_search($op = 'search', $keys = null) {
'snippet' => search_excerpt($keys, $node->body));
}
return $results;
case 'form':
$form = array();
// Keyword boxes
$form['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced search'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#attributes' => array('class' => 'search-advanced'),
);
$form['advanced']['keywords'] = array(
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
);
$form['advanced']['keywords']['or'] = array(
'#type' => 'textfield',
'#title' => t('Containing any of the words'),
'#size' => 30,
'#maxlength' => 255,
);
$form['advanced']['keywords']['phrase'] = array(
'#type' => 'textfield',
'#title' => t('Containing the phrase'),
'#size' => 30,
'#maxlength' => 255,
);
$form['advanced']['keywords']['negative'] = array(
'#type' => 'textfield',
'#title' => t('Containing none of the words'),
'#size' => 30,
'#maxlength' => 255,
);
// Taxonomy box
if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) {
$form['advanced']['category'] = array(
'#type' => 'select',
'#title' => t('Only in the category(s)'),
'#prefix' => '<div class="criterion">',
'#size' => 10,
'#suffix' => '</div>',
'#options' => $taxonomy,
'#multiple' => TRUE,
);
}
// Node types
$types = node_get_types();
$form['advanced']['type'] = array(
'#type' => 'checkboxes',
'#title' => t('Only of the type(s)'),
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
'#options' => $types,
);
$form['advanced']['submit'] = array(
'#type' => 'submit',
'#value' => t('Advanced search'),
'#prefix' => '<div class="action">',
'#suffix' => '</div><br clear="all" />',
);
return $form;
case 'post':
// Insert extra restrictions into the search keywords string.
$edit = &$_POST['edit'];
if (isset($edit['type']) && is_array($edit['type'])) {
$keys = search_query_insert($keys, 'type', implode(',', array_keys($edit['type'])));
}
if (isset($edit['category']) && is_array($edit['category'])) {
$keys = search_query_insert($keys, 'category', implode(',', $edit['category']));
}
if ($edit['or'] != '') {
if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' '. $edit['or'], $matches)) {
$keys = $keys .' '. implode(' OR ', $matches[1]);
}
}
if ($edit['negative'] != '') {
if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' '. $edit['negative'], $matches)) {
$keys = $keys .' -'. implode(' -', $matches[1]);
}
}
if ($edit['phrase'] != '') {
$keys .= ' "'. str_replace('"', ' ', $edit['phrase']) .'"';
}
return trim($keys);
}
}
......@@ -2163,14 +2075,126 @@ function node_update_index() {
}
}
/**
* Implementation of hook_form_alter().
*/
function node_form_alter($form_id, &$form) {
// Node publishing options
if (isset($form['type']) && $form['type']['#value'] .'_node_settings' == $form_id) {
$form['workflow']['node_options_'. $form['type']['#value']] = array(
'#type' => 'checkboxes', '#title' => t('Default options'), '#default_value' => variable_get('node_options_'. $form['type']['#value'], array('status', 'promote')),
'#options' => array('status' => t('Published'), 'moderate' => t('In moderation queue'), 'promote' => t('Promoted to front page'), 'sticky' => t('Sticky at top of lists'), 'revision' => t('Create new revision')),
$form['workflow']['node_options_'. $form['type']['#value']] = array('#type' => 'checkboxes',
'#title' => t('Default options'),
'#default_value' => variable_get('node_options_'. $form['type']['#value'], array('status', 'promote')),
'#options' => array(
'status' => t('Published'),
'moderate' => t('In moderation queue'),
'promote' => t('Promoted to front page'),
'sticky' => t('Sticky at top of lists'),
'revision' => t('Create new revision'),
),
'#description' => t('Users with the <em>administer nodes</em> permission will be able to override these options.'),
);
}
// Advanced node search form
elseif ($form_id == 'search_form' && arg(1) == 'node') {
// Keyword boxes:
$form['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced search'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#attributes' => array('class' => 'search-advanced'),
);
$form['advanced']['keywords'] = array(
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
);
$form['advanced']['keywords']['or'] = array(
'#type' => 'textfield',
'#title' => t('Containing any of the words'),
'#size' => 30,
'#maxlength' => 255,
);
$form['advanced']['keywords']['phrase'] = array(
'#type' => 'textfield',
'#title' => t('Containing the phrase'),
'#size' => 30,
'#maxlength' => 255,
);
$form['advanced']['keywords']['negative'] = array(
'#type' => 'textfield',
'#title' => t('Containing none of the words'),
'#size' => 30,
'#maxlength' => 255,
);
// Taxonomy box:
if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) {
$form['advanced']['category'] = array(
'#type' => 'select',
'#title' => t('Only in the category(s)'),
'#prefix' => '<div class="criterion">',
'#size' => 10,
'#suffix' => '</div>',
'#options' => $taxonomy,
'#multiple' => TRUE,
);
}
// Node types:
$types = node_get_types();
$form['advanced']['type'] = array(
'#type' => 'checkboxes',
'#title' => t('Only of the type(s)'),
'#prefix' => '<div class="criterion">',
'#suffix' => '</div>',
'#options' => $types,
);
$form['advanced']['submit'] = array(
'#type' => 'submit',
'#value' => t('Advanced search'),
'#prefix' => '<div class="action">',
'#suffix' => '</div><br clear="all" />',
);
$form['#validate']['node_search_validate'] = array();
}
}
/**
* Form API callback for the search form. Registered in node_form_alter().
*/
function node_search_validate($form_id, $form_values) {
// Initialise using any existing basic search keywords.
$keys = $form_values['processed_keys']['#ref'];
// Insert extra restrictions into the search keywords string.
if (isset($form_values['type']) && is_array($form_values['type'])) {
// Retrieve selected types - Forms API sets the value of unselected checkboxes to 0.
$form_values['type'] = array_filter($form_values['type']);
if (count($form_values['type'])) {
$keys = search_query_insert($keys, 'type', implode(',', array_keys($form_values['type'])));
}
}
if (isset($form_values['category']) && is_array($form_values['category'])) {
$keys = search_query_insert($keys, 'category', implode(',', $form_values['category']));
}
if ($form_values['or'] != '') {
if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' '. $form_values['or'], $matches)) {
$keys .= ' '. implode(' OR ', $matches[1]);
}
}
if ($form_values['negative'] != '') {
if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' '. $form_values['negative'], $matches)) {
$keys .= ' -'. implode(' -', $matches[1]);
}
}
if ($form_values['phrase'] != '') {
$keys .= ' "'. str_replace('"', ' ', $form_values['phrase']) .'"';
}
if (!empty($keys)) {
$form_values['processed_keys']['#ref'] = trim($keys);
}
}
/**
......
......@@ -890,30 +890,19 @@ function search_view() {
// Search form submits with POST but redirects to GET. This way we can keep
// the search query URL clean as a whistle:
// search/type/keyword+keyword
if (isset($_POST['edit']['keys'])) {
if (!isset($_POST['edit']['keys'])) {
if ($type == '') {
$type = 'node';
}
$keys = module_invoke($type, 'search', 'post', $_POST['edit']['keys']);
drupal_goto('search/'. $type .'/'. (is_null($keys) ? $_POST['edit']['keys'] : $keys));
}
else if ($type == '') {
// Note: search/node can not be a default tab because it would take on the
// path of its parent (search). It would prevent remembering keywords when
// switching tabs. This is why we drupal_goto to it from the parent instead.
drupal_goto('search/node');
}
$keys = search_get_keys();
if (user_access('search content')) {
$keys = search_get_keys();
// Only perform search if there is non-whitespace search term:
if (trim($keys)) {
// Log the search keys:
watchdog('search',
t('Search: %keys (%type).', array('%keys' => theme('placeholder', $keys), '%type' => module_invoke($type, 'search', 'name'))),
WATCHDOG_NOTICE,
l(t('results'), 'search/'. $type .'/'. $keys)
);
watchdog('search', t('Search: %keys (%type).', array('%keys' => theme('placeholder', $keys), '%type' => module_invoke($type, 'search', 'name'))), WATCHDOG_NOTICE, l(t('results'), 'search/'. $type .'/'. $keys));
// Collect the search results:
$results = search_data($keys, $type);
......@@ -925,21 +914,15 @@ function search_view() {
$results = theme('box', t('Your search yielded no results'), search_help('search#noresults'));
}
}
else if (isset($_POST['edit'])) {
form_set_error('keys', t('Please enter some keywords.'));
}
// Construct the search form.
// Note, we do this last because of the form_set_error() above.
$output = search_form(NULL, $keys, $type);
$output .= $results;
return $output;
}
else {
drupal_access_denied();
}
return search_form(NULL, $keys, $type);
}
/**
......@@ -985,7 +968,7 @@ function search_view() {
* @return
* An HTML string containing the search form.
*/
function search_form($action = '', $keys = '', $type = null, $prompt = null) {
function search_form($action = '', $keys = '', $type = NULL, $prompt = NULL) {
if (!$action) {
$action = url('search/'. $type);
......@@ -994,18 +977,51 @@ function search_form($action = '', $keys = '', $type = null, $prompt = null) {
$prompt = t('Enter your keywords');
}
$form = array('#action' => $action, '#attributes' => array('class' => 'search-form'), '#redirect' => FALSE);
$form = array(
'#action' => $action,
'#attributes' => array('class' => 'search-form'),
'#redirect' => FALSE,
);
$form['module'] = array('#type' => 'value', '#value' => $type);
$form['basic'] = array('#type' => 'item', '#title' => $prompt);
$form['basic']['inline'] = array('#type' => 'markup', '#prefix' => '<div class="container-inline">', '#suffix' => '</div>');
$form['basic']['inline']['keys'] = array('#type' => 'textfield', '#title' => '', '#default_value' => $keys, '#size' => $prompt ? 40 : 20, '#maxlength' => 255);
$form['basic']['inline'] = array('#prefix' => '<div class="container-inline">', '#suffix' => '</div>');
$form['basic']['inline']['keys'] = array(
'#type' => 'textfield',
'#title' => '',
'#default_value' => $keys,
'#size' => $prompt ? 40 : 20,
'#maxlength' => 255,
);
// processed_keys is used to coordinate keyword passing between other forms that hook into the basic search form.
$form['basic']['inline']['processed_keys'] = array('#type' => 'value', '#value' => array());
$form['basic']['inline']['submit'] = array('#type' => 'submit', '#value' => t('Search'));
$form_module = module_invoke($type, 'search', 'form', $keys);
if (isset($form_module) && is_array($form_module)) {
$form = array_merge($form, $form_module);
return drupal_get_form('search_form', $form);
}
/**
* As the search form collates keys from other modules hooked in via hook_form_alter, the validation
* takes place in _submit. search_form_validate() is used solely to set the #ref property for the basic
* search form.
*/
function search_form_validate($form_id, $form_values) {
$form_values['processed_keys']['#ref'] = trim($form_values['keys']);
}
/**
* Process a search form submission. Uses a forms API #ref to accept processed search keys
* from forms that hook into the default search form.
*/
function search_form_submit($form_id, $form_values) {
$keys = $form_values['processed_keys']['#ref'];
if (trim($keys) == '') {
form_set_error('keys', t('Please enter some keywords.'));
// Fall through to the drupal_goto() call.
$keys = '';
}
return drupal_get_form('search_form', $form);
$type = $form_values['module'] ? $form_values['module'] : 'node';
drupal_goto('search/'. $type .'/'. $keys);
}
/**
......
......@@ -890,30 +890,19 @@ function search_view() {
// Search form submits with POST but redirects to GET. This way we can keep
// the search query URL clean as a whistle:
// search/type/keyword+keyword
if (isset($_POST['edit']['keys'])) {
if (!isset($_POST['edit']['keys'])) {
if ($type == '') {
$type = 'node';
}
$keys = module_invoke($type, 'search', 'post', $_POST['edit']['keys']);
drupal_goto('search/'. $type .'/'. (is_null($keys) ? $_POST['edit']['keys'] : $keys));
}
else if ($type == '') {
// Note: search/node can not be a default tab because it would take on the
// path of its parent (search). It would prevent remembering keywords when
// switching tabs. This is why we drupal_goto to it from the parent instead.
drupal_goto('search/node');
}
$keys = search_get_keys();
if (user_access('search content')) {
$keys = search_get_keys();
// Only perform search if there is non-whitespace search term:
if (trim($keys)) {
// Log the search keys:
watchdog('search',
t('Search: %keys (%type).', array('%keys' => theme('placeholder', $keys), '%type' => module_invoke($type, 'search', 'name'))),
WATCHDOG_NOTICE,
l(t('results'), 'search/'.