Problem/Motivation

D7 Page Manager has the ability to create/assign arbitrary context values.

Proposed resolution

Write the API/storage for arbitrary contexts
Write an event subscriber to get them into the list of contexts
Write a UI to control them for a given page.

Remaining tasks

See resolution

User interface changes

An added UI for arbitrary context

API changes

N/A

CommentFileSizeAuthor
#80 interdiff.txt622 bytestim.plunkett
#80 2284005-static-context-80.patch30.88 KBtim.plunkett
#76 interdiff.txt5.94 KBtim.plunkett
#76 2284005-static-context-76.patch30.84 KBtim.plunkett
#72 implement_static_contexts-2284005-72.interdiff.txt6.01 KBs_leu
#72 implement_static_contexts-2284005-72.patch31.24 KBs_leu
#69 implement_static_contexts-2284005-69.patch31.25 KBs_leu
#69 implement_static_contexts-2284005-69.interdiff.txt3.47 KBs_leu
#67 implement_static_contexts-2284005-67.patch32.05 KBs_leu
#67 implement_static_contexts-2284005-67.interdiff.txt18.19 KBs_leu
#61 implement_static_contexts-2284005-61.interdiff.txt4.51 KBs_leu
#61 implement_static_contexts-2284005-61.patch34.57 KBs_leu
#59 implement_static_contexts-2284005-59.interdiff.txt31.31 KBs_leu
#59 implement_static_contexts-2284005-59.patch33.87 KBs_leu
#58 implement_static_contexts-2284005-58.interdiff.txt3.9 KBs_leu
#58 implement_static_contexts-2284005-58.patch65.18 KBs_leu
#57 implement_static_contexts-2284005-57.interdiff.txt2.37 KBs_leu
#57 implement_static_contexts-2284005-57.patch61.76 KBs_leu
#55 implement_static_contexts-2284005-55.patch30.08 KBmglaman
#51 implement_static_contexts-2284005-48-Reroll.patch30.1 KBAnushka-mp
#48 implement_static_contexts-2284005-48.patch30.6 KBAnushka-mp
#48 implement_static_contexts-2284005-48-interdiff.txt6.59 KBAnushka-mp
#45 implement_static_contexts-2284005-43.patch31.38 KBAnushka-mp
#43 implement_static_contexts-2284005-42.patch31.35 KBAnushka-mp
#41 implement_static_contexts-2284005-41.patch70.96 KBAnushka-mp
#41 implement_static_contexts-2284005-41-interdiff.txt10.27 KBAnushka-mp
#40 interdiff.txt1.48 KBmrjmd
#40 implement_static_contexts-2284005-40.patch36.41 KBmrjmd
#38 implement_static_contexts-2284005-38.patch73.98 KBAnushka-mp
#38 implement_static_contexts-2284005-38-interdiff.txt2.39 KBAnushka-mp
#36 implement_static_contexts-2284005-36-interdiff.txt4.25 KBAnushka-mp
#36 implement_static_contexts-2284005-36.patch36.21 KBAnushka-mp
#34 interdiff.txt20.52 KBrlmumford
#34 2284005-34.patch31.7 KBrlmumford
#32 interdiff.txt7.33 KBrlmumford
#32 2284005-32.patch15.89 KBrlmumford
#24 interdiff.txt2.15 KBrlmumford
#24 2284005-24.patch14.88 KBrlmumford
#19 page_manager_static_context2.png125.47 KBdasjo
#19 page_manager_static_context.png91.95 KBdasjo
#18 2284005-static-contexts-18.patch13.98 KBtim.plunkett
#17 interdiff-2284005-13-17.txt1.39 KBfrega
#17 static-context-2284005-17.patch14.29 KBfrega
#14 interdiff-2284005-13-14.txt1.33 KBfrega
#14 static-context-2284005-14.patch7.76 KBfrega
#13 static-context-2284005-13.patch14.26 KBberdir
#10 static-context-2284005-10.patch14.25 KBberdir
#9 static-context-2284005-9.patch14.65 KBberdir
#7 static-context-2284005-5-interdiff.txt1.28 KBberdir
#7 static-context-2284005-5.patch14.23 KBberdir
#5 optional-context-2287061-9-interdiff.txt1.31 KBberdir
#5 optional-context-2287061-9.patch3.89 KBberdir
#1 static-context-2284005-1.patch14.25 KBberdir

Comments

berdir’s picture

Status: Active » Needs review
StatusFileSize
new14.25 KB

First attempt at this...

Currently displayed directly on the page manager edit form, should probably move to a dialog similar to other stuff.

Currently limited to entities, with autocomplete, then it stores the UUID and then exposes it as a special context class that loads the entity when accessed.

Not possible to remove context again...

Status: Needs review » Needs work

The last submitted patch, 1: static-context-2284005-1.patch, failed testing.

berdir’s picture

Status: Needs work » Needs review

1: static-context-2284005-1.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, 1: static-context-2284005-1.patch, failed testing.

berdir’s picture

Status: Needs work » Needs review
Issue tags: +Needs tests
StatusFileSize
new3.89 KB
new1.31 KB

Didn't test the schema...

Status: Needs review » Needs work

The last submitted patch, 5: optional-context-2287061-9.patch, failed testing.

berdir’s picture

rlmumford’s picture

In Drupal 7, the static contexts are stored as part of the variant, thus each variant can have a different set of static contexts/relationships. I'm not sure, but from this patch it looks like the config is being stored at the page level.

berdir’s picture

Status: Needs work » Needs review
StatusFileSize
new14.65 KB

Re-rolled with the new context definition objects.

@rlmumford: This is a very early proof of concept, I'm fine with moving this to displays, just keeping it up to date to get some initial feedback and looking for input on how to implement it better.. not sure how extendable this should/needs to be.

berdir’s picture

StatusFileSize
new14.25 KB

Re-roll.

Status: Needs review » Needs work

The last submitted patch, 10: static-context-2284005-10.patch, failed testing.

berdir’s picture

Status: Needs work » Needs review
StatusFileSize
new14.26 KB

Another re-roll.

frega’s picture

StatusFileSize
new7.76 KB
new1.33 KB

Minor reroll as FormStateInterface cannot be accessed like an array. Patch and interdiff attached.

Status: Needs review » Needs work

The last submitted patch, 14: static-context-2284005-14.patch, failed testing.

berdir’s picture

Thanks. Patch is much smaller, I think you lost the new files in the re-roll.

+++ b/src/Form/PageEditForm.php
@@ -304,7 +304,8 @@ class PageEditForm extends PageFormBase {
-    $input = $form_state['values']['static']['selection'];
+    $values = $form_state->getValues();
+    $input = $values['static']['selection'];

I would do $input = $form_state->getValue(array('static', 'selection') here.

And directly access it from $form_state below as well.

Or $static_values = getValue('static') and then get all the values from there.

frega’s picture

Status: Needs work » Needs review
StatusFileSize
new14.29 KB
new1.39 KB

Rerolled (with missing files) as per suggestions from #15.

tim.plunkett’s picture

I need to review this properly. Here it is as a reroll for now.
Still needs tests.

dasjo’s picture

StatusFileSize
new91.95 KB
new125.47 KB

From a site builders perspective this looks pretty good.

I was able to add a static context based on a node:

You can then use it for placing content on the block page, e.g.:
- Entity view (Content)
- Entity view (User)

Also if you have multiple contexts of the same type available, you get to select which context to choose from:

rlmumford’s picture

Status: Needs review » Needs work

This seems to work on the whole except the autocomplete controller doesn't work with users as

$entity_type->getKey('label')

is an empty string. That means the autocomplete throws a fatal error.

Is there a generic entity autocomplete we can use in drupal core?

berdir’s picture

I stole the autocomplete from dynamic entity reference, which has adapted the entity reference selection plugins now, which probably fixed this for them. That doesn't really work for us, though, I think.

There is no generic autocomplete, a thing we could try is to special case users. Or consider to add a label key to users even if they also have a label callback.

rlmumford’s picture

Looked into this further, there is no core autocomplete and the User entity type does not provide any keys that we can search against. I guess this leaves a couple of options:

  1. If $entity_type->getKey('label') is don't execute query and return an empty list.
  2. If $entity_type->getKey('label') is empty exclude that entity type from the list of available contexts
  3. If $entity_type->getKey('label') is empty then don't use autocomplete for that entity and instead tell the end user to type the id in
  4. Add a custom work around for users to make the autocomplete work.
rlmumford’s picture

Hi Berdir,

Only just saw your reply. That makes sense, I'm not very keen on adding a work around for Users if we don't allow future module developers to provide a similar work around for their entity types.

rlmumford’s picture

Status: Needs work » Needs review
StatusFileSize
new14.88 KB
new2.15 KB

Here's a potential way round it. I don't know what you think, it allows us to introduce a special case for users without us embedding it somewhere completely out of reach.

Status: Needs review » Needs work

The last submitted patch, 24: 2284005-24.patch, failed testing.

rlmumford’s picture

Status: Needs work » Needs review

I'm pretty sure that test failure is a failure that is already in the code.

  /**
   * Tests changing the admin theme of a page.
   */
  protected function doTestAdminPath() {
    \Drupal::config('system.theme')->set('default', 'bartik')->save();
    $this->drupalGet('admin/foo');

I'm pretty sure you're not allowed to just set the admin theme anymore. I'm going to set this back to needs review and we should probably open another issue up for that bug.

rlmumford’s picture

rlmumford queued 24: 2284005-24.patch for re-testing.

tim.plunkett’s picture

Status: Needs review » Needs work
  1. +++ b/page_manager.module
    @@ -0,0 +1,23 @@
    +function page_manager_entity_type_build(array &$entity_types) {
    

    Why are we doing this on entity_type_build? Is it really better than just checking getKey('label') on runtime?

  2. +++ b/src/Controller/AutocompleteController.php
    @@ -0,0 +1,53 @@
    +    if ($searchField = $entity_type->get('page_manager_search_field')) {
    

    $snake_case, please.

  3. +++ b/page_manager.module
    @@ -0,0 +1,23 @@
    +	foreach ($entity_types as $key => $entity_type) {
    

    Tab, should be spaces

  4. +++ b/page_manager.module
    @@ -0,0 +1,23 @@
    +    // User's don't have a label key so use the name field.
    

    Users, not User's

  5. +++ b/src/Context/EntityLazyLoadContext.php
    @@ -0,0 +1,38 @@
    +  public function __construct(ContextDefinitionInterface $context_definition, $uuid) {
    

    Missing docblock

  6. +++ b/src/Controller/AutocompleteController.php
    @@ -0,0 +1,53 @@
    +    $matches = array();
    

    Can we use [] everywhere please?

  7. +++ b/src/Form/PageEditForm.php
    @@ -44,6 +45,84 @@ class PageEditForm extends PageFormBase {
    +      '#title' => t('Add static context'),
    

    $this->t()

  8. +++ b/src/Form/PageEditForm.php
    @@ -44,6 +45,84 @@ class PageEditForm extends PageFormBase {
    +      '#options' => \Drupal::entityManager()->getEntityTypeLabels(TRUE),
    

    Inject this

  9. +++ b/src/Form/PageEditForm.php
    @@ -204,4 +283,56 @@ class PageEditForm extends PageFormBase {
    +  public function validateStaticContext(array $form, FormStateInterface $form_state) {
    +
    +  }
    

    What's the plan for this?

rlmumford’s picture

The problem outlined in #20 can probably now be resolved using the EntityAutocomplete service introduced in #1959806: Provide a generic 'entity_autocomplete' Form API element

berdir’s picture

It is a bit more complicated due to the dynamic entity type, but I think dynamic_entity_reference solved this issue as well, so I'll look how they did it.

rlmumford’s picture

Status: Needs work » Needs review
StatusFileSize
new15.89 KB
new7.33 KB

Here's a patch. I've updated it to use the entity.autocomplete_matcher service, which removes the need for the hacky stuff added in the previous patch.

@tim.plunkett I believe I've addressed all your concerns. For (9) I just removed the function, I'm not sure whether the form needs the validation handler as if the entity selected doesn't work it just does nothing.

General Question: Do we want to move the 'Add Static Context' stuff into a dialog and move the form into a method on the EntityLazyLoadContext class so that different plugins can be selected?

berdir’s picture

I didn't check this yet, but I think there's a lot more that we can simplify with the autocomplete now that core has the entity_reference field type. I stole a lot of the code from dynamic_entity_reference initially, so we should look at what they did: https://www.drupal.org/project/issues/dynamic_entity_reference, specifically this issue: https://www.drupal.org/node/2411981. Which, as you can see, no longer needs a custom autocomplete controller.

Alternatively, we could also just add some #ajax on the entity type selection and then replace the autocomplete widget with an ajax callback. The we don't need custom JS at all I think.

General Question: Do we want to move the 'Add Static Context' stuff into a dialog and move the form into a method on the EntityLazyLoadContext class so that different plugins can be selected?

+1 on moving it to a modal, it uses a lot of space right now.

I don't really get the second part, or how you want to do it. We certainly need to allow adding other things as well, and make that pluggable somehow, but I don't think adding something to EntityLazyLoadContext would help, as that is already entity specific.

I guess a proper UI/workflow would look like this:

1. An [Add context] button that opens a modal
2. That allows to select you what kind of context, this needs to be pluggable/extendable somehow. Right now, it would just be Entity.
3. After selecting that, then you get the current form with type and autocomplete selection

I'm not sure how much we want to do in this issue for 2. Defining an API/Event/plugins for this might delay this quite a bit, the best option might be to simply hardcode the form for the moment, and refactor it in a follow-up issue.

rlmumford’s picture

StatusFileSize
new31.7 KB
new20.52 KB

Attached is a patch that puts the Add Static context form into a dialog as well as adding "Edit" and "Delete" operations.

I've also added methods to the Page class for CRUD on static contexts. I'm not very happy with these, but they work for now and can be made to use a PluginCollection if/when we make the Static Contexts bit pluggable.

I don't really get the second part, or how you want to do it. We certainly need to allow adding other things as well, and make that pluggable somehow, but I don't think adding something to EntityLazyLoadContext would help, as that is already entity specific.

I meant that we the EntityLazyLoadContext would become an example of a "ConfigurableContext" Plugin. Is that clearer?

Defining an API/Event/plugins for this might delay this quite a bit, the best option might be to simply hardcode the form for the moment, and refactor it in a follow-up issue.

I agree with this. We can make the plugin in another issue. The plugin probably want's to be provided by another module/core anyway? Configurable contexts are going to be used by other modules (I'm thinking mini-panels) that don't depend on Page Manager at the moment.

berdir’s picture

Status: Needs review » Needs work
  1. +++ b/page_manager.routing.yml
    @@ -181,3 +207,10 @@ page_manager.selection_condition_delete:
    +
    +page_manager.autocomplete_entity:
    +  path: '/page_manager/autocomplete/{entity_type_id}'
    +  defaults:
    +    _controller: '\Drupal\page_manager\Controller\AutocompleteController::autocompleteEntity'
    +  requirements:
    +    _permission: 'administer pages'
    

    goal is still to get rid of this I think :)

  2. +++ b/src/Entity/Page.php
    @@ -278,6 +288,62 @@ class Page extends ConfigEntityBase implements PageInterface {
    +    $static_contexts = $this->getStaticContexts();
    +    foreach ($static_contexts as $key => $static_context) {
    +      if ($static_context['name'] == $name) {
    +        $static_contexts[$key] = $configuration;
    +      }
    +    }
    +    $this->set('static_context', $static_contexts);
    

    That's a lot of code (and methods) just to avoid looking at $this->static_context directly, IMHO, that's not worth it?

  3. +++ b/src/EventSubscriber/StaticContext.php
    @@ -0,0 +1,52 @@
    +    $static_contexts = $executable->getPage()->get('static_context');
    

    and it's not yet used here.

  4. +++ b/src/Form/PageEditForm.php
    @@ -204,4 +309,52 @@ class PageEditForm extends PageFormBase {
    +  /**
    +   * Form submit callback to add a context reference.
    +   */
    +  public function submitStaticContext(array $form, FormStateInterface $form_state) {
    +    $input = $form_state->getValue(['static', 'selection']);
    +
    +    // Take "label (entity id)', match the ID from parenthesis when it's a
    +    // number.
    +    if (preg_match("/.+\((\d+)\)/", $input, $matches)) {
    +      $match = $matches[1];
    +    }
    +    // Match the ID when it's a string (e.g. for config entity types).
    

    this shouldn't be needed anymore unless we still call it from the new methods, but I guess not?

I'll see what I can do about those missing tests :)

Anushka-mp’s picture

Status: Needs work » Needs review
StatusFileSize
new36.21 KB
new4.25 KB

Tests added to test the static context.
Some bugs found and fixed.

berdir’s picture

Status: Needs review » Needs work
Issue tags: -Needs tests
  1. +++ b/src/Form/StaticContextFormBase.php
    @@ -153,6 +153,12 @@ abstract class StaticContextFormBase extends FormBase {
    +      $form_state->setError($form, t('Invalid entity type %entity_type', array('%entity_type' => $input)));
    

    Invalid entity, not entity type.

    Also, bonus points for something like @entity_type_label, based on $entity_type->getLabel()

  2. +++ b/src/Tests/PageManagerAdminTest.php
    @@ -345,6 +346,64 @@ class PageManagerAdminTest extends WebTestBase {
    +    $this->assertText(t('Entity view (User)'));
    +    $this->assertText(t('Member for'));
    

    As discussed, add a comment here, that viewing a user does not not actually display anything that we can identify as belonging to the right user. But just by showing that the block is here and is being rendered should be enough to test that the context is working.

  3. +++ b/src/Tests/PageManagerAdminTest.php
    @@ -345,6 +346,64 @@ class PageManagerAdminTest extends WebTestBase {
    +      'context[name]' => 'test_context',
    +      'context[label]' => 'Test context edited',
    +      'context[entity_type]' => 'user',
    +      'context[selection]' => 'administrator ' . '(' . $this->loggedInUser->id() . ')',
    

    I'm not sure if the name should be editable and what happens if you do that.

Anushka-mp’s picture

Entity type label added instead of 'entity'. comment added in the test as suggested.
the name also edited and asserted.

Anushka-mp’s picture

Status: Needs work » Needs review
mrjmd’s picture

StatusFileSize
new36.41 KB
new1.48 KB

Fixed some wording and removed trailing whitespace from patch in #38.

Anushka-mp’s picture

As discussed with Berdir,
Custom autocorrect plugins dropped and the entity_autocomplete form element used.
formValidation dropped from StaticContextFormBase (no longer required)
Tests corrected accordingly and comment modification from #40

Status: Needs review » Needs work

The last submitted patch, 41: implement_static_contexts-2284005-41.patch, failed testing.

Anushka-mp’s picture

Status: Needs work » Needs review
StatusFileSize
new31.35 KB

Messed up patch! Interdiff is fine

Status: Needs review » Needs work

The last submitted patch, 43: implement_static_contexts-2284005-42.patch, failed testing.

Anushka-mp’s picture

StatusFileSize
new31.38 KB

Hm.. I dropped a test line accidentally. added it again

Anushka-mp’s picture

Status: Needs work » Needs review
berdir’s picture

Status: Needs review » Needs work
  1. +++ b/src/Form/PageEditForm.php
    @@ -19,6 +23,36 @@ use Drupal\Core\Url;
    +   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
    +   *   The entity manager.
    +   */
    +  public function __construct(QueryFactory $entity_query, EntityManagerInterface $entity_manager) {
    +    $this->entityQuery = $entity_query;
    +    $this->entityManager = $entity_manager;
    +  }
    ...
    +  /**
    +   * {@inheritdoc}
    +   */
    +  public static function create(ContainerInterface $container) {
    +    return new static(
    +      $container->get('entity.query'),
    +      $container->get('entity.manager')
    +    );
    +  }
    

    Are these still used?

  2. +++ b/src/Form/PageEditForm.php
    @@ -204,4 +309,39 @@ class PageEditForm extends PageFormBase {
    +  /**
    +   * Form submit callback to add a context reference.
    +   */
    +  public function submitStaticContext(array $form, FormStateInterface $form_state) {
    +    $input = $form_state->getValue(['static', 'selection']);
    +
    +    // Take "label (entity id)', match the ID from parenthesis when it's a
    +    // number.
    +    if (preg_match("/.+\((\d+)\)/", $input, $matches)) {
    +      $match = $matches[1];
    

    This is a left-over, can be removed.

  3. +++ b/src/Form/StaticContextFormBase.php
    @@ -0,0 +1,213 @@
    +    $form['context'] = [
    +      '#type' => 'details',
    +      '#title' => $this->t('Add static context'),
    +      '#open' => TRUE,
    +      '#tree' => TRUE,
    +    ];
    +
    

    The details element here seems strange. It made sense when it was part of the whole page, but it doesn't server a purpose here. I'd drop this completely.

  4. +++ b/src/Tests/PageManagerAdminTest.php
    @@ -38,7 +38,7 @@ class PageManagerAdminTest extends WebTestBase {
     
    -    $this->drupalLogin($this->drupalCreateUser(['administer pages', 'access administration pages', 'view the administration theme']));
    +    $this->drupalLogin($this->drupalCreateUser(['administer pages', 'access administration pages', 'view the administration theme']), 'administrator');
    

    I'm not sure what this is, drupalLogin() only has one argument?

Anushka-mp’s picture

Status: Needs work » Needs review
StatusFileSize
new6.59 KB
new30.6 KB

Leftovers dropped. context form element dropped and changes made to the forms and tests accordingly. the second argument should be inside the createUser method :-)

Status: Needs review » Needs work

The last submitted patch, 48: implement_static_contexts-2284005-48.patch, failed testing.

Anushka-mp’s picture

Status: Needs work » Needs review
StatusFileSize
new30.1 KB

Status: Needs review » Needs work

The last submitted patch, 51: implement_static_contexts-2284005-48-Reroll.patch, failed testing.

wim leers’s picture

#2375695-22: Condition plugins should provide cache contexts AND cacheability metadata needs to be exposed pointed out that it's not clear how to make this set the right cache contexts. Could you explain in a bit more detail the obstacles you're seeing?

mglaman’s picture

Status: Needs work » Needs review
StatusFileSize
new30.08 KB

Reroll to get an applicable patch.

s_leu’s picture

Here's a re-roll of the patch which passes all tests.

s_leu’s picture

Adding another patch that includes a basic test for the static context feature.

s_leu’s picture

Removed the accidentally included patch file from the patch.

berdir’s picture

Status: Needs review » Needs work

Just reviewing the interdiffs.

+++ b/src/Context/EntityLazyLoadContext.php
@@ -42,5 +42,14 @@ class EntityLazyLoadContext extends Context {
+    if (!$this->contextValue) {
+      $this->getContextValue();
+    }

Might be useful to add a comment here. Something like // Ensure that the entity is loaded before checking if it exists.

  1. +++ b/src/Tests/StaticContextTest.php
    @@ -0,0 +1,101 @@
    +    // Create a node, and check its page.
    +    $node = $this->drupalCreateNode(['type' => 'article']);
    +    $this->drupalGet('node/' . $node->id());
    +    $this->assertResponse(200);
    +    $this->assertText($node->label());
    +    $this->assertTitle($node->label() . ' | Drupal');
    

    Not sure we need the asserts here.

    Let's also create a second node and add + display them both, so we can test with multiple static contexts.

  2. +++ b/src/Tests/StaticContextTest.php
    @@ -0,0 +1,101 @@
    +    // Create a new page entity to take over node pages.
    +    $edit_page = [
    +      'label' => 'Static node context',
    

    We're not taking over anything anymore, so remove that part from the comment.

  3. +++ b/src/Tests/StaticContextTest.php
    @@ -0,0 +1,101 @@
    +    $this->drupalPostForm('admin/structure/page_manager/add', $edit_page, 'Save');
    +    // Their pages should now use the default 404 display variant.
    +    $this->drupalGet('static-context');
    +    $this->assertResponse(404);
    +    $this->assertNoText($node->label());
    +
    +    //$this->drupalGet('static-context');
    +    // Add a static context to the page.
    +    $this->drupalGet('admin/structure/page_manager/manage/' . $edit_page['id']);
    

    The drupalGet() + asserts here can be removed I think. Then you're already on the right page and don't have to load gain.

s_leu’s picture

Status: Needs work » Needs review
StatusFileSize
new34.57 KB
new4.51 KB

Ok applied the changes as suggested.

The last submitted patch, 55: implement_static_contexts-2284005-55.patch, failed testing.

The last submitted patch, 55: implement_static_contexts-2284005-55.patch, failed testing.

The last submitted patch, 55: implement_static_contexts-2284005-55.patch, failed testing.

berdir’s picture

Status: Needs review » Needs work

Looks pretty good. Some feedback below.

  1. +++ b/config/schema/page_manager.schema.yml
    @@ -29,6 +29,25 @@ page_manager.page.*:
    +    static_context:
    +      type: sequence
    +      label: Static context list
    +      sequence:
    +        - type: mapping
    +          label: 'Static context'
    +          mapping:
    +            machine_name:
    +              type: string
    +              label: 'Machine-readable name of the context'
    +            label:
    +              type: label
    

    We could also store this keyed by the machine name I guess. Not sure what's better, that would make some of the methods easier to implement and the machine name has to be unique anyway.

  2. +++ b/page_manager.routing.yml
    @@ -82,6 +82,32 @@ page_manager.access_condition_delete:
     
    +#### Static Contexts
    +
    +page_manager.static_context_add:
    

    Does routing.yml have similar comments elsewhere? If not then I'm not sure we should keep it.

  3. +++ b/src/Form/PageEditForm.php
    @@ -204,4 +307,24 @@ class PageEditForm extends PageFormBase {
    +  /**
    +   * Form submit callback to add a context reference.
    +   */
    +  public function submitStaticContext(array $form, FormStateInterface $form_state) {
    +    $input = $form_state->getValue(['static', 'selection']);
    +    $entity_type = $form_state->getValue(['static', 'entity_type']);
    +    $entity = $this->entityManager->getStorage($entity_type)->load($input);
    +    $new_static = [
    +      'machine_name' => $form_state->getValue(['static', 'machine_name']),
    +      'label' => $form_state->getValue(['static', 'label']),
    +      'type' => 'entity:' . $entity_type,
    +      'value' => $entity->uuid(),
    

    As commented before, This method is a left-over from the old code and can be removed.

  4. +++ b/src/Form/StaticContextDeleteForm.php
    @@ -0,0 +1,80 @@
    +    return $this->t('Are you sure you want to delete the static context %name?', ['%name' => $this->staticContext['label']]);
    

    placeholder should use label, not name. Possibly elsewhere too.

    In case we change to key the contexts by name then this would have to just store the machine name and fetch it from the page if needed.

  5. +++ b/src/Form/StaticContextFormBase.php
    @@ -0,0 +1,215 @@
    +      '#required' => FALSE,
    

    machine name is also required.

  6. +++ b/src/Form/StaticContextFormBase.php
    @@ -0,0 +1,215 @@
    +    if ($form_state->hasValue(['entity_type'])) {
    +      $entity_type = $form_state->getValue(['entity_type']);
    

    We can remove the [] here.

  7. +++ b/src/Tests/PageManagerAdminTest.php
    @@ -379,6 +380,64 @@ class PageManagerAdminTest extends WebTestBase {
    +   * Tests adding static context page.
    +   */
    +  protected function doTestStaticContext() {
    +    $this->drupalGet('admin/structure/page_manager/manage/foo');
    

    Looks like there were already some tests here, let's remove them, we don't need both. I prefer using nodes as they are easier to validate that they actually show up.

  8. +++ b/src/Tests/StaticContextTest.php
    @@ -0,0 +1,122 @@
    +    // Open the page and verify that the node from the static context is there.
    +    $this->drupalGet($edit_page['path']);
    +    $this->assertText($node->label());
    +    $this->assertText($node->get('body')->getValue()[0]['value']);
    +    $this->assertText($node2->label());
    +    $this->assertText($node2->get('body')->getValue()[0]['value']);
    

    Just like the existing test, this should also testing editing and deleting static context. You could e.g. switch one context to use the other node and then you should see the same node twice on the page.

s_leu’s picture

Status: Needs work » Needs review
StatusFileSize
new18.19 KB
new32.05 KB

placeholder should use label, not name. Possibly elsewhere too.

I replaced this for the static context related output. But there are other parts of code which use this wrong pattern, for example it can be found in src/Form/PageDeleteForm.php:

return $this->t('Are you sure you want to delete the page %name?', ['%name' => $this->entity->label()]);

I applied the other suggested changes and combined the tests.

berdir’s picture

Status: Needs review » Needs work

I think is finally close. A few more minor things below.

  1. +++ b/page_manager.routing.yml
    @@ -82,8 +78,6 @@ page_manager.access_condition_delete:
     
    -#### Static Contexts
    -
     page_manager.static_context_add:
    

    I think I was unclear here :) What I was saying is we shouldn't add a document like this *unless* other places in that file alraedy do it. They clearly do, so we should keep them and re-add ours.

  2. +++ b/src/Entity/Page.php
    @@ -341,11 +323,7 @@ class Page extends ConfigEntityBase implements PageInterface {
       public function removeStaticContext($name) {
         $static_contexts = $this->getStaticContexts();
    -    foreach ($static_contexts as $key => $static_context) {
    -      if ($static_context['machine_name'] == $name) {
    -        unset($static_contexts[$key]);
    -      }
    -    }
    +    unset($static_contexts[$name]);
         $this->set('static_context', $static_contexts);
         return $this;
    

    This can also be simplified to directly work on $this->static_context now.

  3. +++ b/src/Form/StaticContextEditForm.php
    @@ -40,27 +39,14 @@ class StaticContextEditForm extends StaticContextFormBase {
    +    // The machine name mustn't be changed after a static context was created.
    +    $form['machine_name'] = array(
    +      '#type' => 'value',
    +      '#value' => $name,
    +    );
    

    I think this can be simplified a bit to:
    // The machine name of an existing context is read-only.

  4. +++ b/src/Form/StaticContextFormBase.php
    @@ -92,12 +92,12 @@ abstract class StaticContextFormBase extends FormBase {
    -      '#default_value' => $this->staticContext['machine_name'] ?: '',
    +      '#default_value' => $name ? $name : '',
    

    $name is an empty string for the add form so you can just use $name I think?

  5. +++ b/src/Tests/StaticContextTest.php
    @@ -117,6 +117,60 @@ class StaticContextTest extends WebTestBase {
         $this->assertText($node2->get('body')->getValue()[0]['value']);
    +
    +
    +
    +
    +    // Change the second static context to the first node.
    

    One empty line should be enough ere.

s_leu’s picture

Status: Needs work » Needs review
StatusFileSize
new3.47 KB
new31.25 KB

Here's another patch with the suggested changes.

I think I was unclear here :) What I was saying is we shouldn't add a document like this *unless* other places in that file alraedy do it

I agree, it was a bit unclear. I interpreted "other places" as other modules, for example core modules which don't use such comments, so i removed them. Anyway, re-added them now.

tim.plunkett’s picture

Looking good!

  1. +++ b/src/Context/EntityLazyLoadContext.php
    @@ -0,0 +1,56 @@
    +      $this->contextValue = \Drupal::entityManager()->loadEntityByUuid(substr($this->contextDefinition->getDataType(), 7), $this->uuid);
    

    Can the substr call be on another line, either with a very clear variable name, or a comment?

    Also I guess these value classes aren't injectable, but maybe have a getEntityManager() protected method, so would could one day unit test this?

  2. +++ b/src/Entity/Page.php
    @@ -287,6 +297,38 @@ class Page extends ConfigEntityBase implements PageInterface {
    +    return $this->get('static_context');
    

    Most of the places in this class we don't bother with $this->get() and none of these other methods do either...

  3. +++ b/src/EventSubscriber/StaticContext.php
    @@ -0,0 +1,52 @@
    +    $static_contexts = $executable->getPage()->get('static_context');
    

    Shouldn't this use the getStaticContexts() method?

  4. +++ b/src/Form/PageEditForm.php
    @@ -19,6 +21,36 @@ use Drupal\Core\Url;
    +    $this->entityQuery = $entity_query;
    

    Can we be more clear here and use parent::__construct($entity_query) instead?

  5. +++ b/src/Form/StaticContextFormBase.php
    @@ -0,0 +1,214 @@
    +  public function rebuildSubmit($form, FormStateInterface $form_state){
    ...
    +  public function updateEntityType($form, FormStateInterface $form_state){
    

    Missing docblocks and spaces between ) and {

  6. +++ b/src/Tests/PageManagerAdminTest.php
    @@ -38,7 +38,7 @@ class PageManagerAdminTest extends WebTestBase {
    -    $this->drupalLogin($this->drupalCreateUser(['administer pages', 'access administration pages', 'view the administration theme']));
    +    $this->drupalLogin($this->drupalCreateUser(['administer pages', 'access administration pages', 'view the administration theme'], 'administrator'));
    

    Why do we care what the name is?

berdir’s picture

1. We can actually inject I think since we create those objects ourself.
6. That's a left-over from an old test where we used the user as context. Can be reverted.

s_leu’s picture

Here's the new patch including the suggested changes/improvements

berdir’s picture

Status: Needs review » Reviewed & tested by the community

I think this addresses #70, time to get it in? :)

tim.plunkett’s picture

I went to commit this today, but noticed that the autocomplete for adding a static context is completely non-functional (at least for me).
Can you double check that for me?

berdir’s picture

That seems to be a core issue: #2536456: Autocomplete is broken (its JS is not loaded). So they're probably broken everywhere, not just here.

tim.plunkett’s picture

StatusFileSize
new30.84 KB
new5.94 KB

Yep, that was exactly it. Thanks for your patience!

Posting a patch with my tweaks, assuming it passes I'll commit this.

tim.plunkett’s picture

  1. +++ b/page_manager.services.yml
    @@ -11,6 +11,7 @@ services:
    +    arguments: ['@entity.manager']
    
    +++ b/src/EventSubscriber/StaticContext.php
    @@ -32,7 +50,7 @@ public function onPageContext(PageManagerContextEvent $event) {
    -      $context = new EntityLazyLoadContext(new ContextDefinition($static_context['type'], $static_context['label']), \Drupal::entityManager(), $static_context['value']);
    +      $context = new EntityLazyLoadContext(new ContextDefinition($static_context['type'], $static_context['label']), $this->entityManager, $static_context['value']);
    

    DI++

  2. +++ b/src/Context/EntityLazyLoadContext.php
    @@ -7,9 +7,9 @@
    -use Drupal\Component\Plugin\Context\ContextDefinitionInterface;
    ...
    +use Drupal\Core\Plugin\Context\ContextDefinitionInterface;
    
    @@ -23,15 +23,17 @@ class EntityLazyLoadContext extends Context {
    -   * @param \Drupal\Component\Plugin\Context\ContextDefinitionInterface $context_definition
    +   * @param \Drupal\Core\Plugin\Context\ContextDefinitionInterface $context_definition
    

    This was the wrong interface

  3. +++ b/src/Entity/Page.php
    @@ -308,6 +308,7 @@ public function getStaticContext($name) {
    +    return [];
    

    This doesn't say it returns NULL, should it?

  4. +++ b/src/Form/PageEditForm.php
    @@ -21,36 +21,6 @@
    -  protected $entityManager;
    

    Every EntityForm gets the entity manager via setter injection.

berdir’s picture

Changes look good, missed the missing injection in StaticContexts.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 76: 2284005-static-context-76.patch, failed testing.

tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new30.88 KB
new622 bytes

Hmm, why didn't this fail before?

  • tim.plunkett committed 1814c3a on 8.x-1.x
    Issue #2284005 by s_leu, Anushka-mp, Berdir, rlmumford, tim.plunkett,...
tim.plunkett’s picture

Status: Needs review » Fixed

Oh well, committed anyway :)

Thanks all for pushing on this!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.