- Issue created by @freelock
- πΊπΈUnited States freelock Seattle
We created this plugin for a client, and have had it in production for a year now!
namespace Drupal\qcyc_roster\Plugin\Action; use Drupal\Component\Utility\DiffArray; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; use Drupal\eca\Plugin\Action\ConfigurableActionBase; /** * Provides a Load Diffs action. * * @Action( * id = "qcyc_roster_load_diffs", * label = @Translation("Load Diffs"), * description = @Translation("Compare 2 entities and return a list of fields that differ"), * type = "entity" * ) * */ class LoadDiffs extends ConfigurableActionBase { /** * {@inheritDoc} */ public function defaultConfiguration(): array { return [ 'token_name' => '', 'compare' => null, 'return_values' => FALSE, 'exclude_fields' => [], 'include_fields' => [], ] + parent::defaultConfiguration(); } /** * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state): array { $form['token_name'] = [ '#type' => 'textfield', '#title' => $this->t('Name of token'), '#default_value' => $this->configuration['token_name'], '#description' => $this->t('Provide the name of a token that holds the new list.'), '#weight' => -60, ]; $form['compare'] = [ '#type' => 'textfield', '#title' => $this->t('Compare'), '#description' => $this->t('Provide the name of a token that holds the original entity.'), '#default_value' => $this->configuration['compare'], '#weight' => 30, ]; $form['return_values'] = [ '#type' => 'checkbox', '#title' => $this->t('Return values'), '#default_value' => $this->configuration['return_values'], '#description' => $this->t('If checked, the list will return values. If unchecked, it will only return the different machine names of changed fields.'), ]; $form['exclude_fields'] = [ '#type' => 'textarea', '#title' => 'Exclude fields', '#description' => $this->t('List field machine names to remove from difference/ignore'), '#default_value' => implode("\n", $this->configuration['exclude_fields']), '#weight' => 40, ]; $form['include_fields'] = [ '#type' => 'textarea', '#title' => 'Include fields', '#description' => $this->t('List field machine names to include in difference -- all others will be ignored.'), '#default_value' => implode("\n", $this->configuration['include_fields']), '#weight' => 40, ]; return $form; } /** * {@inheritdoc} */ public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void { $this->configuration['token_name'] = $form_state->getValue('token_name'); $this->configuration['compare'] = $form_state->getValue('compare'); $this->configuration['return_values'] = $form_state->getValue('return_values'); $this->configuration['exclude_fields'] = explode("\n", $form_state->getValue('exclude_fields')); $this->configuration['include_fields'] = explode("\n", $form_state->getValue('include_fields')); parent::submitConfigurationForm($form, $form_state); } /** * {@inheritdoc} */ public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { /** @var ContentEntityInterface $object */ $access = $object->access('view', $account, TRUE); return $return_as_object ? $access : $access->isAllowed(); } /** * {@inheritdoc} */ public function execute($entity = NULL) { $compare = $this->tokenServices->getTokenData($this->configuration['compare']); $diff = DiffArray::diffAssocRecursive($entity->toArray(), $compare->toArray()); $exclude_fields = $this->configuration['exclude_fields']; if (count($exclude_fields)) { foreach ($exclude_fields as $field) { unset($diff[$field]); } } $include_fields = $this->configuration['include_fields']; if (count($include_fields)) { $included = []; foreach ($include_fields as $field) { if (isset ($diff[$field])) { $included[$field] = $diff[$field]; } } $diff = $included; } if (!$this->configuration['return_values']) { $diff = array_keys($diff); } $this->tokenServices->addTokenData($this->configuration['token_name'], $diff); } }
- π©πͺGermany jurgenhaas Gottmadingen
Thank you so much @freelock for this contribution, this is nicely implemented.
One thought, though, whether we should make this slightly more generic. Currently, this compares 2 entities by casting them to arrays first. This would probably not work for webform submission data, I guess. And other arrays/objects may be needed to be compared in a similar way as well.
We could turn this into an "Objects diff" action that accepts 2 objects as input. If those objects happen to be arrays already, this can simply continue. If not, the action tries to cast them to arrays first, just like you did with the entities.
With that in place, we could then also add a condition that verifies if 2 objects are different.
Both those plugins could be implemented in the eca_base sub-module and it wouldn't take too much extra effort when we build that on top of your code. I'll start that in an issue fork, then you and maybe others can review that.
- Status changed to Closed: duplicate
7 months ago 8:02am 5 June 2024 - π©πͺGermany jurgenhaas Gottmadingen
Oops, my IDE warned me about duplicate code when I started to implement this. I was surprised and reached out to the other instance, which looked identical. And guess what: we've already implemented that code from @freelock about a year ago, see β¨ New action/condition: entity diff Fixed .
So, we can close this one as a duplicate. Unfortunately, we don't have the more generic approach in the existing implementation, but maybe webform submissions can be compared with the entity diff as well? We will do some tests and open a separate issue, if that doesn't work for some reason.
- Status changed to Active
7 months ago 8:33am 5 June 2024 - π©πͺGermany jurgenhaas Gottmadingen
I'm re-opening this as we have to improve the existing implementation to also support webform submission data.
- Merge request !425Issue #3452549 by jurgenhaas, freelock: Entity Diff: improve support for webform submissions β (Merged) created by jurgenhaas
- Status changed to Needs review
7 months ago 9:10am 5 June 2024 - π©πͺGermany jurgenhaas Gottmadingen
This now works with webform submissions as well, please give it a try and set to RTBC, we can then still add this to ECA 2.0.0
- π©πͺGermany jurgenhaas Gottmadingen
I've just tested this again, the use statement is valid even without the webform being present. @freelock do you want to review that quickly as well?
-
jurgenhaas β
committed 8a615c38 on 2.1.x
Issue #3452549 by jurgenhaas, freelock: Entity Diff: improve support for...
-
jurgenhaas β
committed 8a615c38 on 2.1.x
- Status changed to Fixed
5 months ago 2:48pm 16 August 2024 Automatically closed - issue fixed for 2 weeks with no activity.