Commit d6423787 authored by merlinofchaos's avatar merlinofchaos

#247929: Multiple attachment displays failed due to shallow cloning problems.

parent 8d43831f
......@@ -1994,12 +1994,18 @@ class views_plugin_display_attachment extends views_plugin_display {
return $this->view->render($this->display->id);
}
function attachment_positions($position) {
function attachment_positions($position = NULL) {
$positions = array(
'before' => t('Before'),
'after' => t('After'),
'both' => t('Both'),
);
if ($position) {
return $positions[$position];
}
return $positions;
}
/**
......@@ -2069,7 +2075,7 @@ class views_plugin_display_attachment extends views_plugin_display {
case 'attachment_position':
$form['#title'] .= t('Position');
$form['attachment_position'] = array(
'#type' => 'checkboxes',
'#type' => 'radios',
'#description' => t('Attach before or after the parent display?'),
'#options' => $this->attachment_positions(),
'#default_value' => $this->get_option('attachment_position'),
......@@ -2120,8 +2126,7 @@ class views_plugin_display_attachment extends views_plugin_display {
// Get a fresh view because our current one has a lot of stuff on it because it's
// already been executed.
$view = drupal_clone($this->view);
$view->init_display(TRUE); // totally reset the displays.
$view = $this->view->clone_view();
$args = $this->get_option('inherit_arguments') ? $this->view->args : array();
......
......@@ -138,24 +138,7 @@ class view extends views_db_object {
function init_display($reset = FALSE) {
// The default display is always the first one in the list.
if (isset($this->current_display)) {
if (!$reset) {
return TRUE;
}
else {
if (isset($this->current_display)) {
unset($this->current_display);
}
if (isset($this->display_handler)) {
unset($this->display_handler);
}
foreach ($this->display as $id => $display) {
if (isset($this->display[$id]->handler)) {
unset($this->display[$id]->handler);
}
}
}
return TRUE;
}
// Instantiate all displays
......@@ -680,12 +663,7 @@ class view extends views_db_object {
// Prepare the view with the information we have.
$this->set_arguments($args);
// Give other displays an opportunity to attach to the view.
foreach ($this->display as $id => $display) {
if (!empty($this->display[$id]->handler)) {
$this->display[$id]->handler->attach_to($this->current_display);
}
}
$this->attach_displays();
// Allow the display handler to set up for execution
$this->display_handler->pre_execute();
......@@ -711,12 +689,7 @@ class view extends views_db_object {
$this->preview = TRUE;
// Give other displays an opportunity to attach to the view.
foreach ($this->display as $id => $display) {
if (!empty($this->display[$id]->handler)) {
$this->display[$id]->handler->attach_to($this->current_display);
}
}
$this->attach_displays();
// Allow the display handler to set up for execution
$this->display_handler->pre_execute();
......@@ -725,6 +698,22 @@ class view extends views_db_object {
return $this->display_handler->preview();
}
/**
* Run attachment displays for the view.
*/
function attach_displays() {
if (!$this->display_handler->accept_attachments()) {
return;
}
// Give other displays an opportunity to attach to the view.
foreach ($this->display as $id => $display) {
if (!empty($this->display[$id]->handler)) {
$this->display[$id]->handler->attach_to($this->current_display);
}
}
}
/**
* Called to get hook_menu information from the view and the
* named display handler.
......@@ -1100,6 +1089,40 @@ class view extends views_db_object {
return $view;
}
/**
* Safely clone a view.
*
* Because views are complicated objects within objects, and PHP loves to
* do references to everything, if a View is not properly and safely
* cloned it will still have references to the original view, and can
* actually cause the original view to point to objects in the cloned
* view. This gets ugly fast.
*
* This will completely wipe a view clean so it can be considered fresh.
*/
function clone_view() {
$clone = version_compare(phpversion(), '5.0') < 0 ? $this : clone($this);
$keys = array('current_display', 'display_handler', 'build_info', 'built', 'executed', 'attachment_before', 'attachment_after');
foreach ($keys as $key) {
if (isset($clone->$key)) {
unset($clone->$key);
}
}
// shallow cloning means that all the display objects
// *were not cloned*. We must clone them ourselves.
$displays = array();
foreach ($clone->display as $id => $display) {
$displays[$id] = drupal_clone($display);
if (isset($displays[$id]->handler)) {
unset($displays[$id]->handler);
}
}
$clone->display = $displays;
return $clone;
}
/**
* Make sure the view is completely valid.
*
......
......@@ -912,14 +912,13 @@ function views_get_view($name, $reset = FALSE) {
}
elseif (empty($view) && !empty($default_view)) {
$default_view->type = t('Default');
return drupal_clone($default_view);
return $default_view->clone_view();
}
elseif (!empty($view) && !empty($default_view)) {
$view->type = t('Overridden');
return drupal_clone($view);
}
return drupal_clone($view);
return $view->clone_view();
}
/**
......@@ -1297,4 +1296,3 @@ function views_views_query_substitutions($view) {
global $language;
return array('***CURRENT_TIME***' => time(), '***CURRENT_LANGUAGE***' => $language->language);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment