summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYves Chedemois2008-11-01 23:51:52 (GMT)
committer Yves Chedemois2008-11-01 23:51:52 (GMT)
commit89c0777df893154485e277e62ff5703c261f0409 (patch)
treeefdcc71e61d94ee243f71458a1c5f0f1b745fc1f
parent8031f4e073fe4e189f199052536b36fa4f71073c (diff)
Views integration:
- a few relationship-safe fixes after merlinofchaos had a look a our code :-) - a little refactoring to make content_handler_field / content_handler_field_multiple articulation clearer.
-rw-r--r--CHANGELOG.txt1
-rw-r--r--content.module4
-rw-r--r--includes/views/handlers/content_handler_field.inc49
-rw-r--r--includes/views/handlers/content_handler_field_multiple.inc83
4 files changed, 74 insertions, 63 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 595afac..2caf9f5 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -39,6 +39,7 @@ CCK 6.2-dev
- Content Copy: Import / export weights of dnd-enabled non-CCK fields.
- #327715 Babysit 'invalid foreach' warnings caused by invalid incoming $node objects.
- #328763 Adjust weight of non-cck fields even if there are no CCK fields for the content type.
+- Views integration: fixed a few non-relationship safe areas.
CCK 6.2-rc10
============
diff --git a/content.module b/content.module
index e899e72..1647c64 100644
--- a/content.module
+++ b/content.module
@@ -1660,12 +1660,10 @@ function content_format($field, $item, $formatter_name = 'default', $node = NULL
if ($formatter = _content_get_formatter($formatter_name, $field['type'])) {
$theme = $formatter['module'] .'_formatter_'. $formatter_name;
- // A real node will have the type name in $node->type,
- // a Views pseudo-node will have the type name in $node->node_type.
$element = array(
'#theme' => $theme,
'#field_name' => $field['field_name'],
- '#type_name' => isset($node->type) ? $node->type : (isset($node->node_type) ? $node->node_type : ''),
+ '#type_name' => isset($node->type) ? $node->type :'',
'#formatter' => $formatter_name,
'#node' => $node,
'#delta' => isset($item['#delta']) ? $item['#delta'] : NULL,
diff --git a/includes/views/handlers/content_handler_field.inc b/includes/views/handlers/content_handler_field.inc
index 58ba085..a0afac7 100644
--- a/includes/views/handlers/content_handler_field.inc
+++ b/includes/views/handlers/content_handler_field.inc
@@ -18,6 +18,16 @@ class content_handler_field extends views_handler_field_node {
$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';
+ }
+ // We'll need the node type to render the results.
+ $this->additional_fields['type'] = array('table' => 'node', 'field' => 'type');
+ }
+
function options(&$options) {
parent::options($options);
$field = $this->content_field;
@@ -76,13 +86,13 @@ class content_handler_field extends views_handler_field_node {
);
}
-
+
/**
* Make sure some value is stored as a label.
- *
- * Don't use t(), since Views' views_handler_field already has
+ *
+ * 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) {
@@ -97,14 +107,14 @@ class content_handler_field extends views_handler_field_node {
}
/**
- * @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
+ * @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
+ * 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
+ *
+ * Don't use t(), since Views' views_handler_field already has
* $this->options['label'] marked as a translatable field.
*/
function label() {
@@ -138,16 +148,23 @@ class content_handler_field extends views_handler_field_node {
$options = $this->options;
$db_info = content_database_info($field);
- // $values will be used as a fake $node object;
- // we provide a build_mode for rendering.
- $values->build_mode = NODE_BUILD_NORMAL;
+ // Build a pseudo-node from the retrieved values.
+ $node = $values;
+ // TODO : is nid always correct ?
+ // content_format and formatters will need a 'type'.
+ $node->type = $values->{$this->aliases['type']};
+ // 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->table_alias .'_'. $attributes['column']};
+ $item[$column] = $values->{$this->aliases[$attributes['column']]};
}
- $item['#delta'] = !empty($values->{$this->table_alias . '_delta'}) ? $values->{$this->table_alias . '_delta'} : 0;
- return $this->render_link(content_format($field, $item, $options['format'], $values), $values);
+
+ $item['#delta'] = $field['multiple'] ? $values->{$this->aliases['delta']} : 0;
+
+ return $this->render_link(content_format($field, $item, $options['format'], $node), $values);
}
} \ No newline at end of file
diff --git a/includes/views/handlers/content_handler_field_multiple.inc b/includes/views/handlers/content_handler_field_multiple.inc
index e9f2695..0ecbe57 100644
--- a/includes/views/handlers/content_handler_field_multiple.inc
+++ b/includes/views/handlers/content_handler_field_multiple.inc
@@ -14,10 +14,19 @@ class content_handler_field_multiple extends content_handler_field {
function init(&$view, $options) {
$field = $this->content_field;
parent::init($view, $options);
- if ($field['multiple']) {
- $this->additional_fields['delta'] = 'delta';
+
+ $this->defer_query = $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, which wil be used to render the results.
+ $this->additional_fields = array(
+ 'vid' => array('table' => 'node', 'field' => 'vid'),
+ 'type' => array('table' => 'node', 'field' => 'type'),
+ );
}
- $this->additional_fields['type'] = array('table' => 'node', 'field' => 'type');
}
function options(&$options) {
@@ -89,43 +98,25 @@ class content_handler_field_multiple extends content_handler_field {
$field = $this->content_field;
$options = $this->options;
- return !empty($this->definition['click sortable']) && !($options['multiple']['group'] && $field['multiple']);
+ // Grouped fields are not click-sortable.
+ return !empty($this->definition['click sortable']) && !$this->defer_query;
}
function query() {
- $field = $this->content_field;
- $options = $this->options;
-
- // 'Group multiple values' : the values for the field will be retrieved
- // in a separate query (one per field).
- $this->defer_query = $options['multiple']['group'] && $field['multiple'];
-
- // Non-grouped field: use the generic field handler query.
+ // If this is not a grouped field, use the generic query().
if (!$this->defer_query) {
return parent::query();
}
- // Grouped field: overwrite the existing additional_fields, because they
- // would cause duplicate rows for multiple values. The only field we add
- // is vid, which will be used to retrieve the actual values in pre_render.
- $this->additional_fields = array('vid' => array('table' => 'node', 'field' => 'vid'));
+ // Grouped field: do NOT call ensure_my_table, only add additional fields.
$this->add_additional_fields();
$this->field_alias = $this->aliases['vid'];
-
- // If the field is sortable (table sort), we just have to join the table
- // ("Node: Distinct" will be required to avoid duplicates...)
- // if ($field['sortable']) {
- // $this->ensure_my_table();
- // }
}
function pre_render($values) {
- // There are no values to render in a summary view.
- if (isset($this->view->build_info['summary'])) {
- return parent::pre_render($values);
- }
- // If this is not a grouped field, use the parent pre_render().
- if (!$this->defer_query || empty($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);
}
@@ -133,7 +124,6 @@ class content_handler_field_multiple extends content_handler_field {
$db_info = content_database_info($field);
$options = $this->options;
- $this->field_values = array();
// Build the list of vids to retrieve.
// TODO: try fetching from cache_content first ??
$vids = array();
@@ -146,11 +136,10 @@ class content_handler_field_multiple extends content_handler_field {
// List columns to retrieve.
$alias = content_views_tablename($field);
-
$query_columns = array(
- 'node.type',
- "$alias.vid AS parent_vid",
- "$alias.delta"
+ // Prefix with '_' to avoid clashing with field columns named 'vid' or 'delta'.
+ "node.vid AS _vid",
+ "$alias.delta as _delta"
);
foreach ($db_info['columns'] as $column => $attributes) {
$query_columns[] = "$alias.$attributes[column] AS $column";
@@ -158,15 +147,17 @@ class content_handler_field_multiple extends content_handler_field {
$query = 'SELECT '. implode(', ', $query_columns) .
' FROM {'. $db_info['table'] ."} $alias".
" LEFT JOIN {node} node ON node.vid = $alias.vid".
- " WHERE $alias.vid IN (". implode(',', $vids) .')'.
+ " WHERE node.vid IN (". implode(',', $vids) .')'.
" ORDER BY node.nid ASC, $alias.delta ". ($options['multiple']['multiple_reversed'] ? 'DESC' : 'ASC');
$result = db_query($query);
while ($item = db_fetch_array($result)) {
- $delta = !empty($item['delta']) ? $item['delta'] : 0;
- $item['#delta'] = $item['delta'];
- unset($item['delta']);
- $this->field_values[$item['parent_vid']][$delta] = $item;
+ $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;
}
}
@@ -179,13 +170,9 @@ class content_handler_field_multiple extends content_handler_field {
$field = $this->content_field;
$options = $this->options;
- // $values will be used as a fake $node object;
- // we provide a build_mode for rendering.
- $values->build_mode = NODE_BUILD_NORMAL;
-
// This needs to be set for the $this->render_link() to work. It would
// have been set in the query, if we hadn't bypassed the normal query.
- // TODO there may be a better way to do this.
+ // TODO : Not relatioship safe !.
$this->aliases['nid'] = 'nid';
$vid = $values->{$this->field_alias};
@@ -205,6 +192,14 @@ class content_handler_field_multiple extends content_handler_field {
$count_skipped++;
}
+ // Build a pseudo-node from the retrieved values.
+ $node = $values;
+ // content_format and formatters will need a 'type'.
+ $node->type = $values->{$this->aliases['type']};
+ // 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']))) {
@@ -212,7 +207,7 @@ class content_handler_field_multiple extends content_handler_field {
if (content_handle('formatter', 'multiple values', $formatter) == CONTENT_HANDLE_CORE) {
// Single-value formatter.
foreach ($items as $item) {
- $output = content_format($field, $item, $formatter_name, $values);
+ $output = content_format($field, $item, $formatter_name, $node);
if (!empty($output)) {
$rendered[] = $this->render_link($output, $values);
}