? form_element_2.patch
? views_form_element1.patch
Index: views.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/views/views.module,v
retrieving revision 1.166.2.43
diff -u -p -r1.166.2.43 views.module
--- views.module 14 Jul 2007 18:54:16 -0000 1.166.2.43
+++ views.module 18 Aug 2007 18:37:15 -0000
@@ -1,6 +1,9 @@
access) {
+ if (!$view->access) {
return TRUE;
}
@@ -523,7 +526,7 @@ function views_build_view($type, &$view,
if ($args == NULL) {
$args = array();
}
-
+
// if no filter values are passed in, get them from the $_GET array
if ($filters == NULL) {
$filters = views_get_filter_values();
@@ -592,6 +595,15 @@ function views_build_view($type, &$view,
return $info;
}
+ // modify the view if it is a form -- remove exposed filters and add in
+ // any items that have been selected by the user
+ if($view->page_type == 'form') {
+ if ($view->missing) {
+ $items = array_merge($view->missing, $items);
+ }
+ $view->exposed_filter = array();
+ }
+
// Call a hook that'll let modules modify the view just before it is displayed.
foreach (module_implements('views_pre_view') as $module) {
$function = $module .'_views_pre_view';
@@ -832,47 +844,47 @@ function views_invalidate_cache() {
*/
function _views_view_fields() {
return array(
- 'vid' => '%d',
- 'name' => "'%s'",
- 'description' => "'%s'",
- 'access' => "'%s'",
- 'page' => '%d',
- 'page_title' => "'%s'",
- 'page_header' => "'%s'",
- 'page_header_format' => '%d',
- 'page_footer' => "'%s'",
- 'page_footer_format' => '%d',
- 'page_empty' => "'%s'",
- 'page_empty_format' => '%d',
- 'page_type' => "'%s'",
- 'use_pager' => '%d',
- 'nodes_per_page' => '%d',
- 'url' => "'%s'",
- 'menu' => '%d',
- 'menu_tab' => '%d',
- 'menu_tab_default' => '%d',
- 'menu_tab_weight' => '%d',
- 'menu_title' => "'%s'",
+ 'vid' => '%d',
+ 'name' => "'%s'",
+ 'description' => "'%s'",
+ 'access' => "'%s'",
+ 'page' => '%d',
+ 'page_title' => "'%s'",
+ 'page_header' => "'%s'",
+ 'page_header_format' => '%d',
+ 'page_footer' => "'%s'",
+ 'page_footer_format' => '%d',
+ 'page_empty' => "'%s'",
+ 'page_empty_format' => '%d',
+ 'page_type' => "'%s'",
+ 'use_pager' => '%d',
+ 'nodes_per_page' => '%d',
+ 'url' => "'%s'",
+ 'menu' => '%d',
+ 'menu_tab' => '%d',
+ 'menu_tab_default' => '%d',
+ 'menu_tab_weight' => '%d',
+ 'menu_title' => "'%s'",
'menu_tab_default_parent_type' => "'%s'",
- 'menu_parent_title' => "'%s'",
- 'menu_parent_tab_weight' => '%d',
- 'block' => '%d',
- 'block_title' => "'%s'",
- 'block_use_page_header' => '%d',
- 'block_header' => "'%s'",
- 'block_header_format' => '%d',
- 'block_use_page_footer' => '%d',
- 'block_footer' => "'%s'",
- 'block_footer_format' => '%d',
- 'block_use_page_empty' => '%d',
- 'block_empty' => "'%s'",
- 'block_empty_format' => '%d',
- 'block_type' => "'%s'",
- 'nodes_per_block' => '%d',
- 'block_more' => '%d',
- 'breadcrumb_no_home' => '%d',
- 'changed' => '%d',
- 'view_args_php' => "'%s'",
+ 'menu_parent_title' => "'%s'",
+ 'menu_parent_tab_weight' => '%d',
+ 'block' => '%d',
+ 'block_title' => "'%s'",
+ 'block_use_page_header' => '%d',
+ 'block_header' => "'%s'",
+ 'block_header_format' => '%d',
+ 'block_use_page_footer' => '%d',
+ 'block_footer' => "'%s'",
+ 'block_footer_format' => '%d',
+ 'block_use_page_empty' => '%d',
+ 'block_empty' => "'%s'",
+ 'block_empty_format' => '%d',
+ 'block_type' => "'%s'",
+ 'nodes_per_block' => '%d',
+ 'block_more' => '%d',
+ 'breadcrumb_no_home' => '%d',
+ 'changed' => '%d',
+ 'view_args_php' => "'%s'",
'is_cacheable' => '%d',
);
}
@@ -1314,7 +1326,7 @@ function views_filters($view) {
$form['#action'] = url($view->real_url ? $view->real_url : $view->url, NULL, NULL, true);
$form['view'] = array('#type' => 'value', '#value' => $view);
$form['submit'] = array('#type' => 'button', '#name' => '', '#value' => t('Submit'));
-
+
// clean URL get forms breaks if we don't give it a 'q'.
if (!(bool)variable_get('clean_url', '0')) {
$form['q'] = array(
@@ -1386,7 +1398,7 @@ function _views_build_filters_form($view
}
$form["filter$count"] = $item;
}
-
+
return $form;
}
@@ -1854,6 +1866,14 @@ function views_views_style_plugins() {
'theme' => 'views_view_nodes',
'weight' => -7,
),
+ 'form' => array(
+ 'name' => t('View Form'),
+ 'theme' => 'views_view_form',
+ 'needs_fields' => true,
+ 'needs_table_header' => true,
+ 'weight' => -9,
+ 'hide' => true,
+ ),
);
}
@@ -1999,7 +2019,7 @@ function views_handler_filter_null($op,
$operator = $filter['operator'];
$query->add_where("$field $operator NULL");
break;
- }
+ }
}
/**
@@ -2143,4 +2163,40 @@ function views_form_alter($form_id, &$fo
// An implementation of hook_devel_caches() from devel.module. Must be in views.module so it always is included.
function views_devel_caches() {
return array('cache_views');
-}
\ No newline at end of file
+}
+
+/**
+* Implementation of hook_elements();
+*
+* Here we define a views_node_selector form element that can be used to
+* get back 1 or more nids using a view. We use the front page view as a
+* default, as this ships with every views install. Of course, you'll want to
+* override this default in your use of the element.
+*
+* We also provide a #multiple field to indicate if this field is a single
+* select or multi-select.
+*/
+function views_elements() {
+
+ $type['views_node_selector'] = array(
+ '#input' => TRUE,
+ '#process' => array('views_form_process_element' => array()),
+ '#view' => VIEWS_FORM_DEFAULT_VIEW,
+ '#multiple' => false,
+ '#page' => 0,
+ '#collapsed' => false,
+ '#collapsible' => false,
+ '#arguments' => array(),
+ '#embedded' => false, // kratib: This new setting controls whether we're embedding the selector in its own view.
+ );
+
+ return $type;
+}
+
+/**
+ * A place holder for the element processing function, located in views_form.inc
+ */
+function views_form_process_element($element) {
+ include_once drupal_get_path('module', 'views') . '/views_form.inc';
+ return _views_form_process_element($element);
+}
Index: views_cache.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/views/Attic/views_cache.inc,v
retrieving revision 1.2.2.18
diff -u -p -r1.2.2.18 views_cache.inc
--- views_cache.inc 14 Jul 2007 19:12:02 -0000 1.2.2.18
+++ views_cache.inc 18 Aug 2007 18:37:15 -0000
@@ -307,7 +307,7 @@ function _views_get_query(&$view, $args,
* array is cached in a static variable so that arguments
* are only constructed once per run.
*/
-function _views_get_style_plugins($titles = false) {
+function _views_get_style_plugins($titles = false, $display_only = false) {
static $views_style_plugins;
global $locale;
@@ -331,5 +331,16 @@ function _views_get_style_plugins($title
cache_set("views_style_plugins:$locale", 'cache_views', serialize($cache));
}
}
- return ($titles ? $views_style_plugins['title'] : $views_style_plugins['base']);
-}
\ No newline at end of file
+ $return = $views_style_plugins;
+ // remove any plugins that are not listed in drop down menu if $display_only is true
+ if ($display_only) {
+ foreach($views_style_plugins['base'] as $plugin => $def) {
+ if ($def['hide'] == true) {
+ unset($return['base'][$plugin]);
+ unset($return['titles'][$plugin]);
+ }
+ }
+ }
+
+ return ($titles ? $return['title'] : $return['base']);
+}
Index: views_form.inc
===================================================================
RCS file: views_form.inc
diff -N views_form.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ views_form.inc 18 Aug 2007 18:37:15 -0000
@@ -0,0 +1,407 @@
+';
+
+ // add the filters, if any
+ if ($filters) {
+ $element['#children'] .= $filters;
+ }
+
+ // users always seen something, regardless
+ $element['#children'] .= '
';
+ if ($built) {
+ $element['#children'] .= $built;
+ }
+ else {
+ $element['#children'] .= t('No content to display. You may not make any selections at this time.');
+ }
+ $element['#children'] .= '
';
+
+ // finally, the pager, if there is one.
+ if ($pager) {
+ $element['#children'] .= '' . $pager . '
';
+ }
+ $element['#children'] .= '';
+
+ // add the standard required textualizin'
+ $element['#title'] .= $element['#required'] ?
+ ' *' : '';
+
+ unset($element['#value']); // fieldsets can have values? strange....
+
+ return theme('fieldset', $element);
+}
+
+/**
+ * Display the nodes of a view as a form. Should only be used by the
+ * views_node_selector form element.
+ */
+function theme_views_view_form($view, $nodes, $type) {
+ $fields = _views_get_fields();
+ $props = $view->select_column_props;
+ $output = '';
+
+ foreach ($nodes as $node) {
+ $row = array();
+
+ // add the first cell as a selection element
+ if ($props['multiple']) {
+ // this form is a set of checkboxes
+ $element = array (
+ '#name' => $props['parent_name'] . '[' . $node->nid . ']',
+ '#id' => $props['parent_id'] . '-' . $node->nid,
+ '#return_value' => $node->nid,
+ '#parents' => $props['super_parents'],
+ );
+
+ if (in_array($node->nid, $props['setval'] )) {
+ $element['#value'] = true;
+ }
+
+ $form = theme('checkbox', $element);
+ }
+ else {
+ // this form is a set of radio buttons
+ $element = array (
+ '#name' => $props['parent_name'],
+ '#value' => $props['setval'],
+ '#return_value' => $node->nid,
+ '#parents' => $props['super_parents'],
+ );
+
+ $form = theme('radio', $element);
+ }
+
+ $row[] = array(
+ 'data' => $form,
+ 'class' => "view-field view-form-element"
+ );
+
+ foreach ($view->field as $field) {
+ if ($fields[$field['id']]['visible'] !== FALSE) {
+ $cell['data'] = views_theme_field('views_handle_field', $field['queryname'],
+ $fields, $field, $node, $view);
+ $cell['class'] = "view-field ". views_css_safe('view-field-'. $field['queryname']);
+ $row[] = $cell;
+ }
+ }
+ $rows[] = $row;
+ }
+
+ // add a column to the header to accomodate our selection column, include
+ // 'select all' checkbox
+ array_unshift($view->table_header, theme('table_select_header_cell'));
+
+ $output = theme('table', $view->table_header, $rows);
+
+ return $output;
+}
+
+/**
+ * Theme function for the filter form. A wrapper for the default filter form.
+ */
+function theme_views_form_filter_form($form) {
+ $output = '';
+ // move the 'filter_button' element over to 'submit'
+ // to conform to what the views theme function expects
+ $form['submit'] = $form['filter_button'];
+ unset($form['filter_button']);
+
+ $output = '';
+ $output .= theme('views_filters', $form);
+ $output .= '
';
+ return $output;
+}
+
+/**
+ * True form element expansion function. Turns the element into a view, using
+ * the style plugin 'form'. Can either be a single or multiple form (checkboxes
+ * vs. radio). See views_elements() for a complete list of the properties.
+ */
+function _views_form_process_element($element) {
+ $element['#tree'] = true;
+
+ if (!isset($element['#value']['selected']) || !is_array($element['#value'])) {
+ if (is_array($element['#value'])) {
+ foreach($element['#value'] as $key => $value) {
+ if (is_int($key)) {
+ $element['#value']['selected'][] = $value;
+ }
+ }
+ }
+ else {
+ $tmp = $element['#value'];
+ unset($element['#value']);
+ $element['#value']['selected'] = $tmp;
+ }
+ }
+
+ // the clone is necessary in case we're on php5 and we run on the same
+ // view multiple times in a single form (quite possible really)
+ $view = drupal_clone(views_get_view($element['#view']));
+ _views_form_add_title_if_empty($view);
+
+ if ($element['#multiple']) {
+ $item_value = is_array($element['#value']['selected']) ? $element['#value']['selected'] : array();
+ }
+ else {
+ $item_value = $element['#value']['selected'];
+ }
+
+ // add the selection field
+ $view->select_column_props = array (
+ // these next items are shoved into the field to pass to the themeing func
+ 'multiple' => $element['#multiple'],
+ 'setval' => $item_value,
+ 'parent_name' => $element['#name'] . '[selected]',
+ 'parent_id' => $element['#id'] . '-selected',
+ 'super_parents' => array_merge($element['#parents'], array('selected')),
+ );
+
+ // change the view to our internal rendering plugin definition
+ $view->page_type = 'form';
+
+ // save the view for render time
+ $element['#view'] = $view;
+
+ // parse out the exposed filters
+ if (isset($element['#value']['filters'])) {
+ $element['#filters'] = views_get_filter_values($element['#value']['filters']);
+ }
+
+ // get the exposed filters form
+ if (!$element['#embedded'] && ($filter_form = _views_build_filters_form($view))) {
+ $filter_form['view'] = array (
+ '#type' => 'value',
+ '#value' => $view,
+ );
+
+ $filter_form['#theme'] = 'views_form_filter_form';
+
+ $element['filters'] = $filter_form;
+ $element['filters']['filter_button'] = array (
+ '#type' => 'button',
+ '#value' => t('Filter results'),
+ '#name' => $element['#name'] . '[filter_button]',
+ );
+ }
+
+ // if someone intentionally filtered, we return to page zero, to avoid invalid values
+ if ($element['#value']['filter_button']) {
+ $element['#value']['pager']['pages'] = 0;
+ }
+
+ // retrieve the total number of possible pages for this view
+ // reset the page to 0 if it is greater than the max possible pages
+ $page_data = _views_form_get_page_data($view, $element['#arguments'], $element['#filters']);
+ $page_opts = array();
+ $max = 0;
+
+ for($i = 0; $i < $page_data['pages']; ++$i) {
+ $page_opts[$i] = t('Page') . ' ' . ($i + 1);
+ $max = max($max, $i);
+ }
+
+ // update the page if we have a value for it
+ if (isset($element['#value']['pager']['pages'])) {
+ $element['#page'] = $element['#value']['pager']['pages'] > $max ? 0 : $element['#value']['pager']['pages'];
+ }
+
+ // build the view as specified in the element. just for counting
+ $view_nodes = _views_form_build_view_from_element($element, 'items');
+
+ // use the result of the query to build a list of possible nodes to select
+ $options = array();
+ if (!empty($view_nodes['items'])) {
+ foreach($view_nodes['items'] as $node) {
+ $options[$node->nid] = '';
+ }
+ }
+
+ // find any missing nodes (ie. things that won't be in the view)
+ $missing = array();
+ // make sure there is a selected value, or we get extra queries later
+ if (isset($element['#value']['selected'])) {
+ if (is_array($element['#value']['selected'])) {
+ foreach($element['#value']['selected'] as $nid) {
+ if (!isset($options[$nid]) && $nid) {
+ $missing[$nid] = true;
+ }
+ }
+ }
+ else if (!isset($options[$element['#value']['selected']])) {
+ $missing[$element['#value']['selected']] = true;
+ }
+ }
+
+ if (!empty($missing)) {
+
+ $missing_view = drupal_clone($element['#view']);
+
+ // run the missing query and stash it in the $element['view']->missing
+ // making the already selected table
+ // the only filter we want is nid in missing array
+ $missing_view->filter = array();
+ $missing_view->filter[] = array (
+ 'vid' => $missing_view->vid,
+ 'tablename' => '',
+ 'field' => 'node.include_exclude',
+ 'value' => array_keys($missing),
+ 'operator' => 'OR',
+ 'options' => '',
+ 'position' => 0,
+ 'id' => 'node.include_exclude',
+ );
+
+ // remove some caching of queries and other data
+ // we do not need on the "missing" view
+ $missing_view->is_cacheable = false;
+ unset($missing_view->query);
+ unset($missing_view->countquery);
+ unset($missing_view->num_rows);
+
+ $missing_built = views_build_view('items', $missing_view);
+ $missing_items = $missing_built['items'];
+ $element['#view']->missing = $missing_items;
+ // add the missing nodes to the options list
+ foreach(array_keys($missing) as $new_opt) {
+ $options[$new_opt] = '';
+ }
+ }
+
+
+ // a set of checkboxes or radio buttons to make sure the form
+ // passes validation
+ $element['selected'] = array (
+ '#type' => $element['#multiple'] ? 'checkboxes' : 'radios',
+ '#options' => $options,
+ '#required' => $element['#required'],
+ '#title' => $element['#title'],
+ //'#parents' => array_merge($element['#parents'], array('selected')),
+ );
+
+ // form based pager
+ // hide on views with only 1 page or no pages, also hide if paging is turned off
+ if (!$element['#embedded'] && (count($page_opts) > 1) && $view->use_pager) {
+ $element['pager']['pages'] = array (
+ '#type' => 'select',
+ '#options' => $page_opts,
+ '#title' => t('Select another page'),
+ '#value' => $element['#page'],
+ );
+ $element['pager']['go'] = array (
+ '#type' => 'button',
+ '#value' => t('Go!'),
+ '#name' => $element['#name'] . '[go]',
+ );
+ }
+
+ return $element;
+}
+
+function _views_form_build_view_from_element($element, $mode = 'embed', $view = NULL, $filters = NULL) {
+ if (is_null($view)) {
+ $view = $element['#view'];
+ }
+
+ // clone for safety
+ $view = drupal_clone($view);
+
+ if (is_null($filters)) {
+ $filters = $element['#filters'];
+ }
+
+ // Remove internal pager except for embedded views
+ $output = views_build_view(
+ $mode,
+ $view,
+ $element['#arguments'],
+ $element['#embedded'] ? $view->use_pager : FALSE,
+ $view->nodes_per_page,
+ $element['#page'],
+ 0,
+ $filters
+ );
+
+ if ($element['#embedded'] && $mode == 'embed') {
+ $output = preg_replace('(