Right now, the IPE is tightly coupled to Page Manager and can only edit Panels used by Page Manager's PageVariants.

We need to allow the IPE to somehow store the Panels its editing with the underlying storage of the thing providing the Panel in a generic way. I'm thinking we need a way to integrating modules (like Page Manager) to tell the IPE, "For the PanelsDisplayVariant with the ID of XYZ, use this handler/plugin/class/thinger to save it."

This will mean that not all code that can use PanelsDisplayVariants (for example, something that works with variant plugins generically) will be able to use the IPE. So, we should have some way for wrapping code to indicate that it's IPE compatible, and if it doesn't perform this secret handshake, we shouldn't show the "In-place editor" builder option.

CommentFileSizeAuthor
#22 interdiff.txt965 bytesdsnopek
#22 panels-ipe-decoupled-2636478-22.patch60.89 KBdsnopek
#20 interdiff.txt12.95 KBdsnopek
#20 panels-ipe-decoupled-2636478-20.patch60.88 KBdsnopek
#17 panels-ipe-decoupled-2636478-17.patch58.95 KBdsnopek
#15 interdiff.txt5 KBdsnopek
#15 panels-ipe-decoupled-2636478-15.patch68.61 KBdsnopek
#14 interdiff.txt3.93 KBdsnopek
#14 panels-ipe-decoupled-2636478-14.patch59.16 KBdsnopek
#11 interdiff.txt770 bytesdsnopek
#11 panels-ipe-decoupled-2636478-11.patch59.09 KBdsnopek
#10 interdiff.txt1.9 KBdsnopek
#10 panels-ipe-decoupled-2636478-10.patch59.09 KBdsnopek
#9 interdiff.txt723 bytesdsnopek
#9 panels-ipe-decoupled-2636478-8.patch59.11 KBdsnopek
#7 interdiff.txt11.64 KBdsnopek
#7 panels-ipe-decoupled-2636478-7.patch59.11 KBdsnopek
#5 interdiff.txt6.84 KBdsnopek
#5 panels-ipe-decoupled-2636478-5.patch51.23 KBdsnopek
#4 interdiff.txt28.62 KBdsnopek
#4 panels-ipe-decoupled-2636478-4.patch50.38 KBdsnopek
#3 interdiff.txt25.58 KBdsnopek
#3 panels-ipe-decoupled-2636478-3.patch29.91 KBdsnopek
#2 panels-ipe-decoupled-2636478-2.patch7.06 KBdsnopek
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dsnopek created an issue. See original summary.

dsnopek’s picture

Status: Active » Needs work
FileSize
7.06 KB

Here's a re-roll of my first "idea" patch from #2600634-50: Implement Panels In-place editor display builder in panels_ipe module. It still needs loads of work!

dsnopek’s picture

FileSize
29.91 KB
25.58 KB

This still needs lots of work, but here's an in-progress patch that shows more or less what I'm thinking for this.

Basically, it allows other modules that want to integrate with IPE to provide a tagged service which knows how to store the underlying config entity that holds the PanelsDisplayVariant. Then the integrator puts some storage information on the PanelsDisplayVariant, which signals to it, that the IPE can be used to edit it!

This will require some specific integration code to be added to page_manager, which I'm already working on, but I'm not going to post just yet (I wanna get it a little more fleshed out and cleaned up first).

dsnopek’s picture

FileSize
50.38 KB
28.62 KB

Here's my latest iteration on this! It fully decouples the IPE from page_manager, but it still needs some clean-up, and testing with Panelizer before it's ready to commit.

And here's the companion page_manager issue that integrates it with the IPE (necessary to allow the IPE to work with page_manager):

#2642452: Integrate Page Manager with the Panels IPE

dsnopek’s picture

Status: Needs work » Needs review
FileSize
51.23 KB
6.84 KB

Ok, I did all the clean-up I wanted to do! This should be ready for review. :-)

Status: Needs review » Needs work

The last submitted patch, 5: panels-ipe-decoupled-2636478-5.patch, failed testing.

dsnopek’s picture

Status: Needs work » Needs review
FileSize
59.11 KB
11.64 KB

Ok, this should fix the tests!

I also found that CTools had a recent change that broke the Panels tests:

#2642786: Improve dependency injection in BlockDisplayVariant

However, this patch includes a workaround for that, which we can remove once the CTools issue is committed.

Status: Needs review » Needs work

The last submitted patch, 7: panels-ipe-decoupled-2636478-7.patch, failed testing.

dsnopek’s picture

Status: Needs work » Needs review
FileSize
59.11 KB
723 bytes

Gah! A little think-o that snuck in from a previous iteration of my dependency injection fix. THIS should be the patch to review/commit. :-)

dsnopek’s picture

Read through the patch again and made some small changes to comments (including a stray left-over @todo that no longer applies).

dsnopek’s picture

Another minor comment fix. This one looks like PHPStorm's 'Change signature' refactor mangling the docblock. :-/ Ok, I'm going to try really hard not to nit pick this anymore. :-)

samuel.mortenson’s picture

Recoverable fatal error: Argument 8 passed to Drupal\ctools\Plugin\DisplayVariant\BlockDisplayVariant::__construct() must be an instance of Drupal\Core\Block\BlockManager, none given, called in /Users/x/Sites/devdesktop/drupal/modules/panels/src/Plugin/DisplayVariant/PanelsDisplayVariant.php on line 115 and defined in Drupal\ctools\Plugin\DisplayVariant\BlockDisplayVariant->__construct() (line 97 of /Users/x/Sites/devdesktop/drupal/modules/ctools/src/Plugin/DisplayVariant/BlockDisplayVariant.php).

I'm getting this error when trying to add a Panels variant. Using dev everything as well as the related page_manager patch.

Ignore this, I was using an incompatible CTools release (dev).

samuel.mortenson’s picture

When toggling a block form preview twice, I get this error:

Fatal error: Call to a member function getContexts() on null in /Users/x/Sites/devdesktop/drupal/modules/panels/panels_ipe/src/Form/PanelsIPEBlockPluginForm.php on line 332

It looks like the temporary value for "panels_display" is lost after the first PanelsIPEBlockPluginForm::submitPreview() call. I remember running into this with other persistent values like plugin_id, variant_id, and uuid, which is why I set them as Form values rather than temporary values (see PanelsIPEBlockPluginForm.php lines 162-165). We could re-load the panels_display every call based on the "variant_id" value, or figure out why temporary values are not working out for us.

dsnopek’s picture

@samuel.mortenson: Thanks for the testing! Here's a patch that fixes the issue with hitting "Toggle preview" multiple times.

I think the thing is that setTemporaryValue() will serialize/unserialize the object in certain cases, and the contexts don't get serialized with the display variant.

Anyway, this version is actually easier to read!

dsnopek’s picture

Alright, here's a change that requires the Panels storage services to give a 'storage_type' rather than just using the service id. This should allow the services to be private! I updated the rest of the arguments to be $storage_type rather than $type for consistency.

Status: Needs review » Needs work

The last submitted patch, 15: panels-ipe-decoupled-2636478-15.patch, failed testing.

dsnopek’s picture

Status: Needs work » Needs review
FileSize
58.95 KB

Gah! Please ignore the last patch -- I made it from the wrong branch. However, the interdiff is correct! Here's a better patch.

phenaproxima’s picture

Status: Needs review » Needs work

OK, looked through this thoroughly. I don't see anything glaringly wrong (95% of this is documentation fixes), but I don't feel qualified to RTBC this patch; maybe @EclipseGc or @tim.plunkett should look over the more heavy-duty parts...

  1. +++ b/panels_ipe/panels_ipe.info.yml
    @@ -5,4 +5,3 @@ core: 8.x
    -  - page_manager
    \ No newline at end of file
    

    Missing a new line!

  2. +++ b/panels_ipe/src/Controller/PanelsIPEPageController.php
    @@ -45,6 +46,11 @@ class PanelsIPEPageController extends ControllerBase {
       /**
    +   * @var \Drupal\panels\Storage\PanelsStorageManagerInterface
    +   */
    +  protected $panelsStorage;
    

    Needs a description.

  3. +++ b/panels_ipe/src/Controller/PanelsIPEPageController.php
    @@ -80,42 +88,43 @@ class PanelsIPEPageController extends ControllerBase {
    +   * @param \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $panels_display
    +   *   The current Panels display.
    

    Can the description be changed to something like "The Panels display to be saved"?

  4. +++ b/panels_ipe/src/Controller/PanelsIPEPageController.php
    @@ -80,42 +88,43 @@ class PanelsIPEPageController extends ControllerBase {
    +   * @return \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant
    +   *
    +   * @throws \Drupal\user\TempStoreException
    

    Need descriptions for @return and @throws.

  5. +++ b/panels_ipe/src/Form/PanelsIPEBlockPluginForm.php
    @@ -47,6 +46,11 @@ class PanelsIPEBlockPluginForm extends FormBase {
       /**
    +   * @var \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant
    +   */
    +  protected $panelsDisplay;
    

    Needs a description.

  6. +++ b/panels_ipe/src/Form/PanelsIPEBlockPluginForm.php
    @@ -89,7 +93,7 @@ class PanelsIPEBlockPluginForm extends FormBase {
    +   * @param \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $panels_display
        *   The current PageVariant ID.
    

    Looks like the description needs to be updated.

  7. +++ b/src/Plugin/DisplayBuilder/DisplayBuilderBase.php
    @@ -21,7 +21,8 @@ abstract class DisplayBuilderBase extends PluginBase implements DisplayBuilderIn
    +  public function build(PanelsDisplayVariant $panels_display) {
    +    $regions = $this->getRegionAssignments();
         return $regions;
    

    Isn't getRegionAssignments() a method of PanelsDisplayVariant? Why is it being called on $this?

  8. +++ b/src/Plugin/DisplayVariant/PanelsDisplayVariant.php
    @@ -31,6 +35,20 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
       /**
    +   * @var \Drupal\Core\Condition\ConditionManager
    +   *
    +   * @todo Remove when fixed in CTools: https://www.drupal.org/node/2642786
    +   */
    +  protected $conditionManager;
    +
    +  /**
    +   * @var \Drupal\Core\Block\BlockManager
    +   *
    +   * @todo Remove when fixed in CTools: https://www.drupal.org/node/2642786
    +   */
    +  protected $blockManager;
    

    The issue landed, so time for these to be shown the door! :)

  9. +++ b/src/Plugin/DisplayVariant/PanelsDisplayVariant.php
    @@ -75,20 +93,26 @@ class PanelsDisplayVariant extends BlockDisplayVariant {
    +    // Inject dependencies as early as possible, so they can be used in
    +    // configuration.
    +    // @todo Remove when fixed in CTools: https://www.drupal.org/node/2642786
    +    $this->uuidGenerator = $uuid_generator;
    +    $this->blockManager = $block_manager;
    +    $this->conditionManager = $condition_manager;
    

    #2642786: Improve dependency injection in BlockDisplayVariant landed, so should these go away?

  10. +++ b/src/Plugin/DisplayVariant/PanelsDisplayVariant.php
    @@ -135,6 +161,40 @@ class PanelsDisplayVariant extends BlockDisplayVariant {
    +   * @param string $type
    +   *   The id of the IPE storage service to save with.
    

    Why does the description specifically mention IPE?

  11. +++ b/src/Plugin/DisplayVariant/PanelsDisplayVariant.php
    @@ -135,6 +161,40 @@ class PanelsDisplayVariant extends BlockDisplayVariant {
    +  public function getStorageType() {
    +    return $this->configuration['storage_type'] ?: NULL;
    +  }
    

    Will emit a notice if $this->configuration['storage_type'] is not set.

  12. +++ b/src/Plugin/DisplayVariant/PanelsDisplayVariant.php
    @@ -135,6 +161,40 @@ class PanelsDisplayVariant extends BlockDisplayVariant {
    +  public function getStorageId() {
    +    return $this->configuration['storage_id'] ?: NULL;
    +  }
    

    If storage_id is not set in $this->configuration, this will emit a notice. One possibility is to do return @$this->configuration['storage_id'].

  13. +++ b/src/Plugin/DisplayVariant/PanelsDisplayVariant.php
    @@ -359,4 +433,28 @@ class PanelsDisplayVariant extends BlockDisplayVariant {
    +  /**
    +   * {@inheritdoc}
    +   *
    +   * @todo Remove when fixed in CTools: https://www.drupal.org/node/2642786
    +   */
    +  public function getSelectionConditions() {
    +    if (!$this->selectionConditionCollection) {
    +      $this->selectionConditionCollection = new ConditionPluginCollection($this->conditionManager, $this->getSelectionConfiguration());
    +    }
    +    return $this->selectionConditionCollection;
    +  }
    +
    +  /**
    +   * {@inheritdoc}
    +   *
    +   * @todo Remove when fixed in CTools: https://www.drupal.org/node/2642786
    +   */
    +  protected function getBlockCollection() {
    +    if (!$this->blockPluginCollection) {
    +      $this->blockPluginCollection = new BlockPluginCollection($this->blockManager, $this->getBlockConfig());
    +    }
    +    return $this->blockPluginCollection;
    +  }
    +
    

    #2642786: Improve dependency injection in BlockDisplayVariant appears to have landed, so I guess these can both be removed?

  14. +++ b/src/Storage/PanelsStorageAccess.php
    @@ -0,0 +1,54 @@
    + * Contains \Drupal\panels\Storage\PanelsStorageAccess
    

    Missing a period.

  15. +++ b/src/Storage/PanelsStorageAccess.php
    @@ -0,0 +1,54 @@
    +  /**
    +   * @var \Drupal\panels\Storage\PanelsStorageManagerInterface
    +   */
    +  protected $panelsStorage;
    

    Missing description.

  16. +++ b/src/Storage/PanelsStorageAccess.php
    @@ -0,0 +1,54 @@
    +   * @param \Drupal\panels\Storage\PanelsStorageManagerInterface $panels_storage
    +   */
    +  public function __construct(PanelsStorageManagerInterface $panels_storage) {
    

    $panels_storage is missing a description.

  17. +++ b/src/Storage/PanelsStorageAccess.php
    @@ -0,0 +1,54 @@
    +   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
    +   *   The parametrized route
    

    Missing a period.

  18. +++ b/src/Storage/PanelsStorageAccess.php
    @@ -0,0 +1,54 @@
    +   * @param \Drupal\Core\Session\AccountInterface $account
    +   *   The currently logged in account.
    

    Can $account be optional, to use the currently logged-in user?

  19. +++ b/src/Storage/PanelsStorageAccess.php
    @@ -0,0 +1,54 @@
    +}
    \ No newline at end of file
    

    Missing a new line.

  20. +++ b/src/Storage/PanelsStorageInterface.php
    @@ -0,0 +1,56 @@
    + * Contains \Drupal\panels_ipe\PanelsStorageInterface
    

    Missing period after class name.

  21. +++ b/src/Storage/PanelsStorageInterface.php
    @@ -0,0 +1,56 @@
    +   *   The Panels display to save. Must have it's id within this storage service
    

    Nit: "it's" should be "its". And can this also be rephrased for clarity? Maybe something like "$panels_display->getStorageId() should return the display's ID as known to this storage service."

  22. +++ b/src/Storage/PanelsStorageInterface.php
    @@ -0,0 +1,56 @@
    +   * @param $id
    +   *   The id for the Panels display within this storage service.
    +   * @param $op
    +   *   The operation to perform (ie. create, read, update, delete).
    

    Missing type hints.

  23. +++ b/src/Storage/PanelsStorageInterface.php
    @@ -0,0 +1,56 @@
    +   * @param \Drupal\Core\Session\AccountInterface $account
    +   *   The user to check access for.
    

    Can $account be made optional to use the currently logged in user?

  24. +++ b/src/Storage/PanelsStorageManager.php
    @@ -0,0 +1,72 @@
    + * Contains \Drupal\panels_ipe\PanelsStorageManager
    

    Missing a period after the class name.

  25. +++ b/src/Storage/PanelsStorageManager.php
    @@ -0,0 +1,72 @@
    +  /**
    +   * @var \Drupal\panels\Storage\PanelsStorageInterface[]
    +   */
    +  protected $storage = [];
    

    Missing description.

  26. +++ b/src/Storage/PanelsStorageManager.php
    @@ -0,0 +1,72 @@
    +   * @return \Drupal\panels\Storage\PanelsStorageInterface
    +   *
    +   * @throws \Exception
    +   */
    +  protected function getStorage($storage_type) {
    

    Missing descriptions in @return and @throws.

  27. +++ b/src/Storage/PanelsStorageManager.php
    @@ -0,0 +1,72 @@
    +  /**
    +   * {@inheritdoc}
    +   */
    +  public function save(PanelsDisplayVariant $panels_display) {
    +    $storage = $this->getStorage($panels_display->getStorageType());
    +    $storage->save($panels_display);
    +  }
    +
    

    This never throws the exception mentioned in the interface documentation. What gives?

  28. +++ b/src/Storage/PanelsStorageManager.php
    @@ -0,0 +1,72 @@
    +}
    \ No newline at end of file
    

    Missing a new line here too.

  29. +++ b/src/Storage/PanelsStorageManagerInterface.php
    @@ -0,0 +1,69 @@
    + * Contains \Drupal\panels_ipe\PanelsStorageManagerInterface
    

    Missing period after class name.

  30. +++ b/src/Storage/PanelsStorageManagerInterface.php
    @@ -0,0 +1,69 @@
    +/**
    + * Interface for the Panels storage manager service.
    + */
    +interface PanelsStorageManagerInterface {
    

    Can this comment be expanded to explain a little more about what PanelsStorageManagerInterface is and does?

  31. +++ b/src/Storage/PanelsStorageManagerInterface.php
    @@ -0,0 +1,69 @@
    +   * @param $storage_type
    +   *   The storage type to use for this storage service.
    

    Missing type hint.

  32. +++ b/src/Storage/PanelsStorageManagerInterface.php
    @@ -0,0 +1,69 @@
    +   *   If the storage information isn't set, or there is no such Panels display.
    

    Er...what is meant by "if there is no such Panels display"? If we're passing the display in, doesn't it exist (even if only in memory)? Can this be clarified a bit?

  33. +++ b/src/Storage/PanelsStorageManagerInterface.php
    @@ -0,0 +1,69 @@
    +   * @param \Drupal\Core\Session\AccountInterface $account
    +   *   The user to check access for.
    

    It would be handy to allow $account to be NULL, in which case it should default to the current user.

  34. +++ b/src/Storage/PanelsStorageManagerInterface.php
    @@ -0,0 +1,69 @@
    +}
    \ No newline at end of file
    

    Missing a new line :)

dsnopek’s picture

Thanks, @phenaproxima!

I'll address this review in a moment, but just wanted to quickly reply to #18.9 and #18.13:

Even though #2642786: Improve dependency injection in BlockDisplayVariant has been committed, it's only in CTools 8.x-3.x-dev which the tests won't use, so I'd like to defer removing that code to #2644104: Update for BlockDisplayVariant changes in CTools (issue #2642786) which we can commit after the next CTools release. Otherwise, all our tests will fail on all issues until CTools has a new release. :-/

dsnopek’s picture

Status: Needs work » Needs review
FileSize
60.88 KB
12.95 KB

Alright! I addressed all the review in #18 except for the items responded to below... Hopefully, I didn't miss anything!

re #18.11/12: $this->configuration['storage_type'] is always set because it's default is in defaultConfiguration() - that code just switches it from an empty string (which what we want in the config object, so the schema is always a string) to a NULL for API purposes. (This patch doesn't include a config schema, though - that's in progress on another issue.)

re #18.18: This is a routing access class which will have its access() function always called with an $account by the routing system - normal developers won't be calling this function, so I don't think it's really worth the extra code to allow $account to be optional.

re #18.23: Since this is an interface (with no matching base class), I'd rather not make $account optional because that would mean that every class that implements this interface will need to have the extra code to optionally grab the current user. I'd rather make this the job of the thing calling this function, which is most likely the routing system (via PanelsStorageAccess) which already gives us this for free.

re #18.27: Yes, it does, via getStorage() and the storage service it delegates to!

re #18.33: Ok, yes, here it makes sense to allow $account to be optional! :-) This function will be called by developers and there likely won't be alternate implementations of this interface (except in some crazy edge case), so I've made this change.

phenaproxima’s picture

Interdiff looks good! Two nitpicks:

  1. +++ b/src/Storage/PanelsStorageManagerInterface.php
    @@ -42,10 +54,14 @@ interface PanelsStorageManagerInterface {
    +   *   $panels_display->getStorageId() must return the storage type and id as
    +   *   to the storage service.
    

    Needs to be "as known to the storage service", but that can be fixed on commit :)

  2. +++ b/src/Storage/PanelsStorageManagerInterface.php
    @@ -42,10 +54,14 @@ interface PanelsStorageManagerInterface {
    +   *   storage service can't be found, or there is no Panels display found in
    +   *   storage service with the given id.
    

    Should be "...if there is no Panels display found in THE storage service with the given id." Fixable on commit.

dsnopek’s picture

FileSize
60.89 KB
965 bytes

This patch address the nit picks in #21.

japerry’s picture

Status: Needs review » Needs work

Its looking pretty good, ran some manual tests and ran into one issue -- the block titles don't get saved. Tested against HEAD, which is working properly.

dsnopek’s picture

@japerry: Hrm. I just tested updating a blocks title, and it worked for me! Can you give some steps to reproduce? Maybe it had to do with the specific block, or the order of steps or something?

japerry’s picture

Status: Needs work » Needs review

So did some more testing and now I cannot reproduce the title issue. Hopefully it was just a fluke. Needs more review!

  • EclipseGc committed 8a9fc53 on 8.x-3.x authored by dsnopek
    Issue #2636478 by dsnopek, samuel.mortenson, phenaproxima, japerry: IPE...
EclipseGc’s picture

Status: Needs review » Fixed

Looks like everyone has reviewed this. David and I did a higher level review of this and I'm quite happy with what I see. Since Jakob has done a separate review, I went ahead and committed this since it will unblock a number of IPE issues.

Eclipse

dsnopek’s picture

Woohoo! Thanks, everyone, for your help on this one!

Status: Fixed » Closed (fixed)

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