finder_id);
if (is_array($finder_form_state)) {
$form_state = array_merge($form_state, $finder_form_state);
}
finder_invoke_finderapi($finder, 'finder_form', $form, $form_state);
$form['finder_id'] = array (
'#type' => 'value',
'#value' => $finder->finder_id,
);
$form['#action'] = url($finder->path);
$form['finder_form'] = array(
'#weight' => 0,
'#prefix' => '
',
'#suffix' => '
',
);
$form['finder_form']['#prefix'] .= $finder->settings['form']['prefix'] ? ''. $finder->settings['form']['prefix'] .'
' : '';
$max_weight = 0;
foreach ((array)$finder->elements as $element) {
$max_weight = max($max_weight, $element->weight);
if (isset($form_state['values'][$element->finder_element_id])) {
$element_default = $form_state['values'][$element->finder_element_id];
}
else {
$element_default = $element->settings['form']['default_value'];
}
$form['finder_form'][$element->finder_element_id] = array(
'#title' => $element->title,
'#weight' => $element->weight,
'#description' => $element->description,
'#prefix' => $element->settings['form']['prefix'],
'#suffix' => $element->settings['form']['suffix'],
'#default_value' => $element_default,
'#required' => $element->settings['form']['required'],
'#executes_submit_callback' => TRUE,
);
$module = &$element->element_handler['#module'];
// module_invoke doesn't seem to handle references.
$handler_function = $module .'_finder_element';
if (function_exists($handler_function)) {
$handler_function($element, $form['finder_form'][$element->finder_element_id]);
}
}
if ($finder->settings['advanced']['submission']) {
$form['finder_form']['submit'] = array(
'#type' => 'submit',
'#name' => 'find',
'#value' => $finder->settings['form']['button_text'],
'#weight' => $max_weight + 1000,
);
if ($finder->settings['advanced']['ahah']) {
$form['finder_form']['submit']['#ahah'] = array(
'path' => 'finder/finder_ahah/'. $finder->finder_id,
'wrapper' => $finder->finder_view_build_id,
'method' => 'replace',
'effect' => $finder->settings['advanced']['ahah_effect'],
);
}
if ($finder->settings['advanced']['goto'] == 'go') {
$form['finder_form']['submit']['#prefix'] = '';
$form['finder_form']['go'] = array(
'#type' => 'submit',
'#name' => 'go',
'#value' => $finder->settings['form']['go_text'],
'#weight' => $max_weight + 1010,
'#suffix' => '
',
);
}
}
$form['finder_form']['#suffix'] = ($finder->settings['form']['suffix'] ? ''. $finder->settings['form']['suffix'] .'
' : '') . $form['finder_form']['#suffix'];
$form['#submit'] = array(
'finder_form_submit',
);
return $form;
}
/**
* Submit function for finder form.
*
* Adds some needed data to $form_state and calls finder_form_state().
*
* @see finder_form()
*/
function finder_form_submit($form, &$form_state) {
$finder_id = $form_state['values']['finder_id'];
$finder = finder_load($finder_id);
$form_state['storage']['finder'] = $finder;
$form_state['storage']['values'] = $form_state['values'];
$form_state['storage']['finished'] = TRUE;
finder_form_state($finder->finder_id, $form_state);
}
/**
* Statically 'get' or 'set' the FAPI form state in a per-finder cache.
*
* When used to 'set' the form state it will also check to see if a redirect
* is required to go to the results path with arguments. When used to 'get'
* the form state it will check the static cache for a stored form state, then
* it will check the session for a form state carried over from another page,
* and finally it will attempt to build a form state out of the path arguments.
*
* @param $finder_id
* The finder's ID.
* @param $form_state
* The Forms API form state (if supplied, will 'set' the form state).
* @return
* A copy of the Forms API form state.
*/
function finder_form_state($finder_id, $form_state = NULL) {
static $finder_form_state = NULL;
if ($form_state) { // we are setting the form_state in a submit.
// last chance for modules to intefere before potential redirect.
drupal_alter('finder_form_state', $form_state, $finder_id);
$finder_form_state[$finder_id] = $form_state;
// handle URL stuff.
$finder = finder_load($finder_id);
if (!$finder->settings['advanced']['hide_args']) {
$sep = &$finder->settings['advanced']['arg_sep'];
$query = array();
foreach ($finder->elements as $element) {
$keyword = array();
//if (!is_null($form_state['values'][$element->finder_element_id])) { // this was intefering [#593060]
$keyword = (array)$form_state['values'][$element->finder_element_id];
foreach($keyword as $k => $v) {
if (strpos($v, $sep) !== FALSE) {
$v = '"'. $v .'"';
}
$keyword[$k] = $v ? trim($v) : ' ';
}
//}
$keywords[$element->finder_element_id] = implode(',', $keyword);
}
if (!$form_state['storage']['finished']) {
$query['finished'] = '0';
}
if ($form_state['clicked_button']['#name'] == 'go' && $form_state['storage']['finished']) {
$query['go'] = '1';
}
finder_form_goto($sep, $finder->path .'/'. implode('/', $keywords), $query);
}
}
elseif (!isset($finder_form_state[$finder_id])) {
$finder = finder_load($finder_id);
if ($finder->settings['advanced']['hide_args'] && isset($_GET['finder'])) { // check the session
$finder_form_state[$finder_id] = $_SESSION['finder'][$_GET['finder']];
}
elseif (!isset($_GET['finder']) &&
strlen($finder->path) < strlen($_GET['q']) &&
stripos($_GET['q'], $finder->path) === 0) { // check the URL
$args = explode('/', str_replace($finder->path .'/', '', $_GET['q']));
$form_state['storage']['finished'] = TRUE;
$sep = &$finder->settings['advanced']['arg_sep'];
$csv_regex = "/". $sep ."(?!(?:[^\\\"". $sep ."]|[^\\\"]". $sep ."[^\\\"])+\\\")/";
foreach ($finder->elements as $key => $element) {
$keywords = preg_split($csv_regex, $args[$key]);
foreach ($keywords as $k => $v) {
$v = str_replace(urlencode($sep), $sep, trim($v));
if (strpos($v, $sep) !== FALSE && $v[0] == '"' && $v[strlen($v)-1] == '"') {
$v = substr($v, 1, strlen($v)-2);
}
unset($keywords[$k]);
if ($v) {
$keywords[$v] = $v;
}
}
if (count($keywords) === 1) {
$keywords = current($keywords);
}
elseif (!count($keywords)) {
$keywords = NULL;
}
$form_state['values'][$element->finder_element_id] = $keywords;
}
$finder_form_state[$finder_id] = $form_state;
}
}
return $finder_form_state[$finder_id];
}
/**
* Redirect from a finder form.
*
* The difference between this and drupal_goto() is that this undoes the
* encoding of the arguments seperator, as such encoding inteferes with finder.
*
* @param $sep
* The arguments seperator string.
* @param $path
* A Drupal path or a full URL.
* @param $query
* A query string component, if any.
* @param $fragment
* A destination fragment identifier (named anchor).
* @param $http_response_code
* Valid values for an actual "goto" as per RFC 2616 section 10.3 are:
* - 301 Moved Permanently (the recommended value for most redirects)
* - 302 Found (default in Drupal and PHP, sometimes used for spamming search
* engines)
* - 303 See Other
* - 304 Not Modified
* - 305 Use Proxy
* - 307 Temporary Redirect (alternative to "503 Site Down for Maintenance")
* Note: Other values are defined by RFC 2616, but are rarely used and poorly
* supported.
* @see drupal_goto()
*/
function finder_form_goto($sep, $path = '', $query = NULL, $fragment = NULL, $http_response_code = 302) {
if (isset($_REQUEST['destination'])) {
extract(parse_url(urldecode($_REQUEST['destination'])));
}
else if (isset($_REQUEST['edit']['destination'])) {
extract(parse_url(urldecode($_REQUEST['edit']['destination'])));
}
$url = url($path, array('query' => $query, 'fragment' => $fragment, 'absolute' => TRUE));
// custom changes - undo separator encoding
$url = str_replace(urlencode($sep), $sep, $url);
// Remove newlines from the URL to avoid header injection attacks.
$url = str_replace(array("\n", "\r"), '', $url);
// Allow modules to react to the end of the page request before redirecting.
// We do not want this while running update.php.
if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') {
module_invoke_all('exit', $url);
}
// Even though session_write_close() is registered as a shutdown function, we
// need all session data written to the database before redirecting.
session_write_close();
header('Location: '. $url, TRUE, $http_response_code);
// The "Location" header sends a redirect status code to the HTTP daemon. In
// some cases this can be wrong, so we make sure none of the code below the
// drupal_goto() call gets executed upon redirection.
exit();
}