? 2 ? forms.patch ? scratch ? includes/form.inc ? includes/legacy.inc Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.476 diff -u -r1.476 common.inc --- includes/common.inc 31 Aug 2005 18:37:30 -0000 1.476 +++ includes/common.inc 12 Sep 2005 13:28:13 -0000 @@ -489,38 +489,6 @@ } /** - * An unchecked checkbox is not present in $_POST so we fix it here by - * proving a default value of 0. Also, with form_checkboxes() we expect - * an array, but HTML does not send the empty array. This is also taken - * care off. - */ -function fix_checkboxes() { - if (isset($_POST['form_array'])) { - $_POST['edit'] = _fix_checkboxes($_POST['edit'], $_POST['form_array'], array()); - } - if (isset($_POST['form_zero'])) { - $_POST['edit'] = _fix_checkboxes($_POST['edit'], $_POST['form_zero'], 0); - } -} - -function _fix_checkboxes($array1, $array2, $value) { - if (is_array($array2) && count($array2)) { - foreach ($array2 as $k => $v) { - if (is_array($v) && count($v)) { - $array1[$k] = _fix_checkboxes($array1[$k], $v, $value); - } - else if (!isset($array1[$k])) { - $array1[$k] = $value; - } - } - } - else { - $array1 = $value; - } - return $array1; -} - -/** * @name Conversion * @{ * Converts data structures to different types. @@ -559,6 +527,41 @@ return $array; } + +/** + * Apply a user function recursively to every member of an array + * + * Taken from PHP Compat package in PEAR. + */ +if (!function_exists('array_walk_recursive')) { + function array_walk_recursive(&$input, $funcname) { + if (!is_callable($funcname)) { + if (is_array($funcname)) { + $funcname = $funcname[0] . '::' . $funcname[1]; + } + user_error('array_walk_recursive() Not a valid callback ' . $user_func, E_USER_WARNING); + return; + } + if (!is_array($input)) { + user_error('array_walk_recursive() The argument should be an array', E_USER_WARNING); + return; + } + $args = func_get_args(); + foreach ($input as $key => $item) { + if (is_array($item)) { + array_walk_recursive($item, $funcname, $args); + $input[$key] = $item; + } else { + $args[0] = &$item; + $args[1] = &$key; + call_user_func_array($funcname, $args); + $input[$key] = $item; + } + } + } +} + + /** * @} End of "Conversion". */ @@ -1009,552 +1012,6 @@ * @} End of "defgroup format". */ -/** - * @defgroup form Form generation - * @{ - * Functions to enable output of HTML forms and form elements. - * - * Drupal uses these functions to achieve consistency in its form presentation, - * while at the same time simplifying code and reducing the amount of HTML that - * must be explicitly generated by modules. - */ - -/** - * Generate a form from a set of form elements. - * - * @param $form - * An HTML string containing one or more form elements. - * @param $method - * The query method to use ("post" or "get"). - * @param $action - * The URL to send the form contents to, if not the current page. - * @param $attributes - * An associative array of attributes to add to the form tag. - * @result - * An HTML string with the contents of $form wrapped in a form tag. - */ -function form($form, $method = 'post', $action = NULL, $attributes = NULL) { - if (!$action) { - $action = request_uri(); - } - // Anonymous div to satisfy XHTML compliancy. - return '
\n
". $form ."\n
\n"; -} - -/** - * File an error against the form element with the specified name. - */ -function form_set_error($name, $message) { - $GLOBALS['form'][$name] = $message; - drupal_set_message($message, 'error'); -} - -/** - * Return an associative array of all errors. - */ -function form_get_errors() { - if (array_key_exists('form', $GLOBALS)) { - return $GLOBALS['form']; - } -} - -/** - * Return the error message filed against the form with the specified name. - */ -function _form_get_error($name) { - if (array_key_exists('form', $GLOBALS)) { - return $GLOBALS['form'][$name]; - } -} - -function _form_get_class($name, $required, $error) { - return $name. ($required ? ' required' : '') . ($error ? ' error' : ''); -} - -/** - * Format a general form item. - * - * @param $title - * The label for the form item. - * @param $value - * The contents of the form item. - * @param $description - * Explanatory text to display after the form item. - * @param $id - * A unique identifier for the form item. - * @param $required - * Whether the user must fill in this form element before submitting the form. - * @param $error - * An error message to display alongside the form element. - * @return - * A themed HTML string representing the form item. - */ -function form_item($title, $value, $description = NULL, $id = NULL, $required = FALSE, $error = FALSE) { - return theme('form_element', $title, $value, $description, $id, $required, $error); -} - -/** - * Format a group of form items. - * - * @param $legend - * The label for the form item group. - * @param $group - * The form items within the group, as an HTML string. - * @param $description - * Explanatory text to display after the form item group. - * @param $attributes - * An associative array of HTML attributes to add to the fieldset tag. - * @return - * A themed HTML string representing the form item group. - */ -function form_group($legend, $group, $description = NULL, $attributes = NULL) { - return '' . ($legend ? ''. $legend .'' : '') . $group . ($description ? '
'. $description .'
' : '') . "\n"; -} - -/** - * Format a group of form items. - * - * @param $legend - * The label for the form item group. - * @param $group - * The form items within the group, as an HTML string. - * @param $collapsed - * A boolean value decided whether the group starts collapsed. - * @param $description - * Explanatory text to display after the form item group. - * @param $attributes - * An associative array of HTML attributes to add to the fieldset tag. - * @return - * A themed HTML string representing the form item group. - */ -function form_group_collapsible($legend, $group, $collapsed = FALSE, $description = NULL, $attributes = NULL) { - drupal_add_js('misc/collapse.js'); - - $attributes['class'] .= ' collapsible'; - if ($collapsed) { - $attributes['class'] .= ' collapsed'; - } - - return '' . ($legend ? ''. $legend .'' : '') . $group . ($description ? '
'. $description .'
' : '') . "\n"; -} - -/** - * Format a radio button. - * - * @param $title - * The label for the radio button. - * @param $name - * The internal name used to refer to the button. - * @param $value - * The value that the form element takes on when selected. - * @param $checked - * Whether the button will be initially selected when the page is rendered. - * @param $description - * Explanatory text to display after the form item. - * @param $attributes - * An associative array of HTML attributes to add to the button. - * @param $required - * Whether the user must select this radio button before submitting the form. - * @return - * A themed HTML string representing the radio button. - */ -function form_radio($title, $name, $value = 1, $checked = FALSE, $description = NULL, $attributes = NULL, $required = FALSE) { - $element = ''; - if (!is_null($title)) { - $element = ''; - } - return theme('form_element', NULL, $element, $description, $name, $required, _form_get_error($name)); -} - -/** - * Format a set of radio buttons. - * - * @param $title - * The label for the radio buttons as a group. - * @param $name - * The internal name used to refer to the buttons. - * @param $value - * The currently selected radio button's key. - * @param $options - * An associative array of buttons to display. The keys in this array are - * button values, while the values are the labels to display for each button. - * @param $description - * Explanatory text to display after the form item. - * @param $required - * Whether the user must select a radio button before submitting the form. - * @param $attributes - * An associative array of HTML attributes to add to each button. - * @return - * A themed HTML string representing the radio button set. - */ -function form_radios($title, $name, $value, $options, $description = NULL, $required = FALSE, $attributes = NULL) { - if (count($options) > 0) { - $choices = ''; - foreach ($options as $key => $choice) { - $choices .= '
'; - } - return theme('form_element', $title, $choices, $description, NULL, $required, _form_get_error($name)); - } -} - -/** - * Format a checkbox. - * - * @param $title - * The label for the checkbox. - * @param $name - * The internal name used to refer to the button. - * @param $value - * The value that the form element takes on when selected. - * @param $checked - * Whether the button will be initially selected when the page is rendered. - * @param $description - * Explanatory text to display after the form item. - * @param $attributes - * An associative array of HTML attributes to add to the button. - * @param $required - * Whether the user must check this box before submitting the form. - * @return - * A themed HTML string representing the checkbox. - */ -function form_checkbox($title, $name, $value = 1, $checked = FALSE, $description = NULL, $attributes = NULL, $required = FALSE) { - $element = ''; - if (!is_null($title)) { - $element = ''; - } - return form_hidden($name, 1, 'form_zero') . theme('form_element', NULL, $element, $description, $name, $required, _form_get_error($name)); -} - -/** - * Format a set of checkboxes. - * - * @param $title - * The label for the checkboxes as a group. - * @param $name - * The internal name used to refer to the buttons. - * @param $values - * A linear array of keys of the initially checked boxes. - * @param $options - * An associative array of buttons to display. The keys in this array are - * button values, while the values are the labels to display for each button. - * @param $description - * Explanatory text to display after the form item. - * @param $attributes - * An associative array of HTML attributes to add to each button. - * @param $required - * Whether the user must check a box before submitting the form. - * @return - * A themed HTML string representing the checkbox set. - */ -function form_checkboxes($title, $name, $values, $options, $description = NULL, $attributes = NULL, $required = FALSE) { - if (count($options) > 0) { - if (!isset($values) || $values == 0) { - $values = array(); - } - $choices = ''; - foreach ($options as $key => $choice) { - $choices .= '
'; - } - return form_hidden($name, 1, 'form_array') . theme('form_element', $title, $choices, $description, NULL, $required, _form_get_error($name)); - } -} - -/** - * Format a single-line text field. - * - * @param $title - * The label for the text field. - * @param $name - * The internal name used to refer to the field. - * @param $value - * The initial value for the field at page load time. - * @param $size - * A measure of the visible size of the field (passed directly to HTML). - * @param $maxlength - * The maximum number of characters that may be entered in the field. - * @param $description - * Explanatory text to display after the form item. - * @param $attributes - * An associative array of HTML attributes to add to the form item. - * @param $required - * Whether the user must enter some text in the field. - * @return - * A themed HTML string representing the field. - */ -function form_textfield($title, $name, $value, $size, $maxlength, $description = NULL, $attributes = NULL, $required = FALSE) { - $size = $size ? ' size="'. $size .'"' : ''; - return theme('form_element', $title, '', $description, 'edit-'. $name, $required, _form_get_error($name)); -} - -/** - * Format a single-line text field that uses Ajax for autocomplete. - * - * @param $title - * The label for the text field. - * @param $name - * The internal name used to refer to the field. - * @param $value - * The initial value for the field at page load time. - * @param $size - * A measure of the visible size of the field (passed directly to HTML). - * @param $maxlength - * The maximum number of characters that may be entered in the field. - * @param $callback_path - * A drupal path for the Ajax autocomplete callback. - * @param $description - * Explanatory text to display after the form item. - * @param $attributes - * An associative array of HTML attributes to add to the form item. - * @param $required - * Whether the user must enter some text in the field. - * @return - * A themed HTML string representing the field. - */ -function form_autocomplete($title, $name, $value, $size, $maxlength, $callback_path, $description = NULL, $attributes = NULL, $required = FALSE) { - drupal_add_js('misc/autocomplete.js'); - - $size = $size ? ' size="'. $size .'"' : ''; - - $output = theme('form_element', $title, '', $description, 'edit-'. $name, $required, _form_get_error($name)); - $output .= ''; - - return $output; -} - -/** - * Format a single-line text field that does not display its contents visibly. - * - * @param $title - * The label for the text field. - * @param $name - * The internal name used to refer to the field. - * @param $value - * The initial value for the field at page load time. - * @param $size - * A measure of the visible size of the field (passed directly to HTML). - * @param $maxlength - * The maximum number of characters that may be entered in the field. - * @param $description - * Explanatory text to display after the form item. - * @param $attributes - * An associative array of HTML attributes to add to the form item. - * @param $required - * Whether the user must enter some text in the field. - * @return - * A themed HTML string representing the field. - */ -function form_password($title, $name, $value, $size, $maxlength, $description = NULL, $attributes = NULL, $required = FALSE) { - $size = $size ? ' size="'. $size .'"' : ''; - return theme('form_element', $title, '', $description, 'edit-'. $name, $required, _form_get_error($name)); -} - -/** - * Format a multiple-line text field. - * - * @param $title - * The label for the text field. - * @param $name - * The internal name used to refer to the field. - * @param $value - * The initial value for the field at page load time. - * @param $cols - * The width of the field, in columns of text. - * @param $rows - * The height of the field, in rows of text. - * @param $description - * Explanatory text to display after the form item. - * @param $attributes - * An associative array of HTML attributes to add to the form item. - * @param $required - * Whether the user must enter some text in the field. - * @return - * A themed HTML string representing the field. - */ -function form_textarea($title, $name, $value, $cols, $rows, $description = NULL, $attributes = NULL, $required = FALSE) { - $cols = $cols ? ' cols="'. $cols .'"' : ''; - $pre = ''; - $post = ''; - - // optionally plug in a WYSIWYG editor - foreach (module_list() as $module_name) { - if (module_hook($module_name, 'textarea')) { - $pre .= module_invoke($module_name, 'textarea', 'pre', $name); - $post .= module_invoke($module_name, 'textarea', 'post', $name); - } - } - - return theme('form_element', $title, $pre .''. check_plain($value) .''. $post, $description, 'edit-'. $name, $required, _form_get_error($name)); -} - -/** - * Format a dropdown menu or scrolling selection box. - * - * @param $title - * The label for the form element. - * @param $name - * The internal name used to refer to the form element. - * @param $value - * The key of the currently selected item, or a linear array of keys of all the - * currently selected items if multiple selections are allowed. - * @param $options - * An associative array of buttons to display. The keys in this array are - * button values, while the values are the labels to display for each button. - * @param $description - * Explanatory text to display after the form item. - * @param $extra - * Additional HTML to inject into the select element tag. - * @param $multiple - * Whether the user may select more than one item. - * @param $required - * Whether the user must select a value before submitting the form. - * @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 form_select($title, $name, $value, $options, $description = NULL, $extra = 0, $multiple = FALSE, $required = FALSE) { - $select = ''; - foreach ($options as $key => $choice) { - if (is_array($choice)) { - $select .= ''; - foreach ($choice as $key => $choice) { - $select .= ''; - } - $select .= ''; - } - else { - $select .= ''; - } - } - return theme('form_element', $title, '', $description, 'edit-'. $name, $required, _form_get_error($name)); -} - -/** - * 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 form_file($title, $name, $size, $description = NULL, $required = FALSE) { - return theme('form_element', $title, '\n", $description, 'edit-'. $name, $required, _form_get_error($name)); -} - -/** - * Store data in a hidden form field. - * - * @param $name - * The internal name used to refer to the field. - * @param $value - * The stored data. - * @param $edit - * The array name to prefix to the $name. - * @param $attributes - * An array of HTML attributes for the input tag. - * @return - * A themed HTML string representing the hidden field. - * - * This function can be useful in retaining information between page requests, - * but be sure to validate the data on the receiving page as it is possible for - * an attacker to change the value before it is submitted. - */ -function form_hidden($name, $value, $edit = 'edit', $attributes = NULL) { - return '\n"; -} - -/** - * Format an action button. - * - * @param $value - * Both the label for the button, and the value passed to the target page - * when this button is clicked. - * @param $name - * The internal name used to refer to the button. - * @param $type - * What type to pass to the HTML input tag. - * @param $attributes - * An associative array of HTML attributes to add to the form item. - * @return - * A themed HTML string representing the button. - */ -function form_button($value, $name = 'op', $type = 'submit', $attributes = NULL) { - return '\n"; -} - -/** - * Format a form submit button. - * - * @param $value - * Both the label for the button, and the value passed to the target page - * when this button is clicked. - * @param $name - * The internal name used to refer to the button. - * @param $attributes - * An associative array of HTML attributes to add to the form item. - * @return - * A themed HTML string representing the button. - */ -function form_submit($value, $name = 'op', $attributes = NULL) { - return form_button($value, $name, 'submit', $attributes); -} - -/** - * Format a weight selection menu. - * - * @param $title - * The label for the form element. - * @param $name - * The internal name used to refer to the form element. - * @param $value - * The selected weight value at page load time. - * @param $delta - * The largest in absolute value the weight can be. For example, if set to 10, - * weights could range from -10 to 10 inclusive. - * @param $description - * Explanatory text to display after the form item. - * @param $extra - * Additional HTML to inject into the select element tag. - * @return - * A themed HTML string representing the form element. - */ -function form_weight($title = NULL, $name = 'weight', $value = 0, $delta = 10, $description = NULL, $extra = 0) { - for ($n = (-1 * $delta); $n <= $delta; $n++) { - $weights[$n] = $n; - } - - return form_select($title, $name, $value, $weights, $description, $extra); -} - -/** - * 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('][', '-', $id); - return $id; -} - -/** - * @} End of "defgroup form". - */ /** * Generate an internal Drupal URL. @@ -1915,6 +1372,8 @@ require_once './includes/file.inc'; require_once './includes/unicode.inc'; require_once './includes/image.inc'; + require_once './includes/form.inc'; + require_once './includes/legacy.inc'; // Set the Drupal custom error handler. set_error_handler('error_handler'); // Emit the correct charset HTTP header. Index: includes/unicode.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/unicode.inc,v retrieving revision 1.4 diff -u -r1.4 unicode.inc --- includes/unicode.inc 25 Aug 2005 21:14:16 -0000 1.4 +++ includes/unicode.inc 12 Sep 2005 13:28:14 -0000 @@ -81,7 +81,8 @@ $options = array(UNICODE_SINGLEBYTE => t('Standard PHP: operations on Unicode strings are emulated on a best-effort basis. Install the PHP mbstring extension for improved Unicode support.', array('%url' => 'http://www.php.net/manual/nl/ref.mbstring.php')), UNICODE_MULTIBYTE => t('Multi-byte: operations on Unicode strings are supported through the PHP mbstring extension.', array('%url' => 'http://www.php.net/manual/nl/ref.mbstring.php')), UNICODE_ERROR => t('Invalid: the current configuration is incompatible with Drupal.')); - return form_item(t('String handling method'), $options[$status]); + $form['settings'] = array(type => 'item', title =>t('String handling method'), value => $options[$status]); + return $form; } /** @@ -449,3 +450,4 @@ } } + Index: misc/drupal.css =================================================================== RCS file: /cvs/drupal/drupal/misc/drupal.css,v retrieving revision 1.120 diff -u -r1.120 drupal.css --- misc/drupal.css 7 Sep 2005 20:56:00 -0000 1.120 +++ misc/drupal.css 12 Sep 2005 13:28:14 -0000 @@ -629,3 +629,8 @@ display: block; } +/* +** Temporary CSS for porting of drupal forms. +*/ +form { border: 3px solid red; } +form.form-api { border : 0px; } Index: modules/aggregator.module =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator.module,v retrieving revision 1.253 diff -u -r1.253 aggregator.module --- modules/aggregator.module 8 Sep 2005 20:08:42 -0000 1.253 +++ modules/aggregator.module 12 Sep 2005 13:28:17 -0000 @@ -72,12 +72,30 @@ $items = array(0 => t('none')) + drupal_map_assoc(array(3, 5, 10, 15, 20, 25), '_aggregator_items'); $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval'); - $output = ''; - $output .= form_textfield(t('Allowed HTML tags'), 'aggregator_allowed_html_tags', variable_get('aggregator_allowed_html_tags', '
      • '), 80, 255, t('The list of tags which are allowed in feeds, i.e., which will not be removed by Drupal.')); - $output .= form_select(t('Items shown in sources and categories pages'), 'aggregator_summary_items', variable_get('aggregator_summary_items', 3), $items, t('The number of items which will be shown with each feed or category in the feed and category summary pages.')); - $output .= form_select(t('Discard news items older than'), 'aggregator_clear', variable_get('aggregator_clear', 9676800), $period, t('Older news items will be automatically discarded. Requires crontab.')); - $output .= form_radios(t('Category selection type'), 'aggregator_category_selector', variable_get('aggregator_category_selector', 'check'), array('check' => t('checkboxes'), 'select' => t('multiple selector')), t('The type of category selection widget which is shown on categorization pages. Checkboxes are easier to use; a multiple selector is good for working with large numbers of categories.')); - return $output; + $form['aggregator_allowed_html_tags'] = array( + type => 'textfield', title => t('Allowed HTML tags'), size => 80, maxlength => 255, + default_value => variable_get('aggregator_allowed_html_tags', '
          • '), + description => t('The list of tags which are allowed in feeds, i.e., which will not be removed by Drupal.') + ); + + $form['aggregator_summary_items'] = array( + type => 'select', title => t('Items shown in sources and categories pages') , + default_value => variable_get('aggregator_summary_items', 3), options => $items, + description => t('The number of items which will be shown with each feed or category in the feed and category summary pages.') + ); + + $form['aggregator_clear'] = array( + type => 'select', title => t('Discard news items older than'), + default_value => variable_get('aggregator_clear', 9676800), options => $period, + description => t('Older news items will be automatically discarded. Requires crontab.') + ); + + $form['aggregator_category_selector'] = array( + type => 'radios', title => t('Category selection type'), default_value => variable_get('aggregator_category_selector', 'check'), + options => array('check' => t('checkboxes'), 'select' => t('multiple selector')), + description => t('The type of category selection widget which is shown on categorization pages. Checkboxes are easier to use; a multiple selector is good for working with large numbers of categories.') + ); + return $form; } /** @@ -219,9 +237,8 @@ else { $value = db_result(db_query('SELECT block FROM {aggregator_feed} WHERE fid = %d', $id)); } - - $output = form_select(t('Number of news items in block'), 'block', $value, drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20))); - return $output; + $form['block'] = array(type => 'select', title => t('Number of news items in block'), default_value => $value, options => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20))); + return $form; } else if ($op == 'save') { list($type, $id) = explode('-', $delta); @@ -658,16 +675,16 @@ } function aggregator_form_category($edit = array()) { - $form = form_textfield(t('Title'), 'title', $edit['title'], 60, 64); - $form .= form_textarea(t('Description'), 'description', $edit['description'], 60, 5); - $form .= form_submit(t('Submit')); + $form['title'] = array(type => 'textfield', title => t('Title'), default_value => $edit['title'], size => 60, maxlength => 64); + $form['description'] = array(type => 'textarea', title => t('Description'), default_value => $edit['description'], size => 60, maxlength => 5); + $form['submit'] = array(type => 'submit', value =>t('Submit')); if ($edit['cid']) { - $form .= form_submit(t('Delete')); - $form .= form_hidden('cid', $edit['cid']); + $form['delete'] = array(type => 'submit', value =>t('Delete')); + $form['cid'] = array('type' => 'hidden', value => $edit['cid']); } - return form($form); + return drupal_get_form('aggregator_form_category', $form); } function aggregator_save_category($edit) { @@ -691,9 +708,10 @@ $edit['refresh'] = 3600; } - $form .= form_textfield(t('Title'), 'title', $edit['title'], 60, 64, t('The name of the feed; typically the name of the web site you syndicate content from.')); - $form .= form_textfield(t('URL'), 'url', $edit['url'], 60, 255, t('The fully-qualified URL of the feed.')); - $form .= form_select(t('Update interval'), 'refresh', $edit['refresh'], $period, t('The refresh interval indicating how often you want to update this feed. Requires crontab.')); + + $form['title'] = array(type => 'textfield', title => t('Title'), default_value => $edit['title'], size => 60, maxlength => 64, description => t('The name of the feed; typically the name of the web site you syndicate content from.')); + $form['url'] = array(type => 'textfield', title => t('URL'), default_value => $edit['url'], size => 60, maxlength => 255, description => t('The fully-qualified URL of the feed.')); + $form['refresh'] = array(type => 'select', title => t('Update interval'), default_value => $edit['refresh'], options => $period, description => t('The refresh interval indicating how often you want to update this feed. Requires crontab.')); // Handling of categories: $options = array(); @@ -704,17 +722,16 @@ if ($category->fid) $values[] = check_plain($category->cid); } if ($options) { - $form .= form_checkboxes(t('Categorize news items'), 'category', $values, $options, t('New items in this feed will be automatically filed in the checked categories as they are received.')); + $form['category'] = array(type => 'checkboxes', title => t('Categorize news items'), default_value => $values, options => $options, description => t('New items in this feed will be automatically filed in the checked categories as they are received.')); } + $form['submit'] = array(type => 'submit', value =>t('Submit')); - // Form buttons: - $form .= form_submit(t('Submit')); if ($edit['fid']) { - $form .= form_submit(t('Delete')); - $form .= form_hidden('fid', $edit['fid']); + $form['delete'] = array(type => 'submit', value =>t('Delete')); + $form['fid'] = array('type' => 'hidden', value => $edit['cid']); } - return form($form); + return drupal_get_form('aggregator_form_feed', $form); } function aggregator_save_feed($edit) { @@ -786,7 +803,6 @@ } function aggregator_edit() { - if ($_POST['op'] == t('Submit')) { if (arg(1) == 'categories') { aggregator_save_category($_POST['edit']); @@ -941,85 +957,96 @@ * menu callbacks use this function to print their feeds. */ function _aggregator_page_list($sql, $op, $header = '') { - if (user_access('administer news feeds') && $op == 'categorize') { - if ($edit = $_POST['edit']) { - foreach ($edit['categories'] as $iid => $selection) { - db_query('DELETE FROM {aggregator_category_item} WHERE iid = %d', $iid); - foreach ($selection as $cid) { - if ($cid) { - db_query('INSERT INTO {aggregator_category_item} (cid, iid) VALUES (%d, %d)', $cid, $iid); - } - } - } - drupal_set_message(t('The categories have been saved.')); - drupal_goto($_GET['q']); - } - else { - $categorize = true; - } - } + $categorize = (user_access('administer news feeds') && ($op == 'categorize')); $output = '
            '; - if ($header) { - $output .= $header; - } - if ($links) { - $output .= theme('links', $links); - } - $result = pager_query($sql, 20); + $form['header'] = array(value => $header); + $output .= $form['header'][value]; - $rows = array(); + $result = pager_query($sql, 20); $categories = array(); while ($item = db_fetch_object($result)) { + $form['items'][$item->iid] = array(value => theme('aggregator_page_item', $item)); + $output .= $form['items'][$item->iid][value]; + $form['categories'][$item->iid] = array(); + if ($categorize) { + $categories_result = db_query('SELECT c.cid, c.title, ci.iid FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid AND ci.iid = %d', $item->iid); - if (variable_get('aggregator_category_selector', 'check') == 'select') { - $selected = array(); - while ($category = db_fetch_object($categories_result)) { - if (!$done) { - $categories[$category->cid] = check_plain($category->title); - } - if ($category->iid) { - $selected[] = $category->cid; - } + $selected = array(); + while ($category = db_fetch_object($categories_result)) { + if (!$done) { + $categories[$category->cid] = check_plain($category->title); } - $done = true; - $form = form_select(NULL, 'categories]['. $item->iid, $selected, $categories, NULL, 'size="10"', true); - } - else { - $form = ''; - while ($category = db_fetch_object($categories_result)) { - $form .= form_checkbox(check_plain($category->title), 'categories]['. $item->iid .'][', $category->cid, !is_null($category->iid)); + if ($category->iid) { + $selected[] = $category->cid; } } - $rows[] = array(theme('aggregator_page_item', $item), array('data' => $form, 'class' => 'categorize-item')); - } - else { - $output .= theme('aggregator_page_item', $item); + $done = true; + $form['categories'][$item->iid] = array( + type => variable_get('aggregator_category_selector', 'checkboxes'), + default_value => $selected, options => $categories, + size => 10, multiple => true + ); } } - if ($categorize) { - $output .= form(theme('table', array('', t('Categorize')), $rows) . form_submit(t('Save categories'))); - } - $output .= '
            '; - - if ($pager = theme('pager', NULL, 20, 0)) { - $output .= $pager; - } + $output .= ''; + $form['submit'] = array(type => 'submit', value => t('Save categories')); + $form['pager'] = array(value => theme('pager', NULL, 20, 0)); + $output .= $form['pager'][value]; // arg(1) is undefined if we are at the top aggregator URL // is there a better way to do this? if (!arg(1)) { - $output .= theme('xml_icon', url('aggregator/rss')); + $form['xml_icon'] = array(value => theme('xml_icon', url('aggregator/rss'))); } elseif (arg(1) == 'categories' && arg(2) && !arg(3)) { - $output .= theme('xml_icon', url('aggregator/rss/' . arg(2))); + $form['xml_icon'] = array(value => theme('xml_icon', url('aggregator/rss/' . arg(2)))); } + $output .= $form['xml_icon'][value]; + return ($categorize) ? drupal_get_form('aggregator_page_list', $form) : $output; +} + +function theme_aggregator_page_list($form) { + $output = '
            '; + $output .= form_render($form['header']); + $rows = array(); + foreach ($form['items'] as $key => $element) { + if (element_child($key)) { + $rows[] = array(form_render($form['items'][$key]), array('data' => form_render($form['categories'][$key]), 'class' => 'categorize-item')); + } + } + $output .= theme('table', array('', t('Categorize')), $rows); + $output .= form_render($form['submit']); + $output .= '
            '; + $output .= form_render($form); return $output; } +function aggregator_page_list_validate($form_id, &$form) { + if (!user_access('administer news feeds')) { + form_error($form, t('You are not allowed to categorize this feed item.')); + } +} + +function aggregator_page_list_execute($form_id, $form) { + global $form_values; + foreach ($form_values['categories'] as $iid => $selection) { + db_query('DELETE FROM {aggregator_category_item} WHERE iid = %d', $iid); + foreach ($selection as $cid) { + if ($cid) { + db_query('INSERT INTO {aggregator_category_item} (cid, iid) VALUES (%d, %d)', $cid, $iid); + } + } + } + drupal_set_message(t('The categories have been saved.')); + drupal_goto($_GET['q']); +} + + + /** * Menu callback; displays all the feeds used by the aggregator. */ Index: modules/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block.module,v retrieving revision 1.178 diff -u -r1.178 block.module --- modules/block.module 25 Aug 2005 21:14:16 -0000 1.178 +++ modules/block.module 12 Sep 2005 13:28:18 -0000 @@ -54,15 +54,18 @@ $items = array(); if ($may_cache) { - $items[] = array('path' => 'admin/block', 'title' => t('blocks'), + $items[] = array('path' => 'admin/display/regions', 'title' => t('regions'), 'access' => user_access('administer blocks'), - 'callback' => 'block_admin'); - $items[] = array('path' => 'admin/block/list', 'title' => t('list'), + 'callback' => 'block_admin', + 'type' => MENU_LOCAL_TASK); + $items[] = array('path' => 'admin/display/regions/list', 'title' => t('list'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10); - $items[] = array('path' => 'admin/block/configure', 'title' => t('configure block'), + + $items[] = array('path' => 'admin/display/regions/configure', 'title' => t('configure block'), 'access' => user_access('administer blocks'), 'callback' => 'block_admin_configure', 'type' => MENU_CALLBACK); + $items[] = array('path' => 'admin/block/delete', 'title' => t('delete block'), 'access' => user_access('administer blocks'), 'callback' => 'block_box_delete', Index: modules/blog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blog.module,v retrieving revision 1.226 diff -u -r1.226 blog.module --- modules/blog.module 7 Sep 2005 20:17:18 -0000 1.226 +++ modules/blog.module 12 Sep 2005 13:28:19 -0000 @@ -42,7 +42,11 @@ */ function blog_user($type, &$edit, &$user) { if ($type == 'view' && user_access('edit own blog', $user)) { - return array(t('History') => form_item(t('Blog'), l(t('view recent blog entries'), "blog/$user->uid", array('title' => t("Read %username's latest blog entries.", array('%username' => $user->name)))))); + $form['blog'] = array( + type => 'item', title => t('Blog'), + value => l(t('view recent blog entries'), "blog/$user->uid", array('title' => t("Read %username's latest blog entries.", array('%username' => $user->name)))) + ); + return array(t('History') => $form); } } @@ -204,16 +208,17 @@ // Note: $item->description has been validated on aggregation. $node->body = '
            '. check_plain($item->title) .' - '. $item->description .' ['. check_plain($item->ftitle) ."]\n"; } + } if (function_exists('taxonomy_node_form')) { - $output .= implode('', taxonomy_node_form('blog', $node)); + $form['taxonomy'] = taxonomy_node_form('blog', $node); } - $output .= form_textarea(t('Body'), 'body', $node->body, 60, 20, '', NULL, TRUE); - $output .= filter_form('format', $node->format); + $form['body'] = array(type => 'textarea', title => t('Body'), default_value => $node->body, required => TRUE, weight => 1); + $form = array_merge($form, filter_form($node->format)); - return $output; + return $form; } /** Index: modules/blogapi.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blogapi.module,v retrieving revision 1.56 diff -u -r1.56 blogapi.module --- modules/blogapi.module 2 Sep 2005 02:11:41 -0000 1.56 +++ modules/blogapi.module 12 Sep 2005 13:28:20 -0000 @@ -548,11 +548,20 @@ } function blogapi_settings() { - $output = form_select(t('XML-RPC Engine'), 'blogapi_engine', variable_get('blogapi_engine', 0), array(0 => 'Blogger', 1 => 'MetaWeblog', 2 => 'Movabletype'), t('RSD or Really-Simple-Discovery is a mechanism which allows external blogger tools to discover the APIs they can use to interact with Drupal. Here you can set the preferred method for blogger tools to interact with your site. The common XML-RPC engines are Blogger, MetaWeblog and Movabletype. If you are not sure which is the correct setting, choose Blogger.')); + $form['blogapi_engine'] = array( + type => 'select', title => t('XML-RPC Engine'), default_value => variable_get('blogapi_engine', 0), + options => array(0 => 'Blogger', 1 => 'MetaWeblog', 2 => 'Movabletype'), + description => t('RSD or Really-Simple-Discovery is a mechanism which allows external blogger tools to discover the APIs they can use to interact with Drupal. Here you can set the preferred method for blogger tools to interact with your site. The common XML-RPC engines are Blogger, MetaWeblog and Movabletype. If you are not sure which is the correct setting, choose Blogger.') + ); $node_types = node_get_types(); $defaults = isset($node_types['blog']) ? array('blog') : array(); - $output .= form_checkboxes(t('Blog types'), "blogapi_node_types", variable_get('blogapi_node_types', $defaults), $node_types, t('Select the content types for which you wish to enable posting via blogapi. Each type will appear as a different "blog" in the client application (if supported).'), 0, 1); - return $output; + $form['blogapi_node_types'] = array( + type => 'checkboxes', title => t('Blog types'), required => TRUE, + default_value => variable_get('blogapi_node_types', $defaults), options => $node_types, + description => t('Select the content types for which you wish to enable posting via blogapi. Each type will appear as a different "blog" in the client application (if supported).') + ); + + return $form; } function blogapi_menu($may_cache) { Index: modules/book.module =================================================================== RCS file: /cvs/drupal/drupal/modules/book.module,v retrieving revision 1.315 diff -u -r1.315 book.module --- modules/book.module 6 Sep 2005 18:55:41 -0000 1.315 +++ modules/book.module 12 Sep 2005 13:28:27 -0000 @@ -231,27 +231,38 @@ * Implementation of hook_form(). */ function book_form(&$node) { - $output = form_select(t('Parent'), 'parent', ($node->parent ? $node->parent : arg(4)), book_toc($node->nid), t('The parent that this page belongs in. Note that pages whose parent is <top-level> are regarded as independent, top-level books.')); + $form['parent'] = array( + type => 'select', title => t('Parent'), default_value => ($node->parent ? $node->parent : arg(4)), options => book_toc($node->nid), + description => t('The parent that this page belongs in. Note that pages whose parent is <top-level> are regarded as independent, top-level books.') + ); if (function_exists('taxonomy_node_form')) { - $output .= implode('', taxonomy_node_form('book', $node)); + $form['taxonomy'] = taxonomy_node_form('blog', $node); } - $output .= form_textarea(t('Body'), 'body', $node->body, 60, 20, '', NULL, TRUE); - $output .= filter_form('format', $node->format); - - $output .= form_textarea(t('Log message'), 'log', $node->log, 60, 5, t('An explanation of the additions or updates being made to help other authors understand your motivations.')); + $form['body'] = array( + type => 'textarea', title => t('Body'), default_value => $node->body, required => TRUE + ); + $form = array_merge($form, filter_form($node->format)); + + $form['log'] = array( + type => 'textarea', title => t('Log message'), default_value => $node->log, required => TRUE, rows => 5, + description => t('An explanation of the additions or updates being made to help other authors understand your motivations.') + ); if (user_access('administer nodes')) { - $output .= form_weight(t('Weight'), 'weight', $node->weight, 15, t('Pages at a given level are ordered first by weight and then by title.')); + $form['weight'] = array( + type => 'weight', title => t('Weight'), default_value => $node->weight, delta => 15, + description => t('Pages at a given level are ordered first by weight and then by title.') + ); } else { // If a regular user updates a book page, we create a new revision // authored by that user: - $output .= form_hidden('revision', 1); + $form['revision'] = array(type => 'hidden', value => 1); } - return $output; + return $form; } /** Index: modules/contact.module =================================================================== RCS file: /cvs/drupal/drupal/modules/contact.module,v retrieving revision 1.22 diff -u -r1.22 contact.module --- modules/contact.module 25 Aug 2005 21:14:16 -0000 1.22 +++ modules/contact.module 12 Sep 2005 13:28:29 -0000 @@ -58,7 +58,12 @@ * Implementation of hook_settings(). */ function contact_settings() { - return form_textarea(t('Additional information'), 'contact_form_information', variable_get('contact_form_information', t('You can leave us a message using the contact form below.')), 60, 5, t('Information to show on the contact page. Can be anything from submission guidelines to your postal address or telephone number.', array('%form' => url('contact')))); + $form['contact_form_information'] = array( + type => 'textarea', title => t('Additional information'), cols => 60, rows => 5, + default_value => ariable_get('contact_form_information', t('You can leave us a message using the contact form below.')), + description => t('Information to show on the contact page. Can be anything from submission guidelines to your postal address or telephone number.', array('%form' => url('contact'))) + ); + return $form; } /** Index: modules/drupal.module =================================================================== RCS file: /cvs/drupal/drupal/modules/drupal.module,v retrieving revision 1.106 diff -u -r1.106 drupal.module --- modules/drupal.module 25 Aug 2005 21:14:16 -0000 1.106 +++ modules/drupal.module 12 Sep 2005 13:28:30 -0000 @@ -33,19 +33,28 @@ */ function drupal_settings() { // Check if all required fields are present for the Drupal directory - if ((variable_get('site_name', 'drupal') == 'drupal') || (variable_get('site_name', 'drupal') == '')) + if ((variable_get('site_name', 'drupal') == 'drupal') || (variable_get('site_name', 'drupal') == '')) { form_set_error('drupal_directory', t('You must set the name of your site on the administer » settings page.', array('%url' => url('admin/settings')))); - else if (variable_get('site_mail', ini_get('sendmail_from')) == '') + } + else if (variable_get('site_mail', ini_get('sendmail_from')) == '') { form_set_error('drupal_directory', t('You must set an e-mail address for your site on the administer » settings page.', array('%url' => url('admin/settings')))); - else if (variable_get('site_slogan', '') == '') + } + else if (variable_get('site_slogan', '') == '') { form_set_error('drupal_directory', t('You must set your site slogan on the administer » settings page.', array('%url' => url('admin/settings')))); - else if (variable_get('site_mission', '') == '') + } + else if (variable_get('site_mission', '') == '') { form_set_error('drupal_directory', t('You must set your site mission on the administer » settings page.' , array('%url' => url('admin/settings')))); + } + + $form['drupal_server'] = array(type => 'textfield', title => t('Drupal XML-RPC server'), default_value => variable_get('drupal_server', 'http://www.drupal.org/xmlrpc.php'), size => 60, maxlength => 128, description => t('The URL of your root Drupal XML-RPC server.')); - $output = form_textfield(t('Drupal XML-RPC server'), 'drupal_server', variable_get('drupal_server', 'http://www.drupal.org/xmlrpc.php'), 60, 128, t('The URL of your root Drupal XML-RPC server.')); - $output .= form_radios(t('Drupal directory'), 'drupal_directory', variable_get('drupal_directory', 0), array(t('Disabled'), t('Enabled')), t("If enabled, your Drupal site will make itself known to the Drupal directory at the specified Drupal XML-RPC server. For this to work properly, you must set your site's name, e-mail address, slogan and mission statement. When the \"Drupal XML-RPC server\" field is set to \"%drupal-xml-rpc\", your web site will get listed on the Drupal sites page. Requires the cron feature to be enabled.", array("%drupal-xml-rpc" => "http://www.drupal.org/xmlrpc.php", "%drupal-sites" => "http://www.drupal.org/drupal-sites/"))); + $form['drupal_directory'] = array( + type => 'radios', title => t('Drupal directory'), default_value => variable_get('drupal_directory', 0), + options => array(t('Disabled'), t('Enabled')), + description => t("If enabled, your Drupal site will make itself known to the Drupal directory at the specified Drupal XML-RPC server. For this to work properly, you must set your site's name, e-mail address, slogan and mission statement. When the \"Drupal XML-RPC server\" field is set to \"%drupal-xml-rpc\", your web site will get listed on the Drupal sites page. Requires the cron feature to be enabled.", array("%drupal-xml-rpc" => "http://www.drupal.org/xmlrpc.php", "%drupal-sites" => "http://www.drupal.org/drupal-sites/")) + ); - return $output; + return $form; } /** Index: modules/filter.module =================================================================== RCS file: /cvs/drupal/drupal/modules/filter.module,v retrieving revision 1.71 diff -u -r1.71 filter.module --- modules/filter.module 25 Aug 2005 21:14:16 -0000 1.71 +++ modules/filter.module 12 Sep 2005 13:28:33 -0000 @@ -726,32 +726,26 @@ * @return * HTML for the form element. */ -function filter_form($name = 'format', $value = FILTER_FORMAT_DEFAULT) { +function filter_form($value = FILTER_FORMAT_DEFAULT) { if ($value == FILTER_FORMAT_DEFAULT) { $value = variable_get('filter_default_format', 1); } $formats = filter_formats(); $extra = l(t('More information about formatting options'), 'filter/tips'); - + + $form['format'] = array(type => 'fieldset', title => t('Input format'), collapsible => TRUE, collapsed => TRUE); if (count($formats) > 1) { // Multiple formats available: display radio buttons with tips. - $output = ''; foreach ($formats as $format) { - $tips = _filter_tips($format->format, false); - - // TODO: get support for block-level radios so the
            is not output? - $output .= '
            '; - $output .= ''; - $output .= theme('filter_tips', $tips); - $output .= '
            '; + $form['format'][$format->name] = array(type=> 'filter_format', title => $format->name, default_value => $value, return_value => $format->fid, description => theme('filter_tips', _filter_tips($format->format, false))); } - $group = theme('form_element', NULL, $output, $extra, NULL, _form_get_error($name)); - return form_group_collapsible(t('Input format'), $group, TRUE); + return $form; } else { // Only one format available: use a hidden form item and only show tips. $format = array_shift($formats); + $form['format'][$format->name] = array(type => 'hidden', value => $format->format); $output = form_hidden($name, $format->format); $tips = _filter_tips(variable_get('filter_default_format', 1), false); $output .= form_item(t('Formatting guidelines'), theme('filter_tips', $tips, false, $extra), $extra); @@ -759,6 +753,20 @@ } } +function filter_elements() { + $type['filter_format'] = array(); + return $type; +} + +function theme_filter_format($element) { + $output .= '
            '; + $output .= ''; + $output .= $element[description]; + $output .= '
            '; + return $output; +} + + /** * Returns true if the user is allowed to access this format. */ Index: modules/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node.module,v retrieving revision 1.527 diff -u -r1.527 node.module --- modules/node.module 2 Sep 2005 02:11:41 -0000 1.527 +++ modules/node.module 12 Sep 2005 13:28:37 -0000 @@ -6,6 +6,8 @@ * The core that allows content to be submitted to the site. */ +include_once 'includes/form.inc'; + define('NODE_NEW_LIMIT', time() - 30 * 24 * 60 * 60); /** @@ -1295,121 +1297,92 @@ return $node; } + /** * Generate the node editing form. */ -function node_form($edit) { - // Validate the node if we don't already know the errors. +function node_form($node) { if (!$edit->validated) { $edit = node_validate($edit); } + // Set the id of the top-level form tag + $form[attributes]['id'] = 'node-form'; + // Prepend extra node form elements. - $form = implode('', node_invoke_nodeapi($edit, 'form pre')); + $form = array_merge($form, node_invoke_nodeapi($node, 'form pre')); + + /** + * Basic node information. + * These elements set the value property, making them immutable. + */ + $form['uid'] = array(type => 'hidden', value => $node->uid); + $form['created'] = array(type => 'hidden', value => $node->created); + $form['changed'] = array(type => 'hidden', value => $node->changed); + $form['type'] = array(type => 'hidden', value => $node->type); // Get the node-specific bits. // We can't use node_invoke() because $param must be passed by reference. - $function = node_get_base($edit) .'_form'; + $function = _node_names('base', $node) .'_form'; $param = array(); if (function_exists($function)) { - $form .= $function($edit, $param); + $node_form = $function($node, $param); + $form = array_merge($form, $function($node, $param)); } // Append extra node form elements. - $form .= implode('', node_invoke_nodeapi($edit, 'form post')); - - $output .= '
            '; - - // Add hidden 'op' variable, which specifies the default operation (Preview). - $output .= '\n"; - - // Add the admin-specific parts. - if (user_access('administer nodes')) { - $output .= '
            '; + $form = array_merge($form, node_invoke_nodeapi($node, 'form post')); - $author = form_autocomplete(t('Authored by'), 'name', $edit->name, 30, 60, 'user/autocomplete'); - $author .= form_textfield(t('Authored on'), 'date', $edit->date, 30, 25, NULL, NULL, TRUE); + /** + * Node author information + */ + $form['author'] = array(type => 'fieldset', title => t('Authoring information'), collapsible => TRUE, collapsed => TRUE, weight => -2); + $form['author']['name'] = array(type => 'textfield', title => t('Authored by'), maxlength => 60, autocomplete_path => 'user/autocomplete', default_value => $node->name, weight => -1); + $form['author']['date'] = array(type => 'textfield', title =>t('Authored on'), maxlength => 25, required => TRUE, default_value => $node->date); + + + $node_options = variable_get('node_options_'. $node->type, array('status', 'promote')); + + /** + * Node options + */ + $form['options'] = array(type => 'fieldset', title => t('Publishing options'), collapsible => TRUE, collapsed => TRUE, weight => -2); + $form['options']['status'] = array(type => 'checkbox', title => t('Published'), default_value => in_array('status', $node_options)); + $form['options']['moderate'] = array(type => 'checkbox', title => t('In moderation queue'), default_value => in_array('moderate', $node_options)); + $form['options']['promote'] = array(type => 'checkbox', title => t('Promoted to front page'), default_value => in_array('promote', $node_options)); + $form['options']['sticky'] = array(type => 'checkbox', title =>t('Sticky at top of lists'), default_value => in_array('sticky', $node_options)); + $form['options']['revision'] = array(type => 'checkbox', title =>t('Create new revision'), default_value => in_array('revision', $node_options)); - $output .= '
            '; - $output .= form_group_collapsible(t('Authoring information'), $author, TRUE); - $output .= "
            \n"; - - $node_options = variable_get('node_options_'. $edit->type, array('status', 'promote')); - $options .= form_checkbox(t('Published'), 'status', 1, isset($edit->status) ? $edit->status : in_array('status', $node_options)); - $options .= form_checkbox(t('In moderation queue'), 'moderate', 1, isset($edit->moderate) ? $edit->moderate : in_array('moderate', $node_options)); - $options .= form_checkbox(t('Promoted to front page'), 'promote', 1, isset($edit->promote) ? $edit->promote : in_array('promote', $node_options)); - $options .= form_checkbox(t('Sticky at top of lists'), 'sticky', 1, isset($edit->sticky) ? $edit->sticky : in_array('sticky', $node_options)); - $options .= form_checkbox(t('Create new revision'), 'revision', 1, isset($edit->revision) ? $edit->revision : in_array('revision', $node_options)); - - $output .= '
            '; - $output .= form_group_collapsible(t('Publishing options'), $options, TRUE); - $output .= "
            \n"; - - $extras .= implode('
            ', node_invoke_nodeapi($edit, 'form admin')); - $output .= $extras ? '
            '. $extras .'
            ' : '
            '; - } // Add the default fields. - $output .= '
            '; - $output .= form_textfield(t('Title'), 'title', $edit->title, 60, 128, NULL, NULL, TRUE); - - // Add the node-type-specific fields. - $output .= $form; - - // Add the hidden fields. - if ($edit->nid) { - $output .= form_hidden('nid', $edit->nid); - } - - if (isset($edit->uid)) { - // The use of isset() is mandatory in the context of user IDs, because - // user ID 0 denotes the anonymous user. - $output .= form_hidden('uid', $edit->uid); - } - - if ($edit->created) { - $output .= form_hidden('created', $edit->created); - } - - if ($edit->changed) { - $output .= form_hidden('changed', $edit->changed); - } - - $output .= form_hidden('type', $edit->type); + $form['title'] = array(type => 'textfield', title => t('Title'), size => 60, maxlength => 128, required => TRUE, default_value => $node->title, weight => -1); // Add the buttons. - $output .= form_submit(t('Preview')); - - if ($edit->type && (($_POST['op'] == t('Preview') && !form_get_errors()) || !variable_get('node_preview', 0))) { - $output .= form_submit(t('Submit')); - } + $form['preview'] = array(type => 'submit', value => t('Preview'), weight => 19); - if ($edit->nid && node_access('delete', $edit)) { - $output .= form_submit(t('Delete')); + if ($node->type && (($_POST['op'] == t('Preview') && !form_get_errors()) || !variable_get('node_preview', 0))) { + $form['submit'] = array(type => 'submit', value => t('Submit'), weight => 20); } - $output .= '
            '; - $extra = node_invoke_nodeapi($edit, 'form param'); - foreach ($extra as $key => $value) { - if (is_array($value)) { - if (isset($param[$key])) { - $param[$key] = array_merge($param[$key], $value); - } - else { - $param[$key] = $value; - } - } - else { - $param[$key] = $value; - } - } + return drupal_get_form($node->type . '_node_form', $form, 'node_form'); +} - $attributes = array('id' => 'node-form'); - if (is_array($param['options'])) { - $attributes = array_merge($param['options'], $attributes); - } - return form($output, ($param['method'] ? $param['method'] : 'post'), $param['action'], $attributes); +function theme_node_form($form) { + $output .= '
            '; + $output .= '
            '; + $output .= '
            '; + $output .= form_render($form['author']); + $output .= '
            '; + $output .= '
            '; + $output .= form_render($form['options']); + $output .= '
            '; + $output .= '
            '; + $output .= '
            '; + $output .= form_render($form); + $output .= '
            '; + $output .= '
            '; + return $output; } /** @@ -1432,7 +1405,7 @@ $node[$field] = $_GET['edit'][$field]; } } - $output = node_form($node); + $output = node_form(array2object($node)); drupal_set_title(t('Submit %name', array('%name' => node_get_name($node)))); } else { Index: modules/page.module =================================================================== RCS file: /cvs/drupal/drupal/modules/page.module,v retrieving revision 1.136 diff -u -r1.136 page.module --- modules/page.module 30 Aug 2005 15:22:29 -0000 1.136 +++ modules/page.module 12 Sep 2005 13:28:37 -0000 @@ -68,15 +68,21 @@ */ function page_form(&$node) { if (function_exists('taxonomy_node_form')) { - $output .= implode('', taxonomy_node_form('page', $node)); + $form['taxonomy'] = taxonomy_node_form('blog', $node); } - $output .= form_textarea(t('Body'), 'body', $node->body, 60, 20, '', NULL, TRUE); - $output .= filter_form('format', $node->format); + $form['body'] = array( + type => 'textarea', title => t('Body'), default_value => $node->body, required => TRUE + ); + $form = array_merge($form, filter_form($node->format)); - $output .= form_textarea(t('Log message'), 'log', $node->log, 60, 5, t('An explanation of the additions or updates being made to help other authors understand your motivations.')); - return $output; + $form['log'] = array( + type => 'textarea', title => t('Log message'), default_value => $node->log, required => TRUE, rows => 5, + description => t('An explanation of the additions or updates being made to help other authors understand your motivations.') + ); + + return $form; } Index: modules/story.module =================================================================== RCS file: /cvs/drupal/drupal/modules/story.module,v retrieving revision 1.170 diff -u -r1.170 story.module --- modules/story.module 29 Aug 2005 19:58:49 -0000 1.170 +++ modules/story.module 12 Sep 2005 13:28:37 -0000 @@ -67,16 +67,22 @@ * Implementation of hook_form(). */ function story_form(&$node) { - $output = ''; - if (function_exists('taxonomy_node_form')) { - $output .= implode('', taxonomy_node_form('story', $node)); + $form['taxonomy'] = taxonomy_node_form('blog', $node); } - $output .= form_textarea(t('Body'), 'body', $node->body, 60, 20, '', NULL, TRUE); - $output .= filter_form('format', $node->format); + $form['body'] = array( + type => 'textarea', title => t('Body'), default_value => $node->body, required => TRUE + ); + $form = array_merge($form, filter_form($node->format)); + + + $form['log'] = array( + type => 'textarea', title => t('Log message'), default_value => $node->log, required => TRUE, rows => 5, + description => t('An explanation of the additions or updates being made to help other authors understand your motivations.') + ); - return $output; + return $form; } Index: modules/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system.module,v retrieving revision 1.233 diff -u -r1.233 system.module --- modules/system.module 8 Sep 2005 20:25:08 -0000 1.233 +++ modules/system.module 12 Sep 2005 13:28:40 -0000 @@ -50,6 +50,35 @@ } /** + * Implementation of hook_elements(). + */ +function system_elements() { + // Top level form + $type['form'] = array(method => 'POST', action => request_uri()); + + // Inputs + $type['checkbox'] = array(input => TRUE, return_value => 1); + $type['submit'] = array(input => TRUE, name => 'op', button_type => 'submit'); + $type['button'] = array(input => TRUE, name => 'op', button_type => 'submit'); + $type['textfield'] = array(input => TRUE, size => 60, maxlength => 70, autocomplete_path => FALSE); + $type['password'] = array(input => TRUE, size => 60, maxlength => 70); + $type['textarea'] = array(input => TRUE, cols => 60, rows => 20); + $type['radios'] = array(input => TRUE, process => 'expand_radios'); + $type['radio'] = array(input => TRUE); + $type['checkboxes'] = array(input => TRUE, process => 'expand_checkboxes'); + $type['checkbox'] = array(input => TRUE); + $type['select'] = array(input => TRUE); + $type['weight'] = array(input => TRUE); + + // Form structure + $type['item'] = array(); + $type['hidden'] = array(input => TRUE); + $type['markup'] = array(prefix => '', suffix => ''); + $type['fieldset'] = array(collapsible => FALSE, collapsed => FALSE); + return $type; +} + +/** * Implementation of hook_menu(). */ function system_menu($may_cache) { @@ -180,63 +209,136 @@ function system_view_general() { // General settings: - $group = form_textfield(t('Name'), 'site_name', variable_get('site_name', 'drupal'), 60, 70, t('The name of this web site.')); - $group .= form_textfield(t('E-mail address'), 'site_mail', variable_get('site_mail', ini_get('sendmail_from')), 60, 128, t('A valid e-mail address for this website, used by the auto-mailer during registration, new password requests, notifications, etc.')); - $group .= form_textfield(t('Slogan'), 'site_slogan', variable_get('site_slogan', ''), 60, 128, t('The slogan of this website. Some themes display a slogan when available.')); - $group .= form_textarea(t('Mission'), 'site_mission', variable_get('site_mission', ''), 60, 5, t('Your site\'s mission statement or focus.')); - $group .= form_textarea(t('Footer message'), 'site_footer', variable_get('site_footer', ''), 60, 5, t('This text will be displayed at the bottom of each page. Useful for adding a copyright notice to your pages.')); - $group .= form_textfield(t('Anonymous user'), 'anonymous', variable_get('anonymous', 'Anonymous'), 60, 70, t('The name used to indicate anonymous users.')); - $group .= form_textfield(t('Default front page'), 'site_frontpage', variable_get('site_frontpage', 'node'), 60, 70, t('The home page displays content from this relative URL. If you are not using clean URLs, specify the part after "?q=". If unsure, specify "node".')); + $form['general'] = array( + type => 'fieldset', title => t('General settings'), + collapsible => TRUE, collapsed => TRUE + ); + $form['general']['site_name'] = array( + type => 'textfield', title => t('Name'), default_value => variable_get('site_name', 'drupal'), + description => t('The name of this web site.') + ); + $form['general']['site_mail'] = array( + type => 'textfield', title => t('E-mail address'), default_value => variable_get('site_mail', ini_get('sendmail_from')), maxlength => 128, + description => t('A valid e-mail address for this website, used by the auto-mailer during registration, new password requests, notifications, etc.') + ); + $form['general']['site_slogan'] = array( + type => 'textfield', title => t('Slogan'), default_value => variable_get('site_slogan', ''), + maxlength => 128, description => t('The slogan of this website. Some themes display a slogan when available.') + ); + + $form['general']['site_mission'] = array( + type => 'textarea', title => t('Mission'), default_value => variable_get('site_mission', ''), + rows => 5, description => t('Your site\'s mission statement or focus.') + ); + $form['general']['site_footer'] = array( + type => 'textarea', title => t('Footer message'), default_value => variable_get('site_footer', ''), rows => 5, + description => t('This text will be displayed at the bottom of each page. Useful for adding a copyright notice to your pages.') + ); + $form['general']['anonymous'] = array( + type => 'textfield', title => t('Anonymous user'), default_value => variable_get('anonymous', 'Anonymous'), + description => t('The name used to indicate anonymous users.') + ); + $form['general']['site_frontpage'] = array( + type => 'textfield', title => t('Default front page'), default_value => variable_get('site_frontpage', 'node'), + description => t('The home page displays content from this relative URL. If you are not using clean URLs, specify the part after "?q=". If unsure, specify "node".') + ); // We check for clean URL support using an image on the client side. - $group .= form_radios(t('Clean URLs'), 'clean_url', variable_get('clean_url', 0), array(t('Disabled'), t('Enabled')), t('This option makes Drupal emit clean URLs (i.e. without ?q= in the URL). You\'ll need ModRewrite support for this to work. See the .htaccess file in Drupal\'s top-level directory for more information.')); + $form['general']['clean_url'] = array( + type => 'radios', title => t('Clean URLs'), default_value => variable_get('clean_url', 0), options => array(t('Disabled'), t('Enabled')), + description => t('This option makes Drupal emit clean URLs (i.e. without ?q= in the URL). You\'ll need ModRewrite support for this to work. See the .htaccess file in Drupal\'s top-level directory for more information.') + ); + variable_set('clean_url_ok', 0); global $base_url; // We will use a random URL so there is no way a proxy or a browser could cache the "no such image" answer. - $group .= ''; - - $output = form_group_collapsible(t('General settings'), $group, TRUE); + $form['general']['clean_url_test'] = array(type => 'markup', value => ''); // Error handling: + + $form['errors'] = array( type => 'fieldset', title =>t('Error handling'), collapsible => TRUE, collapsed => TRUE ); + $form['errors']['site_403'] = array( + type => 'textfield', title => t('Default 403 (access denied) page'), default_value => variable_get('site_403', ''), + description => t('This page is displayed when the requested document is denied to the current user. If you are not using clean URLs, specify the part after "?q=". If unsure, specify nothing.') + ); + + $form['errors']['site_404'] = array( + type => 'textfield', title => t('Default 404 (not found) page'), default_value => variable_get('site_404', ''), + description => t('This page is displayed when no other content matches the requested document. If you are not using clean URLs, specify the part after "?q=". If unsure, specify nothing.') + ); + + $form['errors']['error_level'] = array( + type => 'select', title => t('Error reporting'), default_value => variable_get('error_level', 1), + options => array(t('Write errors to the log'), t('Write errors to the log and to the screen')), + description => t('Where Drupal, PHP and SQL errors are logged. On a production server it is recommended that errors are only written to the error log. On a test server it can be helpful to write logs to the screen.') + ); + $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200), 'format_interval'); $period['1000000000'] = t('Never'); - $group = form_textfield(t('Default 403 (access denied) page'), 'site_403', variable_get('site_403', ''), 60, 70, t('This page is displayed when the requested document is denied to the current user. If you are not using clean URLs, specify the part after "?q=". If unsure, specify nothing.')); - $group .= form_textfield(t('Default 404 (not found) page'), 'site_404', variable_get('site_404', ''), 60, 70, t('This page is displayed when no other content matches the requested document. If you are not using clean URLs, specify the part after "?q=". If unsure, specify nothing.')); - $group .= form_select(t('Error reporting'), 'error_level', variable_get('error_level', 1), array(t('Write errors to the log'), t('Write errors to the log and to the screen')), t('Where Drupal, PHP and SQL errors are logged. On a production server it is recommended that errors are only written to the error log. On a test server it can be helpful to write logs to the screen.')); - $group .= form_select(t('Discard log entries older than'), 'watchdog_clear', variable_get('watchdog_clear', 604800), $period, t('The time log entries should be kept. Older entries will be automatically discarded. Requires crontab.')); + $form['errors']['watchdog_clear'] = array( + type => 'select', title => t('Discard log entries older than'), default_value => variable_get('watchdog_clear', 604800), options => $period, + description => t('The time log entries should be kept. Older entries will be automatically discarded. Requires crontab.') + ); - $output .= form_group_collapsible(t('Error handling'), $group, TRUE); // Caching: - $group = form_radios(t('Page cache'), 'cache', variable_get('cache', CACHE_DISABLED), array(CACHE_DISABLED => t('Disabled'), CACHE_ENABLED => t('Enabled')), t("Drupal has a caching mechanism which stores dynamically generated web pages in a database. By caching a web page, Drupal does not have to create the page each time someone wants to view it, instead it takes only one SQL query to display it, reducing response time and the server's load. Only pages requested by \"anonymous\" users are cached. In order to reduce server load and save bandwidth, Drupal stores and sends compressed cached pages.")); + $form['cache'] = array(type => 'fieldset', title => t('Cache settings'), collapsible => TRUE, collapsed => TRUE); + + $form['cache']['cache'] = array( + type => 'radios', title => t('Page cache'), default_value => variable_get('cache', CACHE_DISABLED), + options => array(CACHE_DISABLED => t('Disabled'), CACHE_ENABLED => t('Enabled')), + description => t("Drupal has a caching mechanism which stores dynamically generated web pages in a database. By caching a web page, Drupal does not have to create the page each time someone wants to view it, instead it takes only one SQL query to display it, reducing response time and the server's load. Only pages requested by \"anonymous\" users are cached. In order to reduce server load and save bandwidth, Drupal stores and sends compressed cached pages.") + ); + $period = drupal_map_assoc(array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400), 'format_interval'); $period[0] = t('none'); - $group .= form_select(t('Minimum cache lifetime'), 'cache_lifetime', variable_get('cache_lifetime', 0), $period, t('Enabling the cache will offer a sufficient performance boost for most low-traffic and medium-traffic sites. On high-traffic sites it can become necessary to enforce a minimum cache lifetime. The minimum cache lifetime is the minimum amount of time that will go by before the cache is emptied and recreated. A larger minimum cache lifetime offers better performance, but users will not see new content for a longer period of time.')); + $form['cache']['cache_lifetime'] = array( + type => 'select', title => t('Minimum cache lifetime'), default_value => variable_get('cache_lifetime', 0), options => $period, + description => t('Enabling the cache will offer a sufficient performance boost for most low-traffic and medium-traffic sites. On high-traffic sites it can become necessary to enforce a minimum cache lifetime. The minimum cache lifetime is the minimum amount of time that will go by before the cache is emptied and recreated. A larger minimum cache lifetime offers better performance, but users will not see new content for a longer period of time.') + ); - $output .= form_group_collapsible(t('Cache settings'), $group, TRUE); // File system: + $form['files'] = array(type => 'fieldset', title => t('File system settings'), collapsible => TRUE, collapsed => TRUE); + $directory_path = variable_get('file_directory_path', 'files'); file_check_directory($directory_path, FILE_CREATE_DIRECTORY, 'file_directory_path'); + $form['files']['file_directory_path'] = array( + type => 'textfield', title => t('File system path'), default_value => $directory_path, maxlength => 255, valid => 'directory', + description => t('A file system path where the files will be stored. This directory has to exist and be writable by Drupal. If the download method is set to public this directory has to be relative to Drupal installation directory, and be accessible over the web. When download method is set to private this directory should not be accessible over the web. Changing this location after the site has been in use will cause problems so only change this setting on an existing site if you know what you are doing.') + ); + $directory_temp = variable_get('file_directory_temp', FILE_DIRECTORY_TEMP); file_check_directory($directory_temp, FILE_CREATE_DIRECTORY, 'file_directory_temp'); + + $form['files']['file_directory_tmp'] = array( + type => 'textfield', title => t('Temporary directory'), default_value => $directory_temp, maxlength => 255, valid => 'directory', + description => t('Location where uploaded files will be kept during previews. Relative paths will be resolved relative to the file system path.') + ); + + $form['files']['file_downloads'] = array( + type => 'radios', title => t('Download method'), default_value => variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC), + options => array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using http directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are transferred by Drupal.')), + description => t('If you want any sort of access control on the downloading of files, this needs to be set to private. You can change this at any time, however all download URLs will change and there may be unexpected problems so it is not recommended.') + ); - $group = form_textfield(t('File system path'), 'file_directory_path', $directory_path, 60, 255, t('A file system path where the files will be stored. This directory has to exist and be writable by Drupal. If the download method is set to public this directory has to be relative to Drupal installation directory, and be accessible over the web. When download method is set to private this directory should not be accessible over the web. Changing this location after the site has been in use will cause problems so only change this setting on an existing site if you know what you are doing.')); - $group .= form_textfield(t('Temporary directory'), 'file_directory_temp', $directory_temp, 60, 255, t('Location where uploaded files will be kept during previews. Relative paths will be resolved relative to the Drupal installation directory.')); - $group .= form_radios(t('Download method'), 'file_downloads', variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC), array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using http directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are transferred by Drupal.')), t('If you want any sort of access control on the downloading of files, this needs to be set to private. You can change this at any time, however all download URLs will change and there may be unexpected problems so it is not recommended.')); - $output .= form_group_collapsible(t('File system settings'), $group, TRUE); - + /* // Image handling: - $group = ''; + $group = array(); $toolkits_available = image_get_available_toolkits(); if (count($toolkits_available) > 1) { - $group .= form_radios(t('Select an image processing toolkit'), 'image_toolkit', variable_get('image_toolkit', image_get_toolkit()), $toolkits_available); - } - $group .= image_toolkit_invoke('settings'); - if ($group) { - $output .= form_group_collapsible(t('Image handling'), '

            '. $group .'

            ', TRUE); + $group['image_toolkit'] = array( + type => 'radios', title => t('Select an image processing toolkit'), + default_value => variable_get('image_toolkit', image_get_toolkit()), options => $toolkits_available + ); + } + $group['toolkit'] = image_toolkit_invoke('settings'); + if (is_array($group)) { + $form['image'] = array(type => 'fieldset', title => t('Image handling'), collapsible => TRUE, collapsed => true); + $form['image'] = array_merge($form['image'], $group); } + */ // Date settings: $zones = _system_zonelist(); @@ -264,19 +366,44 @@ $datelongchoices[$f] = format_date(time(), 'custom', $f); } - $group = form_select(t('Default time zone'), 'date_default_timezone', variable_get('date_default_timezone', 0), $zones, t('Select the default site time zone.')); - $group .= form_radios(t('Configurable time zones'), 'configurable_timezones', variable_get('configurable_timezones', 1), array(t('Disabled'), t('Enabled')), t('Enable or disable user-configurable time zones. When enabled, users can set their own time zone and dates will be updated accordingly.')); - $group .= form_select(t('Short date format'), 'date_format_short', variable_get('date_format_short', $dateshort[0]), $dateshortchoices, t('The short format of date display.')); - $group .= form_select(t('Medium date format'), 'date_format_medium', variable_get('date_format_medium', $datemedium[0]), $datemediumchoices, t('The medium sized date display.')); - $group .= form_select(t('Long date format'), 'date_format_long', variable_get('date_format_long', $datelong[0]), $datelongchoices, t('Longer date format used for detailed display.')); - $group .= form_select(t('First day of week'), 'date_first_day', variable_get('date_first_day', 0), array(0 => t('Sunday'), 1 => t('Monday'), 2 => t('Tuesday'), 3 => t('Wednesday'), 4 => t('Thursday'), 5 => t('Friday'), 6 => t('Saturday')), t('The first day of the week for calendar views.')); + $form['dates'] = array(type => 'fieldset', title => t('Date settings'), collapsible => TRUE, collapsed => TRUE); + $form['dates']['date_default_timezone'] = array( + type => 'select', title => t('Default time zone'), default_value => variable_get('date_default_timezone', 0), + options => $zones, description => t('Select the default site time zone.') + ); + + $form['dates']['configurable_timezones'] = array( + type => 'radios', title => t('Configurable time zones'), default_value => variable_get('configurable_timezones', 1), options => array(t('Disabled'), t('Enabled')), + description => t('Enable or disable user-configurable time zones. When enabled, users can set their own time zone and dates will be updated accordingly.') + ); + + $form['dates']['date_format_short'] = array( + type => 'select', title => t('Short date format'), default_value => variable_get('date_format_short', $dateshort[0]), + options => $dateshortchoices, description => t('The short format of date display.') + ); + + $form['dates']['date_format_medium'] = array( + type => 'select', title => t('Medium date format'), default_value => variable_get('date_format_medium', $datemedium[0]), + options => $datemediumchoices, description => t('The medium sized date display.') + ); + + $form['dates']['date_format_long'] = array( + type => 'select', title => t('Long date format'), default_value => variable_get('date_format_long', $datelong[0]), + options => $datelongchoices, description => t('Longer date format used for detailed display.') + ); + + $form['dates']['date_first_day'] = array( + type => 'select', title => t('First day of week'), default_value => variable_get('date_first_day', 0), + options => array(0 => t('Sunday'), 1 => t('Monday'), 2 => t('Tuesday'), 3 => t('Wednesday'), 4 => t('Thursday'), 5 => t('Friday'), 6 => t('Saturday')), + description => t('The first day of the week for calendar views.') + ); - $output .= form_group_collapsible(t('Date settings'), $group, TRUE); // String handling: report status and errors. - $output .= form_group_collapsible(t('String handling'), unicode_settings(), TRUE); + $form['strings'] = array(type => 'fieldset', title => t('String handling'), collapsible => TRUE, collapsed => TRUE); + $form['strings']['settings'] = array_merge($from['strings'], unicode_settings()); - return $output; + return $form; } /** @@ -467,37 +594,6 @@ /** * Generate a list of all the available theme/style combinations. */ -function system_theme_listing() { - $themes = system_theme_data(); - ksort($themes); - - foreach ($themes as $info) { - $info->screenshot = dirname($info->filename) . '/screenshot.png'; - $row = array(); - - // Screenshot column. - $row[] = file_exists($info->screenshot) ? theme('image', $info->screenshot, t('Screenshot for %theme theme', array('%theme' => $info->name)), '', array('class' => 'screenshot'), false) : t('no screenshot'); - - // Information field. - $row[] = "$info->name
            " . dirname($info->filename) . ''; - - // enabled, default, and operations columns - $row[] = array('data' => form_checkbox('', 'status]['. $info->name, 1, $info->status), 'align' => 'center'); - $row[] = array('data' => form_radio('', 'theme_default', $info->name, (variable_get('theme_default', 'bluemarine') == $info->name) ? 1 : 0), 'align' => 'center'); - if ($info->status && (function_exists($info->prefix . '_settings') || function_exists($info->prefix . '_features'))) { - $row[] = array('data' => l(t('configure'), 'admin/themes/settings/' . $info->name), 'align' => 'center'); - } - else { - $row[] = ''; - } - $rows[] = $row; - } - - $header = array(t('Screenshot'), t('Name'), t('Enabled'), t('Default'), t('Operations')); - $output = form_hidden('type', 'theme'); - $output .= theme('table', $header, $rows); - return $output; -} /** * Generate a list of all the available modules, as well as update the system list. @@ -608,52 +704,134 @@ } } -function system_settings_form($form) { - $form .= form_submit(t('Save configuration')); - $form .= form_submit(t('Reset to defaults')); +// Add the submit / reset buttons and run drupal_get_form() +function system_settings_form($form_id, $form) { + $form['buttons']['submit'] = array(type => 'submit', value => t('Save configuration') ); + $form['buttons']['reset'] = array(type => 'submit', value => t('Reset to defaults') ); - return form($form); + return drupal_get_form($form_id, $form, 'system_settings_form'); } -function system_settings_save() { +/** + * Execute the system_settings_form. + */ +function system_settings_form_execute($form_id, $form) { $op = $_POST['op']; - $edit = $_POST['edit']; + global $form_values; if ($op == t('Reset to defaults')) { - if (is_array($edit)) { - foreach ($edit as $name => $value) { - variable_del($name); - } - } + array_walk_recursive($form_values, 'system_settings_reset'); drupal_set_message(t('The configuration options have been reset to their default values.')); } else if ($op == t('Save configuration')) { - if (is_array($edit)) { - if ($edit['clean_url'] && !variable_get('clean_url_ok', 0)) { - drupal_set_message(t('It appears your host is not configured correctly for Clean URLs. Please check for ModRewrite support with your administrator.'), 'error'); - $edit['clean_url'] = 0; - } - foreach ($edit as $name => $value) { - variable_set($name, $value); - } - } + array_walk_recursive($form_values, 'system_settings_save'); drupal_set_message(t('The configuration options have been saved.')); + } - else { - return; - } + menu_rebuild(); - drupal_goto($_GET['q']); } /** + * Save all the variables submitted to the system table. + */ +function system_settings_save($key, $value) { + variable_set($key, $value); +} + +function system_settings_reset($key, $value) { + variable_del($key); +} + +/** + * Do the clean url validation, changing the form property if it doesn't work. + */ +function system_settings_validate($form_id, &$form) { + #TODO .. fix here. + if ($edit['clean_url'] && !variable_get('clean_url_ok', 0)) { + drupal_set_message(t('It appears your host is not configured correctly for Clean URLs. Please check for ModRewrite support with your administrator.'), 'error'); + $edit['clean_url'] = 0; + } + +} + + + + +/** * Menu callback; displays a listing of all themes. */ function system_themes() { - system_listing_save(); - $form = system_theme_listing(); - $form .= form_submit(t('Save configuration')); - return form($form); + $themes = system_theme_data(); + ksort($themes); + + foreach ($themes as $info) { + $info->screenshot = dirname($info->filename) . '/screenshot.png'; + $screenshot = file_exists($info->screenshot) ? theme('image', $info->screenshot, t('Screenshot for %theme theme', array('%theme' => $info->name)), '', array('class' => 'screenshot'), false) : t('no screenshot'); + + $form[$info->name]['screenshot'] = array(type => 'markup', value => $screenshot); + $form[$info->name]['description'] = array(type => 'item', title => $info->name, value => dirname($info->filename)); + $options[$info->name] = ''; + if ($info->status) { + $status[] = $info->name; + } + if ($info->status && (function_exists($info->prefix . '_settings') || function_exists($info->prefix . '_features'))) { + $form[$info->name]['operations'] = array(type => 'markup', value => l(t('configure'), 'admin/themes/settings/' . $info->name) ); + } + else { + // Dummy element for form_render. Cleaner than adding a check in the theme function. + $form[$info->name]['operations'] = array(); + } + } + + $form['status'] = array(type => 'checkboxes', options => $options, default_value => $status); + $form['theme_default'] = array(type => 'radios', options => $options, default_value => variable_get('theme_default', 'bluemarine')); + $form['buttons']['submit'] = array(type => 'submit', value => t('Save configuration') ); + $form['buttons']['reset'] = array(type => 'submit', value => t('Reset to defaults') ); + + return drupal_get_form('system_themes', $form); +} + +function theme_system_themes($form) { + foreach ($form as $key => $element) { + $row = array(); + if (is_array($element['description'])) { + + $row[] = form_render($form[$key]['screenshot']); + $row[] = form_render($form[$key]['description']); + $row[] = array('data' => form_render($form['status'][$key]), 'align' => 'center'); + $row[] = array('data' => form_render($form['theme_default'][$key]), 'align' => 'center'); + $row[] = array('data' => form_render($form[$key]['operations']), 'align' => 'center'); + } + $rows[] = $row; + } + + $header = array(t('Screenshot'), t('Name'), t('Enabled'), t('Default'), t('Operations')); + $output = theme('table', $header, $rows); + $output .= form_render($form); + return $output; +} + + +function system_themes_execute($form_id, $form) { + global $form_values; + + db_query("UPDATE {system} SET status = 0 WHERE type = 'theme'"); + + if ($_POST['op'] == t('Save configuration')) { + variable_set('theme_default', $form_values['theme_default']); + if (is_array($form_values['status'])) { + foreach ($form_values['status'] as $key => $choice) { + if ($key == $choice) { + db_query("UPDATE {system} SET status = 1 WHERE type = 'theme' and name = '%s'", $choice); + } + } + } + } + else { + variable_del('theme_default'); + } + drupal_set_message(t('The configuration options have been saved.')); } /** @@ -670,16 +848,16 @@ * Menu callback; displays a module's settings page. */ function system_site_settings($module = NULL) { - system_settings_save(); if ($module) { $form = module_invoke($module, 'settings'); } else { $form = system_view_general(); + $module = 'system'; } - return system_settings_form($form); + return system_settings_form($module . '_settings_form', $form); } /** @@ -725,7 +903,6 @@ } } - system_settings_save(); $form = ''; @@ -864,4 +1041,16 @@ } +function search_box() { + $form[action] = url('search'); + $form['keys'] = array(type => 'textfield', size=> 15, value => '', attributes => array('alt' => t('Enter the terms you wish to search for.'), 'class' => 'form-text')); + $form['submit'] = array(type => 'submit', value => t('search')); + return drupal_get_form('search_box', $form); +} +function theme_search_box($form) { + $output = ''; + return $output; +} Index: modules/taxonomy.module =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy.module,v retrieving revision 1.222 diff -u -r1.222 taxonomy.module --- modules/taxonomy.module 28 Aug 2005 16:30:50 -0000 1.222 +++ modules/taxonomy.module 12 Sep 2005 13:28:43 -0000 @@ -510,14 +510,18 @@ } } $typed_string = implode(', ', $typed_terms) . (array_key_exists('tags', $terms) ? $terms['tags'][$vocabulary->vid] : NULL); - $result[] = form_autocomplete($vocabulary->name, "$name][tags][". $vocabulary->vid, $typed_string, 60, 100, 'taxonomy/autocomplete/'. $vocabulary->vid, t('A comma-separated list of terms describing this content (Example: funny, bungie jumping, "Company, Inc.").'), NULL, ($vocabulary->required ? TRUE : FALSE)); + + + $form[$name]['tags'][$vocabulary->vid] = array( type => textfield, default_value => $typed_string, size => 60, maxlength => 100, + autocomplete_path => 'taxonomy/autocomplete/'. $vocabulary->vid, required => ($vocabulary->required ? TRUE : FALSE), title => $vocabulary->name, + description => t('A comma-separated list of terms describing this content (Example: funny, bungie jumping, "Company, Inc.").') ); } else { $ntterms = array_key_exists('taxonomy', $node) ? $terms : array_keys($terms); - $result[] = taxonomy_form($vocabulary->vid, $ntterms, $help, $name); + $form[$name][$vocabulary->vid] = taxonomy_form($vocabulary->vid, $ntterms, $help, $name); } } - return $result ? $result : array(); + return $form ? $form : array(); } /** @@ -888,8 +892,8 @@ $value = $tree[0]->tid; } } - - return form_select($title, $name . ($multiple ? '' : ']['), $value, $options, $description, $multiple ? 'size="'. min(12, count($options)) .'"' : 0, $multiple); + $form[$name] = array(type => 'select', default_value => $value, options => $options, description => $description, multiple => $multiple, size => $multiple ? 'size="'. min(12, count($options)) .'"' : 0); + return $form; } function _taxonomy_depth($depth, $graphic = '--') { Index: modules/upload.module =================================================================== RCS file: /cvs/drupal/drupal/modules/upload.module,v retrieving revision 1.51 diff -u -r1.51 upload.module --- modules/upload.module 2 Sep 2005 02:11:41 -0000 1.51 +++ modules/upload.module 12 Sep 2005 13:28:44 -0000 @@ -163,7 +163,6 @@ $node->list[$key] = $file->list; } } - if (($file = file_check_upload('upload')) && user_access('upload files')) { global $user; @@ -393,35 +392,24 @@ } function _upload_form($node) { - $header = array(t('Delete'), t('List'), t('Url'), t('Size')); - $rows = array(); - $output = ''; - if (is_array($node->files)) { foreach ($node->files as $key => $file) { - $rows[] = array( - form_checkbox('', "remove][$key", 1, $file->remove), - form_checkbox('', "list][$key", 1, $file->list), - $file->filename ."
            ". file_create_url(($file->fid ? $file->filepath : file_create_filename($file->filename, file_create_path()))) ."", - format_size($file->filesize) - ); - } - } + $remove[$key] = $file->remove; + $list[$key] = $file->list; - if (count($node->files)) { - $output .= theme('table', $header, $rows); + $form[$key]['description'] = array(type => 'markup', value => $file->filename ."
            ". file_create_url(($file->fid ? $file->filepath : file_create_filename($file->filename, file_create_path()))) .""); + $form[$key]['size'] = array(type => 'markup', value => format_size($file->filesize)); + } } if (user_access('upload files')) { - $output .= '
            '; - $output .= form_file(t('Attach new file'), "upload", 40); - $output .= form_button(t('Attach'), 'fileop'); - // The class triggers the js upload behaviour. - $output .= form_hidden('fileop', url('upload/js', NULL, NULL, TRUE), 'edit', array('class' => 'upload')); - $output .= '
            '; + $form['upload_file'] = array(prefix => '
            ', suffix => '
            '); + $form['upload_file']['upload'] = array(type => 'file', title => ('Attach new file'), size => 40); + $form['upload_file']['attach'] = array(type => 'submit', title => t('Attach'), name =>'fileop'); + $form['upload_file']['fileop'] = array(type => 'hidden', value => url('upload/js', NULL, NULL, TRUE), attributes => array('class' => 'upload')); } - return $output; + return $form; } function upload_load($node) { Index: modules/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user.module,v retrieving revision 1.509 diff -u -r1.509 user.module --- modules/user.module 8 Sep 2005 19:46:05 -0000 1.509 +++ modules/user.module 12 Sep 2005 13:28:48 -0000 @@ -6,6 +6,8 @@ * Enables the user registration and login system. */ +include_once './includes/form.inc'; + /** * Invokes hook_user() in every module. * @@ -515,17 +517,10 @@ case 0: // For usability's sake, avoid showing two login forms on one page. if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) { - $edit = $_POST['edit']; - - // NOTE: special care needs to be taken because on pages with forms, - // such as node and comment submission pages, the $edit variable - // might already be set. - - $output .= form_textfield(t('Username'), 'name', $edit['name'], 15, 64); - $output .= form_password(t('Password'), 'pass', '', 15, 64); - $output .= form_submit(t('Log in')); - - $output = form($output, 'post', url('user/login', drupal_get_destination()), array('id' => 'user-login-form')); + $form['name'] = array(type => 'textfield', title => t('Username'), maxlength => 64, size => 15, required => TRUE); + $form['pass'] = array(type => 'password', title => t('Password'), maxlength => 64, size => 15, required => TRUE); + $form['submit'] = array(type => 'submit', value => t('Log in')); + $output .= drupal_get_form('user_login_block', $form, 'user_login'); if (variable_get('user_register', 1)) { $items[] = l(t('Create new account'), 'user/register', array('title' => t('Create a new user account.'))); @@ -597,6 +592,15 @@ } } + + +function theme_user_login_block($form) { + $output = "\n"; + return $output; +} + function theme_user_picture($account) { if (variable_get('user_pictures', 0)) { if ($account->picture && file_exists($account->picture)) { @@ -813,6 +817,8 @@ /*** User features *********************************************************/ + + function user_login($edit = array(), $msg = '') { global $user, $base_url; @@ -865,16 +871,27 @@ if ($msg) { $output .= "

            $msg

            "; } + $form['name'] = array(type => 'textfield', title => t('Username'), size => 30, maxlength => 64, required => TRUE); if (count(user_auth_help_links()) > 0) { - $output .= form_textfield(t('Username'), 'name', $edit['name'], 30, 64, t('Enter your %s username, or an ID from one of our affiliates: %a.', array('%s' => variable_get('site_name', 'local'), '%a' => implode(', ', user_auth_help_links())))); + $form['name'][description] = t('Enter your %s username, or an ID from one of our affiliates: %a.', array('%s' => variable_get('site_name', 'local'), '%a' => implode(', ', user_auth_help_links()))); } else { - $output .= form_textfield(t('Username'), 'name', $edit['name'], 30, 64, t('Enter your %s username.', array('%s' => variable_get('site_name', 'local')))); + $form['name'][description] = t('Enter your %s username.', array('%s' => variable_get('site_name', 'local'))); + } + $form['pass'] = array(type => 'password', title => t('Password'), size => 30, maxlength => 64, description => t('Enter the password that accompanies your username.'), required => TRUE); + $form['submit'] = array(type => 'submit', value => t('Log in'), weight => 2); + return drupal_get_form('user_login', $form); +} + +function user_login_validate($form_id, $form) { + if (!user_authenticate($form['name'][value], $form['pass'][value])) { + form_set_error($form['name'][name], t('invalid username and password')); } - $output .= form_password(t('Password'), 'pass', $pass, 30, 64, t('Enter the password that accompanies your username.')); - $output .= form_submit(t('Log in')); +} - return form($output, 'post', url('user/login', drupal_get_destination())); +function user_login_execute($form) { + global $form_variables; + return user_login($form_variables); } function user_authenticate($name, $pass) { @@ -1309,10 +1326,6 @@ case 'register': return user_register($edit); break; - case t('Log in'): - case 'login': - return user_login($edit); - break; default: if (!arg(1)) { if ($user->uid) { Index: sites/default/settings.php =================================================================== RCS file: /cvs/drupal/drupal/sites/default/settings.php,v retrieving revision 1.17 diff -u -r1.17 settings.php --- sites/default/settings.php 28 Aug 2005 18:26:20 -0000 1.17 +++ sites/default/settings.php 12 Sep 2005 13:28:49 -0000 @@ -1,5 +1,5 @@ 'Visitor' //); +?> Index: themes/bluemarine/page.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/themes/bluemarine/page.tpl.php,v retrieving revision 1.9 diff -u -r1.9 page.tpl.php --- themes/bluemarine/page.tpl.php 24 Aug 2005 15:28:53 -0000 1.9 +++ themes/bluemarine/page.tpl.php 12 Sep 2005 13:28:49 -0000 @@ -20,12 +20,7 @@
            -
            - -
            + Index: themes/engines/phptemplate/phptemplate.engine =================================================================== RCS file: /cvs/drupal/drupal/themes/engines/phptemplate/phptemplate.engine,v retrieving revision 1.17 diff -u -r1.17 phptemplate.engine --- themes/engines/phptemplate/phptemplate.engine 9 Sep 2005 05:32:31 -0000 1.17 +++ themes/engines/phptemplate/phptemplate.engine 12 Sep 2005 13:28:49 -0000 @@ -199,10 +199,7 @@ 'primary_links' => theme_get_setting('primary_links'), 'site_name' => (theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : ''), 'site_slogan' => (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : ''), - 'search_box' => theme_get_setting('toggle_search'), - 'search_button_text' => t('search'), - 'search_description' => t('Enter the terms you wish to search for.'), - 'search_url' => url('search'), + 'search_box' => (theme_get_setting('toggle_search') ? search_box() : ''), 'secondary_links' => theme_get_setting('secondary_links'), 'sidebar_left' => $sidebar_left, 'sidebar_right' => $sidebar_right, Index: themes/pushbutton/page.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/themes/pushbutton/page.tpl.php,v retrieving revision 1.5 diff -u -r1.5 page.tpl.php --- themes/pushbutton/page.tpl.php 16 Aug 2005 18:06:18 -0000 1.5 +++ themes/pushbutton/page.tpl.php 12 Sep 2005 13:28:51 -0000 @@ -45,14 +45,7 @@ - -
            - -
            - +