array('label' => 'View Reference'), ); } /** * Implementation of hook_field_settings(). */ function viewfield_field_settings($op, $field) { switch ($op) { /* These are off until we need them case 'form': return $form; case 'save': return array(); */ case 'database columns': $columns = array( 'vname' => array('type' => 'char', 'length' => 32), 'vargs' => array('type' => 'varchar', 'not null' => false, 'default' => "''", 'sortable' => TRUE, 'length' => 255), ); return $columns; /* case 'filters': return array( 'default' => array( 'list' => '_viewfield_filter_handler', 'list-type' => 'list', 'operator' => 'views_handler_operator_or', 'value-type' => 'array', 'extra' => array('field' => $field), ), ); */ } } /** * Implementation of hook_field_formatter_info(). */ function viewfield_field_formatter_info() { $formatters = array( 'default' => array( 'label' => 'Entire view (using default style)', 'field types' => array('viewfield'), ), 'count' => array( 'label' => 'Count of items in view', 'field types' => array('viewfield'), ), ); include_once(drupal_get_path('module', 'views') .'/views_cache.inc'); $plugins = _views_get_style_plugins(); foreach ($plugins as $type => $details) { $formatters[$type] = array( 'label' => $details['name'], 'field types' => array('viewfield') ); } return $formatters; } /** * Implementation of hook_field_formatter(). */ function viewfield_field_formatter($field, $item, $formatter, $node) { // these are Eaton's tests for his normal, defaults, content type wide settings stuff //$v = ($field['configurability'] == 'none') ? $field['vname'] : $item['vname']; //$a = ($field['configurability'] == 'none') ? $field['vargs'] : $item['vargs']; // using the $v, $a convention in case I uncomment the above lines. $v = $item['vname']; $a = $item['vargs']; if (!empty($v)) { // XXX this probably not multi-select safe... global $user; $view = views_get_view($v); $translated_args = strtr($a, array('%nid' => $node->nid, '%author' => $node->uid, '%viewer' => $user->uid)); $args = explode(',', $translated_args); if ($formatter != 'default' && $formatter != 'count') { $view->page_type = $formatter; } // need to prevent recusive views and node building, but don't need to do it on new node previews if ($node->nid) { _viewfield_nodestack_push($node->nid); } switch ($formatter) { default: if ($view->use_pager) { // fix for multiple pagers global $pager_total; static $viewfield_pager_elements = array(); $key = $node->nid . '-' . $field['field_name'] . '-' . $view->name; // set a unique key for the view in the current node if (!isset($viewfield_pager_elements[$key])) { // set the viewfield pager element to the max + 1 $max1 = is_array($pager_total) ? @max(array_values($pager_total)) : 1; $max2 = @max(array_values($viewfield_pager_elements)); $viewfield_pager_elements[$key] = @max($max1, $max2) + 1; } $use_pager = $viewfield_pager_elements[$key]; } else { $use_pager = 0; } $output = views_build_view('embed', $view, $args, $use_pager, $view->nodes_per_page); break; case 'count': // TODO use the the new 'queries' $op instead $results = views_build_view('items', $view, $args); $count = count($results['items']); $output = $count; break; } // this node is "safe" again if ($node->nid) { _viewfield_nodestack_pop(); } return $output; } } /** * Implementation of hook_widget_info(). */ function viewfield_widget_info() { return array( 'viewfield_select' => array( 'label' => 'Select List', 'field types' => array('viewfield'), ), /* 'viewfield_autocomplete' => array( 'label' => 'Autocomplete View Field', 'field types' => array('viewfield'), ), */ ); } /** * Implementation of hook_widget(). */ function viewfield_widget($op, &$node, $field, &$node_field) { switch ($op) { case 'prepare form values': $node_field_transposed = content_transpose_array_rows_cols($node_field); $node_field['default vnames'] = $node_field_transposed['vname']; break; case 'form': $form = array(); $options = _viewfield_potential_references($field); $form[$field['field_name']] = array('#tree' => TRUE); $form[$field['field_name']]['vnames'] = array( '#type' => 'select', '#title' => t($field['widget']['label']), '#default_value' => $node_field['default vnames'], '#multiple' => $field['multiple'], '#options' => $options, '#required' => $field['required'], '#description' => $field['widget']['description'], ); $form[$field['field_name']]['vargs'] = array( '#type' => 'textarea', '#title' => 'arguments', '#default_value' => $node_field[0]['vargs'], // all views share args (for now ...) '#required' => false, '#description' => t('Provide a comma separated list of arguments to pass to the view. You may use %nid for the node id of the current node. %author for the node author and %viewer for user viewing the node. These arguments will be passed to EACH selected view.'), ); return $form; case 'process form values': if ($field['multiple']) { $items = $node_field['vnames']; foreach($items as $item) { $node_field[] = array ( 'vname' => $item, 'vargs' => $node_field['vargs'], ); } } else { $node_field[0]['vname'] = $node_field['vnames']; $node_field[0]['vargs'] = $node_field['vargs']; } // Remove the widget's data representation so it isn't saved. unset($node_field['vnames']); unset($node_field['vargs']); } } /*** Private functions ***/ /** * Prepare a list of views for selection. */ function _viewfield_potential_references($field) { $options = array(); include_once(drupal_get_path('module', 'views') . '/views_cache.inc'); $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; } } return $options; } /** * Functions for manipulating a global stack of nids. This prevents us from recursively * building a node, with a view, with the node, with the view.... etc */ function _viewfield_nodestack_push($nid) { global $viewfield_stack; if (!isset($viewfield_stack)) { $_GLOBAL['viewfield_stack'] = array(); global $viewfield_stack; } $viewfield_stack[] = $nid; } function _viewfield_nodestack_pop() { global $viewfield_stack; return array_pop($viewfield_stack); } /** * Implementation of hook_db_rewrite_sql * * Prevent views from loading the node containing the view. */ function viewfield_db_rewrite_sql($query, $primary_table, $primary_field, $args) { global $viewfield_stack; if (!empty($viewfield_stack)) { if ($primary_field == 'nid') { $return['where'] = "$primary_table.nid NOT IN (" . implode(',', $viewfield_stack). ')'; return $return; } } }