'views_node_selector', '#default_value' => array(1,2,3), // where 1, 2, and 3 are nids .... ); */ 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))) { // kratib // theming $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) { // kratib $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; } /** * Theme function for the views_node_selector form element */ function theme_views_node_selector($element) { // build the real view $built = _views_form_build_view_from_element($element, 'embed'); // some other stuff in our element array $filters = $element['filters']['#children']; $pager = $element['pager']['#children']; // the entire bundle of output goes in one div $element['#children'] = '
'; // 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; 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 //array_unshift($view->table_header, array('data' => '', 'class' => 'view-cell-header')); array_unshift($view->table_header, theme('table_select_header_cell')); // kratib: Add the select-all checkbox $out = theme('table', $view->table_header, $rows); return $out; } /** * Theme function for the filter form. A wrapper for the default filter form. */ function theme_views_form_filter_form($form) { // 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; } function _views_form_add_title_if_empty(&$view) { // if the form doesn't have any fields, we add the node title (with link) // option. This is fragile as it depends on the field code not changing. // if somethig breaks, look here. // the views_view_add_field would be prefered, but we need the query name computed by this point // and views_view_add_field doesn't have arguments for queryname if (empty($view->field)) { $title = array ( 'vid' => $view->vid, 'tablename' => 'node', 'field' => 'title', 'label' => t('Title'), 'handler' => 'views_handler_field_nodelink', 'sortable' => 0, 'defaultsort' => 0, 'options' => 'link', 'position' => 0, 'fullname' => 'node.title', 'id' => 'node.title', 'queryname' => 'node_title', ); $view->field[] = $title; } } 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']; } // kratib: remove internal pager $output = views_build_view( $mode, $view, $element['#arguments'], $element['#embedded'] ? $view->use_pager : FALSE, // kratib: keep pager use if embedded // we do not want the built in pager $view->nodes_per_page, // use the default paging setting $element['#page'], 0, $filters); if ($element['#embedded'] && $mode == 'embed') $output = preg_replace('(
.*?<\/div>)','',$output); return $output; } function _views_form_get_page_data($view, $args = NULL, $filters = NULL) { $element = array( '#arguments' => $args, '#page' => 0, '#filters' => $filters, '#view' => $view, ); $queries = _views_form_build_view_from_element($element, 'queries'); if (empty($queries)) { return array ('count' => 0, 'pages' => 0); } // rewrite the query appropriately $cquery = db_rewrite_sql($queries['countquery'], 'node', 'nid'); $count = db_result(db_query($cquery, $queries['args'])); if ($view->nodes_per_page) { $pages = ceil($count / $view->nodes_per_page); } else { $pages = 1; } return array ( 'count' => $count, 'pages' => $pages, ); }