Now all modules are in core modules folder
This commit is contained in:
parent
5ba1cdfa0b
commit
05b6a91b0c
1907 changed files with 0 additions and 0 deletions
374
modules/cck/includes/views/content.views.inc
Normal file
374
modules/cck/includes/views/content.views.inc
Normal file
|
@ -0,0 +1,374 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Interface between content.module and views.module.
|
||||
*/
|
||||
|
||||
// Include the files defining the classes we extend.
|
||||
// This is needed in case the /cck folder lives in the main
|
||||
// /modules folder (views_module_include() will then load
|
||||
// content.views.inc before node.views.inc)
|
||||
module_load_include('inc', 'views', 'modules/node.views');
|
||||
|
||||
/**
|
||||
* Implementation of hook_views_handlers().
|
||||
*/
|
||||
function content_views_handlers() {
|
||||
return array(
|
||||
'info' => array(
|
||||
'path' => drupal_get_path('module', 'content') . '/includes/views/handlers',
|
||||
),
|
||||
'handlers' => array(
|
||||
|
||||
// argument handlers
|
||||
'content_handler_argument' => array(
|
||||
'parent' => 'views_handler_argument',
|
||||
),
|
||||
'content_handler_argument_string' => array(
|
||||
'parent' => 'views_handler_argument_string',
|
||||
),
|
||||
'content_handler_argument_numeric' => array(
|
||||
'parent' => 'views_handler_argument_numeric',
|
||||
),
|
||||
'content_handler_argument_reference' => array(
|
||||
'parent' => 'content_handler_argument_numeric',
|
||||
),
|
||||
'content_handler_argument_many_to_one' => array(
|
||||
'parent' => 'views_handler_argument_many_to_one',
|
||||
),
|
||||
|
||||
// field handlers
|
||||
'content_handler_field' => array(
|
||||
'parent' => 'views_handler_field_node',
|
||||
),
|
||||
'content_handler_field_multiple' => array(
|
||||
'parent' => 'content_handler_field',
|
||||
),
|
||||
|
||||
// filter handlers
|
||||
'content_handler_filter_string' => array(
|
||||
'parent' => 'views_handler_filter_string',
|
||||
),
|
||||
'content_handler_filter_numeric' => array(
|
||||
'parent' => 'views_handler_filter_numeric',
|
||||
),
|
||||
'content_handler_filter_float' => array(
|
||||
'parent' => 'views_handler_filter_float',
|
||||
),
|
||||
'content_handler_filter_many_to_one' => array(
|
||||
'parent' => 'views_handler_filter_many_to_one',
|
||||
),
|
||||
|
||||
// relationship handlers
|
||||
'content_handler_relationship' => array(
|
||||
'parent' => 'views_handler_relationship',
|
||||
),
|
||||
|
||||
// sort handlers
|
||||
'content_handler_sort' => array(
|
||||
'parent' => 'views_handler_sort',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_views_plugins.
|
||||
*
|
||||
* Defines some plugins used by the Views modes for
|
||||
* nodereference and userreference.
|
||||
*/
|
||||
function content_views_plugins() {
|
||||
$plugins = array(
|
||||
'module' => 'content', // This just tells our themes are elsewhere.
|
||||
'display' => array(
|
||||
'content_simple' => array(
|
||||
'path' => drupal_get_path('module', 'content') . '/includes/views/handlers',
|
||||
// Those strings are not translated for now.
|
||||
// We'll need to change that if / when we remove 'no ui'
|
||||
'title' => 'Simple', // TODO: better name ? (currently not displayed anyway)
|
||||
'help' => 'Destination-agnostic display. Mostly useful for programmatic views.',
|
||||
'handler' => 'content_plugin_display_simple',
|
||||
'no ui' => TRUE, // Programmatic use only.
|
||||
'uses hook menu' => FALSE,
|
||||
'use ajax' => FALSE,
|
||||
'use pager' => FALSE,
|
||||
'accept attachments' => FALSE,
|
||||
),
|
||||
'content_references' => array(
|
||||
'path' => drupal_get_path('module', 'content') . '/includes/views/handlers',
|
||||
// Those strings are not translated for now.
|
||||
// We'll need to change that if / when we remove 'no ui'
|
||||
'title' => 'Simple - for reference fields', // TODO: better name ? (currently not displayed anyway)
|
||||
'help' => 'Destination-agnostic display. Mostly useful for programmatic views.',
|
||||
'parent' => 'content_simple',
|
||||
'handler' => 'content_plugin_display_references',
|
||||
'no ui' => TRUE, // Programmatic use only.
|
||||
'uses hook menu' => FALSE,
|
||||
'use ajax' => FALSE,
|
||||
'use pager' => FALSE,
|
||||
'accept attachments' => FALSE,
|
||||
),
|
||||
),
|
||||
'style' => array(
|
||||
'content_php_array_autocomplete' => array(
|
||||
'path' => drupal_get_path('module', 'content') . '/includes/views/handlers',
|
||||
// Those strings are not translated for now.
|
||||
// We'll need to change that if / when we remove 'no ui'
|
||||
'title' => 'Results array (with title)',
|
||||
'help' => 'Returns the view as a PHP array of names + rendered rows.',
|
||||
'handler' => 'content_plugin_style_php_array_ac',
|
||||
'no ui' => TRUE, // Programmatic use only.
|
||||
'uses row plugin' => TRUE,
|
||||
'uses fields' => TRUE,
|
||||
'type' => 'content_simple',
|
||||
'even empty' => TRUE,
|
||||
),
|
||||
),
|
||||
);
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_views_data().
|
||||
*
|
||||
* Exposes all fields to the views system.
|
||||
*/
|
||||
function content_views_data() {
|
||||
$data = array();
|
||||
foreach (content_fields() as $field) {
|
||||
$module = $field['module'];
|
||||
$result = (array) module_invoke($module, 'field_settings', 'views data', $field);
|
||||
drupal_alter('field_settings', $result, 'views data', $field);
|
||||
if (empty($result)) {
|
||||
$result = content_views_field_views_data($field);
|
||||
}
|
||||
if (is_array($result)) {
|
||||
$data = array_merge($data, $result);
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
function content_views_field_views_data($field) {
|
||||
$field_types = _content_field_types();
|
||||
|
||||
// Check the field module is available.
|
||||
// TODO: is this really how we should do it ?
|
||||
if (isset($field_types[$field['type']])) {
|
||||
$db_info = content_database_info($field);
|
||||
|
||||
// Field modules that do not store data in the database
|
||||
// should not create views data tables.
|
||||
if (empty($db_info['columns'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$table_alias = content_views_tablename($field);
|
||||
|
||||
$types = array();
|
||||
foreach (content_types() as $type) {
|
||||
if (isset($type['fields'][$field['field_name']])) {
|
||||
// TODO : run check_plain here instead of on the imploded string below ?
|
||||
$types[] = $type['name'];
|
||||
}
|
||||
}
|
||||
|
||||
$data = array();
|
||||
$data['table']['group'] = t('Content');
|
||||
$data['table']['join']['node'] = array(
|
||||
'table' => $db_info['table'],
|
||||
'left_field' => 'vid',
|
||||
'field' => 'vid',
|
||||
);
|
||||
$data['table']['join']['node_revisions'] = array(
|
||||
'table' => $db_info['table'],
|
||||
'left_field' => 'vid',
|
||||
'field' => 'vid',
|
||||
);
|
||||
|
||||
// Build the list of columns enabled for default views integration.
|
||||
$db_columns = array();
|
||||
$additional_fields = array();
|
||||
foreach ($db_info['columns'] as $column => $attributes) {
|
||||
// Select explicitly enabled field columns.
|
||||
if (!empty($attributes['views'])) {
|
||||
$db_columns[$column] = $attributes;
|
||||
}
|
||||
// Ensure all columns are retrieved.
|
||||
$additional_fields[$attributes['column']] = $attributes['column'];
|
||||
}
|
||||
// Pick up the first column when none has been explicitly enabled
|
||||
// (pre CCK 2.2 backwards compatibility).
|
||||
if (empty($db_columns)) {
|
||||
// Can't use array_slice(), it won't work in PHP4 for assoc array.
|
||||
foreach ($db_info['columns'] as $column => $attributes) {
|
||||
$db_columns[$column] = $attributes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$columns = array();
|
||||
$db_fields = array();
|
||||
$arguments = array();
|
||||
$filters = array();
|
||||
foreach ($db_columns as $column => $attributes) {
|
||||
$columns[] = $column;
|
||||
$db_fields[] = $attributes['column'];
|
||||
$sorts[] = !empty($attributes['sortable']) ? TRUE : FALSE;
|
||||
|
||||
// Identify likely filters and arguments for each column based on field type.
|
||||
switch ($attributes['type']) {
|
||||
case 'int':
|
||||
case 'mediumint':
|
||||
case 'tinyint':
|
||||
case 'bigint':
|
||||
case 'serial':
|
||||
$filters[] = 'content_handler_filter_numeric';
|
||||
$arguments[] = 'content_handler_argument_numeric';
|
||||
break;
|
||||
case 'numeric':
|
||||
case 'float':
|
||||
$filters[] = 'content_handler_filter_float';
|
||||
$arguments[] = 'content_handler_argument_numeric';
|
||||
break;
|
||||
|
||||
case 'text':
|
||||
case 'blob':
|
||||
// TODO add markup handlers for these types
|
||||
default:
|
||||
$filters[] = 'content_handler_filter_string';
|
||||
$arguments[] = 'content_handler_argument_string';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Provide automatic filters, sorts, and arguments for each column, not just the first.
|
||||
$db_fields_count = count($db_fields);
|
||||
foreach ($db_fields as $i => $db_field) {
|
||||
$label_truncated = truncate_utf8(t($field['widget']['label']), 10, TRUE);
|
||||
if ($db_fields_count == 1) {
|
||||
$title = t('@label (!name)', array('@label' => t($field['widget']['label']), '!name' => $field['field_name']));
|
||||
$title_short = check_plain($label_truncated);
|
||||
}
|
||||
else {
|
||||
$title = t('@label (!name) - !column', array('@label' => t($field['widget']['label']), '!name' => $field['field_name'], '!column' => $columns[$i]));
|
||||
$title_short = t('@label-truncated - !column', array('@label-truncated' => $label_truncated, '!column' => $columns[$i]));
|
||||
}
|
||||
|
||||
$data[$db_field] = array(
|
||||
'group' => t('Content'),
|
||||
'title' => $title,
|
||||
'title short' => $title_short,
|
||||
'help' => t($field_types[$field['type']]['label']) .' - '. t('Appears in: @types', array('@types' => implode(', ', $types))),
|
||||
);
|
||||
if ($i == 0) {
|
||||
$data[$db_field]['field'] = array(
|
||||
'title' => t('@label (!name)', array('@label' => t($field['widget']['label']), '!name' => $field['field_name'])),
|
||||
'title short' => check_plain($label_truncated),
|
||||
'field' => $db_field,
|
||||
'table' => $db_info['table'],
|
||||
'handler' => 'content_handler_field_multiple',
|
||||
'click sortable' => $sorts[$i],
|
||||
'additional fields' => $additional_fields,
|
||||
'content_field_name' => $field['field_name'],
|
||||
'access callback' => 'content_access',
|
||||
'access arguments' => array('view', $field),
|
||||
);
|
||||
}
|
||||
$data[$db_field]['argument'] = array(
|
||||
'field' => $db_field,
|
||||
'table' => $db_info['table'],
|
||||
'handler' => $arguments[$i],
|
||||
'additional fields' => $additional_fields,
|
||||
'content_field_name' => $field['field_name'],
|
||||
'empty field name' => t('<No value>'),
|
||||
);
|
||||
$data[$db_field]['filter'] = array(
|
||||
'field' => $db_field,
|
||||
'table' => $db_info['table'],
|
||||
'handler' => $filters[$i],
|
||||
'additional fields' => $additional_fields,
|
||||
'content_field_name' => $field['field_name'],
|
||||
'allow empty' => TRUE,
|
||||
);
|
||||
if (!empty($sorts[$i])) {
|
||||
$data[$db_field]['sort'] = array(
|
||||
'field' => $db_field,
|
||||
'table' => $db_info['table'],
|
||||
'handler' => 'content_handler_sort',
|
||||
'additional fields' => $additional_fields,
|
||||
'content_field_name' => $field['field_name'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Expose additional delta column for multiple value fields.
|
||||
if ($field['multiple']) {
|
||||
$title = t('@label (!name) - delta', array('@label' => t($field['widget']['label']), '!name' => $field['field_name']));
|
||||
$title_short = t('@label-truncated - delta', array('@label-truncated' => $label_truncated));
|
||||
|
||||
$db_field = 'delta';
|
||||
$data[$db_field] = array(
|
||||
'group' => t('Content'),
|
||||
'title' => $title,
|
||||
'title short' => $title_short,
|
||||
'help' => t('Delta - Appears in: @types', array('@types' => implode(', ', $types))),
|
||||
);
|
||||
$data[$db_field]['field'] = array(
|
||||
'title' => $title,
|
||||
'title short' => $title_short,
|
||||
'field' => $db_field,
|
||||
'table' => $db_info['table'],
|
||||
'handler' => 'views_handler_field_numeric',
|
||||
'click sortable' => TRUE,
|
||||
'additional fields' => $additional_fields,
|
||||
'access callback' => 'content_access',
|
||||
'access arguments' => array('view', $field),
|
||||
);
|
||||
$data[$db_field]['argument'] = array(
|
||||
'field' => $db_field,
|
||||
'table' => $db_info['table'],
|
||||
'handler' => 'views_handler_argument_numeric',
|
||||
'additional fields' => $additional_fields,
|
||||
'empty field name' => t('<No value>'),
|
||||
);
|
||||
$data[$db_field]['filter'] = array(
|
||||
'field' => $db_field,
|
||||
'table' => $db_info['table'],
|
||||
'handler' => 'views_handler_filter_numeric',
|
||||
'additional fields' => $additional_fields,
|
||||
'allow empty' => TRUE,
|
||||
);
|
||||
$data[$db_field]['sort'] = array(
|
||||
'field' => $db_field,
|
||||
'table' => $db_info['table'],
|
||||
'handler' => 'views_handler_sort',
|
||||
'additional fields' => $additional_fields,
|
||||
);
|
||||
}
|
||||
|
||||
return array($table_alias => $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function so it is possible to change the Views tablename
|
||||
* in the future without re-writing code.
|
||||
*/
|
||||
function content_views_tablename($field) {
|
||||
return 'node_data_'. $field['field_name'];
|
||||
}
|
||||
|
||||
function theme_content_view_multiple_field($items, $field, $values) {
|
||||
$output = '';
|
||||
$i = 0;
|
||||
foreach ($items as $item) {
|
||||
if (!empty($item) || $item == '0') {
|
||||
$output .= '<div class="field-item field-item-'. $i .'">'. $item .'</div>';
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
71
modules/cck/includes/views/content.views_convert.inc
Normal file
71
modules/cck/includes/views/content.views_convert.inc
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Field conversion for fields handled by this module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of hook_views_convert().
|
||||
*
|
||||
* Intervene to convert field values from the Views 1 format to the
|
||||
* Views 2 format. Intervene only if $view->add_item() won't produce
|
||||
* the right results, usually needed to set field options or values.
|
||||
*/
|
||||
function content_views_convert($display, $type, &$view, $views_field) {
|
||||
static $views_fields;
|
||||
|
||||
if (empty($views_fields)) {
|
||||
$views_fields = array();
|
||||
$types = content_types();
|
||||
foreach ($types as $ctype) {
|
||||
foreach ($ctype['fields'] as $field) {
|
||||
$module = $field['module'];
|
||||
$result = (array) module_invoke($module, 'field_settings', 'views data', $field);
|
||||
drupal_alter('field_settings', $result, 'views data', $field);
|
||||
if (empty($result)) {
|
||||
// The views field name had the column name appended,
|
||||
// like field_name_value or field_username_uid.
|
||||
$column = array_shift(array_keys($field['columns']));
|
||||
$views_fields[$field['field_name'] .'_'. $column] = $field;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Is this a field that CCK should handle? If not, return.
|
||||
if (!in_array($views_field['field'], array_keys($views_fields))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Now update values, options, etc. to those selected in the imported view.
|
||||
switch ($type) {
|
||||
case 'field':
|
||||
$view->display[$display]->display_options['fields'][$views_field['field']]['format'] = $views_field['options'];
|
||||
if ($views_field['handler'] == 'content_views_field_handler_group') {
|
||||
$view->display[$display]->display_options['fields'][$views_field['field']]['multiple']['group'] = 1;
|
||||
}
|
||||
else {
|
||||
$view->display[$display]->display_options['fields'][$views_field['field']]['multiple']['group'] = 0;
|
||||
}
|
||||
return;
|
||||
|
||||
case 'filter':
|
||||
// TODO
|
||||
return;
|
||||
|
||||
case 'exposed_filter':
|
||||
// TODO
|
||||
return;
|
||||
|
||||
case 'argument':
|
||||
// TODO
|
||||
return;
|
||||
|
||||
case 'sort':
|
||||
// TODO
|
||||
break;
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The subclass simply adds properties,
|
||||
* for field-specific subclasses to use if they need to.
|
||||
*/
|
||||
class content_handler_argument extends views_handler_argument {
|
||||
var $content_field;
|
||||
|
||||
function construct() {
|
||||
parent::construct();
|
||||
|
||||
$this->content_field = content_fields($this->definition['content_field_name']);
|
||||
$this->additional_fields = $this->definition['additional fields'];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Handler for 'content_handler_argument_many_to_one' style.
|
||||
*/
|
||||
class content_handler_argument_many_to_one extends views_handler_argument_many_to_one {
|
||||
var $content_field;
|
||||
|
||||
function construct() {
|
||||
parent::construct();
|
||||
|
||||
$this->content_field = content_fields($this->definition['content_field_name']);
|
||||
$this->additional_fields = $this->definition['additional fields'];
|
||||
}
|
||||
|
||||
function summary_name($data) {
|
||||
$options = $this->allowed_values();
|
||||
$value = $data->{$this->name_alias};
|
||||
if (isset($options[$value])) {
|
||||
$value = $options[$value];
|
||||
}
|
||||
else {
|
||||
$value = parent::summary_name($data);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
function title_query() {
|
||||
$options = $this->allowed_values();
|
||||
$values = $this->value;
|
||||
foreach ($values as $key => $value) {
|
||||
if (isset($options[$value])) {
|
||||
$values[$key] = $options[$value];
|
||||
}
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
function allowed_values() {
|
||||
$field = $this->content_field;
|
||||
$function = $field['module'] .'_allowed_values';
|
||||
$options = function_exists($function) ? $function($field) : content_allowed_values($field);
|
||||
return (array) $options;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The subclass simply adds properties,
|
||||
* for field-specific subclasses to use if they need to.
|
||||
*/
|
||||
class content_handler_argument_numeric extends views_handler_argument_numeric {
|
||||
var $content_field;
|
||||
|
||||
function construct() {
|
||||
parent::construct();
|
||||
|
||||
$this->content_field = content_fields($this->definition['content_field_name']);
|
||||
$this->additional_fields = $this->definition['additional fields'];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provide handler to replace reference with title.
|
||||
*/
|
||||
class content_handler_argument_reference extends content_handler_argument_numeric {
|
||||
/**
|
||||
* Override the behavior of title().
|
||||
*/
|
||||
function title_query() {
|
||||
$titles = array();
|
||||
$placeholders = implode(', ', array_fill(0, sizeof($this->value), '%d'));
|
||||
|
||||
$table_data = views_fetch_data($this->name_table);
|
||||
$table = array_shift($table_data['table']['join']);
|
||||
|
||||
$result = db_query("SELECT $this->name_field AS title FROM {". $table['table'] ."} WHERE ". $table['field'] ." IN ($placeholders)", $this->value);
|
||||
while ($row = db_fetch_object($result)) {
|
||||
$titles[] = check_plain($row->title);
|
||||
}
|
||||
return $titles;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The subclass simply adds properties,
|
||||
* for field-specific subclasses to use if they need to.
|
||||
*/
|
||||
class content_handler_argument_string extends views_handler_argument_string {
|
||||
var $content_field;
|
||||
|
||||
function construct() {
|
||||
parent::construct();
|
||||
|
||||
$this->content_field = content_fields($this->definition['content_field_name']);
|
||||
$this->additional_fields = $this->definition['additional fields'];
|
||||
}
|
||||
}
|
228
modules/cck/includes/views/handlers/content_handler_field.inc
Normal file
228
modules/cck/includes/views/handlers/content_handler_field.inc
Normal file
|
@ -0,0 +1,228 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The subclass adds basic field and formatter info,
|
||||
* for field-specific subclasses to use if they need to.
|
||||
*
|
||||
* Fields could extend this class if they want field and formatter handling
|
||||
* but don't want the multiple value grouping options created by
|
||||
* content_handler_field_multiple.
|
||||
*/
|
||||
class content_handler_field extends views_handler_field_node {
|
||||
var $content_field;
|
||||
|
||||
function construct() {
|
||||
parent::construct();
|
||||
$this->content_field = content_fields($this->definition['content_field_name']);
|
||||
}
|
||||
|
||||
function init(&$view, $options) {
|
||||
$field = $this->content_field;
|
||||
parent::init($view, $options);
|
||||
if ($field['multiple']) {
|
||||
$this->additional_fields['delta'] = 'delta';
|
||||
}
|
||||
// Make sure we grab enough information to build a pseudo-node with enough
|
||||
// credentials at render-time.
|
||||
$this->additional_fields['type'] = array('table' => 'node', 'field' => 'type');
|
||||
$this->additional_fields['nid'] = array('table' => 'node', 'field' => 'nid');
|
||||
$this->additional_fields['vid'] = array('table' => 'node', 'field' => 'vid');
|
||||
}
|
||||
|
||||
function option_definition() {
|
||||
$options = parent::option_definition();
|
||||
$field = $this->content_field;
|
||||
|
||||
// Override views_handler_field_node's default label
|
||||
$options['label'] = array('default' => '', 'translatable' => TRUE);
|
||||
$options['label_type'] = array('default' => 'widget');
|
||||
$options['format'] = array('default' => 'default');
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide formatter option.
|
||||
*/
|
||||
function options_form(&$form, &$form_state) {
|
||||
parent::options_form($form, $form_state);
|
||||
// TODO: do we want the 'link to node' checkbox ?
|
||||
// That's usually formatters business...
|
||||
|
||||
$field = $this->content_field;
|
||||
$options = $this->options;
|
||||
|
||||
$form['label_type'] = array(
|
||||
'#title' => t('Label'),
|
||||
'#type' => 'radios',
|
||||
'#options' => array(
|
||||
'none' => t('None'),
|
||||
'widget' => t('Widget label (@label)', array('@label' => $field['widget']['label'])),
|
||||
'custom' => t('Custom'),
|
||||
),
|
||||
'#default_value' => $options['label_type'],
|
||||
'#weight' => 2,
|
||||
);
|
||||
$form['label'] = array(
|
||||
'#title' => t('Custom label'),
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $options['label'],
|
||||
'#process' => array('views_process_dependency'),
|
||||
'#dependency' => array('radio:options[label_type]' => array('custom')),
|
||||
'#weight' => 3,
|
||||
);
|
||||
|
||||
$field_types = _content_field_types();
|
||||
$formatters = array();
|
||||
if (is_array($field_types[$field['type']]['formatters'])) {
|
||||
foreach ($field_types[$field['type']]['formatters'] as $name => $info) {
|
||||
$formatters[$name] = $info['label'];
|
||||
}
|
||||
}
|
||||
$form['format'] = array(
|
||||
'#title' => t('Format'),
|
||||
'#type' => 'select',
|
||||
'#options' => $formatters,
|
||||
'#required' => TRUE,
|
||||
'#default_value' => $options['format'],
|
||||
'#weight' => 4,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make sure some value is stored as a label.
|
||||
*
|
||||
* Don't use t(), since Views' views_handler_field already has
|
||||
* $this->options['label'] marked as a translatable field.
|
||||
*
|
||||
* @see http://drupal.org/node/285470
|
||||
*/
|
||||
function options_submit($form, &$form_state) {
|
||||
switch ($form_state['values']['options']['label_type']) {
|
||||
case 'none':
|
||||
$form_state['values']['options']['label'] = '';
|
||||
break;
|
||||
case 'widget':
|
||||
$form_state['values']['options']['label'] = $this->content_field['widget']['label'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @TODO
|
||||
* Now that we save the label in the submit process above we could
|
||||
* get rid of this function. Leave it here for now to be sure the
|
||||
* label works for fields that haven't been updated since this
|
||||
* change was made, since $this->options['label'] will be missing a
|
||||
* value until it is updated in the view.
|
||||
*
|
||||
* Don't use t(), since Views' views_handler_field already has
|
||||
* $this->options['label'] marked as a translatable field.
|
||||
*/
|
||||
function label() {
|
||||
$field = $this->content_field;
|
||||
switch ($this->options['label_type']) {
|
||||
case 'none':
|
||||
return '';
|
||||
case 'widget':
|
||||
return $field['widget']['label'];
|
||||
default:
|
||||
return $this->options['label'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return DIV or SPAN based upon the field's element type.
|
||||
*/
|
||||
function element_type($none_supported = FALSE, $default_empty = FALSE) {
|
||||
// The 'element_type' property denotes Views 3.x ('semantic views'
|
||||
// functionnality). If the property is set, and not set to '' ("default"),
|
||||
// let the generic method handle the output.
|
||||
if (isset($this->options['element_type']) && $this->options['element_type'] !== '') {
|
||||
return parent::element_type($none_supported, $default_empty);
|
||||
}
|
||||
|
||||
if ($default_empty) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (isset($this->definition['element type'])) {
|
||||
return $this->definition['element type'];
|
||||
}
|
||||
|
||||
// TODO Figure out exactly when to return a div or a <span>. Any field
|
||||
// that ever needs to be shown inline in Views UI. It needs to return
|
||||
// a div for textareas to prevent wrapping a <span> around a <p>.
|
||||
// Earl says we need to be sure that other fields we don't know
|
||||
// about won't end up wrapping a span around a block-level element.
|
||||
if ($this->content_field['widget']['type'] == 'text_textarea') {
|
||||
return 'div';
|
||||
}
|
||||
else {
|
||||
return 'span';
|
||||
}
|
||||
}
|
||||
|
||||
function options_validate($form, &$form_state) { }
|
||||
|
||||
/**
|
||||
* Provide text for the administrative summary
|
||||
*/
|
||||
function admin_summary() {
|
||||
// Display the formatter name.
|
||||
$field = $this->content_field;
|
||||
$field_types = _content_field_types();
|
||||
if (isset($field_types[$field['type']]['formatters'][$this->options['format']])) {
|
||||
return t($field_types[$field['type']]['formatters'][$this->options['format']]['label']);
|
||||
}
|
||||
}
|
||||
|
||||
function render($values) {
|
||||
// We're down to a single node here, so we can retrieve the actual field
|
||||
// definition for the node type being considered.
|
||||
$field = content_fields($this->content_field['field_name'], $values->{$this->aliases['type']});
|
||||
|
||||
// If the field does not appear in the node type, then we have no value
|
||||
// to display, and can just return.
|
||||
if (empty($field)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$options = $this->options;
|
||||
$db_info = content_database_info($field);
|
||||
|
||||
// Build a pseudo-node from the retrieved values.
|
||||
$node = drupal_clone($values);
|
||||
$node->type = $values->{$this->aliases['type']};
|
||||
$node->nid = $values->{$this->aliases['nid']};
|
||||
$node->vid = $values->{$this->aliases['vid']};
|
||||
// Some formatters need to behave differently depending on the build_mode
|
||||
// (for instance: preview), so we provide one.
|
||||
$node->build_mode = NODE_BUILD_NORMAL;
|
||||
|
||||
$item = array();
|
||||
foreach ($db_info['columns'] as $column => $attributes) {
|
||||
$item[$column] = $values->{$this->aliases[$attributes['column']]};
|
||||
}
|
||||
|
||||
$item['#delta'] = $field['multiple'] ? $values->{$this->aliases['delta']} : 0;
|
||||
|
||||
// Render items.
|
||||
$formatter_name = $options['format'];
|
||||
if ($formatter = _content_get_formatter($formatter_name, $field['type'])) {
|
||||
if (content_handle('formatter', 'multiple values', $formatter) == CONTENT_HANDLE_CORE) {
|
||||
// Single-value formatter.
|
||||
$output = content_format($field, $item, $formatter_name, $node);
|
||||
}
|
||||
else {
|
||||
// Multiple values formatter - we actually have only one value to display.
|
||||
$output = content_format($field, array($item), $formatter_name, $node);
|
||||
}
|
||||
return $this->render_link($output, $values);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,321 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* An extended subclass for field handling that adds multiple field grouping.
|
||||
*
|
||||
* Fields that want multiple value grouping options in addition to basic
|
||||
* field and formatter handling can extend this class.
|
||||
*/
|
||||
class content_handler_field_multiple extends content_handler_field {
|
||||
var $defer_query;
|
||||
|
||||
function init(&$view, $options) {
|
||||
$field = $this->content_field;
|
||||
parent::init($view, $options);
|
||||
|
||||
$this->defer_query = !empty($options['multiple']['group']) && $field['multiple'];
|
||||
|
||||
if ($this->defer_query) {
|
||||
// Grouped field: ditch the existing additional_fields (field columns + delta).
|
||||
// In the main query we'll only need:
|
||||
// - vid, which will be used to retrieve the actual values in pre_render,
|
||||
// - node type and nid, which wil be used in the pseudo-node used when
|
||||
// rendering.
|
||||
$this->additional_fields = array(
|
||||
'type' => array('table' => 'node', 'field' => 'type'),
|
||||
'nid' => array('table' => 'node', 'field' => 'nid'),
|
||||
);
|
||||
if ($view->base_table == 'node_revisions') {
|
||||
$this->additional_fields['vid'] = array('table' => 'node_revisions', 'field' => 'vid');
|
||||
}
|
||||
else {
|
||||
$this->additional_fields['vid'] = array('table' => 'node', 'field' => 'vid');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function option_definition() {
|
||||
$options = parent::option_definition();
|
||||
|
||||
$options['multiple'] = array(
|
||||
'contains' => array(
|
||||
'group' => array('default' => TRUE),
|
||||
'multiple_number' => array('default' => ''),
|
||||
'multiple_from' => array('default' => ''),
|
||||
'multiple_reversed' => array('default' => FALSE),
|
||||
),
|
||||
);
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide 'group multiple values' option.
|
||||
*/
|
||||
function options_form(&$form, &$form_state) {
|
||||
parent::options_form($form, $form_state);
|
||||
|
||||
$field = $this->content_field;
|
||||
$options = $this->options;
|
||||
|
||||
$form['multiple'] = array(
|
||||
'#access' => $field['multiple'],
|
||||
'#weight' => 1,
|
||||
);
|
||||
$form['multiple']['group'] = array(
|
||||
'#title' => t('Group multiple values'),
|
||||
'#type' => 'checkbox',
|
||||
'#default_value' => $options['multiple']['group'],
|
||||
'#description' => t('If unchecked, each item in the field will create a new row, which may appear to cause duplicates. This setting is not compatible with click-sorting in table displays.'),
|
||||
);
|
||||
// Make the string translatable by keeping it as a whole rather than
|
||||
// translating prefix and suffix separately.
|
||||
list($prefix, $suffix) = explode('@count', t('Show @count value(s)'));
|
||||
$form['multiple']['multiple_number'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#size' => 5,
|
||||
'#field_prefix' => $prefix,
|
||||
'#field_suffix' => $suffix,
|
||||
'#default_value' => $options['multiple']['multiple_number'],
|
||||
'#prefix' => '<div class="container-inline">',
|
||||
'#process' => array('views_process_dependency'),
|
||||
'#dependency' => array('edit-options-multiple-group' => array(TRUE)),
|
||||
);
|
||||
list($prefix, $suffix) = explode('@count', t('starting from @count'));
|
||||
$form['multiple']['multiple_from'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#size' => 5,
|
||||
'#field_prefix' => $prefix,
|
||||
'#field_suffix' => $suffix,
|
||||
'#default_value' => $options['multiple']['multiple_from'],
|
||||
'#process' => array('views_process_dependency'),
|
||||
'#dependency' => array('edit-options-multiple-group' => array(TRUE)),
|
||||
'#description' => t('(first item is 0)'),
|
||||
);
|
||||
$form['multiple']['multiple_reversed'] = array(
|
||||
'#title' => t('Reversed'),
|
||||
'#type' => 'checkbox',
|
||||
'#default_value' => $options['multiple']['multiple_reversed'],
|
||||
'#suffix' => '</div>',
|
||||
'#process' => array('views_process_dependency'),
|
||||
'#dependency' => array('edit-options-multiple-group' => array(TRUE)),
|
||||
'#description' => t('(start from last values)'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this field is click sortable.
|
||||
*/
|
||||
function click_sortable() {
|
||||
$field = $this->content_field;
|
||||
$options = $this->options;
|
||||
|
||||
// Grouped fields are not click-sortable.
|
||||
return !empty($this->definition['click sortable']) && !$this->defer_query;
|
||||
}
|
||||
|
||||
function query() {
|
||||
// If this is not a grouped field, use the generic query().
|
||||
if (!$this->defer_query) {
|
||||
return parent::query();
|
||||
}
|
||||
|
||||
// Grouped field: do NOT call ensure_my_table, only add additional fields.
|
||||
$this->add_additional_fields();
|
||||
$this->field_alias = $this->aliases['vid'];
|
||||
}
|
||||
|
||||
function pre_render($values) {
|
||||
// If there are no values to render (displaying a summary, or query returned no results),
|
||||
// or if this is not a grouped field, do nothing specific.
|
||||
if (isset($this->view->build_info['summary']) || empty($values) || !$this->defer_query) {
|
||||
return parent::pre_render($values);
|
||||
}
|
||||
|
||||
$field = $this->content_field;
|
||||
$db_info = content_database_info($field);
|
||||
$options = $this->options;
|
||||
|
||||
// Build the list of vids to retrieve.
|
||||
// TODO: try fetching from cache_content first ??
|
||||
$vids = array();
|
||||
$this->field_values = array();
|
||||
foreach ($values as $result) {
|
||||
if (isset($result->{$this->field_alias})) {
|
||||
$vids[] = $result->{$this->field_alias};
|
||||
}
|
||||
}
|
||||
|
||||
// It may happend that the multiple values field is related to a non
|
||||
// required relation for which no node data related to the field being
|
||||
// processed here is available.
|
||||
if (empty($vids)) {
|
||||
return parent::pre_render($values);
|
||||
}
|
||||
|
||||
// List columns to retrieve.
|
||||
$alias = content_views_tablename($field);
|
||||
// Prefix aliases with '_' to avoid clashing with field columns names.
|
||||
$query_columns = array(
|
||||
'vid AS _vid',
|
||||
"delta as _delta",
|
||||
// nid is needed to generate the links for 'link to node' option.
|
||||
'nid AS _nid',
|
||||
);
|
||||
// The actual field columns.
|
||||
foreach ($db_info['columns'] as $column => $attributes) {
|
||||
$query_columns[] = "$attributes[column] AS $column";
|
||||
}
|
||||
$query = 'SELECT '. implode(', ', $query_columns) .
|
||||
' FROM {'. $db_info['table'] ."}".
|
||||
" WHERE vid IN (". implode(',', $vids) .')'.
|
||||
" ORDER BY _nid ASC, _delta ". ($options['multiple']['multiple_reversed'] ? 'DESC' : 'ASC');
|
||||
$result = db_query($query);
|
||||
|
||||
while ($item = db_fetch_array($result)) {
|
||||
// Clean up the $item from vid and delta. We keep nid for now.
|
||||
$vid = $item['_vid'];
|
||||
unset($item['_vid']);
|
||||
$delta = !empty($item['_delta']) ? $item['_delta'] : 0;
|
||||
$item['#delta'] = $item['_delta'];
|
||||
unset($item['_delta']);
|
||||
$this->field_values[$vid][$delta] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return DIV or SPAN based upon the field's element type.
|
||||
*
|
||||
* Fields rendered with the 'group multiple' option use <div> markers,
|
||||
* and thus shouldn't be wrapped in a <span>.
|
||||
*/
|
||||
function element_type($none_supported = FALSE, $default_empty = FALSE) {
|
||||
// If this is not a grouped field, use the parent method.
|
||||
if (!$this->defer_query) {
|
||||
return parent::element_type($none_supported, $default_empty);
|
||||
}
|
||||
|
||||
// The 'element_type' property denotes Views 3.x ('semantic views'
|
||||
// functionnality). If the property is set, and not set to '' ("default"),
|
||||
// let the generic method handle the output.
|
||||
if (isset($this->options['element_type']) && $this->options['element_type'] !== '') {
|
||||
return parent::element_type($none_supported, $default_empty);
|
||||
}
|
||||
|
||||
if ($default_empty) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (isset($this->definition['element type'])) {
|
||||
return $this->definition['element type'];
|
||||
}
|
||||
|
||||
return 'div';
|
||||
}
|
||||
|
||||
function render($values) {
|
||||
// If this is not a grouped field, use content_handler_field::render().
|
||||
if (!$this->defer_query) {
|
||||
return parent::render($values);
|
||||
}
|
||||
|
||||
// We're down to a single node here, so we can retrieve the actual field
|
||||
// definition for the node type being considered.
|
||||
$field = content_fields($this->content_field['field_name'], $values->{$this->aliases['type']});
|
||||
|
||||
// If the field does not appear in the node type, then we have no value
|
||||
// to display, and can just return.
|
||||
if (empty($field)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$options = $this->options;
|
||||
|
||||
$vid = $values->{$this->field_alias};
|
||||
if (isset($this->field_values[$vid])) {
|
||||
// Gather items, respecting the 'Display n values starting from m' settings.
|
||||
$count_skipped = 0;
|
||||
$items = array();
|
||||
foreach ($this->field_values[$vid] as $item) {
|
||||
if (empty($options['multiple']['multiple_from']) || ($count_skipped >= $options['multiple']['multiple_from'])) {
|
||||
if (empty($options['multiple']['multiple_number']) || (count($items) < $options['multiple']['multiple_number'])) {
|
||||
// Grab the nid - needed for render_link().
|
||||
$nid = $item['_nid'];
|
||||
unset($item['_nid']);
|
||||
$items[] = $item;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$count_skipped++;
|
||||
}
|
||||
|
||||
// Build a pseudo-node from the retrieved values.
|
||||
$node = drupal_clone($values);
|
||||
// content_format and formatters will need a 'type'.
|
||||
$node->type = $values->{$this->aliases['type']};
|
||||
$node->nid = $values->{$this->aliases['nid']};
|
||||
$node->vid = $values->{$this->aliases['vid']};
|
||||
|
||||
// Some formatters need to behave differently depending on the build_mode
|
||||
// (for instance: preview), so we provide one.
|
||||
$node->build_mode = NODE_BUILD_NORMAL;
|
||||
|
||||
// Render items.
|
||||
$formatter_name = $options['format'];
|
||||
if ($items && ($formatter = _content_get_formatter($formatter_name, $field['type']))) {
|
||||
$rendered = array();
|
||||
if (content_handle('formatter', 'multiple values', $formatter) == CONTENT_HANDLE_CORE) {
|
||||
// Single-value formatter.
|
||||
foreach ($items as $item) {
|
||||
$output = content_format($field, $item, $formatter_name, $node);
|
||||
if (!empty($output)) {
|
||||
$rendered[] = $this->render_link($output, (object) array('nid' => $nid));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Multiple values formatter.
|
||||
$output = content_format($field, $items, $formatter_name, $values);
|
||||
if (!empty($output)) {
|
||||
$rendered[] = $this->render_link($output, (object) array('nid' => $nid));
|
||||
}
|
||||
}
|
||||
|
||||
if (count($rendered) > 1) {
|
||||
// TODO: could we use generic field display ?
|
||||
return theme('content_view_multiple_field', $rendered, $field, $values);
|
||||
}
|
||||
elseif ($rendered) {
|
||||
return $rendered[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function render_link($data, $values) {
|
||||
if (!$this->defer_query) {
|
||||
return parent::render_link($data, $values);
|
||||
}
|
||||
|
||||
if (!empty($this->options['link_to_node']) && $data !== NULL && $data !== '') {
|
||||
if (method_exists('render_as_link', 'views_handler_field')) {
|
||||
// Views 2.3+
|
||||
$this->options['alter']['make_link'] = TRUE;
|
||||
$this->options['alter']['path'] = "node/" . $values->{$this->aliases['nid']};
|
||||
}
|
||||
else {
|
||||
// Views up to 2.2
|
||||
return l($data, "node/" . $values->nid, array('html' => TRUE));
|
||||
}
|
||||
}
|
||||
else {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The subclass simply adds properties,
|
||||
* for field-specific subclasses to use if they need to.
|
||||
*/
|
||||
|
||||
// Ensure compatibility with Views pre 2.4, where the
|
||||
// views_handler_filter_float class lived in views_handler_filter_numeric.inc.
|
||||
if (!class_exists('views_handler_filter_float')) {
|
||||
// Manually include the parent class.
|
||||
$definition = views_fetch_handler_data('views_handler_filter_numeric');
|
||||
views_include_handler($definition, 'handler');
|
||||
}
|
||||
|
||||
class content_handler_filter_float extends views_handler_filter_float {
|
||||
var $content_field;
|
||||
|
||||
function construct() {
|
||||
parent::construct();
|
||||
$this->content_field = content_fields($this->definition['content_field_name']);
|
||||
$this->additional_fields = $this->definition['additional fields'];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The subclass simply adds properties,
|
||||
* for field-specific subclasses to use if they need to.
|
||||
*/
|
||||
class content_handler_filter_many_to_one extends views_handler_filter_many_to_one {
|
||||
var $content_field;
|
||||
|
||||
function construct() {
|
||||
parent::construct();
|
||||
$this->content_field = content_fields($this->definition['content_field_name']);
|
||||
$this->additional_fields = $this->definition['additional fields'];
|
||||
$field = $this->content_field;
|
||||
$this->value_title = $field['widget']['label'];
|
||||
}
|
||||
|
||||
function get_value_options() {
|
||||
$this->value_options = $this->allowed_values();
|
||||
}
|
||||
|
||||
// Get allowed values from hook_allowed_values(), if any,
|
||||
// or from content_allowed_values();
|
||||
function allowed_values() {
|
||||
$field = $this->content_field;
|
||||
$function = $field['module'] .'_allowed_values';
|
||||
if ($this->value_form_type == 'select') {
|
||||
// Select elements accept multidimensional arrays to support optgroups.
|
||||
$options = function_exists($function) ? $function($field) : content_allowed_values($field, FALSE);
|
||||
// For selects, HTML should be filtered out and entities left unencoded.
|
||||
// See content_allowed_values / content_filter_xss / filter_xss.
|
||||
content_allowed_values_filter_html($options);
|
||||
}
|
||||
else {
|
||||
$options = function_exists($function) ? $function($field) : content_allowed_values($field);
|
||||
}
|
||||
return (array) $options;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The subclass simply adds properties,
|
||||
* for field-specific subclasses to use if they need to.
|
||||
*/
|
||||
class content_handler_filter_numeric extends views_handler_filter_numeric {
|
||||
var $content_field;
|
||||
|
||||
function construct() {
|
||||
parent::construct();
|
||||
$this->content_field = content_fields($this->definition['content_field_name']);
|
||||
$this->additional_fields = $this->definition['additional fields'];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The subclass simply adds properties,
|
||||
* for field-specific subclasses to use if they need to.
|
||||
*/
|
||||
class content_handler_filter_string extends views_handler_filter_string {
|
||||
var $content_field;
|
||||
|
||||
function construct() {
|
||||
parent::construct();
|
||||
$this->content_field = content_fields($this->definition['content_field_name']);
|
||||
$this->additional_fields = $this->definition['additional fields'];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Handles content relationships and deals properly with multiple
|
||||
* values by allowing the views administrator to select deltas.
|
||||
*/
|
||||
class content_handler_relationship extends views_handler_relationship {
|
||||
var $content_field;
|
||||
|
||||
function construct() {
|
||||
parent::construct();
|
||||
|
||||
$this->content_field = content_fields($this->definition['content_field_name']);
|
||||
}
|
||||
|
||||
function option_definition() {
|
||||
$options = parent::option_definition();
|
||||
$options['delta'] = array('default' => -1);
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a delta selector for multiple fields.
|
||||
*/
|
||||
function options_form(&$form, &$form_state) {
|
||||
$field = $this->content_field;
|
||||
parent::options_form($form, $form_state);
|
||||
|
||||
// Only add the form gadget if the field is multiple.
|
||||
if ($field['multiple']) {
|
||||
$max_delta = $field['multiple'];
|
||||
// 1 means unlimited.
|
||||
if ($max_delta == 1) {
|
||||
$max_delta = 10;
|
||||
}
|
||||
|
||||
$options = array('-1' => t('All'));
|
||||
for ($i = 0; $i < $max_delta; $i++) {
|
||||
$options[$i] = $i + 1;
|
||||
}
|
||||
$form['delta'] = array(
|
||||
'#type' => 'select',
|
||||
'#options' => $options,
|
||||
'#default_value' => $this->options['delta'],
|
||||
'#title' => t('Delta'),
|
||||
'#description' => t('The delta allows you to select which item in a multiple value field to key the relationship off of. Select "1" to use the first item, "2" for the second item, and so on. If you select "All", each item in the field will create a new row, which may appear to cause duplicates.'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function ensure_my_table() {
|
||||
if (!isset($this->table_alias)) {
|
||||
$join = $this->get_join();
|
||||
if (!isset($join->extra)) {
|
||||
$join->extra = array();
|
||||
}
|
||||
$delta = isset($this->options['delta']) ? $this->options['delta'] : -1;
|
||||
if ($delta != -1) {
|
||||
$join->extra[] = array(
|
||||
'field' => 'delta',
|
||||
'value' => $delta,
|
||||
'numeric' => TRUE,
|
||||
);
|
||||
}
|
||||
|
||||
$this->table_alias = $this->query->add_table($this->table, $this->relationship, $join);
|
||||
}
|
||||
return $this->table_alias;
|
||||
}
|
||||
}
|
73
modules/cck/includes/views/handlers/content_handler_sort.inc
Normal file
73
modules/cck/includes/views/handlers/content_handler_sort.inc
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Handles sorts and deals properly with multiple
|
||||
* values by allowing the views administrator to select deltas.
|
||||
*/
|
||||
class content_handler_sort extends views_handler_sort {
|
||||
var $content_field;
|
||||
|
||||
function construct() {
|
||||
parent::construct();
|
||||
|
||||
$this->content_field = content_fields($this->definition['content_field_name']);
|
||||
$this->additional_fields = $this->definition['additional fields'];
|
||||
}
|
||||
|
||||
function option_definition() {
|
||||
$options = parent::option_definition();
|
||||
$options['delta'] = array('default' => -1);
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a delta selector for multiple fields.
|
||||
*/
|
||||
function options_form(&$form, &$form_state) {
|
||||
$field = $this->content_field;
|
||||
parent::options_form($form, $form_state);
|
||||
|
||||
// Only add the form gadget if the field is multiple.
|
||||
if ($field['multiple']) {
|
||||
$max_delta = $field['multiple'];
|
||||
// 1 means unlimited.
|
||||
if ($max_delta == 1) {
|
||||
$max_delta = 10;
|
||||
}
|
||||
|
||||
$options = array('-1' => t('All'));
|
||||
for ($i = 0; $i < $max_delta; $i++) {
|
||||
$options[$i] = $i + 1;
|
||||
}
|
||||
$form['delta'] = array(
|
||||
'#type' => 'select',
|
||||
'#options' => $options,
|
||||
'#default_value' => $this->options['delta'],
|
||||
'#title' => t('Delta'),
|
||||
'#description' => t('The delta allows you to select which item in a multiple value field will be used for sorting. Select "1" to use the first item, "2" for the second item, and so on. If you select "All", each item in the field will create a new row, which may appear to cause duplicates.'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function ensure_my_table() {
|
||||
if (!isset($this->table_alias)) {
|
||||
$join = $this->get_join();
|
||||
if (!isset($join->extra)) {
|
||||
$join->extra = array();
|
||||
}
|
||||
$delta = isset($this->options['delta']) ? $this->options['delta'] : -1;
|
||||
if ($delta != -1) {
|
||||
$join->extra[] = array(
|
||||
'field' => 'delta',
|
||||
'value' => $delta,
|
||||
'numeric' => TRUE,
|
||||
);
|
||||
}
|
||||
|
||||
$this->table_alias = $this->query->ensure_table($this->table, $this->relationship, $join);
|
||||
}
|
||||
return $this->table_alias;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Handler for 'content_simple' display.
|
||||
*/
|
||||
class content_plugin_display_simple extends views_plugin_display {
|
||||
function execute() {
|
||||
return $this->view->render($this->display->id);
|
||||
}
|
||||
|
||||
function render() {
|
||||
return !empty($this->view->result) || !empty($this->view->style_plugin->definition['even empty']) ? $this->view->style_plugin->render($this->view->result) : '';
|
||||
}
|
||||
|
||||
function uses_exposed() {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
class content_plugin_display_references extends content_plugin_display_simple {
|
||||
function query() {
|
||||
$options = $this->get_option('content_options');
|
||||
|
||||
if ($options['string'] !== '') {
|
||||
$like = $GLOBALS["db_type"] == 'pgsql' ? "ILIKE" : "LIKE";
|
||||
$match_clauses = array(
|
||||
'contains' => "$like '%%%s%%'",
|
||||
'equals' => "= '%s'",
|
||||
'starts_with' => "$like '%s%%'",
|
||||
);
|
||||
$clause = isset($match_clauses[$options['match']]) ? $match_clauses[$options['match']] : $match_clauses['contains'];
|
||||
$alias = $this->view->query->ensure_table($options['table']);
|
||||
$this->view->query->add_where(NULL, "$alias.$options[field_string] $clause", $options['string']);
|
||||
}
|
||||
elseif ($options['ids']) {
|
||||
$alias = $this->view->query->ensure_table($options['table']);
|
||||
$this->view->query->add_where(NULL, "$alias.$options[field_id] IN (" . db_placeholders($options['ids']) . ')', $options['ids']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Handler for 'content_php_array_autocomplete' style.
|
||||
*/
|
||||
class content_plugin_style_php_array_ac extends views_plugin_style {
|
||||
function render() {
|
||||
$results = array();
|
||||
|
||||
// Group the rows according to the grouping field, if specified.
|
||||
$sets = $this->render_grouping($this->view->result, $this->options['grouping']);
|
||||
|
||||
$base_field = $this->view->base_field;
|
||||
$title_field = $this->display->display_options['content_title_field'];
|
||||
$title_field_alias = $this->view->field[$title_field]->field_alias;
|
||||
|
||||
// TODO : We don't display grouping info for now.
|
||||
// Could be useful for select widget, though.
|
||||
$this->view->row_index = 0;
|
||||
foreach ($sets as $title => $records) {
|
||||
foreach ($records as $label => $row) {
|
||||
$results[$row->{$base_field}] = array(
|
||||
'title' => $row->{$title_field_alias},
|
||||
'rendered' => $this->row_plugin->render($row),
|
||||
);
|
||||
$this->view->row_index++;
|
||||
}
|
||||
}
|
||||
unset($this->view->row_index);
|
||||
return $results;
|
||||
}
|
||||
}
|
Reference in a new issue