You are here

public function RendererPlaceholdersTest::providerPlaceholders in Drupal 10

Same name and namespace in other branches
  1. 8 core/tests/Drupal/Tests/Core/Render/RendererPlaceholdersTest.php \Drupal\Tests\Core\Render\RendererPlaceholdersTest::providerPlaceholders()
  2. 9 core/tests/Drupal/Tests/Core/Render/RendererPlaceholdersTest.php \Drupal\Tests\Core\Render\RendererPlaceholdersTest::providerPlaceholders()

Provides the two classes of placeholders: cacheable and uncacheable.

I.e. with or without #cache[keys].

Also, different types:

  • A) automatically generated placeholder

    • 1) manually triggered (#create_placeholder = TRUE)
    • 2) automatically triggered (based on max-age = 0 at the top level)
    • 3) automatically triggered (based on high cardinality cache contexts at the top level)
    • 4) automatically triggered (based on high-invalidation frequency cache tags at the top level)
    • 5) automatically triggered (based on max-age = 0 in its subtree, i.e. via bubbling)
    • 6) automatically triggered (based on high cardinality cache contexts in its subtree, i.e. via bubbling)
    • 7) automatically triggered (based on high-invalidation frequency cache tags in its subtree, i.e. via bubbling)
  • B) manually generated placeholder

So, in total 2*8 = 16 permutations. (On one axis: uncacheable vs. uncacheable = 2; on the other axis: A1–7 and B = 8.)

@todo Case A5 is not yet supported by core. So that makes for only 14 permutations currently, instead of 16. That will be done in https://www.drupal.org/node/2559847

Return value

array

File

core/tests/Drupal/Tests/Core/Render/RendererPlaceholdersTest.php, line 66
Contains \Drupal\Tests\Core\Render\RendererPlaceholdersTest.

Class

RendererPlaceholdersTest
@coversDefaultClass \Drupal\Core\Render\Renderer @covers \Drupal\Core\Render\RenderCache @covers \Drupal\Core\Render\PlaceholderingRenderCache @group Render

Namespace

Drupal\Tests\Core\Render

Code

public function providerPlaceholders() {
  $args = [
    $this
      ->randomContextValue(),
  ];
  $generate_placeholder_markup = function ($cache_keys = NULL) use ($args) {
    $token_render_array = [
      '#lazy_builder' => [
        'Drupal\\Tests\\Core\\Render\\PlaceholdersTest::callback',
        $args,
      ],
    ];
    if (is_array($cache_keys)) {
      $token_render_array['#cache']['keys'] = $cache_keys;
    }
    $token = Crypt::hashBase64(serialize($token_render_array));

    // \Drupal\Core\Render\Markup::create() is necessary as the render
    // system would mangle this markup. As this is exactly what happens at
    // runtime this is a valid use-case.
    return Markup::create('<drupal-render-placeholder callback="Drupal\\Tests\\Core\\Render\\PlaceholdersTest::callback" arguments="' . '0=' . $args[0] . '" token="' . $token . '"></drupal-render-placeholder>');
  };
  $extract_placeholder_render_array = function ($placeholder_render_array) {
    return array_intersect_key($placeholder_render_array, [
      '#lazy_builder' => TRUE,
      '#cache' => TRUE,
    ]);
  };

  // Note the presence of '#create_placeholder'.
  $base_element_a1 = [
    '#attached' => [
      'drupalSettings' => [
        'foo' => 'bar',
      ],
    ],
    'placeholder' => [
      '#cache' => [
        'contexts' => [],
      ],
      '#create_placeholder' => TRUE,
      '#lazy_builder' => [
        'Drupal\\Tests\\Core\\Render\\PlaceholdersTest::callback',
        $args,
      ],
    ],
  ];

  // Note the absence of '#create_placeholder', presence of max-age=0 at the
  // top level.
  $base_element_a2 = [
    '#attached' => [
      'drupalSettings' => [
        'foo' => 'bar',
      ],
    ],
    'placeholder' => [
      '#cache' => [
        'contexts' => [],
        'max-age' => 0,
      ],
      '#lazy_builder' => [
        'Drupal\\Tests\\Core\\Render\\PlaceholdersTest::callback',
        $args,
      ],
    ],
  ];

  // Note the absence of '#create_placeholder', presence of high cardinality
  // cache context at the top level.
  $base_element_a3 = [
    '#attached' => [
      'drupalSettings' => [
        'foo' => 'bar',
      ],
    ],
    'placeholder' => [
      '#cache' => [
        'contexts' => [
          'user',
        ],
      ],
      '#lazy_builder' => [
        'Drupal\\Tests\\Core\\Render\\PlaceholdersTest::callback',
        $args,
      ],
    ],
  ];

  // Note the absence of '#create_placeholder', presence of high-invalidation
  // frequency cache tag at the top level.
  $base_element_a4 = [
    '#attached' => [
      'drupalSettings' => [
        'foo' => 'bar',
      ],
    ],
    'placeholder' => [
      '#cache' => [
        'contexts' => [],
        'tags' => [
          'current-temperature',
        ],
      ],
      '#lazy_builder' => [
        'Drupal\\Tests\\Core\\Render\\PlaceholdersTest::callback',
        $args,
      ],
    ],
  ];

  // Note the absence of '#create_placeholder', presence of max-age=0 created
  // by the #lazy_builder callback.
  // @todo in https://www.drupal.org/node/2559847
  $base_element_a5 = [];

  // Note the absence of '#create_placeholder', presence of high cardinality
  // cache context created by the #lazy_builder callback.
  // @see \Drupal\Tests\Core\Render\PlaceholdersTest::callbackPerUser()
  $base_element_a6 = [
    '#attached' => [
      'drupalSettings' => [
        'foo' => 'bar',
      ],
    ],
    'placeholder' => [
      '#cache' => [
        'contexts' => [],
      ],
      '#lazy_builder' => [
        'Drupal\\Tests\\Core\\Render\\PlaceholdersTest::callbackPerUser',
        $args,
      ],
    ],
  ];

  // Note the absence of '#create_placeholder', presence of high-invalidation
  // frequency cache tag created by the #lazy_builder callback.
  // @see \Drupal\Tests\Core\Render\PlaceholdersTest::callbackTagCurrentTemperature()
  $base_element_a7 = [
    '#attached' => [
      'drupalSettings' => [
        'foo' => 'bar',
      ],
    ],
    'placeholder' => [
      '#cache' => [
        'contexts' => [],
      ],
      '#lazy_builder' => [
        'Drupal\\Tests\\Core\\Render\\PlaceholdersTest::callbackTagCurrentTemperature',
        $args,
      ],
    ],
  ];

  // Note the absence of '#create_placeholder', but the presence of
  // '#attached[placeholders]'.
  $base_element_b = [
    '#markup' => $generate_placeholder_markup(),
    '#attached' => [
      'drupalSettings' => [
        'foo' => 'bar',
      ],
      'placeholders' => [
        (string) $generate_placeholder_markup() => [
          '#lazy_builder' => [
            'Drupal\\Tests\\Core\\Render\\PlaceholdersTest::callback',
            $args,
          ],
        ],
      ],
    ],
  ];
  $keys = [
    'placeholder',
    'output',
    'can',
    'be',
    'render',
    'cached',
    'too',
  ];
  $cases = [];

  // Case one: render array that has a placeholder that is:
  // - automatically created, but manually triggered (#create_placeholder = TRUE)
  // - uncacheable
  $element_without_cache_keys = $base_element_a1;
  $expected_placeholder_render_array = $extract_placeholder_render_array($base_element_a1['placeholder']);
  $cases[] = [
    $element_without_cache_keys,
    $args,
    $expected_placeholder_render_array,
    FALSE,
    [],
    [],
    [],
  ];

  // Case two: render array that has a placeholder that is:
  // - automatically created, but manually triggered (#create_placeholder = TRUE)
  // - cacheable
  $element_with_cache_keys = $base_element_a1;
  $element_with_cache_keys['placeholder']['#cache']['keys'] = $keys;
  $expected_placeholder_render_array['#cache']['keys'] = $keys;
  $cases[] = [
    $element_with_cache_keys,
    $args,
    $expected_placeholder_render_array,
    $keys,
    [],
    [],
    [
      '#markup' => '<p>This is a rendered placeholder!</p>',
      '#attached' => [
        'drupalSettings' => [
          'dynamic_animal' => $args[0],
        ],
      ],
      '#cache' => [
        'contexts' => [],
        'tags' => [],
        'max-age' => Cache::PERMANENT,
      ],
    ],
  ];

  // Case three: render array that has a placeholder that is:
  // - automatically created, and automatically triggered due to max-age=0
  // - uncacheable
  $element_without_cache_keys = $base_element_a2;
  $expected_placeholder_render_array = $extract_placeholder_render_array($base_element_a2['placeholder']);
  $cases[] = [
    $element_without_cache_keys,
    $args,
    $expected_placeholder_render_array,
    FALSE,
    [],
    [],
    [],
  ];

  // Case four: render array that has a placeholder that is:
  // - automatically created, but automatically triggered due to max-age=0
  // - cacheable
  $element_with_cache_keys = $base_element_a2;
  $element_with_cache_keys['placeholder']['#cache']['keys'] = $keys;
  $expected_placeholder_render_array['#cache']['keys'] = $keys;
  $cases[] = [
    $element_with_cache_keys,
    $args,
    $expected_placeholder_render_array,
    FALSE,
    [],
    [],
    [],
  ];

  // Case five: render array that has a placeholder that is:
  // - automatically created, and automatically triggered due to high
  //   cardinality cache contexts
  // - uncacheable
  $element_without_cache_keys = $base_element_a3;
  $expected_placeholder_render_array = $extract_placeholder_render_array($base_element_a3['placeholder']);
  $cases[] = [
    $element_without_cache_keys,
    $args,
    $expected_placeholder_render_array,
    FALSE,
    [],
    [],
    [],
  ];

  // Case six: render array that has a placeholder that is:
  // - automatically created, and automatically triggered due to high
  //   cardinality cache contexts
  // - cacheable
  $element_with_cache_keys = $base_element_a3;
  $element_with_cache_keys['placeholder']['#cache']['keys'] = $keys;
  $expected_placeholder_render_array['#cache']['keys'] = $keys;

  // The CID parts here consist of the cache keys plus the 'user' cache
  // context, which in this unit test is simply the given cache context token,
  // see \Drupal\Tests\Core\Render\RendererTestBase::setUp().
  $cid_parts = array_merge($keys, [
    'user',
  ]);
  $cases[] = [
    $element_with_cache_keys,
    $args,
    $expected_placeholder_render_array,
    $cid_parts,
    [],
    [],
    [
      '#markup' => '<p>This is a rendered placeholder!</p>',
      '#attached' => [
        'drupalSettings' => [
          'dynamic_animal' => $args[0],
        ],
      ],
      '#cache' => [
        'contexts' => [
          'user',
        ],
        'tags' => [],
        'max-age' => Cache::PERMANENT,
      ],
    ],
  ];

  // Case seven: render array that has a placeholder that is:
  // - automatically created, and automatically triggered due to high
  //   invalidation frequency cache tags
  // - uncacheable
  $element_without_cache_keys = $base_element_a4;
  $expected_placeholder_render_array = $extract_placeholder_render_array($base_element_a4['placeholder']);
  $cases[] = [
    $element_without_cache_keys,
    $args,
    $expected_placeholder_render_array,
    FALSE,
    [],
    [],
    [],
  ];

  // Case eight: render array that has a placeholder that is:
  // - automatically created, and automatically triggered due to high
  //   invalidation frequency cache tags
  // - cacheable
  $element_with_cache_keys = $base_element_a4;
  $element_with_cache_keys['placeholder']['#cache']['keys'] = $keys;
  $expected_placeholder_render_array['#cache']['keys'] = $keys;
  $cases[] = [
    $element_with_cache_keys,
    $args,
    $expected_placeholder_render_array,
    $keys,
    [],
    [],
    [
      '#markup' => '<p>This is a rendered placeholder!</p>',
      '#attached' => [
        'drupalSettings' => [
          'dynamic_animal' => $args[0],
        ],
      ],
      '#cache' => [
        'contexts' => [],
        'tags' => [
          'current-temperature',
        ],
        'max-age' => Cache::PERMANENT,
      ],
    ],
  ];

  // Case nine: render array that DOES NOT have a placeholder that is:
  // - NOT created, despite max-age=0 that is bubbled
  // - uncacheable
  // (because the render element with #lazy_builder does not have #cache[keys]
  // and hence the max-age=0 bubbles up further)
  // @todo in https://www.drupal.org/node/2559847
  // Case ten: render array that has a placeholder that is:
  // - automatically created, and automatically triggered due to max-age=0
  //   that is bubbled
  // - cacheable
  // @todo in https://www.drupal.org/node/2559847
  // Case eleven: render array that DOES NOT have a placeholder that is:
  // - NOT created, despite high cardinality cache contexts that are bubbled
  // - uncacheable
  $element_without_cache_keys = $base_element_a6;
  $expected_placeholder_render_array = $extract_placeholder_render_array($base_element_a6['placeholder']);
  $cases[] = [
    $element_without_cache_keys,
    $args,
    $expected_placeholder_render_array,
    FALSE,
    [
      'user',
    ],
    [],
    [],
  ];

  // Case twelve: render array that has a placeholder that is:
  // - automatically created, and automatically triggered due to high
  //   cardinality cache contexts that are bubbled
  // - cacheable
  $element_with_cache_keys = $base_element_a6;
  $element_with_cache_keys['placeholder']['#cache']['keys'] = $keys;
  $expected_placeholder_render_array['#cache']['keys'] = $keys;
  $cases[] = [
    $element_with_cache_keys,
    $args,
    $expected_placeholder_render_array,
    $keys,
    [
      'user',
    ],
    [],
    [
      '#markup' => '<p>This is a rendered placeholder!</p>',
      '#attached' => [
        'drupalSettings' => [
          'dynamic_animal' => $args[0],
        ],
      ],
      '#cache' => [
        'contexts' => [
          'user',
        ],
        'tags' => [],
        'max-age' => Cache::PERMANENT,
      ],
    ],
  ];

  // Case thirteen: render array that has a placeholder that is:
  // - automatically created, and automatically triggered due to high
  //   invalidation frequency cache tags that are bubbled
  // - uncacheable
  $element_without_cache_keys = $base_element_a7;
  $expected_placeholder_render_array = $extract_placeholder_render_array($base_element_a7['placeholder']);
  $cases[] = [
    $element_without_cache_keys,
    $args,
    $expected_placeholder_render_array,
    FALSE,
    [],
    [
      'current-temperature',
    ],
    [],
  ];

  // Case fourteen: render array that has a placeholder that is:
  // - automatically created, and automatically triggered due to high
  //   invalidation frequency cache tags that are bubbled
  // - cacheable
  $element_with_cache_keys = $base_element_a7;
  $element_with_cache_keys['placeholder']['#cache']['keys'] = $keys;
  $expected_placeholder_render_array['#cache']['keys'] = $keys;
  $cases[] = [
    $element_with_cache_keys,
    $args,
    $expected_placeholder_render_array,
    $keys,
    [],
    [],
    [
      '#markup' => '<p>This is a rendered placeholder!</p>',
      '#attached' => [
        'drupalSettings' => [
          'dynamic_animal' => $args[0],
        ],
      ],
      '#cache' => [
        'contexts' => [],
        'tags' => [
          'current-temperature',
        ],
        'max-age' => Cache::PERMANENT,
      ],
    ],
  ];

  // Case fifteen: render array that has a placeholder that is:
  // - manually created
  // - uncacheable
  $x = $base_element_b;
  $expected_placeholder_render_array = $x['#attached']['placeholders'][(string) $generate_placeholder_markup()];
  unset($x['#attached']['placeholders'][(string) $generate_placeholder_markup()]['#cache']);
  $cases[] = [
    $x,
    $args,
    $expected_placeholder_render_array,
    FALSE,
    [],
    [],
    [],
  ];

  // Case sixteen: render array that has a placeholder that is:
  // - manually created
  // - cacheable
  $x = $base_element_b;
  $x['#markup'] = $placeholder_markup = $generate_placeholder_markup($keys);
  $placeholder_markup = (string) $placeholder_markup;
  $x['#attached']['placeholders'] = [
    $placeholder_markup => [
      '#lazy_builder' => [
        'Drupal\\Tests\\Core\\Render\\PlaceholdersTest::callback',
        $args,
      ],
      '#cache' => [
        'keys' => $keys,
      ],
    ],
  ];
  $expected_placeholder_render_array = $x['#attached']['placeholders'][$placeholder_markup];
  $cases[] = [
    $x,
    $args,
    $expected_placeholder_render_array,
    $keys,
    [],
    [],
    [
      '#markup' => '<p>This is a rendered placeholder!</p>',
      '#attached' => [
        'drupalSettings' => [
          'dynamic_animal' => $args[0],
        ],
      ],
      '#cache' => [
        'contexts' => [],
        'tags' => [],
        'max-age' => Cache::PERMANENT,
      ],
    ],
  ];
  return $cases;
}