Updated Rector to commit eed1dca02b44f63a00f232631763eddce1545094

eed1dca02b [DX] remove branch alias to avoid miss-versioning, use specific tag instead (#4715)
This commit is contained in:
Tomas Votruba 2023-08-08 08:50:04 +00:00
parent 580a5566b1
commit 3c5f7a4dd4
27 changed files with 79 additions and 964 deletions

View File

@ -15,11 +15,6 @@
"bootstrap.php"
]
},
"extra": {
"branch-alias": {
"dev-main": "0.15-dev"
}
},
"conflict": {
"rector/rector-phpunit": "*",
"rector/rector-symfony": "*",

View File

@ -19,12 +19,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = '211deb44af8953bc0e67095d64aa45ec0e17d157';
public const PACKAGE_VERSION = 'eed1dca02b44f63a00f232631763eddce1545094';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2023-08-08 08:54:16';
public const RELEASE_DATE = '2023-08-08 08:46:35';
/**
* @var int
*/

2
vendor/autoload.php vendored
View File

@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit24cd621939e1c0be213e3232a0d86dbd::getLoader();
return ComposerAutoloaderInit9529323d9728a32f7dfa8b6e233dc465::getLoader();

View File

@ -409,9 +409,9 @@ return array(
'RectorPrefix202308\\Doctrine\\Inflector\\Rules\\Word' => $vendorDir . '/doctrine/inflector/lib/Doctrine/Inflector/Rules/Word.php',
'RectorPrefix202308\\Doctrine\\Inflector\\RulesetInflector' => $vendorDir . '/doctrine/inflector/lib/Doctrine/Inflector/RulesetInflector.php',
'RectorPrefix202308\\Doctrine\\Inflector\\WordInflector' => $vendorDir . '/doctrine/inflector/lib/Doctrine/Inflector/WordInflector.php',
'RectorPrefix202308\\Evenement\\EventEmitter' => $vendorDir . '/evenement/evenement/src/Evenement/EventEmitter.php',
'RectorPrefix202308\\Evenement\\EventEmitterInterface' => $vendorDir . '/evenement/evenement/src/Evenement/EventEmitterInterface.php',
'RectorPrefix202308\\Evenement\\EventEmitterTrait' => $vendorDir . '/evenement/evenement/src/Evenement/EventEmitterTrait.php',
'RectorPrefix202308\\Evenement\\EventEmitter' => $vendorDir . '/evenement/evenement/src/EventEmitter.php',
'RectorPrefix202308\\Evenement\\EventEmitterInterface' => $vendorDir . '/evenement/evenement/src/EventEmitterInterface.php',
'RectorPrefix202308\\Evenement\\EventEmitterTrait' => $vendorDir . '/evenement/evenement/src/EventEmitterTrait.php',
'RectorPrefix202308\\Fidry\\CpuCoreCounter\\CpuCoreCounter' => $vendorDir . '/fidry/cpu-core-counter/src/CpuCoreCounter.php',
'RectorPrefix202308\\Fidry\\CpuCoreCounter\\Diagnoser' => $vendorDir . '/fidry/cpu-core-counter/src/Diagnoser.php',
'RectorPrefix202308\\Fidry\\CpuCoreCounter\\Executor\\ProcOpenExecutor' => $vendorDir . '/fidry/cpu-core-counter/src/Executor/ProcOpenExecutor.php',

View File

@ -42,7 +42,7 @@ return array(
'RectorPrefix202308\\Illuminate\\Contracts\\' => array($vendorDir . '/illuminate/contracts'),
'RectorPrefix202308\\Illuminate\\Container\\' => array($vendorDir . '/illuminate/container'),
'RectorPrefix202308\\Fidry\\CpuCoreCounter\\' => array($vendorDir . '/fidry/cpu-core-counter/src'),
'RectorPrefix202308\\Evenement\\' => array($vendorDir . '/evenement/evenement/src/Evenement'),
'RectorPrefix202308\\Evenement\\' => array($vendorDir . '/evenement/evenement/src'),
'RectorPrefix202308\\Doctrine\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Inflector'),
'RectorPrefix202308\\Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'),
'RectorPrefix202308\\Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit24cd621939e1c0be213e3232a0d86dbd
class ComposerAutoloaderInit9529323d9728a32f7dfa8b6e233dc465
{
private static $loader;
@ -22,17 +22,17 @@ class ComposerAutoloaderInit24cd621939e1c0be213e3232a0d86dbd
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit24cd621939e1c0be213e3232a0d86dbd', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit9529323d9728a32f7dfa8b6e233dc465', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit24cd621939e1c0be213e3232a0d86dbd', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit9529323d9728a32f7dfa8b6e233dc465', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit24cd621939e1c0be213e3232a0d86dbd::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit9529323d9728a32f7dfa8b6e233dc465::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
$filesToLoad = \Composer\Autoload\ComposerStaticInit24cd621939e1c0be213e3232a0d86dbd::$files;
$filesToLoad = \Composer\Autoload\ComposerStaticInit9529323d9728a32f7dfa8b6e233dc465::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInit24cd621939e1c0be213e3232a0d86dbd
class ComposerStaticInit9529323d9728a32f7dfa8b6e233dc465
{
public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
@ -227,7 +227,7 @@ class ComposerStaticInit24cd621939e1c0be213e3232a0d86dbd
),
'RectorPrefix202308\\Evenement\\' =>
array (
0 => __DIR__ . '/..' . '/evenement/evenement/src/Evenement',
0 => __DIR__ . '/..' . '/evenement/evenement/src',
),
'RectorPrefix202308\\Doctrine\\Inflector\\' =>
array (
@ -663,9 +663,9 @@ class ComposerStaticInit24cd621939e1c0be213e3232a0d86dbd
'RectorPrefix202308\\Doctrine\\Inflector\\Rules\\Word' => __DIR__ . '/..' . '/doctrine/inflector/lib/Doctrine/Inflector/Rules/Word.php',
'RectorPrefix202308\\Doctrine\\Inflector\\RulesetInflector' => __DIR__ . '/..' . '/doctrine/inflector/lib/Doctrine/Inflector/RulesetInflector.php',
'RectorPrefix202308\\Doctrine\\Inflector\\WordInflector' => __DIR__ . '/..' . '/doctrine/inflector/lib/Doctrine/Inflector/WordInflector.php',
'RectorPrefix202308\\Evenement\\EventEmitter' => __DIR__ . '/..' . '/evenement/evenement/src/Evenement/EventEmitter.php',
'RectorPrefix202308\\Evenement\\EventEmitterInterface' => __DIR__ . '/..' . '/evenement/evenement/src/Evenement/EventEmitterInterface.php',
'RectorPrefix202308\\Evenement\\EventEmitterTrait' => __DIR__ . '/..' . '/evenement/evenement/src/Evenement/EventEmitterTrait.php',
'RectorPrefix202308\\Evenement\\EventEmitter' => __DIR__ . '/..' . '/evenement/evenement/src/EventEmitter.php',
'RectorPrefix202308\\Evenement\\EventEmitterInterface' => __DIR__ . '/..' . '/evenement/evenement/src/EventEmitterInterface.php',
'RectorPrefix202308\\Evenement\\EventEmitterTrait' => __DIR__ . '/..' . '/evenement/evenement/src/EventEmitterTrait.php',
'RectorPrefix202308\\Fidry\\CpuCoreCounter\\CpuCoreCounter' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/CpuCoreCounter.php',
'RectorPrefix202308\\Fidry\\CpuCoreCounter\\Diagnoser' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Diagnoser.php',
'RectorPrefix202308\\Fidry\\CpuCoreCounter\\Executor\\ProcOpenExecutor' => __DIR__ . '/..' . '/fidry/cpu-core-counter/src/Executor/ProcOpenExecutor.php',
@ -3009,9 +3009,9 @@ class ComposerStaticInit24cd621939e1c0be213e3232a0d86dbd
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit24cd621939e1c0be213e3232a0d86dbd::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit24cd621939e1c0be213e3232a0d86dbd::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit24cd621939e1c0be213e3232a0d86dbd::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit9529323d9728a32f7dfa8b6e233dc465::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit9529323d9728a32f7dfa8b6e233dc465::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit9529323d9728a32f7dfa8b6e233dc465::$classMap;
}, null, ClassLoader::class);
}

View File

@ -390,31 +390,31 @@
},
{
"name": "evenement\/evenement",
"version": "v3.0.1",
"version_normalized": "3.0.1.0",
"version": "v3.0.2",
"version_normalized": "3.0.2.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/igorw\/evenement.git",
"reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7"
"reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/igorw\/evenement\/zipball\/531bfb9d15f8aa57454f5f0285b18bec903b8fb7",
"reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7",
"url": "https:\/\/api.github.com\/repos\/igorw\/evenement\/zipball\/0a16b0d71ab13284339abb99d9d2bd813640efbc",
"reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc",
"shasum": ""
},
"require": {
"php": ">=7.0"
},
"require-dev": {
"phpunit\/phpunit": "^6.0"
"phpunit\/phpunit": "^9 || ^6"
},
"time": "2017-07-23T21:35:13+00:00",
"time": "2023-08-08T05:53:35+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"RectorPrefix202308\\Evenement\\": "src\/Evenement\/"
"RectorPrefix202308\\Evenement\\": "src\/"
}
},
"notification-url": "https:\/\/packagist.org\/downloads\/",
@ -434,7 +434,7 @@
],
"support": {
"issues": "https:\/\/github.com\/igorw\/evenement\/issues",
"source": "https:\/\/github.com\/igorw\/evenement\/tree\/master"
"source": "https:\/\/github.com\/igorw\/evenement\/tree\/v3.0.2"
},
"install-path": "..\/evenement\/evenement"
},

File diff suppressed because one or more lines are too long

View File

@ -1,35 +0,0 @@
CHANGELOG
=========
* v3.0.1 (2017-07-23)
* Resolved regression introduced in once listeners in v3.0.0 [#49](https://github.com/igorw/evenement/pull/49)
* v3.0.0 (2017-07-23)
* Passing null as event name throw exception [#46](https://github.com/igorw/evenement/pull/46), and [#47](https://github.com/igorw/evenement/pull/47)
* Performance improvements [#39](https://github.com/igorw/evenement/pull/39), and [#45](https://github.com/igorw/evenement/pull/45)
* Remove once listeners [#44](https://github.com/igorw/evenement/pull/44), [#45](https://github.com/igorw/evenement/pull/45)
* v2.1.0 (2017-07-17)
* Chaining for "on" method [#30](https://github.com/igorw/evenement/pull/30)
* Unit tests (on Travis) improvements [#33](https://github.com/igorw/evenement/pull/33), [#36](https://github.com/igorw/evenement/pull/36), and [#37](https://github.com/igorw/evenement/pull/37)
* Benchmarks added [#35](https://github.com/igorw/evenement/pull/35), and [#40](https://github.com/igorw/evenement/pull/40)
* Minor performance improvements [#42](https://github.com/igorw/evenement/pull/42), and [#38](https://github.com/igorw/evenement/pull/38)
* v2.0.0 (2012-11-02)
* Require PHP >=5.4.0
* Added EventEmitterTrait
* Removed EventEmitter2
* v1.1.0 (2017-07-17)
* Chaining for "on" method [#29](https://github.com/igorw/evenement/pull/29)
* Minor performance improvements [#43](https://github.com/igorw/evenement/pull/43)
* v1.0.0 (2012-05-30)
* Inital stable release

View File

@ -2,51 +2,23 @@
Événement is a very simple event dispatching library for PHP.
It has the same design goals as [Silex](http://silex-project.org) and
[Pimple](http://pimple-project.org), to empower the user while staying concise
It has the same design goals as [Silex](https://silex.symfony.com/) and
[Pimple](https://github.com/silexphp/Pimple), to empower the user while staying concise
and simple.
It is very strongly inspired by the EventEmitter API found in
It is very strongly inspired by the [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) API found in
[node.js](http://nodejs.org).
[![Build Status](https://secure.travis-ci.org/igorw/evenement.png?branch=master)](http://travis-ci.org/igorw/evenement)
![Continuous Integration](https://github.com/igorw/evenement/workflows/CI/badge.svg)
[![Latest Stable Version](https://poser.pugx.org/evenement/evenement/v/stable.png)](https://packagist.org/packages/evenement/evenement)
[![Total Downloads](https://poser.pugx.org/evenement/evenement/downloads.png)](https://packagist.org/packages/evenement/evenement/stats)
[![License](https://poser.pugx.org/evenement/evenement/license.png)](https://packagist.org/packages/evenement/evenement)
## Fetch
The recommended way to install Événement is [through composer](http://getcomposer.org).
The recommended way to install Événement is [through composer](http://getcomposer.org). By running the following command:
Just create a composer.json file for your project:
```JSON
{
"require": {
"evenement/evenement": "^3.0 || ^2.0"
}
}
```
**Note:** The `3.x` version of Événement requires PHP 7 and the `2.x` version requires PHP 5.4. If you are
using PHP 5.3, please use the `1.x` version:
```JSON
{
"require": {
"evenement/evenement": "^1.0"
}
}
```
And run these two commands to install it:
$ curl -s http://getcomposer.org/installer | php
$ php composer.phar install
Now you can add the autoloader, and you will have access to the library:
```php
<?php
require 'vendor/autoload.php';
```
$ composer require evenement/evenement
## Usage
@ -66,6 +38,15 @@ $emitter->on('user.created', function (User $user) use ($logger) {
});
```
### Removing Listeners
```php
<?php
$emitter->removeListener('user.created', function (User $user) use ($logger) {
$logger->log(sprintf("User '%s' was created.", $user->getLogin()));
});
```
### Emitting Events
```php

View File

@ -16,19 +16,19 @@
"php": ">=7.0"
},
"require-dev": {
"phpunit\/phpunit": "^6.0"
"phpunit\/phpunit": "^9 || ^6"
},
"autoload": {
"psr-4": {
"RectorPrefix202308\\Evenement\\": "src\/Evenement\/"
"RectorPrefix202308\\Evenement\\": "src\/"
}
},
"autoload-dev": {
"files": [
"tests\/Evenement\/Tests\/functions.php"
],
"psr-4": {
"RectorPrefix202308\\Evenement\\": "tests\/Evenement\/"
}
"RectorPrefix202308\\Evenement\\Tests\\": "tests\/"
},
"files": [
"tests\/functions.php"
]
}
}

View File

@ -1,28 +0,0 @@
# Introduction
Événement is is French and means "event". The événement library aims to
provide a simple way of subscribing to events and notifying those subscribers
whenever an event occurs.
The API that it exposes is almost a direct port of the EventEmitter API found
in node.js. It also includes an "EventEmitter". There are some minor
differences however.
The EventEmitter is an implementation of the publish-subscribe pattern, which
is a generalized version of the observer pattern. The observer pattern
specifies an observable subject, which observers can register themselves to.
Once something interesting happens, the subject notifies its observers.
Pub/sub takes the same idea but encapsulates the observation logic inside a
separate object which manages all of its subscribers or listeners. Subscribers
are bound to an event name, and will only receive notifications of the events
they subscribed to.
**TLDR: What does evenement do, in short? It provides a mapping from event
names to a list of listener functions and triggers each listener for a given
event when it is emitted.**
Why do we do this, you ask? To achieve decoupling.
It allows you to design a system where the core will emit events, and modules
are able to subscribe to these events. And respond to them.

View File

@ -1,91 +0,0 @@
# API
The API that événement exposes is defined by the
`Evenement\EventEmitterInterface`. The interface is useful if you want to
define an interface that extends the emitter and implicitly defines certain
events to be emitted, or if you want to type hint an `EventEmitter` to be
passed to a method without coupling to the specific implementation.
## on($event, callable $listener)
Allows you to subscribe to an event.
Example:
```php
$emitter->on('user.created', function (User $user) use ($logger) {
$logger->log(sprintf("User '%s' was created.", $user->getLogin()));
});
```
Since the listener can be any callable, you could also use an instance method
instead of the anonymous function:
```php
$loggerSubscriber = new LoggerSubscriber($logger);
$emitter->on('user.created', array($loggerSubscriber, 'onUserCreated'));
```
This has the benefit that listener does not even need to know that the emitter
exists.
You can also accept more than one parameter for the listener:
```php
$emitter->on('numbers_added', function ($result, $a, $b) {});
```
## once($event, callable $listener)
Convenience method that adds a listener which is guaranteed to only be called
once.
Example:
```php
$conn->once('connected', function () use ($conn, $data) {
$conn->send($data);
});
```
## emit($event, array $arguments = [])
Emit an event, which will call all listeners.
Example:
```php
$conn->emit('data', [$data]);
```
The second argument to emit is an array of listener arguments. This is how you
specify more args:
```php
$result = $a + $b;
$emitter->emit('numbers_added', [$result, $a, $b]);
```
## listeners($event)
Allows you to inspect the listeners attached to an event. Particularly useful
to check if there are any listeners at all.
Example:
```php
$e = new \RuntimeException('Everything is broken!');
if (0 === count($emitter->listeners('error'))) {
throw $e;
}
```
## removeListener($event, callable $listener)
Remove a specific listener for a specific event.
## removeAllListeners($event = null)
Remove all listeners for a specific event or all listeners all together. This
is useful for long-running processes, where you want to remove listeners in
order to allow them to get garbage collected.

View File

@ -1,155 +0,0 @@
# Example: Plugin system
In this example I will show you how to create a generic plugin system with
événement where plugins can alter the behaviour of the app. The app is a blog.
Boring, I know. By using the EventEmitter it will be easy to extend this blog
with additional functionality without modifying the core system.
The blog is quite basic. Users are able to create blog posts when they log in.
The users are stored in a static config file, so there is no sign up process.
Once logged in they get a "new post" link which gives them a form where they
can create a new blog post with plain HTML. That will store the post in a
document database. The index lists all blog post titles by date descending.
Clicking on the post title will take you to the full post.
## Plugin structure
The goal of the plugin system is to allow features to be added to the blog
without modifying any core files of the blog.
The plugins are managed through a config file, `plugins.json`. This JSON file
contains a JSON-encoded list of class-names for plugin classes. This allows
you to enable and disable plugins in a central location. The initial
`plugins.json` is just an empty array:
```json
[]
```
A plugin class must implement the `PluginInterface`:
```php
interface PluginInterface
{
function attachEvents(EventEmitterInterface $emitter);
}
```
The `attachEvents` method allows the plugin to attach any events to the
emitter. For example:
```php
class FooPlugin implements PluginInterface
{
public function attachEvents(EventEmitterInterface $emitter)
{
$emitter->on('foo', function () {
echo 'bar!';
});
}
}
```
The blog system creates an emitter instance and loads the plugins:
```php
$emitter = new EventEmitter();
$pluginClasses = json_decode(file_get_contents('plugins.json'), true);
foreach ($pluginClasses as $pluginClass) {
$plugin = new $pluginClass();
$pluginClass->attachEvents($emitter);
}
```
This is the base system. There are no plugins yet, and there are no events yet
either. That's because I don't know which extension points will be needed. I
will add them on demand.
## Feature: Markdown
Writing blog posts in HTML sucks! Wouldn't it be great if I could write them
in a nice format such as markdown, and have that be converted to HTML for me?
This feature will need two extension points. I need to be able to mark posts
as markdown, and I need to be able to hook into the rendering of the post body
and convert it from markdown to HTML. So the blog needs two new events:
`post.create` and `post.render`.
In the code that creates the post, I'll insert the `post.create` event:
```php
class PostEvent
{
public $post;
public function __construct(array $post)
{
$this->post = $post;
}
}
$post = createPostFromRequest($_POST);
$event = new PostEvent($post);
$emitter->emit('post.create', [$event]);
$post = $event->post;
$db->save('post', $post);
```
This shows that you can wrap a value in an event object to make it mutable,
allowing listeners to change it.
The same thing for the `post.render` event:
```php
public function renderPostBody(array $post)
{
$emitter = $this->emitter;
$event = new PostEvent($post);
$emitter->emit('post.render', [$event]);
$post = $event->post;
return $post['body'];
}
<h1><?= $post['title'] %></h1>
<p><?= renderPostBody($post) %></p>
```
Ok, the events are in place. It's time to create the first plugin, woohoo! I
will call this the `MarkdownPlugin`, so here's `plugins.json`:
```json
[
"MarkdownPlugin"
]
```
The `MarkdownPlugin` class will be autoloaded, so I don't have to worry about
including any files. I just have to worry about implementing the plugin class.
The `markdown` function represents a markdown to HTML converter.
```php
class MarkdownPlugin implements PluginInterface
{
public function attachEvents(EventEmitterInterface $emitter)
{
$emitter->on('post.create', function (PostEvent $event) {
$event->post['format'] = 'markdown';
});
$emitter->on('post.render', function (PostEvent $event) {
if (isset($event->post['format']) && 'markdown' === $event->post['format']) {
$event->post['body'] = markdown($event->post['body']);
}
});
}
}
```
There you go, the blog now renders posts as markdown. But all of the previous
posts before the addition of the markdown plugin are still rendered correctly
as raw HTML.
## Feature: Comments
TODO
## Feature: Comment spam control
TODO

View File

@ -1,25 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202308;
/*
* This file is part of Evenement.
*
* (c) Igor Wiedler <igor@wiedler.ch>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
const ITERATIONS = 10000000;
use RectorPrefix202308\Evenement\EventEmitter;
require __DIR__ . '/../vendor/autoload.php';
$emitter = new EventEmitter();
$emitter->on('event', function () {
});
$start = \microtime(\true);
for ($i = 0; $i < \RectorPrefix202308\ITERATIONS; $i++) {
$emitter->emit('event');
}
$time = \microtime(\true) - $start;
echo 'Emitting ', \number_format(\RectorPrefix202308\ITERATIONS), ' events took: ', \number_format($time, 2), 's', \PHP_EOL;

View File

@ -1,26 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202308;
/*
* This file is part of Evenement.
*
* (c) Igor Wiedler <igor@wiedler.ch>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
\ini_set('memory_limit', '512M');
const ITERATIONS = 100000;
use RectorPrefix202308\Evenement\EventEmitter;
require __DIR__ . '/../vendor/autoload.php';
$emitter = new EventEmitter();
for ($i = 0; $i < \RectorPrefix202308\ITERATIONS; $i++) {
$emitter->once('event', function ($a, $b, $c) {
});
}
$start = \microtime(\true);
$emitter->emit('event', [1, 2, 3]);
$time = \microtime(\true) - $start;
echo 'Emitting one event to ', \number_format(\RectorPrefix202308\ITERATIONS), ' once listeners took: ', \number_format($time, 2), 's', \PHP_EOL;

View File

@ -1,25 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202308;
/*
* This file is part of Evenement.
*
* (c) Igor Wiedler <igor@wiedler.ch>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
const ITERATIONS = 10000000;
use RectorPrefix202308\Evenement\EventEmitter;
require __DIR__ . '/../vendor/autoload.php';
$emitter = new EventEmitter();
$emitter->on('event', function ($a) {
});
$start = \microtime(\true);
for ($i = 0; $i < \RectorPrefix202308\ITERATIONS; $i++) {
$emitter->emit('event', [1]);
}
$time = \microtime(\true) - $start;
echo 'Emitting ', \number_format(\RectorPrefix202308\ITERATIONS), ' events took: ', \number_format($time, 2), 's', \PHP_EOL;

View File

@ -1,25 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202308;
/*
* This file is part of Evenement.
*
* (c) Igor Wiedler <igor@wiedler.ch>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
const ITERATIONS = 10000000;
use RectorPrefix202308\Evenement\EventEmitter;
require __DIR__ . '/../vendor/autoload.php';
$emitter = new EventEmitter();
$emitter->on('event', function ($a, $b, $c) {
});
$start = \microtime(\true);
for ($i = 0; $i < \RectorPrefix202308\ITERATIONS; $i++) {
$emitter->emit('event', [1, 2, 3]);
}
$time = \microtime(\true) - $start;
echo 'Emitting ', \number_format(\RectorPrefix202308\ITERATIONS), ' events took: ', \number_format($time, 2), 's', \PHP_EOL;

View File

@ -1,35 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202308;
/*
* This file is part of Evenement.
*
* (c) Igor Wiedler <igor@wiedler.ch>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
\ini_set('memory_limit', '512M');
const ITERATIONS = 100000;
use RectorPrefix202308\Evenement\EventEmitter;
require __DIR__ . '/../vendor/autoload.php';
$emitter = new EventEmitter();
$listeners = [];
for ($i = 0; $i < \RectorPrefix202308\ITERATIONS; $i++) {
$listeners[] = function ($a, $b, $c) {
};
}
$start = \microtime(\true);
foreach ($listeners as $listener) {
$emitter->once('event', $listener);
}
$time = \microtime(\true) - $start;
echo 'Adding ', \number_format(\RectorPrefix202308\ITERATIONS), ' once listeners took: ', \number_format($time, 2), 's', \PHP_EOL;
$start = \microtime(\true);
foreach ($listeners as $listener) {
$emitter->removeListener('event', $listener);
}
$time = \microtime(\true) - $start;
echo 'Removing ', \number_format(\RectorPrefix202308\ITERATIONS), ' once listeners took: ', \number_format($time, 2), 's', \PHP_EOL;

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
>
<testsuites>
<testsuite name="Evenement Test Suite">
<directory>./tests/Evenement/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src/</directory>
</whitelist>
</filter>
</phpunit>

View File

@ -12,6 +12,12 @@ declare (strict_types=1);
namespace RectorPrefix202308\Evenement;
use InvalidArgumentException;
use function count;
use function array_keys;
use function array_merge;
use function array_search;
use function array_unique;
use function array_values;
trait EventEmitterTrait
{
protected $listeners = [];
@ -44,19 +50,19 @@ trait EventEmitterTrait
throw new InvalidArgumentException('event name must not be null');
}
if (isset($this->listeners[$event])) {
$index = \array_search($listener, $this->listeners[$event], \true);
$index = array_search($listener, $this->listeners[$event], \true);
if (\false !== $index) {
unset($this->listeners[$event][$index]);
if (\count($this->listeners[$event]) === 0) {
if (count($this->listeners[$event]) === 0) {
unset($this->listeners[$event]);
}
}
}
if (isset($this->onceListeners[$event])) {
$index = \array_search($listener, $this->onceListeners[$event], \true);
$index = array_search($listener, $this->onceListeners[$event], \true);
if (\false !== $index) {
unset($this->onceListeners[$event][$index]);
if (\count($this->onceListeners[$event]) === 0) {
if (count($this->onceListeners[$event]) === 0) {
unset($this->onceListeners[$event]);
}
}
@ -79,28 +85,35 @@ trait EventEmitterTrait
{
if ($event === null) {
$events = [];
$eventNames = \array_unique(\array_merge(\array_keys($this->listeners), \array_keys($this->onceListeners)));
$eventNames = array_unique(array_merge(array_keys($this->listeners), array_keys($this->onceListeners)));
foreach ($eventNames as $eventName) {
$events[$eventName] = \array_merge(isset($this->listeners[$eventName]) ? $this->listeners[$eventName] : [], isset($this->onceListeners[$eventName]) ? $this->onceListeners[$eventName] : []);
$events[$eventName] = array_merge(isset($this->listeners[$eventName]) ? $this->listeners[$eventName] : [], isset($this->onceListeners[$eventName]) ? $this->onceListeners[$eventName] : []);
}
return $events;
}
return \array_merge(isset($this->listeners[$event]) ? $this->listeners[$event] : [], isset($this->onceListeners[$event]) ? $this->onceListeners[$event] : []);
return array_merge(isset($this->listeners[$event]) ? $this->listeners[$event] : [], isset($this->onceListeners[$event]) ? $this->onceListeners[$event] : []);
}
public function emit($event, array $arguments = [])
{
if ($event === null) {
throw new InvalidArgumentException('event name must not be null');
}
$listeners = [];
if (isset($this->listeners[$event])) {
foreach ($this->listeners[$event] as $listener) {
$listeners = array_values($this->listeners[$event]);
}
$onceListeners = [];
if (isset($this->onceListeners[$event])) {
$onceListeners = array_values($this->onceListeners[$event]);
}
if (empty($listeners) === \false) {
foreach ($listeners as $listener) {
$listener(...$arguments);
}
}
if (isset($this->onceListeners[$event])) {
$listeners = $this->onceListeners[$event];
if (empty($onceListeners) === \false) {
unset($this->onceListeners[$event]);
foreach ($listeners as $listener) {
foreach ($onceListeners as $listener) {
$listener(...$arguments);
}
}

View File

@ -1,345 +0,0 @@
<?php
declare (strict_types=1);
/*
* This file is part of Evenement.
*
* (c) Igor Wiedler <igor@wiedler.ch>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace RectorPrefix202308\Evenement\Tests;
use RectorPrefix202308\Evenement\EventEmitter;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
class EventEmitterTest extends TestCase
{
private $emitter;
public function setUp()
{
$this->emitter = new EventEmitter();
}
public function testAddListenerWithLambda()
{
$this->emitter->on('foo', function () {
});
}
public function testAddListenerWithMethod()
{
$listener = new Listener();
$this->emitter->on('foo', [$listener, 'onFoo']);
}
public function testAddListenerWithStaticMethod()
{
$this->emitter->on('bar', ['RectorPrefix202308\\Evenement\\Tests\\Listener', 'onBar']);
}
public function testAddListenerWithInvalidListener()
{
try {
$this->emitter->on('foo', 'not a callable');
$this->fail();
} catch (\Exception $e) {
} catch (\TypeError $e) {
}
}
public function testOnce()
{
$listenerCalled = 0;
$this->emitter->once('foo', function () use(&$listenerCalled) {
$listenerCalled++;
});
$this->assertSame(0, $listenerCalled);
$this->emitter->emit('foo');
$this->assertSame(1, $listenerCalled);
$this->emitter->emit('foo');
$this->assertSame(1, $listenerCalled);
}
public function testOnceWithArguments()
{
$capturedArgs = [];
$this->emitter->once('foo', function ($a, $b) use(&$capturedArgs) {
$capturedArgs = array($a, $b);
});
$this->emitter->emit('foo', array('a', 'b'));
$this->assertSame(array('a', 'b'), $capturedArgs);
}
public function testEmitWithoutArguments()
{
$listenerCalled = \false;
$this->emitter->on('foo', function () use(&$listenerCalled) {
$listenerCalled = \true;
});
$this->assertSame(\false, $listenerCalled);
$this->emitter->emit('foo');
$this->assertSame(\true, $listenerCalled);
}
public function testEmitWithOneArgument()
{
$test = $this;
$listenerCalled = \false;
$this->emitter->on('foo', function ($value) use(&$listenerCalled, $test) {
$listenerCalled = \true;
$test->assertSame('bar', $value);
});
$this->assertSame(\false, $listenerCalled);
$this->emitter->emit('foo', ['bar']);
$this->assertSame(\true, $listenerCalled);
}
public function testEmitWithTwoArguments()
{
$test = $this;
$listenerCalled = \false;
$this->emitter->on('foo', function ($arg1, $arg2) use(&$listenerCalled, $test) {
$listenerCalled = \true;
$test->assertSame('bar', $arg1);
$test->assertSame('baz', $arg2);
});
$this->assertSame(\false, $listenerCalled);
$this->emitter->emit('foo', ['bar', 'baz']);
$this->assertSame(\true, $listenerCalled);
}
public function testEmitWithNoListeners()
{
$this->emitter->emit('foo');
$this->emitter->emit('foo', ['bar']);
$this->emitter->emit('foo', ['bar', 'baz']);
}
public function testEmitWithTwoListeners()
{
$listenersCalled = 0;
$this->emitter->on('foo', function () use(&$listenersCalled) {
$listenersCalled++;
});
$this->emitter->on('foo', function () use(&$listenersCalled) {
$listenersCalled++;
});
$this->assertSame(0, $listenersCalled);
$this->emitter->emit('foo');
$this->assertSame(2, $listenersCalled);
}
public function testRemoveListenerMatching()
{
$listenersCalled = 0;
$listener = function () use(&$listenersCalled) {
$listenersCalled++;
};
$this->emitter->on('foo', $listener);
$this->emitter->removeListener('foo', $listener);
$this->assertSame(0, $listenersCalled);
$this->emitter->emit('foo');
$this->assertSame(0, $listenersCalled);
}
public function testRemoveListenerNotMatching()
{
$listenersCalled = 0;
$listener = function () use(&$listenersCalled) {
$listenersCalled++;
};
$this->emitter->on('foo', $listener);
$this->emitter->removeListener('bar', $listener);
$this->assertSame(0, $listenersCalled);
$this->emitter->emit('foo');
$this->assertSame(1, $listenersCalled);
}
public function testRemoveAllListenersMatching()
{
$listenersCalled = 0;
$this->emitter->on('foo', function () use(&$listenersCalled) {
$listenersCalled++;
});
$this->emitter->removeAllListeners('foo');
$this->assertSame(0, $listenersCalled);
$this->emitter->emit('foo');
$this->assertSame(0, $listenersCalled);
}
public function testRemoveAllListenersNotMatching()
{
$listenersCalled = 0;
$this->emitter->on('foo', function () use(&$listenersCalled) {
$listenersCalled++;
});
$this->emitter->removeAllListeners('bar');
$this->assertSame(0, $listenersCalled);
$this->emitter->emit('foo');
$this->assertSame(1, $listenersCalled);
}
public function testRemoveAllListenersWithoutArguments()
{
$listenersCalled = 0;
$this->emitter->on('foo', function () use(&$listenersCalled) {
$listenersCalled++;
});
$this->emitter->on('bar', function () use(&$listenersCalled) {
$listenersCalled++;
});
$this->emitter->removeAllListeners();
$this->assertSame(0, $listenersCalled);
$this->emitter->emit('foo');
$this->emitter->emit('bar');
$this->assertSame(0, $listenersCalled);
}
public function testCallablesClosure()
{
$calledWith = null;
$this->emitter->on('foo', function ($data) use(&$calledWith) {
$calledWith = $data;
});
$this->emitter->emit('foo', ['bar']);
self::assertSame('bar', $calledWith);
}
public function testCallablesClass()
{
$listener = new Listener();
$this->emitter->on('foo', [$listener, 'onFoo']);
$this->emitter->emit('foo', ['bar']);
self::assertSame(['bar'], $listener->getData());
}
public function testCallablesClassInvoke()
{
$listener = new Listener();
$this->emitter->on('foo', $listener);
$this->emitter->emit('foo', ['bar']);
self::assertSame(['bar'], $listener->getMagicData());
}
public function testCallablesStaticClass()
{
$this->emitter->on('foo', '\\Evenement\\Tests\\Listener::onBar');
$this->emitter->emit('foo', ['bar']);
self::assertSame(['bar'], Listener::getStaticData());
}
public function testCallablesFunction()
{
$this->emitter->on('foo', 'RectorPrefix202308\\Evenement\\Tests\\setGlobalTestData');
$this->emitter->emit('foo', ['bar']);
self::assertSame('bar', $GLOBALS['evenement-evenement-test-data']);
unset($GLOBALS['evenement-evenement-test-data']);
}
public function testListeners()
{
$onA = function () {
};
$onB = function () {
};
$onC = function () {
};
$onceA = function () {
};
$onceB = function () {
};
$onceC = function () {
};
self::assertCount(0, $this->emitter->listeners('event'));
$this->emitter->on('event', $onA);
self::assertCount(1, $this->emitter->listeners('event'));
self::assertSame([$onA], $this->emitter->listeners('event'));
$this->emitter->once('event', $onceA);
self::assertCount(2, $this->emitter->listeners('event'));
self::assertSame([$onA, $onceA], $this->emitter->listeners('event'));
$this->emitter->once('event', $onceB);
self::assertCount(3, $this->emitter->listeners('event'));
self::assertSame([$onA, $onceA, $onceB], $this->emitter->listeners('event'));
$this->emitter->on('event', $onB);
self::assertCount(4, $this->emitter->listeners('event'));
self::assertSame([$onA, $onB, $onceA, $onceB], $this->emitter->listeners('event'));
$this->emitter->removeListener('event', $onceA);
self::assertCount(3, $this->emitter->listeners('event'));
self::assertSame([$onA, $onB, $onceB], $this->emitter->listeners('event'));
$this->emitter->once('event', $onceC);
self::assertCount(4, $this->emitter->listeners('event'));
self::assertSame([$onA, $onB, $onceB, $onceC], $this->emitter->listeners('event'));
$this->emitter->on('event', $onC);
self::assertCount(5, $this->emitter->listeners('event'));
self::assertSame([$onA, $onB, $onC, $onceB, $onceC], $this->emitter->listeners('event'));
$this->emitter->once('event', $onceA);
self::assertCount(6, $this->emitter->listeners('event'));
self::assertSame([$onA, $onB, $onC, $onceB, $onceC, $onceA], $this->emitter->listeners('event'));
$this->emitter->removeListener('event', $onB);
self::assertCount(5, $this->emitter->listeners('event'));
self::assertSame([$onA, $onC, $onceB, $onceC, $onceA], $this->emitter->listeners('event'));
$this->emitter->emit('event');
self::assertCount(2, $this->emitter->listeners('event'));
self::assertSame([$onA, $onC], $this->emitter->listeners('event'));
}
public function testOnceCallIsNotRemovedWhenWorkingOverOnceListeners()
{
$aCalled = \false;
$aCallable = function () use(&$aCalled) {
$aCalled = \true;
};
$bCalled = \false;
$bCallable = function () use(&$bCalled, $aCallable) {
$bCalled = \true;
$this->emitter->once('event', $aCallable);
};
$this->emitter->once('event', $bCallable);
self::assertFalse($aCalled);
self::assertFalse($bCalled);
$this->emitter->emit('event');
self::assertFalse($aCalled);
self::assertTrue($bCalled);
$this->emitter->emit('event');
self::assertTrue($aCalled);
self::assertTrue($bCalled);
}
public function testEventNameMustBeStringOn()
{
self::expectException(InvalidArgumentException::class);
self::expectExceptionMessage('event name must not be null');
$this->emitter->on(null, function () {
});
}
public function testEventNameMustBeStringOnce()
{
self::expectException(InvalidArgumentException::class);
self::expectExceptionMessage('event name must not be null');
$this->emitter->once(null, function () {
});
}
public function testEventNameMustBeStringRemoveListener()
{
self::expectException(InvalidArgumentException::class);
self::expectExceptionMessage('event name must not be null');
$this->emitter->removeListener(null, function () {
});
}
public function testEventNameMustBeStringEmit()
{
self::expectException(InvalidArgumentException::class);
self::expectExceptionMessage('event name must not be null');
$this->emitter->emit(null);
}
public function testListenersGetAll()
{
$a = function () {
};
$b = function () {
};
$c = function () {
};
$d = function () {
};
$this->emitter->once('event2', $c);
$this->emitter->on('event', $a);
$this->emitter->once('event', $b);
$this->emitter->on('event', $c);
$this->emitter->once('event', $d);
self::assertSame(['event' => [$a, $c, $b, $d], 'event2' => [$c]], $this->emitter->listeners());
}
public function testOnceNestedCallRegression()
{
$first = 0;
$second = 0;
$this->emitter->once('event', function () use(&$first, &$second) {
$first++;
$this->emitter->once('event', function () use(&$second) {
$second++;
});
$this->emitter->emit('event');
});
$this->emitter->emit('event');
self::assertSame(1, $first);
self::assertSame(1, $second);
}
}

View File

@ -1,43 +0,0 @@
<?php
declare (strict_types=1);
/*
* This file is part of Evenement.
*
* (c) Igor Wiedler <igor@wiedler.ch>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace RectorPrefix202308\Evenement\Tests;
class Listener
{
private $data = [];
private $magicData = [];
private static $staticData = [];
public function onFoo($data)
{
$this->data[] = $data;
}
public function __invoke($data)
{
$this->magicData[] = $data;
}
public static function onBar($data)
{
self::$staticData[] = $data;
}
public function getData()
{
return $this->data;
}
public function getMagicData()
{
return $this->magicData;
}
public static function getStaticData()
{
return self::$staticData;
}
}

View File

@ -1,17 +0,0 @@
<?php
declare (strict_types=1);
/*
* This file is part of Evenement.
*
* (c) Igor Wiedler <igor@wiedler.ch>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace RectorPrefix202308\Evenement\Tests;
function setGlobalTestData($data)
{
$GLOBALS['evenement-evenement-test-data'] = $data;
}