Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
namespace Joomla\Component\Content\Administrator\Model;

use Joomla\CMS\Date\Date;
use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Event\EventFactory;
use Joomla\CMS\Factory;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Form\Form;
Expand Down Expand Up @@ -843,7 +843,7 @@ public function featured($pks, $value = 0, $featuredUp = null, $featuredDown = n
// Trigger the before change state event.
$eventResult = Factory::getApplication()->getDispatcher()->dispatch(
$this->event_before_change_featured,
AbstractEvent::create(
EventFactory::create(
$this->event_before_change_featured,
[
'eventClass' => FeatureEvent::class,
Expand Down Expand Up @@ -948,7 +948,7 @@ public function featured($pks, $value = 0, $featuredUp = null, $featuredDown = n
// Trigger the change state event.
Factory::getApplication()->getDispatcher()->dispatch(
$this->event_after_change_featured,
AbstractEvent::create(
EventFactory::create(
$this->event_after_change_featured,
[
'eventClass' => FeatureEvent::class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
namespace Joomla\Component\Scheduler\Administrator\Helper;

use Joomla\CMS\Application\AdministratorApplication;
use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Event\EventFactory;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\Component\Scheduler\Administrator\Task\TaskOptions;
Expand Down Expand Up @@ -53,7 +53,7 @@ public static function getTaskOptions(): TaskOptions
/** @var AdministratorApplication $app */
$app = Factory::getApplication();
$options = new TaskOptions();
$event = AbstractEvent::create(
$event = EventFactory::create(
'onTaskOptionsList',
[
'subject' => $options,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

use Joomla\CMS\Application\AdministratorApplication;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Event\EventFactory;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\FormFactoryInterface;
Expand Down Expand Up @@ -698,7 +698,7 @@ public function unlock(array &$pks): bool
return true;
}

$event = AbstractEvent::create(
$event = EventFactory::create(
$this->event_before_unlock,
[
'subject' => $this,
Expand All @@ -723,7 +723,7 @@ public function unlock(array &$pks): bool
}

// Trigger the after unlock event
$event = AbstractEvent::create(
$event = EventFactory::create(
$this->event_unlock,
[
'subject' => $this,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace Joomla\Component\Scheduler\Administrator\Table;

use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Event\EventFactory;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Model\AdminModel;
Expand Down Expand Up @@ -208,7 +208,7 @@ public function bind($src, $ignore = []): bool
public function unlock(array $pks = [], ?int $userId = null): bool
{
// Pre-processing by observers
$event = AbstractEvent::create(
$event = EventFactory::create(
'onTaskBeforeUnlock',
[
'subject' => $this,
Expand Down Expand Up @@ -282,7 +282,7 @@ public function unlock(array $pks = [], ?int $userId = null): bool
}

// Pre-processing by observers
$event = AbstractEvent::create(
$event = EventFactory::create(
'onTaskAfterUnlock',
[
'subject' => $this,
Expand Down
6 changes: 3 additions & 3 deletions administrator/components/com_scheduler/src/Task/Task.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Event\EventFactory;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Log\Log;
Expand Down Expand Up @@ -211,7 +211,7 @@ public function run(): bool
$this->snapshot['netDuration'] = 0;

/** @var ExecuteTaskEvent $event */
$event = AbstractEvent::create(
$event = EventFactory::create(
'onExecuteTask',
[
'eventClass' => ExecuteTaskEvent::class,
Expand Down Expand Up @@ -466,7 +466,7 @@ protected function dispatchExitEvent(): void
$exitCode = $this->snapshot['status'] ?? 'NA';
$eventName = self::EVENTS_MAP[$exitCode] ?? self::EVENTS_MAP['NA'];

$event = AbstractEvent::create(
$event = EventFactory::create(
$eventName,
[
'subject' => $this,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace Joomla\Module\Sampledata\Administrator\Helper;

use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Event\EventFactory;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;

Expand Down Expand Up @@ -40,7 +40,7 @@ public function getSampledataList()
->getDispatcher()
->dispatch(
'onSampledataGetOverview',
AbstractEvent::create(
EventFactory::create(
'onSampledataGetOverview',
[
'subject' => new \stdClass(),
Expand Down
7 changes: 4 additions & 3 deletions libraries/src/Event/AbstractEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
*
* You can create a new Event with something like this:
*
* $event = AbstractEvent::create('onModelBeforeSomething', $myModel, $arguments);
* $event = \Joomla\CMS\Event\EventFactory::create('onModelBeforeSomething', $myModel, $arguments);
*
* You can access the subject object from your event Listener using $event['subject']. It is up to your listener to
* determine whether it should apply its functionality against the subject.
Expand All @@ -52,7 +52,8 @@ abstract class AbstractEvent extends Event
* @return static
*
* @since 4.0.0
* @throws \BadMethodCallException If you do not provide a subject argument
* @throws \BadMethodCallException If you do not provide a subject argument
* @deprecated 6.0 Use \Joomla\CMS\Event\EventFactory::create instead
*/
public static function create(string $eventName, array $arguments = [])
{
Expand Down Expand Up @@ -109,7 +110,7 @@ public static function create(string $eventName, array $arguments = [])
*/
public function __construct(string $name, array $arguments = [])
{
parent::__construct($name, $arguments);
parent::__construct($name);

foreach ($arguments as $argumentName => $value) {
$this->setArgument($argumentName, $value);
Expand Down
39 changes: 35 additions & 4 deletions libraries/src/Event/AbstractImmutableEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@

namespace Joomla\CMS\Event;

use Joomla\Event\AbstractEvent;
use BadMethodCallException;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects

/**
* This class implements the immutable base Event object used system-wide to offer orthogonality.
* Note that it's implementation is very similar to \Joomla\Event\EventImmutable but it also contains the same custom
* setter logic for constructors as in \Joomla\CMS\Event\AbstractEvent
*
* @see \Joomla\CMS\Event\AbstractEvent
* @since 4.0.0
Expand Down Expand Up @@ -48,7 +53,33 @@ public function __construct(string $name, array $arguments = [])

$this->constructed = true;

parent::__construct($name, $arguments);
parent::__construct($name);

// Same setter logic as in \Joomla\CMS\Event\AbstractEvent::setArgument
foreach ($arguments as $argumentName => $value) {
// Look for the method for the value pre-processing/validation
$ucfirst = ucfirst($name);
$methodName1 = 'onSet' . $ucfirst;
$methodName2 = 'set' . $ucfirst;

if (method_exists($this, $methodName1)) {
$value = $this->{$methodName1}($value);
} elseif (method_exists($this, $methodName2)) {
@trigger_error(
sprintf(
'Use method "%s" for value pre-processing is deprecated, and will not work in Joomla 6. Use "%s" instead. Event %s',
$methodName2,
$methodName1,
\get_class($this)
),
E_USER_DEPRECATED
);

$value = $this->{$methodName2}($value);
}

$this->arguments[$argumentName] = $value;
}
}

/**
Expand All @@ -62,11 +93,11 @@ public function __construct(string $name, array $arguments = [])
* @since 4.0.0
* @throws \BadMethodCallException
*/
public function offsetSet($name, $value)
public function offsetSet($name, mixed $value): void
{
// B/C check for plugins which use $event['result'] = $result;
if ($name === 'result') {
parent::offsetSet($name, $value);
$this->arguments[$name] = $value;

@trigger_error(
'Setting a result in an immutable event is deprecated, and will not work in Joomla 6. Event ' . $this->getName(),
Expand Down Expand Up @@ -95,7 +126,7 @@ public function offsetSet($name, $value)
* @since 4.0.0
* @throws \BadMethodCallException
*/
public function offsetUnset($name)
public function offsetUnset($name): void
{
throw new \BadMethodCallException(
sprintf(
Expand Down
91 changes: 91 additions & 0 deletions libraries/src/Event/EventFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

/**
* Joomla! Content Management System
*
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE
*/

namespace Joomla\CMS\Event;

use Joomla\Event\Event;
use Joomla\Event\EventInterface;
use Joomla\String\Normalise;

/**
* This class is a factory system that allows the creation of most core events in the Joomla Ecosystem, falling back to
* the creation of a \Joomla\CMS\Event\GenericEvent object for the class if no specific event class is matched. You can
* create a new Event with something like this:
*
* $event = EventFactory::create('onModelBeforeSomething', $myModel, $arguments);
*
* You can access the subject object from your event Listener using $event['subject']. It is up to your listener to
* determine whether it should apply its functionality against the subject.
*
* @since __DEPLOY_VERSION__
*/
abstract class EventFactory {
use CoreEventAware;

/**
* Creates a new CMS event object for a given event name and subject. The following arguments must be given:
* subject object The subject of the event. This is the core object you are going to manipulate.
* eventClass string The Event class name. If you do not provide it Joomla\CMS\Events\<eventNameWithoutOnPrefix>
* will be used.
*
* @param string $eventName The name of the event, e.g. onTableBeforeLoad
* @param array $arguments Additional arguments to pass to the event
*
* @return EventInterface
*
* @since 4.0.0
* @throws \BadMethodCallException If you do not provide a subject argument
*/
public static function create(string $eventName, array $arguments = [])
{
// Get the class name from the arguments, if specified
$eventClassName = '';

if (isset($arguments['eventClass'])) {
$eventClassName = $arguments['eventClass'];

unset($arguments['eventClass']);
}

/**
* If the class name isn't set/found determine it from the event name, e.g. TableBeforeLoadEvent from
* the onTableBeforeLoad event name.
*/
if (empty($eventClassName) || !class_exists($eventClassName, true)) {
$bareName = strpos($eventName, 'on') === 0 ? substr($eventName, 2) : $eventName;
$parts = Normalise::fromCamelCase($bareName, true);
$eventClassName = __NAMESPACE__ . '\\' . ucfirst(array_shift($parts)) . '\\';
$eventClassName .= implode('', $parts);
$eventClassName .= 'Event';
}

// Make sure a non-empty subject argument exists and that it is an object
if (!isset($arguments['subject']) || empty($arguments['subject']) || !\is_object($arguments['subject'])) {
throw new \BadMethodCallException("No subject given for the $eventName event");
}

// Create and return the event object
if (class_exists($eventClassName, true)) {
return new $eventClassName($eventName, $arguments);
}

/**
* The detection code above failed. This is to be expected, it was written back when we only
* had the Table events. It does not address most other core events. So, let's use our
* fancier detection instead.
*/
$eventClassName = self::getEventClassByEventName($eventName);

if (!empty($eventClassName) && ($eventClassName !== Event::class)) {
return new $eventClassName($eventName, $arguments);
}

return new GenericEvent($eventName, $arguments);
}
}
6 changes: 3 additions & 3 deletions libraries/src/Extension/ExtensionManagerTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace Joomla\CMS\Extension;

use Joomla\CMS\Dispatcher\ModuleDispatcherFactory;
use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Event\EventFactory;
use Joomla\CMS\Helper\HelperFactory;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Plugin\PluginHelper;
Expand Down Expand Up @@ -122,7 +122,7 @@ private function loadExtension($type, $extensionName, $extensionPath)

$container->get(DispatcherInterface::class)->dispatch(
'onBeforeExtensionBoot',
AbstractEvent::create(
EventFactory::create(
'onBeforeExtensionBoot',
[
'subject' => $this,
Expand Down Expand Up @@ -163,7 +163,7 @@ private function loadExtension($type, $extensionName, $extensionPath)

$container->get(DispatcherInterface::class)->dispatch(
'onAfterExtensionBoot',
AbstractEvent::create(
EventFactory::create(
'onAfterExtensionBoot',
[
'subject' => $this,
Expand Down
3 changes: 2 additions & 1 deletion libraries/src/MVC/Model/AdminModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace Joomla\CMS\MVC\Model;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Event\EventFactory;
use Joomla\CMS\Event\Model;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\FormFactoryInterface;
Expand Down Expand Up @@ -705,7 +706,7 @@ protected function batchTag($value, $pks, $contexts)
$this->table->reset();
$this->table->load($pk);

$setTagsEvent = \Joomla\CMS\Event\AbstractEvent::create(
$setTagsEvent = EventFactory::create(
'onTableSetNewTags',
[
'subject' => $this->table,
Expand Down
Loading