Ho provato a validare l'home page del sito realizzato con drupal 5.1 usando il tema Garland.
Sull'home page ho visualizzato sia il login che la finestrella del motore di ricerca interno.
Il validatore mi restituisce questo messaggio di erore (da quanto ho capito dovuto al fatto che ID "edit-submit" è stato usato due volte nella stessa pagina):
1. Error Line 76, column 35: ID "edit-submit" already defined .
input type="submit" name="op" id="edit-submit" value="Accedi" class="form-subm
An "id" is a unique identifier. Each time this attribute is used in a document it must have a different value. If you are using this attribute as a hook for style sheets it may be more appropriate to use classes (which group elements) than id (which are used to identify exactly one element).
2. Info Line 48, column 35: ID "edit-submit" first defined here .
input type="submit" name="op" id="edit-submit" value="Cerca" class="form-submi
Su quali file devo agire per operare le modifiche necessarie?
Ho cercato nella cartella del tema Garland ma non ho trovato niente.
Qualcuno può darmi una mano?
Cerca nel forum del sito ufficiale, se ne è parlato ampiamente (è anche ben spiegato su come correggere, ma non ho il link sottomano :D )
Ciao
Marco
--
My blog
Working at @agavee
Non sono riuscito a risolvere il problema.
Ho trovato questi:
http://drupal.org/node/60990
http://drupal.org/node/128619
Ma in nessuno di questi viene dato un aiuto.
Anche il sito www.drupal.org non passa la validazione e anche lì si presenta lo stesso problema.
Qualcuno può lanciarmi qualche suggerimento?
Parti da qui, adessovado di fretta, in ogni caso dovresti risolvere facilmente... altra alternativa per aggirare il problema è di modificare block.tpl.php per cambiare l'ID degli elementi del blocco e poi modificare anche gli style.
Ciao
Marco
--
My blog
Working at @agavee
Ne avevo già parlato in passato di questo problema (e nel frattempo me n'ero pure dimenticato) e il problema compare dalla versione 5 ufficiale. Nelle rc non c'era.
Il file che genera l'errore è form.inc e non uno del tema. Per risolvere al volo ti basta sostituire il file form.inc della 5.1 con quello della 5 rc2.
Sicuramente non è il metodo più appropriato, ma non ho riscontarto errori in seguito a questa sostituzione. Ti posto il contenuto del messaggio che ho scritto a tal proposito quando mi sono accorto del problema:
Errorino...
Inserito da DevilMaster il Lun, 2007/01/22 - 05:02
Nell'ultima versione ufficiale di Drupal, ovvero la 5.0, c'è un errorino nella creazione dell'id dei form. In pratica viene assegnato lo stesso id sia al campo di ricerca che a quello del login (e forse anche ad altri campi di testo, ma per ora mi sono accorto di questi due) e questo fa sì che il codice non venga validato dal w3c.
E' molto strano, in quanto nelle precedenti rc questo problema non c'era mentre si verifica ora nella versione ufficiale.
Comunque, proprio per questo motivo, mi sono andato a guardare il file form.inc (che è quello che genera l'errore) della rc2 e di quello nuovo dell'ufficiale. Vista l'ora gli ho dato giusto un'occhiata e nella creazione del campo la parte che riguarda l'edit (l'id che viene generato e che crea l'errore si chiama edit-submit) mi sembra a posto, per cui suppongo che l'errore avvenga nella generazione di -submit.
Comunque, per ora mi sono limitato a mettere il form.inc della rc2 che risolve il problema, ma ovviamente è solo una soluzione temporanea.
Domani vedo se riesco a capire dove si crea l'inghippo e se riesco a risolverlo. Ovviamente, se qualcuno lo ha già risolto... posti qui la soluzione. :)
Grazie!!!!!!!!!!!!!!!!
Ho sostituito con il file form.inc della rc2 e adesso ho un bel xhtml 1.0 valido!!!!!!!!!!!!!!
Dato che ci siamo, perchè non risolviamo anche il fatto che IE 5.X non vede le colonne laterali di Garland?
Ciao e grazie ancora!
La versione RC2 da scaricare è questa?
http://ftp.osuosl.org/pub/drupal/files/projects/drupal-5.0-rc2.tar.gz
Suppongo di sì. Io la scaricai quando uscì, quindi era l'ultima versione scaricabile.
Visto che Dany ha risolto quando era uscita la release stabile già da un bel po', suppongo che anche lui l'abbia riscaricata in seguito e che i files non siano stati sostituiti. Certo che... scaricarsi una versione intera per un file...
Spetta... mo lo cerco e lo posto, così basta sostituire il contenuto del file (mi sembra troppo assurdo scaricare un pacchetto completo per un file).
<?php
// $Id: form.inc,v 1.171 2007/01/05 19:08:30 dries Exp $
/**
* @defgroup form Form generation
* @{
* Functions to enable the processing and display of HTML forms.
*
* Drupal uses these functions to achieve consistency in its form processing and
* presentation, while simplifying code and reducing the amount of HTML that
* must be explicitly generated by modules.
*
* The drupal_get_form() function handles retrieving, processing, and
* displaying a rendered HTML form for modules automatically. For example:
*
* // display the user registration form
* $output = drupal_get_form('user_register');
*
* Forms can also be built and submitted programmatically without any user input
* using the drupal_execute() function.
*
*
* For information on the format of the structured arrays used to define forms,
* and more detailed explanations of the Form API workflow, see the reference at
* http://api.drupal.org/api/HEAD/file/developer/topics/forms_api_reference.html
* and the quickstart guide at
* http://api.drupal.org/api/HEAD/file/developer/topics/forms_api.html
*/
/**
* Retrieves a form from a builder function, passes it on for
* processing, and renders the form or redirects to its destination
* as appropriate. In multi-step form scenarios, it handles properly
* processing the values using the previous step's form definition,
* then rendering the requested step for display.
*
* @param $form_id
* The unique string identifying the desired form. If a function
* with that name exists, it is called to build the form array.
* Modules that need to generate the same form (or very similar forms)
* using different $form_ids can implement hook_forms(), which maps
* different $form_id values to the proper form building function. Examples
* may be found in node_forms(), search_forms(), and user_forms().
* @param ...
* Any additional arguments needed by the form building function.
* @return
* The rendered form.
*/
function drupal_get_form($form_id) {
// In multi-step form scenarios, the incoming $_POST values are not
// necessarily intended for the current form. We need to build
// a copy of the previously built form for validation and processing,
// then go on to the one that was requested if everything works.
$form_build_id = md5(mt_rand());
if (isset($_POST['form_build_id']) && isset($_SESSION['form'][$_POST['form_build_id']]['args']) && $_POST['form_id'] == $form_id) {
// There's a previously stored multi-step form. We should handle
// IT first.
$stored = TRUE;
$args = $_SESSION['form'][$_POST['form_build_id']]['args'];
$form = call_user_func_array('drupal_retrieve_form', $args);
}
else {
// We're coming in fresh; build things as they would be. If the
// form's #multistep flag is set, store the build parameters so
// the same form can be reconstituted for validation.
$args = func_get_args();
$form = call_user_func_array('drupal_retrieve_form', $args);
if (isset($form['#multistep']) && $form['#multistep']) {
// Clean up old multistep form session data.
_drupal_clean_form_sessions();
$_SESSION['form'][$form_build_id] = array('timestamp' => time(), 'args' => $args);
$form['#build_id'] = $form_build_id;
}
$stored = FALSE;
}
// Process the form, submit it, and store any errors if necessary.
drupal_process_form($args[0], $form);
if ($stored && !form_get_errors()) {
// If it's a stored form and there were no errors, we processed the
// stored form successfully. Now we need to build the form that was
// actually requested. We always pass in the current $_POST values
// to the builder function, as values from one stage of a multistep
// form can determine how subsequent steps are displayed.
$args = func_get_args();
$args[] = $_POST;
$form = call_user_func_array('drupal_retrieve_form', $args);
unset($_SESSION['form'][$_POST['form_build_id']]);
if (isset($form['#multistep']) && $form['#multistep']) {
$_SESSION['form'][$form_build_id] = array('timestamp' => time(), 'args' => $args);
$form['#build_id'] = $form_build_id;
}
drupal_prepare_form($args[0], $form);
}
return drupal_render_form($args[0], $form);
}
/**
* Remove form information that's at least a day old from the
* $_SESSION['form'] array.
*/
function _drupal_clean_form_sessions() {
if (isset($_SESSION['form'])) {
foreach ($_SESSION['form'] as $build_id => $data) {
if ($data['timestamp'] < (time() - 84600)) {
unset($_SESSION['form'][$build_id]);
}
}
}
}
/**
* Retrieves a form using a form_id, populates it with $form_values,
* processes it, and returns any validation errors encountered. This
* function is the programmatic counterpart to drupal_get_form().
*
* @param $form_id
* The unique string identifying the desired form. If a function
* with that name exists, it is called to build the form array.
* Modules that need to generate the same form (or very similar forms)
* using different $form_ids can implement hook_forms(), which maps
* different $form_id values to the proper form building function. Examples
* may be found in node_forms(), search_forms(), and user_forms().
* @param $form_values
* An array of values mirroring the values returned by a given form
* when it is submitted by a user.
* @param ...
* Any additional arguments needed by the form building function.
* @return
* Any form validation errors encountered.
*
* For example:
*
* // register a new user
* $values['name'] = 'robo-user';
* $values['mail'] = '[email protected]';
* $values['pass'] = 'password';
* drupal_execute('user_register', $values);
*
* // Create a new node
* $node = array('type' => 'story');
* $values['title'] = 'My node';
* $values['body'] = 'This is the body text!';
* $values['name'] = 'robo-user';
* drupal_execute('story_node_form', $values, $node);
*/
function drupal_execute($form_id, $form_values) {
$args = func_get_args();
$form_id = array_shift($args);
$form_values = array_shift($args);
array_unshift($args, $form_id);
if (isset($form_values)) {
$form = call_user_func_array('drupal_retrieve_form', $args);
$form['#post'] = $form_values;
return drupal_process_form($form_id, $form);
}
}
/**
* Retrieves the structured array that defines a given form.
*
* @param $form_id
* The unique string identifying the desired form. If a function
* with that name exists, it is called to build the form array.
* Modules that need to generate the same form (or very similar forms)
* using different $form_ids can implement hook_forms(), which maps
* different $form_id values to the proper form building function.
* @param ...
* Any additional arguments needed by the form building function.
*/
function drupal_retrieve_form($form_id) {
static $forms;
// We save two copies of the incoming arguments: one for modules to use
// when mapping form ids to builder functions, and another to pass to
// the builder function itself. We shift out the first argument -- the
// $form_id itself -- from the list to pass into the builder function,
// since it's already known.
$args = func_get_args();
$saved_args = $args;
array_shift($args);
// We first check to see if there's a function named after the $form_id.
// If there is, we simply pass the arguments on to it to get the form.
if (!function_exists($form_id)) {
// In cases where many form_ids need to share a central builder function,
// such as the node editing form, modules can implement hook_forms(). It
// maps one or more form_ids to the correct builder functions.
//
// We cache the results of that hook to save time, but that only works
// for modules that know all their form_ids in advance. (A module that
// adds a small 'rate this comment' form to each comment in a list
// would need a unique form_id for each one, for example.)
//
// So, we call the hook if $forms isn't yet populated, OR if it doesn't
// yet have an entry for the requested form_id.
if (!isset($forms) || !isset($forms[$form_id])) {
$forms = module_invoke_all('forms', $saved_args);
}
$form_definition = $forms[$form_id];
if (isset($form_definition['callback arguments'])) {
$args = array_merge($form_definition['callback arguments'], $args);
}
if (isset($form_definition['callback'])) {
$callback = $form_definition['callback'];
}
}
// If $callback was returned by a hook_forms() implementation, call it.
// Otherwise, call the function named after the form id.
$form = call_user_func_array(isset($callback) ? $callback : $form_id, $args);
// We store the original function arguments, rather than the final $arg
// value, so that form_alter functions can see what was originally
// passed to drupal_retrieve_form(). This allows the contents of #parameters
// to be saved and passed in at a later date to recreate the form.
$form['#parameters'] = $saved_args;
return $form;
}
/**
* This function is the heart of form API. The form gets built, validated and in
* appropriate cases, submitted.
*
* @param $form_id
* The unique string identifying the current form.
* @param $form
* An associative array containing the structure of the form.
* @return
* The path to redirect the user to upon completion.
*/
function drupal_process_form($form_id, &$form) {
global $form_values, $form_submitted, $user, $form_button_counter;
static $saved_globals = array();
// In some scenarios, this function can be called recursively. Pushing any pre-existing
// $form_values and form submission data lets us start fresh without clobbering work done
// in earlier recursive calls.
array_push($saved_globals, array($form_values, $form_submitted, $form_button_counter));
$form_values = array();
$form_submitted = FALSE;
$form_button_counter = array(0, 0);
drupal_prepare_form($form_id, $form);
if (($form['#programmed']) || (!empty($_POST) && (($_POST['form_id'] == $form_id) || ($_POST['form_id'] == $form['#base'])))) {
drupal_validate_form($form_id, $form);
// IE does not send a button value when there is only one submit button (and no non-submit buttons)
// and you submit by pressing enter.
// In that case we accept a submission without button values.
if ((($form['#programmed']) || $form_submitted || (!$form_button_counter[0] && $form_button_counter[1])) && !form_get_errors()) {
$redirect = drupal_submit_form($form_id, $form);
if (!$form['#programmed']) {
drupal_redirect_form($form, $redirect);
}
}
}
// We've finished calling functions that alter the global values, so we can
// restore the ones that were there before this function was called.
list($form_values, $form_submitted, $form_button_counter) = array_pop($saved_globals);
return $redirect;
}
/**
* Prepares a structured form array by adding required elements,
* executing any hook_form_alter functions, and optionally inserting
* a validation token to prevent tampering.
*
* @param $form_id
* A unique string identifying the form for validation, submission,
* theming, and hook_form_alter functions.
* @param $form
* An associative array containing the structure of the form.
*/
function drupal_prepare_form($form_id, &$form) {
global $user;
$form['#type'] = 'form';
if (!isset($form['#post'])) {
$form['#post'] = $_POST;
$form['#programmed'] = FALSE;
}
else {
$form['#programmed'] = TRUE;
}
// In multi-step form scenarios, this id is used to identify
// a unique instance of a particular form for retrieval.
if (isset($form['#build_id'])) {
$form['form_build_id'] = array(
'#type' => 'hidden',
'#value' => $form['#build_id'],
'#id' => $form['#build_id'],
'#name' => 'form_build_id',
);
}
// If $base is set, it is used in place of $form_id when constructing validation,
// submission, and theming functions. Useful for mapping many similar or duplicate
// forms with different $form_ids to the same processing functions.
if (isset($form['#base'])) {
$base = $form['#base'];
}
// Add a token, based on either #token or form_id, to any form displayed to authenticated users.
// This ensures that any submitted form was actually requested previously by the user and protects against
// cross site request forgeries.
if (isset($form['#token'])) {
if ($form['#token'] === FALSE || $user->uid == 0 || $form['#programmed']) {
unset($form['#token']);
}
else {
$form['form_token'] = array('#type' => 'token', '#default_value' => drupal_get_token($form['#token']));
}
}
else if ($user->uid && !$form['#programmed']) {
$form['#token'] = $form_id;
$form['form_token'] = array(
'#id' => form_clean_id('edit-'. $form_id .'-form-token'),
'#type' => 'token',
'#default_value' => drupal_get_token($form['#token']),
);
}
if (isset($form_id)) {
$form['form_id'] = array('#type' => 'hidden', '#value' => $form_id, '#id' => form_clean_id("edit-$form_id"));
}
if (!isset($form['#id'])) {
$form['#id'] = form_clean_id($form_id);
}
$form += _element_info('form');
if (!isset($form['#validate'])) {
if (function_exists($form_id .'_validate')) {
$form['#validate'] = array($form_id .'_validate' => array());
}
elseif (function_exists($base .'_validate')) {
$form['#validate'] = array($base .'_validate' => array());
}
}
if (!isset($form['#submit'])) {
if (function_exists($form_id .'_submit')) {
// we set submit here so that it can be altered but use reference for
// $form_values because it will change later
$form['#submit'] = array($form_id .'_submit' => array());
}
elseif (function_exists($base .'_submit')) {
$form['#submit'] = array($base .'_submit' => array());
}
}
foreach (module_implements('form_alter') as $module) {
$function = $module .'_form_alter';
$function($form_id, $form);
}
$form = form_builder($form_id, $form);
}
/**
* Validates user-submitted form data from a global variable using
* the validate functions defined in a structured form array.
*
* @param $form_id
* A unique string identifying the form for validation, submission,
* theming, and hook_form_alter functions.
* @param $form
* An associative array containing the structure of the form.
*
*/
function drupal_validate_form($form_id, $form) {
global $form_values;
static $validated_forms = array();
if (isset($validated_forms[$form_id])) {
return;
}
// If the session token was set by drupal_prepare_form(), ensure that it
// matches the current user's session
if (isset($form['#token'])) {
if (!drupal_valid_token($form_values['form_token'], $form['#token'])) {
// setting this error will cause the form to fail validation
form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.'));
}
}
_form_validate($form, $form_id);
$validated_forms[$form_id] = TRUE;
}
/**
* Processes user-submitted form data from a global variable using
* the submit functions defined in a structured form array.
*
* @param $form_id
* A unique string identifying the form for validation, submission,
* theming, and hook_form_alter functions.
* @param $form
* An associative array containing the structure of the form.
* @return
* A string containing the path of the page to display when processing
* is complete.
*
*/
function drupal_submit_form($form_id, $form) {
global $form_values;
$default_args = array($form_id, &$form_values);
if (isset($form['#submit'])) {
foreach ($form['#submit'] as $function => $args) {
if (function_exists($function)) {
$args = array_merge($default_args, (array) $args);
// Since we can only redirect to one page, only the last redirect will work
$redirect = call_user_func_array($function, $args);
if (isset($redirect)) {
$goto = $redirect;
}
}
}
}
return $goto;
}
/**
* Renders a structured form array into themed HTML.
*
* @param $form_id
* A unique string identifying the form for validation, submission,
* theming, and hook_form_alter functions.
* @param $form
* An associative array containing the structure of the form.
* @return
* A string containing the path of the page to display when processing
* is complete.
*
*/
function drupal_render_form($form_id, &$form) {
// Don't override #theme if someone already set it.
if (isset($form['#base'])) {
$base = $form['#base'];
}
if (!isset($form['#theme'])) {
if (theme_get_function($form_id)) {
$form['#theme'] = $form_id;
}
elseif (theme_get_function($base)) {
$form['#theme'] = $base;
}
}
if (isset($form['#pre_render'])) {
foreach ($form['#pre_render'] as $function) {
if (function_exists($function)) {
$function($form_id, $form);
}
}
}
$output = drupal_render($form);
return $output;
}
/**
* Redirect the user to a URL after a form has been processed.
*
* @param $form
* An associative array containing the structure of the form.
* @param $redirect
* An optional string containing the destination path to redirect
* to if none is specified by the form.
*
*/
function drupal_redirect_form($form, $redirect = NULL) {
if (isset($redirect)) {
$goto = $redirect;
}
if (isset($form['#redirect'])) {
$goto = $form['#redirect'];
}
if ($goto !== FALSE) {
if (is_array($goto)) {
call_user_func_array('drupal_goto', $goto);
}
elseif (!isset($goto)) {
drupal_goto($_GET['q']);
}
else {
drupal_goto($goto);
}
}
}
function _form_validate($elements, $form_id = NULL) {
// Recurse through all children.
foreach (element_children($elements) as $key) {
if (isset($elements[$key]) && $elements[$key]) {
_form_validate($elements[$key]);
}
}
/* Validate the current input */
if (!isset($elements['#validated']) || !$elements['#validated']) {
if (isset($elements['#needs_validation'])) {
// An empty textfield returns '' so we use empty(). An empty checkbox
// and a textfield could return '0' and empty('0') returns TRUE so we
// need a special check for the '0' string.
if ($elements['#required'] && empty($elements['#value']) && $elements['#value'] !== '0') {
form_error($elements, t('!name field is required.', array('!name' => $elements['#title'])));
}
// Verify that the value is not longer than #maxlength.
if (isset($elements['#maxlength']) && drupal_strlen($elements['#value']) > $elements['#maxlength']) {
form_error($elements, t('!name cannot be longer than %max characters but is currently %length characters long.', array('!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title'], '%max' => $elements['#maxlength'], '%length' => drupal_strlen($elements['#value']))));
}
// Add legal choice check if element has #options. Can be skipped, but then you must validate your own element.
if (isset($elements['#options']) && isset($elements['#value']) && !isset($elements['#DANGEROUS_SKIP_CHECK'])) {
if ($elements['#type'] == 'select') {
$options = form_options_flatten($elements['#options']);
}
else {
$options = $elements['#options'];
}
if (is_array($elements['#value'])) {
$value = $elements['#type'] == 'checkboxes' ? array_keys(array_filter($elements['#value'])) : $elements['#value'];
foreach ($value as $v) {
if (!isset($options[$v])) {
form_error($elements, t('An illegal choice has been detected. Please contact the site administrator.'));
watchdog('form', t('Illegal choice %choice in !name element.', array('%choice' => $v, '!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title'])), WATCHDOG_ERROR);
}
}
}
elseif (!isset($options[$elements['#value']])) {
form_error($elements, t('An illegal choice has been detected. Please contact the site administrator.'));
watchdog('form', t('Illegal choice %choice in %name element.', array('%choice' => $elements['#value'], '%name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title'])), WATCHDOG_ERROR);
}
}
}
// User-applied checks.
if (isset($elements['#validate'])) {
foreach ($elements['#validate'] as $function => $args) {
$args = array_merge(array($elements), $args);
// for the full form we hand over a copy of $form_values
if (isset($form_id)) {
$args = array_merge(array($form_id, $GLOBALS['form_values']), $args);
}
if (function_exists($function)) {
call_user_func_array($function, $args);
}
}
}
$elements['#validated'] = TRUE;
}
}
/**
* File an error against a form element. If the name of the element is
* edit[foo][bar] then you may pass either foo or foo][bar as $name
* foo will set an error for all its children.
*/
function form_set_error($name = NULL, $message = '') {
static $form = array();
if (isset($name) && !isset($form[$name])) {
$form[$name] = $message;
if ($message) {
drupal_set_message($message, 'error');
}
}
return $form;
}
/**
* Return an associative array of all errors.
*/
function form_get_errors() {
$form = form_set_error();
if (!empty($form)) {
return $form;
}
}
/**
* Return the error message filed against the form with the specified name.
*/
function form_get_error($element) {
$form = form_set_error();
$key = $element['#parents'][0];
if (isset($form[$key])) {
return $form[$key];
}
$key = implode('][', $element['#parents']);
if (isset($form[$key])) {
return $form[$key];
}
}
/**
* Flag an element as having an error.
*/
function form_error(&$element, $message = '') {
$element['#error'] = TRUE;
form_set_error(implode('][', $element['#parents']), $message);
}
/**
* Adds some required properties to each form element, which are used
* internally in the form api. This function also automatically assigns
* the value property from the $edit array, provided the element doesn't
* already have an assigned value.
*
* @param $form_id
* A unique string identifying the form for validation, submission,
* theming, and hook_form_alter functions.
* @param $form
* An associative array containing the structure of the form.
*/
function form_builder($form_id, $form) {
global $form_values, $form_submitted, $form_button_counter;
// Initialize as unprocessed.
$form['#processed'] = FALSE;
/* Use element defaults */
if ((!empty($form['#type'])) && ($info = _element_info($form['#type']))) {
// overlay $info onto $form, retaining preexisting keys in $form
$form += $info;
}
if (isset($form['#input']) && $form['#input']) {
if (!isset($form['#name'])) {
$name = array_shift($form['#parents']);
$form['#name'] = $name;
if ($form['#type'] == 'file') {
// to make it easier to handle $_FILES in file.inc, we place all
// file fields in the 'files' array. Also, we do not support
// nested file names
$form['#name'] = 'files['. $form['#name'] .']';
}
elseif (count($form['#parents'])) {
$form['#name'] .= '['. implode('][', $form['#parents']) .']';
}
array_unshift($form['#parents'], $name);
}
if (!isset($form['#id'])) {
$form['#id'] = form_clean_id('edit-'. implode('-', $form['#parents']));
}
if (isset($form['#disabled']) && $form['#disabled']) {
$form['#attributes']['disabled'] = 'disabled';
}
if (!isset($form['#value']) && !array_key_exists('#value', $form)) {
if (($form['#programmed']) || ((!isset($form['#access']) || $form['#access']) && isset($form['#post']) && (isset($form['#post']['form_id']) && $form['#post']['form_id'] == $form_id))) {
$edit = $form['#post'];
foreach ($form['#parents'] as $parent) {
$edit = isset($edit[$parent]) ? $edit[$parent] : NULL;
}
if (!$form['#programmed'] || isset($edit)) {
switch ($form['#type']) {
case 'checkbox':
$form['#value'] = !empty($edit) ? $form['#return_value'] : 0;
break;
case 'select':
if (isset($form['#multiple']) && $form['#multiple']) {
if (isset($edit) && is_array($edit)) {
$form['#value'] = drupal_map_assoc($edit);
}
else {
$form['#value'] = array();
}
}
elseif (isset($edit)) {
$form['#value'] = $edit;
}
break;
case 'textfield':
if (isset($edit)) {
// Equate $edit to the form value to ensure it's marked for validation
$edit = str_replace(array("\r", "\n"), '', $edit);
$form['#value'] = $edit;
}
break;
case 'token':
$form['#value'] = (string)$edit;
break;
default:
if (isset($edit)) {
$form['#value'] = $edit;
}
}
// Mark all posted values for validation
if ((isset($form['#value']) && $form['#value'] === $edit) || (isset($form['#required']) && $form['#required'])) {
$form['#needs_validation'] = TRUE;
}
}
}
if (!isset($form['#value'])) {
$function = $form['#type'] . '_value';
if (function_exists($function)) {
$function($form);
}
else {
$form['#value'] = isset($form['#default_value']) ? $form['#default_value'] : '';
}
}
}
if (isset($form['#executes_submit_callback'])) {
// Count submit and non-submit buttons
$form_button_counter[$form['#executes_submit_callback']]++;
// See if a submit button was pressed
if (isset($form['#post'][$form['#name']]) && $form['#post'][$form['#name']] == $form['#value']) {
$form_submitted = $form_submitted || $form['#executes_submit_callback'];
// In most cases, we want to use form_set_value() to manipulate the global variables.
// In this special case, we want to make sure that the value of this element is listed
// in $form_variables under 'op'.
$form_values[$form['#name']] = $form['#value'];
}
}
}
// Allow for elements to expand to multiple elements, e.g. radios, checkboxes and files.
if (isset($form['#process']) && !$form['#processed']) {
foreach ($form['#process'] as $process => $args) {
if (function_exists($process)) {
$args = array_merge(array($form), array($edit), $args);
$form = call_user_func_array($process, $args);
}
}
$form['#processed'] = TRUE;
}
// Set the $form_values key that gets passed to validate and submit.
// We call this after #process gets called so that #process has a
// chance to update #value if desired.
if (isset($form['#input']) && $form['#input']) {
form_set_value($form, $form['#value']);
}
// Recurse through all child elements.
$count = 0;
foreach (element_children($form) as $key) {
$form[$key]['#post'] = $form['#post'];
$form[$key]['#programmed'] = $form['#programmed'];
// don't squash an existing tree value
if (!isset($form[$key]['#tree'])) {
$form[$key]['#tree'] = $form['#tree'];
}
// deny access to child elements if parent is denied
if (isset($form['#access']) && !$form['#access']) {
$form[$key]['#access'] = FALSE;
}
// don't squash existing parents value
if (!isset($form[$key]['#parents'])) {
// Check to see if a tree of child elements is present. If so, continue down the tree if required.
$form[$key]['#parents'] = $form[$key]['#tree'] && $form['#tree'] ? array_merge($form['#parents'], array($key)) : array($key);
}
// Assign a decimal placeholder weight to preserve original array order
if (!isset($form[$key]['#weight'])) {
$form[$key]['#weight'] = $count/1000;
}
$form[$key] = form_builder($form_id, $form[$key]);
$count++;
}
if (isset($form['#after_build']) && !isset($form['#after_build_done'])) {
foreach ($form['#after_build'] as $function) {
if (function_exists($function)) {
$form = $function($form, $form_values);
}
}
$form['#after_build_done'] = TRUE;
}
return $form;
}
/**
* Use this function to make changes to form values in the form validate
* phase, so they will be available in the submit phase in $form_values.
*
* Specifically, if $form['#parents'] is array('foo', 'bar')
* and $value is 'baz' then this function will make
* $form_values['foo']['bar'] to be 'baz'.
*
* @param $form
* The form item. Keys used: #parents, #value
* @param $value
* The value for the form item.
*/
function form_set_value($form, $value) {
global $form_values;
_form_set_value($form_values, $form, $form['#parents'], $value);
}
/**
* Helper function for form_set_value().
*
* We iterate of $parents and create nested arrays for them
* in $form_values if needed. Then we insert the value in
* the right array.
*/
function _form_set_value(&$form_values, $form, $parents, $value) {
$parent = array_shift($parents);
if (empty($parents)) {
$form_values[$parent] = $value;
}
else {
if (!isset($form_values[$parent])) {
$form_values[$parent] = array();
}
_form_set_value($form_values[$parent], $form, $parents, $value);
}
return $form;
}
/**
* Retrieve the default properties for the defined element type.
*/
function _element_info($type, $refresh = NULL) {
static $cache;
$basic_defaults = array(
'#description' => NULL,
'#attributes' => array(),
'#required' => FALSE,
'#tree' => FALSE,
'#parents' => array()
);
if (!isset($cache) || $refresh) {
$cache = array();
foreach (module_implements('elements') as $module) {
$elements = module_invoke($module, 'elements');
if (isset($elements) && is_array($elements)) {
$cache = array_merge_recursive($cache, $elements);
}
}
if (sizeof($cache)) {
foreach ($cache as $element_type => $info) {
$cache[$element_type] = array_merge_recursive($basic_defaults, $info);
}
}
}
return $cache[$type];
}
function form_options_flatten($array, $reset = TRUE) {
static $return;
if ($reset) {
$return = array();
}
foreach ($array as $key => $value) {
if (is_object($value)) {
form_options_flatten($value->option, FALSE);
}
else if (is_array($value)) {
form_options_flatten($value, FALSE);
}
else {
$return[$key] = 1;
}
}
return $return;
}
/**
* Format a dropdown menu or scrolling selection box.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: title, value, options, description, extra, multiple, required
* @return
* A themed HTML string representing the form element.
*
* It is possible to group options together; to do this, change the format of
* $options to an associative array in which the keys are group labels, and the
* values are associative arrays in the normal $options format.
*/
function theme_select($element) {
$select = '';
$size = $element['#size'] ? ' size="' . $element['#size'] . '"' : '';
_form_set_class($element, array('form-select'));
$multiple = isset($element['#multiple']) && $element['#multiple'];
return theme('form_element', $element, ''. form_select_options($element) .'');
}
function form_select_options($element, $choices = NULL) {
if (!isset($choices)) {
$choices = $element['#options'];
}
// array_key_exists() accommodates the rare event where $element['#value'] is NULL.
// isset() fails in this situation.
$value_valid = isset($element['#value']) || array_key_exists('#value', $element);
$value_is_array = is_array($element['#value']);
$options = '';
foreach ($choices as $key => $choice) {
if (is_array($choice)) {
$options .= '';
$options .= form_select_options($element, $choice);
$options .= '';
}
elseif (is_object($choice)) {
$options .= form_select_options($element, $choice->option);
}
else {
$key = (string)$key;
if ($value_valid && ((string)$element['#value'] === $key || ($value_is_array && in_array($key, $element['#value'])))) {
$selected = ' selected="selected"';
}
else {
$selected = '';
}
$options .= ''. check_plain($choice) .'';
}
}
return $options;
}
/**
* Traverses a select element's #option array looking for any values
* that hold the given key. Returns an array of indexes that match.
*
* This function is useful if you need to modify the options that are
* already in a form element, for example, to remove choices which are
* not valid because of additional filters imposed by another module.
* One example might be altering the choices in a taxonomy selector.
* To correctly handle the case of a multiple hierarchy taxonomy,
* #options arrays can now hold an array of objects, instead of a
* direct mapping of keys to labels, so that multiple choices in the
* selector can have the same key (and label). This makes it difficult
* to manipulate directly, which is why this helper function exists.
*
* This function does not support optgroups (when the elements of the
* #options array are themselves arrays), and will return FALSE if
* arrays are found. The caller must either flatten/restore or
* manually do their manipulations in this case, since returning the
* index is not sufficient, and supporting this would make the
* "helper" too complicated and cumbersome to be of any help.
*
* As usual with functions that can return array() or FALSE, do not
* forget to use === and !== if needed.
*
* @param $element
* The select element to search.
* @param $key
* The key to look for.
* @return
* An array of indexes that match the given $key. Array will be
* empty if no elements were found. FALSE if optgroups were found.
*/
function form_get_options($element, $key) {
$keys = array();
foreach ($element['#options'] as $index => $choice) {
if (is_array($choice)) {
return FALSE;
}
else if (is_object($choice)) {
if (isset($choice->option[$key])) {
$keys[] = $index;
}
}
else if ($index == $key) {
$keys[] = $index;
}
}
return $keys;
}
/**
* Format a group of form items.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: attributes, title, value, description, children, collapsible, collapsed
* @return
* A themed HTML string representing the form item group.
*/
function theme_fieldset($element) {
if ($element['#collapsible']) {
drupal_add_js('misc/collapse.js');
if (!isset($element['#attributes']['class'])) {
$element['#attributes']['class'] = '';
}
$element['#attributes']['class'] .= ' collapsible';
if ($element['#collapsed']) {
$element['#attributes']['class'] .= ' collapsed';
}
}
return '' . ($element['#title'] ? ''. $element['#title'] .'' : '') . ($element['#description'] ? ''. $element['#description'] .'' : '') . $element['#children'] . $element['#value'] . "\n";
}
/**
* Format a radio button.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: required, return_value, value, attributes, title, description
* @return
* A themed HTML string representing the form item group.
*/
function theme_radio($element) {
_form_set_class($element, array('form-radio'));
$output = '';
if (!is_null($element['#title'])) {
$output = ''. $output .' '. $element['#title'] .'';
}
unset($element['#title']);
return theme('form_element', $element, $output);
}
/**
* Format a set of radio buttons.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: title, value, options, description, required and attributes.
* @return
* A themed HTML string representing the radio button set.
*/
function theme_radios($element) {
$class = 'form-radios';
if (isset($element['#attributes']['class'])) {
$class .= ' '. $element['#attributes']['class'];
}
$element['#children'] = ''. $element['#children'] .'';
if ($element['#title'] || $element['#description']) {
unset($element['#id']);
return theme('form_element', $element, $element['#children']);
}
else {
return $element['#children'];
}
}
/**
* Format a password_confirm item.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: title, value, id, required, error.
* @return
* A themed HTML string representing the form item.
*/
function theme_password_confirm($element) {
return theme('form_element', $element, $element['#children']);
}
/*
* Expand a password_confirm field into two text boxes.
*/
function expand_password_confirm($element) {
$element['pass1'] = array(
'#type' => 'password',
'#title' => t('Password'),
'#value' => $element['#value']['pass1'],
);
$element['pass2'] = array(
'#type' => 'password',
'#title' => t('Confirm password'),
'#value' => $element['#value']['pass2'],
);
$element['#validate'] = array('password_confirm_validate' => array());
$element['#tree'] = TRUE;
return $element;
}
/**
* Validate password_confirm element.
*/
function password_confirm_validate($form) {
$pass1 = trim($form['pass1']['#value']);
if (!empty($pass1)) {
$pass2 = trim($form['pass2']['#value']);
if ($pass1 != $pass2) {
form_error($form, t('The specified passwords do not match.'));
}
}
elseif ($form['#required'] && !empty($form['#post'])) {
form_error($form, t('Password field is required.'));
}
// Password field must be converted from a two-element array into a single
// string regardless of validation results.
form_set_value($form['pass1'], NULL);
form_set_value($form['pass2'], NULL);
form_set_value($form, $pass1);
return $form;
}
/**
* Format a date selection element.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: title, value, options, description, required and attributes.
* @return
* A themed HTML string representing the date selection boxes.
*/
function theme_date($element) {
return theme('form_element', $element, ''. $element['#children'] .'');
}
/**
* Roll out a single date element.
*/
function expand_date($element) {
// Default to current date
if (!isset($element['#value'])) {
$element['#value'] = array('day' => format_date(time(), 'custom', 'j'),
'month' => format_date(time(), 'custom', 'n'),
'year' => format_date(time(), 'custom', 'Y'));
}
$element['#tree'] = TRUE;
// Determine the order of day, month, year in the site's chosen date format.
$format = variable_get('date_format_short', 'm/d/Y - H:i');
$sort = array();
$sort['day'] = max(strpos($format, 'd'), strpos($format, 'j'));
$sort['month'] = max(strpos($format, 'm'), strpos($format, 'M'));
$sort['year'] = strpos($format, 'Y');
asort($sort);
$order = array_keys($sort);
// Output multi-selector for date
foreach ($order as $type) {
switch ($type) {
case 'day':
$options = drupal_map_assoc(range(1, 31));
break;
case 'month':
$options = drupal_map_assoc(range(1, 12), 'map_month');
break;
case 'year':
$options = drupal_map_assoc(range(1900, 2050));
break;
}
$parents = $element['#parents'];
$parents[] = $type;
$element[$type] = array(
'#type' => 'select',
'#value' => $element['#value'][$type],
'#attributes' => $element['#attributes'],
'#options' => $options,
);
}
return $element;
}
/**
* Validates the date type to stop dates like February 30, 2006.
*/
function date_validate($form) {
if (!checkdate($form['#value']['month'], $form['#value']['day'], $form['#value']['year'])) {
form_error($form, t('The specified date is invalid.'));
}
}
/**
* Helper function for usage with drupal_map_assoc to display month names.
*/
function map_month($month) {
return format_date(gmmktime(0, 0, 0, $month, 2, 1970), 'custom', 'M', 0);
}
/**
* Helper function to load value from default value for checkboxes
*/
function checkboxes_value(&$form) {
$value = array();
foreach ((array)$form['#default_value'] as $key) {
$value[$key] = 1;
}
$form['#value'] = $value;
}
/**
* If no default value is set for weight select boxes, use 0.
*/
function weight_value(&$form) {
if (isset($form['#default_value'])) {
$form['#value'] = $form['#default_value'];
}
else {
$form['#value'] = 0;
}
}
/**
* Roll out a single radios element to a list of radios,
* using the options array as index.
*/
function expand_radios($element) {
if (count($element['#options']) > 0) {
foreach ($element['#options'] as $key => $choice) {
if (!isset($element[$key])) {
$element[$key] = array('#type' => 'radio', '#title' => $choice, '#return_value' => $key, '#default_value' => $element['#default_value'], '#attributes' => $element['#attributes'], '#parents' => $element['#parents'], '#spawned' => TRUE);
}
}
}
return $element;
}
/**
* Format a form item.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: title, value, description, required, error
* @return
* A themed HTML string representing the form item.
*/
function theme_item($element) {
return theme('form_element', $element, $element['#value'] . $element['#children']);
}
/**
* Format a checkbox.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: title, value, return_value, description, required
* @return
* A themed HTML string representing the checkbox.
*/
function theme_checkbox($element) {
_form_set_class($element, array('form-checkbox'));
$checkbox = '';
if (!is_null($element['#title'])) {
$checkbox = ''. $checkbox .' '. $element['#title'] .'';
}
unset($element['#title']);
return theme('form_element', $element, $checkbox);
}
/**
* Format a set of checkboxes.
*
* @param $element
* An associative array containing the properties of the element.
* @return
* A themed HTML string representing the checkbox set.
*/
function theme_checkboxes($element) {
$class = 'form-checkboxes';
if (isset($element['#attributes']['class'])) {
$class .= ' '. $element['#attributes']['class'];
}
$element['#children'] = ''. $element['#children'] .'';
if ($element['#title'] || $element['#description']) {
unset($element['#id']);
return theme('form_element', $element, $element['#children']);
}
else {
return $element['#children'];
}
}
function expand_checkboxes($element) {
$value = is_array($element['#value']) ? $element['#value'] : array();
$element['#tree'] = TRUE;
if (count($element['#options']) > 0) {
if (!isset($element['#default_value']) || $element['#default_value'] == 0) {
$element['#default_value'] = array();
}
foreach ($element['#options'] as $key => $choice) {
if (!isset($element[$key])) {
$element[$key] = array('#type' => 'checkbox', '#processed' => TRUE, '#title' => $choice, '#return_value' => $key, '#default_value' => isset($value[$key]), '#attributes' => $element['#attributes']);
}
}
}
return $element;
}
function theme_submit($element) {
return theme('button', $element);
}
function theme_button($element) {
//Make sure not to overwrite classes
if (isset($element['#attributes']['class'])) {
$element['#attributes']['class'] = 'form-'. $element['#button_type'] .' '. $element['#attributes']['class'];
}
else {
$element['#attributes']['class'] = 'form-'. $element['#button_type'];
}
return '\n";
}
/**
* Format a hidden form field.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: value, edit
* @return
* A themed HTML string representing the hidden form field.
*/
function theme_hidden($element) {
return '\n";
}
function theme_token($element) {
return theme('hidden', $element);
}
/**
* Format a textfield.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: title, value, description, size, maxlength, required, attributes autocomplete_path
* @return
* A themed HTML string representing the textfield.
*/
function theme_textfield($element) {
$size = $element['#size'] ? ' size="' . $element['#size'] . '"' : '';
$class = array('form-text');
$extra = '';
$output = '';
if ($element['#autocomplete_path']) {
drupal_add_js('misc/autocomplete.js');
$class[] = 'form-autocomplete';
$extra = '';
}
_form_set_class($element, $class);
if (isset($element['#field_prefix'])) {
$output .= ''. $element['#field_prefix'] .' ';
}
$output .= '';
if (isset($element['#field_suffix'])) {
$output .= ' '. $element['#field_suffix'] .'';
}
return theme('form_element', $element, $output). $extra;
}
/**
* Format a form.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: action, method, attributes, children
* @return
* A themed HTML string representing the form.
*/
function theme_form($element) {
// Anonymous div to satisfy XHTML compliance.
$action = $element['#action'] ? 'action="' . check_url($element['#action']) . '" ' : '';
return '\n". $element['#children'] ."\n\n";
}
/**
* Format a textarea.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: title, value, description, rows, cols, required, attributes
* @return
* A themed HTML string representing the textarea.
*/
function theme_textarea($element) {
$class = array('form-textarea');
if ($element['#resizable'] !== FALSE) {
drupal_add_js('misc/textarea.js');
$class[] = 'resizable';
}
$cols = $element['#cols'] ? ' cols="'. $element['#cols'] .'"' : '';
_form_set_class($element, $class);
return theme('form_element', $element, ''. check_plain($element['#value']) .'');
}
/**
* Format HTML markup for use in forms.
*
* This is used in more advanced forms, such as theme selection and filter format.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: value, children.
* @return
* A themed HTML string representing the HTML markup.
*/
function theme_markup($element) {
return (isset($element['#value']) ? $element['#value'] : '') . (isset($element['#children']) ? $element['#children'] : '');
}
/**
* Format a password field.
*
* @param $element
* An associative array containing the properties of the element.
* Properties used: title, value, description, size, maxlength, required, attributes
* @return
* A themed HTML string representing the form.
*/
function theme_password($element) {
$size = $element['#size'] ? ' size="'. $element['#size'] .'" ' : '';
$maxlength = $element['#maxlength'] ? ' maxlength="'. $element['#maxlength'] .'" ' : '';
_form_set_class($element, array('form-text'));
$output = '';
return theme('form_element', $element, $output);
}
/**
* Expand weight elements into selects.
*/
function process_weight($element) {
for ($n = (-1 * $element['#delta']); $n <= $element['#delta']; $n++) {
$weights[$n] = $n;
}
$element['#options'] = $weights;
$element['#type'] = 'select';
$element['#is_weight'] = TRUE;
return $element;
}
/**
* Format a file upload field.
*
* @param $title
* The label for the file upload field.
* @param $name
* The internal name used to refer to the field.
* @param $size
* A measure of the visible size of the field (passed directly to HTML).
* @param $description
* Explanatory text to display after the form item.
* @param $required
* Whether the user must upload a file to the field.
* @return
* A themed HTML string representing the field.
*
* For assistance with handling the uploaded file correctly, see the API
* provided by file.inc.
*/
function theme_file($element) {
_form_set_class($element, array('form-file'));
return theme('form_element', $element, '\n");
}
/**
* Return a themed form element.
*
* @param element
* An associative array containing the properties of the element.
* Properties used: title, description, id, required
* @param $value
* the form element's data
* @return
* a string representing the form element
*/
function theme_form_element($element, $value) {
$output = ''."\n";
$required = !empty($element['#required']) ? '*' : '';
if (!empty($element['#title'])) {
$title = $element['#title'];
if (!empty($element['#id'])) {
$output .= ' '. t('!title: !required', array('!title' => $title, '!required' => $required)) ."\n";
}
else {
$output .= ' '. t('!title: !required', array('!title' => $title, '!required' => $required)) ."\n";
}
}
$output .= " $value\n";
if (!empty($element['#description'])) {
$output .= ' '. $element['#description'] ."\n";
}
$output .= "\n";
return $output;
}
/**
* Sets a form element's class attribute.
*
* Adds 'required' and 'error' classes as needed.
*
* @param &$element
* The form element
* @param $name
* Array of new class names to be added
*/
function _form_set_class(&$element, $class = array()) {
if ($element['#required']) {
$class[] = 'required';
}
if (form_get_error($element)){
$class[] = 'error';
}
if (isset($element['#attributes']['class'])) {
$class[] = $element['#attributes']['class'];
}
$element['#attributes']['class'] = implode(' ', $class);
}
/**
* Remove invalid characters from an HTML ID attribute string.
*
* @param $id
* The ID to clean
* @return
* The cleaned ID
*/
function form_clean_id($id = NULL) {
$id = str_replace(array('][', '_', ' '), '-', $id);
return $id;
}
/**
* @} End of "defgroup form".
*/
Ho risolto il problema per drupal 53 (visto che forse il file form.inc della rc2 non va più bene) seguendo questa discussione:
http://drupal.org/node/111719
Ho risolto il problema per garland applicando il numero #23 agendo sul file template.php
Il problema resta nella pagina del modulo di contatto. Ho risolto non visualizzazndo il blocco con il login in questa pagina con il modulo di contatto.