select vs checkboxes? Arg.
*/
function viewselector_elements() {
//dprint_r("In selector elements");
$type['views_node_selector'] = array(
'#input' => TRUE,
'#process' => array('viewselector_process_element' => array()),
'#view' => 'frontpage',
'#multiple' => false,
'#page' => 0,
'#collapsed' => false,
'#collapsible' => false,
'#arguments' => array(),
);
return $type;
}
function viewselector_process_element($element) {
include_once 'viewselector.inc';
//dprint_r("Processing:");
//dprint_r($element['#value']);
$element['#tree'] = true;
// turn default values into the proper values
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']));
_viewselector_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
$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')),
);
_viewselector_add_selection_column($view, $props);
// modify the view to use the exposed filters
// this will happen if anyone clicks any non submitting form button
if (isset($element['#value']['filters'])) {
_viewselector_edit_filters($view, $element['#value']['filters']);
}
// get the exposed filters form before we remove them manually
$filter_form = _viewselector_filters_form($view);
// change the view to a table based view
// remove the normal exposed filters
$view->page_type = 'table';
$view->viewselector = true;
$view->exposed_filter = array();
// save the view for render time -- no changes to the view after this point
$element['#view'] = $view;
// if someone intentionally filtered, we return to page zero, to avoid invalid values
if ($element['#value']['filter_button']) {
$element['#value']['pager']['pages'] = 0;
}
// reset the page to 0 if it is greater than the max possible pages
$page_data = _viewselector_get_page_data($view, $element['#arguments']);
$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 = _viewselector_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)
// in theme_views_node_selector, we'll put them in their own table.
$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])) {
$missing[$nid] = true;
}
}
} else if (!isset($options[$element['#value']['selected']])) {
$missing[$element['#value']['selected']] = true;
}
}
$element['#missing'] = array_keys($missing);
// add the missing nodes to the options list
foreach($element['#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')),
);
// if there are no exposed filters, dispense with the form
if ($filter_form) {
// the exposed filters
$element['filters'] = $filter_form;
$element['filters']['filter_button'] = array (
'#type' => 'button',
'#value' => t('Filter results'),
'#name' => $element['#name'] . '[filter_button]',
);
}
// form based pager
// hide on views with only 1 page or no pages
// also hide if paging is turned off
if (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]',
);
}
//dprint_r("about to return element");
//dprint_r($element['options']['#options']);
return $element;
}
function theme_views_node_selector($element) {
// dprint_r("In theme views node selector");
// dprint_r($element);
$view = $element['#view'];
// clone the view _prior_ to building it
$missing_view = drupal_clone($view);
// build the real view
$built = _viewselector_build_view_from_element($element);
// some other stuff in our element array
$filters = $element['filters']['#children'];
$pager = $element['pager']['#children'];
$missing = $element['#missing'];
if (!empty($missing)) {
dprint_r($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' => 'node2.nid', // set to node.nid when this gets into views
'value' => $missing,
'operator' => 'OR',
'options' => '',
'position' => 0,
'id' => 'node2.nid', // set to node.nid when this gets into views
);
// remove some caching of queries and other data
// we do not need on the "missing" table
unset($missing_view->query);
unset($missing_view->countquery);
unset($missing_view->num_rows);
unset($missing_view->page_empty);
unset($missing_view->page_header);
unset($missing_view->page_footer);
// make our faked view
$tbl = views_build_view('embed', $missing_view);
if ($tbl) {
$missing_table = '
' . t('Currently Selected') . "
\n";
$missing_table .= $tbl;
$missing_table .= '';
}
}
// the entire bundle of output goes in one div
$element['#children'] = '';
// add the filters, if any
if ($filters) {
$element['#children'] .= '
' . $filters . '
';
}
// add the "missing" table, if any
$element['#children'] .= $missing_table;
// users always seen something, regardless
$element['#children'] .= '
';
if ($built) {
$element['#children'] .= '
' . t('Select Content') . "
\n";
$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);
}
/*** Defining some views related stuff ***/
/**
* Here we create a fake column for use in views. This fake column will hold
* our select boxes/radios.
*/
function viewselector_views_tables() {
$tables['selector'] = array (
'name' => 'viewselector',
'provider' => 'internal', // won't show up in external list.
'fields' => array(
'select' => array(
'name' => t('Node: Select'),
'handler' => 'viewselector_handler_selector',
'sortable' => true,
'option' => '',
'notafield' => 'true',
'help' => t("This should only be used by the viewselector form widget."),
),
),
);
/* the 'nid' filter should be added to the default views_node.inc table.
the inner join is just to get the functionality I need w/o patching views
(yet)
*/
$tables['node2'] = array (
'name' => 'node',
'provider' => 'internal', // won't show up in external list.
'join' => array(
'left' => array(
'table' => 'node',
'field' => 'nid',
),
'right' => array(
'field' => 'nid',
),
'type' => 'inner',
),
'filters' => array(
'nid' => array(
'name' => t('Node: Include/Exclude Nodes in View'),
'field' => 'nid',
'operator' => 'views_handler_operator_or',
'value' => viewselector_handler_filter_nid_value_form('frontpage'),
'value-type' => 'array',
'help' => t('This filter allows you to limit your view to only apply to some specific nodes. You can limit your view to a specific list of nodes, or you can exclude specific nodes from every being returned.'),
),
),
);
return $tables;
}
function viewselector_handler_filter_nid_value_form($view) {
$form['vns'] = array (
'#type' => 'views_node_selector',
'#view' => $view,
'#multiple' => true,
);
return $form;
}
/**
* This function sticks the select element (checkbox or radio) into the built
* view.
*/
function viewselector_handler_selector($fieldinfo, $fielddata, $value, $data) {
// if multiple, we use check boxes, if single we use radio buttons
if ($fielddata['multiple']) {
//dprint_r("I should be making checkboxes");
$element = array (
'#name' => $fielddata['parent_name'] . '[' . $data->nid . ']',
'#id' => $fielddata['parent_id'] . '-' . $data->nid,
'#return_value' => $data->nid,
'#parents' => $fielddata['super_parents'],
);
// dprint_r($fielddata['setval']);
if (in_array($data->nid, $fielddata['setval'] )) {
$element['#value'] = true;
}
//dprint_r($element);
return theme('checkbox', $element);
}
else {
//dprint_r("I should be making radios");
$element = array (
'#name' => $fielddata['parent_name'],
'#value' => $fielddata['setval'],
'#return_value' => $data->nid,
'#parents' => $fielddata['super_parents'],
);
return theme('radio', $element);
}
}
/**
* Hide the above from views
*/
function viewselector_form_alter($form_id, &$form) {
include_once 'viewselector.inc';
if ($form_id == 'views_edit_view') {
// hide the selection field during view creation
unset($form['field']['add']['id']['#options']['selector.select']);
}
}
/* FOR TESTING ONLY */
/**
* Implementation of hook_help()
*/
function viewselector_help($section) {
switch ($section) {
case 'admin/modules#description':
return t('A testing module for a form element to select nodes based on views');
}
}
/**
* Implementation of hook_menu().
*/
function viewselector_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'viewselector', 'title' => t('testing view selector'),
'callback' => 'viewselector_testpage',
'access' => true);
}
return $items;
}
function viewselector_testpage() {
if ($_GET['edit']['view']) {
$edit = $_GET['edit'];
$form['vns'] = array (
'#type' => 'views_node_selector',
'#title' => 'Your test form',
'#view' => $edit['view'],
'#page' => $edit['page'] ? $edit['page'] - 1 : 0,
'#multiple' => $edit['multiple'],
'#arguments' => explode(',', $edit['args']),
'#required' => $edit['required'],
'#default_value' => $edit['multiple'] ? explode(',', $edit['defaults']) : $edit['defaults'],
);
} else {
$options = array();
$default_views = _views_get_default_views();
$res = db_query("SELECT name FROM {view_view} ORDER BY name");
while ($view = db_fetch_object($res)) {
$options[$view->name] = $view->name;
}
if(is_array($default_views)) {
foreach($default_views as $key => $view) {
$options[$key] = $view->name;
}
}
$form['view'] = array (
'#type' => 'select',
'#title' => 'Pick a view to use',
'#options' => $options,
);
$form['page'] = array (
'#type' => 'textfield',
'#title' => 'If you want to start on a given page, put the number in here'
);
$form['args'] = array (
'#type' => 'textfield',
'#title' => 'Args: if you need arguments, put in a comman separated list. eg. 1,34,foo'
);
$form['multiple'] = array (
'#type' => 'checkbox',
'#title' => 'Check this box to make it a multiple form (i.e. checkboxes instead of radios)',
);
$form['defaults'] = array (
'#type' => 'textfield',
'#title' => 'Put in the node id(s) of the default values. If you are using a multiple form, comma separate the list.'
);
$form['required'] = array (
'#type' => 'checkbox',
'#title' => 'Check this box to make it a required form element',
);
$form['#method'] = 'GET';
}
$form['submit'] = array (
'#type' => 'submit',
'#value' => 'submit',
);
return drupal_get_form('viewselector_test_form', $form);
}
function viewselector_test_form_submit($id, $form) {
//dprint_r("In viewselector_test_form_submit");
//dprint_r($form);
if (is_array($form['vns']['selected'])) {
drupal_set_message("(Ignore zeros) You selected: " . implode(', ', $form['vns']['selected']));
} else {
drupal_set_message("You selected: " . $form['vns']['selected']);
}
return 'viewselector';
}
/*
function viewselector_init() {
dprint_r("In init function");
dprint_r("POST:");
dprint_r($_POST);
dprint_r("GET:");
dprint_r($_GET);
}
*/