Skip to content
Snippets Groups Projects
Commit c04b4c3c authored by Artem Sylchuk's avatar Artem Sylchuk Committed by Sean Blommaert
Browse files

Issue #2919092: Viewsreference embeds Views without cache, breaking Dynamic page cache

parent 995215ca
No related branches found
No related tags found
1 merge request!18Issue #2919092: Viewsreference embeds Views without cache, breaking Dynamic page cache
......@@ -2,6 +2,7 @@
namespace Drupal\viewsreference\Plugin\Field\FieldFormatter;
use Drupal\Core\Security\TrustedCallbackInterface;
use Drupal\views\Views;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
......@@ -16,7 +17,7 @@ use Drupal\Core\Form\FormStateInterface;
* field_types = {"viewsreference"}
* )
*/
class ViewsReferenceFieldFormatter extends FormatterBase {
class ViewsReferenceFieldFormatter extends FormatterBase implements TrustedCallbackInterface {
/**
* {@inheritdoc}
......@@ -72,8 +73,8 @@ class ViewsReferenceFieldFormatter extends FormatterBase {
foreach ($items as $delta => $item) {
$view_name = $item->getValue()['target_id'];
$display_id = $item->getValue()['display_id'];
$data = unserialize($item->getValue()['data'], ['allowed_classes' => FALSE]);
$view = Views::getView($view_name);
// Add an extra check because the view could have been deleted.
if (!is_object($view)) {
continue;
......@@ -81,40 +82,84 @@ class ViewsReferenceFieldFormatter extends FormatterBase {
$view->setDisplay($display_id);
$enabled_settings = array_filter($this->getFieldSetting('enabled_settings') ?? []);
// Add properties to the view so our hook_views_pre_build() implementation
// can alter the view. This is pretty hacky, but we need this to fix ajax
// behaviour in views. The hook_views_pre_build() needs to know if the
// view was part of a viewsreference field or not.
$view->element['#viewsreference'] = [
'data' => $data,
'enabled_settings' => $enabled_settings,
$elements[$delta] = [
'#lazy_builder' => [
static::class . '::lazyBuilder',
[
$view_name,
$display_id,
$item->getValue()['data'],
serialize($enabled_settings),
!empty(array_filter($this->getSetting('plugin_types'))),
],
],
'#create_placeholder' => TRUE,
];
}
return $elements;
}
$view->preExecute();
$view->execute($display_id);
if (!empty($view->result) || !empty($view->empty) || !empty($view->exposed_widgets)) {
// Show view if there are results or empty behaviour defined or exposed widgets.
if ($this->getSetting('plugin_types')) {
// Add a custom template if the title is available.
$title = $view->getTitle();
if (!empty($title)) {
// If the title contains tokens, we need to render the view to
// populate the rowTokens.
if (strpos($title, '{{') !== FALSE) {
$view->render();
$title = $view->getTitle();
}
$elements[$delta]['title'] = [
'#theme' => 'viewsreference__view_title',
'#title' => $title,
];
}
}
/**
* {@inheritdoc}
*/
public static function trustedCallbacks() {
return ['lazyBuilder'];
}
$render_array = $view->buildRenderable($display_id, $view->args, FALSE);
/**
* Lazy builder callback.
*
* @param string $view_name
* The view name.
* @param string $display_id
* The display ID.
* @param string $data
* A serialized string containing the settings data.
* @param string $enabled_settings
* A serialized string containing the enabled settings.
* @param bool $plugin_types
* Whether plugin types were enabled.
*/
public static function lazyBuilder(string $view_name, string $display_id, string $data, string $enabled_settings, bool $plugin_types): array {
$data = unserialize($data, ['allowed_classes' => FALSE]);
$enabled_settings = unserialize($enabled_settings, ['allowed_classes' => FALSE]);
$view = Views::getView($view_name);
// Add an extra check because the view could have been deleted.
if (!is_object($view)) {
return [];
}
$view->setDisplay($display_id);
// Add properties to the view so our hook_views_pre_build() implementation
// can alter the view. This is pretty hacky, but we need this to fix ajax
// behaviour in views. The hook_views_pre_build() needs to know if the
// view was part of a viewsreference field or not.
$view->element['#viewsreference'] = [
'data' => $data,
'enabled_settings' => $enabled_settings,
];
$view->preExecute();
$view->execute($display_id);
$render_array = $view->buildRenderable($display_id, $view->args, FALSE);
if ($plugin_types) {
if (!empty($view->result) || !empty($view->empty)) {
// Add a custom template if the title is available.
$title = $view->getTitle();
if (!empty($title)) {
// If the title contains tokens, we need to render the view to
// populate the rowTokens.
if (strpos($title, '{{') !== FALSE) {
$view->render();
$title = $view->getTitle();
}
$render_array['title'] = [
'#theme' => 'viewsreference__view_title',
'#title' => $title,
];
}
// The views_add_contextual_links() function needs the following
// information in the render array in order to attach the contextual
// links to the view.
......@@ -122,11 +167,12 @@ class ViewsReferenceFieldFormatter extends FormatterBase {
$render_array['#view_display_show_admin_links'] = $view->getShowAdminLinks();
$render_array['#view_display_plugin_id'] = $view->getDisplay()->getPluginId();
views_add_contextual_links($render_array, $render_array['#view_display_plugin_id'], $display_id);
$elements[$delta]['contents'] = $render_array;
}
}
return $elements;
// #lazy_builder can't return elements with #type, so we need to add a
// wrapper.
return [$render_array];
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment