Currently, if your looking at the latest revision of a Panelized entity, then editing with the IPE will create a new revision. But if you're viewing an old revision, then editing with the IPE overwrite that revision.

However, if you're employing a workflow module (like Workbench Moderation) then it might not make sense to expose the IPE on the publish revision, or any previous ones, but only the latest draft revision.

This issue proposes to create a plugin type that would allow other modules (like Workbench Moderation, or some integration module) to provide a plugin that can disable the IPE based on custom logic.

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
1.79 KB

Here's a patch that would disable the IPE if on a revision that isn't the latest revision.

However, EclipseGC brought up that this would break a "CPS with the election night scenario" use case. So, this actually won't work long-term. :-(

So, the question is: Do want to include this in the near-term and replace it later? Or, do we want to come up with the full solution first?

EclipseGc’s picture

So I spent some time on this today to see if I could abstract out a plugin type for this work. The patch is a little rough still, but should communicate the idea. I'll put the workbench_moderation plugin below as an example.

Eclipse

/**
 * @file
 * Contains \Drupal\workbench_moderation\Plugin\IPEAccess\WorkbenchModerationIPEAccess.php
 */

namespace Drupal\workbench_moderation\Plugin\IPEAccess;


use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant;
use Drupal\panels_ipe\Annotation\IPEAccess;
use Drupal\panels_ipe\Plugin\IPEAccessBase;
use Drupal\workbench_moderation\ModerationInformationInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * @IPEAccess(
 *   id = "workbench_moderation_ipe",
 *   label = @Translation("Workbench moderation")
 * )
 */
class WorkbenchModerationIPEAccess extends IPEAccessBase implements ContainerFactoryPluginInterface {

  /**
   * The moderation information service.
   *
   * @var \Drupal\workbench_moderation\ModerationInformationInterface
   */
  protected $information;

  /**
   * WorkbenchModerationIPEAccess constructor.
   *
   * @param array $configuration
   * @param string $plugin_id
   * @param mixed $plugin_definition
   * @param \Drupal\workbench_moderation\ModerationInformationInterface $information
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, ModerationInformationInterface $information) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->information = $information;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($configuration, $plugin_id, $plugin_definition, $container->get('workbench_moderation.moderation_information'));
  }

  /**
   * {@inheritdoc}
   */
  public function applies(PanelsDisplayVariant $display) {
    if (!empty($display->getContexts()['@panelizer.entity_context:entity']) && $display->getContexts()['@panelizer.entity_context:entity']->hasContextValue()) {
      $entity = $display->getContexts()['@panelizer.entity_context:entity']->getContextValue();
      return $this->information->isModeratableEntity($entity);
    }
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function access(PanelsDisplayVariant $display) {
    $entity = $display->getContexts()['@panelizer.entity_context:entity']->getContextValue();
    return $this->information->isLatestRevision($entity) && !$this->information->isLiveRevision($entity);
  }

}

dsnopek’s picture

Title: Disable IPE if on an old revision? » Allow other modules to disable the IPE based on custom logic
Project: Panelizer » Panels
Component: Code » In-Place Editor (IPE)
Issue summary: View changes
Status: Needs work » Needs review
Issue tags: +panelizer, +Workbench Moderation

Since @EclipseGC came up with a use case that shot holes through my original proposal to simply bake it into Panelizer to only show the IPE on the latest revision, I've re-purposed this issue for his proposal to add a plugin type to the Panels IPE (and moved this issue there).

dsnopek’s picture

One tiny bit of review!

+++ b/panels_ipe/src/Annotation/IPEAccess.php
@@ -0,0 +1,38 @@
+class IPEAccess extends Plugin {

We don't *really* need the human-readable label. Maybe this could just be PluginId and take only id? These'll never be choosable in the UI.

EclipseGc’s picture

Yeah, but I could imagine a UI that tells you which plugins will apply. That could be really nice for having insight into what's going on and who's making the decisions about when IPE displays.

Eclipse

japerry’s picture

+1 to making it configurable for plugins. It can be a bit daunting if you don't know what plugins are working on what. At a minimum it'd be great to have a page that shows all the plugins that apply.

So this class is basically for IPE... but I feel like we should abstract this access plugin pipeline a bit more. Talked on IRC about any display renderer being able to use similar plugins, and I agree.

As far as the access plugins go, I'm not sure there is a need to take it further out than panels at the moment. Maybe this is one of those components that panels manages?

dsnopek’s picture

So this class is basically for IPE... but I feel like we should abstract this access plugin pipeline a bit more. Talked on IRC about any display renderer being able to use similar plugins, and I agree.

So, what would other display builders do if access is denied? With IPE, it basically falls back on the standard display builder when access is denied. But I'm not sure what we'd do if, for example, the standard display builder were selected and access were denied...

EclipseGc’s picture

well, I think we need to introduce the idea of a frontend renderer. And allow the access check on those. It's a different classification of thing, and administratively, on the backend, I don't really care about wbm's opinion when we're on a panels (or whatever) admin page. But when we're collaborating on rendering something, if we are using a frontend renderer, we should ask other module's opinions.

Eclipse

Crell’s picture

At the risk of picking an old fight with EclipseGc :-), why a plugin? This seems like a simple voter pattern of tagged services. What's the value-add of plugins here over "a bunch o' objects that return yep/nope"? This doesn't feel like a user-configurable problem space to me...

EclipseGc’s picture

It's not a user configurable problem space per say. I've been arguing with myself on this. Beyond the ability to store metadata that can be used in an information UI, I can see an argument for these being a tagged service. Frankly though, I don't think there's a significant benefit either way, and Plugins are frankly a little more ubiquitous. I could be convinced either way.

Eclipse

dsnopek’s picture

I think tagged services is actually a really good fit for this problem, because:

  • You always want to load all classes (they are all loaded when the class that collects them is instantiated)
  • You never need multiple instances of the individual classes, they're singletons (not to mention stateless and taking no configuration)

Plugins would be better if you needed to only load a named class on demand, or needed multiple instances, or configuration of some kind.

So, my vote would be for tagged services!

phenaproxima’s picture

Looking at this patch, I also feel that tagged services is a more appropriate fit for the problem, if only because they are simpler than plugins and have less overhead. I see no reason to needlessly complicate this fix. Plugins are maybe more flexible in a general sense, but how much flexibility is really needed here? And +1 what @dsnopek said about there being no need for multiple instances of these classes.

In this case, I favor simplicity over flexibility.

EclipseGc’s picture

Yup, I agree with all of that, however, we'll have to invent something if we want to show which services apply to a given node.

Crell’s picture

I don't think we have an information UI for anywhere else that tagged services are used, and it's fine. Not everything needs to have a complex introspection UI built for it. (In fact, many things probably shouldn't.) Worst case, there's always drupal console debug tools, which are already quite handy.

EclipseGc’s picture

I wasn't suggesting anything complex, just a listing page to tell you what's actually applying. You'll forgive me, but I'm quite careful with what I decide is or isn't a tagged service. There are a number of examples in core where someone said "Oh, just make that a tagged service." and I've since been very peeved at my inability to make it do something worth while for end users because of that decision. I'd frankly really like to see a comparison in performance between the two because I see a lot of accusations backed up by exactly 0 links to data.

In short, I'm not suggesting anything complex. I'm favoring the adoption of the most common pattern in core, a potential UI that simply lists what plugins are currently applying (not any sort of configuration) and stats if someone has them.

Eclipse

samuel.mortenson’s picture

Is this issue ready for review or are we still working out architectural issues? It's hard to track from the comments, I can mark as Needs work if need be.

samuel.mortenson’s picture

samuel.mortenson’s picture

Bump, I have the same pending question as #17. We're doing a new release of Panels next week and it would be good to see this change in, if the patch is ready for review.

  • japerry committed 607d2d1 on 8.x-3.x authored by EclipseGc
    Issue #2667754 by dsnopek, EclipseGc, japerry, phenaproxima: Allow other...
japerry’s picture

Status: Needs review » Fixed

After discussing with EclipseGC and Phenaproxima, decided that this will go in. If you want a tagged service instead, file a feature request.

Fixed.

Status: Fixed » Closed (fixed)

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