[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Event/ -> ReshapeArgumentsAware.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright  (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
   7   * @license        GNU General Public License version 2 or later; see LICENSE
   8   */
   9  
  10  namespace Joomla\CMS\Event;
  11  
  12  use DomainException;
  13  
  14  // phpcs:disable PSR1.Files.SideEffects
  15  \defined('JPATH_PLATFORM') or die;
  16  // phpcs:enable PSR1.Files.SideEffects
  17  
  18  /**
  19   * A Trait to reshape arguments maintaining b/c with legacy plugin events.
  20   *
  21   * Old plugin event handlers expect positional arguments, not named arguments, since they are simple
  22   * PHP methods, e.g.
  23   * public onExample($foo, $bar, $baz).
  24   * Concrete Event classes, however, use named arguments which can be passed in any order. The
  25   * following two examples are equivalent:
  26   * $event1 = new ConcreteEventClass('onExample', ['foo' => 1, 'bar' => 2, 'baz' => 3];
  27   * $event2 = new ConcreteEventClass('onExample', ['bar' => 2, 'baz' => 3, 'foo' => 1,];
  28   * However, this means that the internal $arguments property of the event object holds the named
  29   * arguments in a **different** order in each case.
  30   *
  31   * When the event handler is aware of the ConcreteEventClass it can retrieve named arguments and
  32   * all is good in the world. However, when you have a legacy plugin listener registered through
  33   * CMSPlugin::registerLegacyListener you have a major problem! The legacy listener is passing the
  34   * arguments **positionally**, in the order they were added to the Event object.
  35   *
  36   * In the previous example, $event1 would work as expected because the foo, bar, and baz arguments
  37   * were given in the same order legacy listeners expected them. On the other hand, $event2 would
  38   * fail miserably because the call order would be $bar, $baz, $foo which is NOT what the legacy
  39   * listener expected.
  40   *
  41   * The only way to fix that is to *reshape the argument* in the concrete event's constructor so that
  42   * the order of arguments is guaranteed to be the same as expected by legacy listeners. Moreover,
  43   * since Joomla is passing all arguments (except the 'result' argument) blindly to the legacy
  44   * listener we must ensure that a. all necessary arguments are set and b. any other named arguments
  45   * do NOT exist. Otherwise our legacy listeners would receive the wrong number of positional
  46   * arguments and break.
  47   *
  48   * All this is achieved by the reshapeArguments() method in this trait which has to be called in the
  49   * constructor of the concrete event class.
  50   *
  51   * This trait is marked as deprecated with a removal target of 5.0 because in Joomla 5 we will only
  52   * be using concrete event classes with named arguments, removing legacy listeners and their
  53   * positional arguments headaches.
  54   *
  55   * @since  4.2.0
  56   *
  57   * @deprecated 5.0
  58   */
  59  trait ReshapeArgumentsAware
  60  {
  61      /**
  62       * Reshape the arguments array to preserve b/c with legacy listeners
  63       *
  64       * @param   array  $arguments      The named arguments array passed to the constructor.
  65       * @param   array  $argumentNames  The allowed argument names (mandatory AND optional).
  66       * @param   array  $defaults       Default values for optional arguments.
  67       *
  68       * @return  array  The reshaped arguments.
  69       *
  70       * @since   4.2.0
  71       */
  72      protected function reshapeArguments(array $arguments, array $argumentNames, array $defaults = [])
  73      {
  74          $mandatoryKeys = array_diff($argumentNames, array_keys($defaults));
  75          $currentKeys   = array_keys($arguments);
  76          $missingKeys   = array_diff($mandatoryKeys, $currentKeys);
  77          $extraKeys     = array_diff($currentKeys, $argumentNames);
  78  
  79          // Am I missing any mandatory arguments?
  80          if ($missingKeys) {
  81              throw new DomainException(sprintf('Missing arguments for ā€˜%sā€™ event: %s', $this->getName(), implode(', ', $missingKeys)));
  82          }
  83  
  84          // Do I have unknown arguments?
  85          if ($extraKeys) {
  86              throw new DomainException(sprintf('Unknown arguments for ā€˜%sā€™ event: %s', $this->getName(), implode(', ', $missingKeys)));
  87          }
  88  
  89          // Reconstruct the arguments in the order specified in $argumentTypes
  90          $reconstructed = [];
  91  
  92          foreach ($argumentNames as $key) {
  93              $reconstructed[$key] = $arguments[$key] ?? $defaults[$key];
  94          }
  95  
  96          // Return the reconstructed arguments array
  97          return $reconstructed;
  98      }
  99  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer