Completed
Push — master ( 508240...149fba )
by Vasily
03:46
created

EventHandlers::cleanupEventHandlers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
namespace PHPDaemon\Traits;
3
4
use PHPDaemon\Core\CallbackWrapper;
5
use PHPDaemon\Core\Daemon;
6
7
/**
8
 * Event handlers trait
9
 * @package PHPDaemon\Traits
10
 * @author  Zorin Vasily <[email protected]>
11
 */
12
trait EventHandlers {
13
	/**
14
	 * @var array Event handlers
15
	 */
16
	protected $eventHandlers = [];
17
18
	/**
19
	 * @var boolean Unshift $this to arguments of callback?
20
	 */
21
	protected $addThisToEvents = true;
22
23
	/**
24
	 * @var string Last called event name
25
	 */
26
	protected $lastEventName;
27
28
	/**
29
	 * Propagate event
30
	 * @param  string $name    Event name
0 ignored issues
show
Bug introduced by
There is no parameter named $name. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
31
	 * @param  mixed  ...$args Arguments
32
	 * @return this
0 ignored issues
show
Documentation introduced by
Should the return type not be EventHandlers?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
33
	 */
34 View Code Duplication
	public function event() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
35
		$args = func_get_args();
36
		$name = array_shift($args);
37
		if ($this->addThisToEvents) {
38
			array_unshift($args, $this);
39
		}
40
		if (isset($this->eventHandlers[$name])) {
41
			$this->lastEventName = $name;
42
			foreach ($this->eventHandlers[$name] as $cb) {
43
				if (call_user_func_array($cb, $args) === true) {
44
					return $this;
45
				}
46
			}
47
		}
48
		return $this;
49
	}
50
51
	/**
52
	 * Propagate event
53
	 * @param  string $name    Event name
0 ignored issues
show
Bug introduced by
There is no parameter named $name. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
54
	 * @param  mixed  ...$args Arguments
55
	 * @return this
0 ignored issues
show
Documentation introduced by
Should the return type not be EventHandlers?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
56
	 */
57 View Code Duplication
	public function trigger() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
58
		$args = func_get_args();
59
		$name = array_shift($args);
60
		if ($this->addThisToEvents) {
61
			array_unshift($args, $this);
62
		}
63
		if (isset($this->eventHandlers[$name])) {
64
			$this->lastEventName = $name;
65
			foreach ($this->eventHandlers[$name] as $cb) {
66
				if (call_user_func_array($cb, $args) === true) {
67
					return $this;
68
				}
69
			}
70
		}
71
		return $this;
72
	}
73
74
	/**
75
	 * Propagate event
76
	 * @param  string $name    Event name
0 ignored issues
show
Bug introduced by
There is no parameter named $name. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
77
	 * @param  mixed  ...$args Arguments
78
	 * @return integer
79
	 */
80
	public function triggerAndCount() {
81
		$args = func_get_args();
82
		$name = array_shift($args);
83
		if ($this->addThisToEvents) {
84
			array_unshift($args, $this);
85
		}
86
		$cnt = 0;
87
		if (isset($this->eventHandlers[$name])) {
88
			$this->lastEventName = $name;
89
			foreach ($this->eventHandlers[$name] as $cb) {
90
				if (call_user_func_array($cb, $args) !== 0) {
91
					++$cnt;
92
				}
93
			}
94
		}
95
		return $cnt;
96
	}
97
98
	/**
99
	 * Use it to define event name, when one callback was bind to more than one events
100
	 * @return string
101
	 */
102
	public function getLastEventName() {
103
		return $this->lastEventName;
104
	}
105
106
	/**
107
	 * Bind event or events
108
	 * @param string|array $event Event name
109
	 * @param callable     $cb    Callback
110
	 * @return this
0 ignored issues
show
Documentation introduced by
Should the return type not be EventHandlers?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
111
	 */
112
	public function bind($event, $cb) {
113
		if ($cb !== null) {
114
			$cb = CallbackWrapper::wrap($cb);
115
		}
116
		is_array($event) or $event = [$event];
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
117
		foreach ($event as $e) {
0 ignored issues
show
Bug introduced by
The expression $event of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
118
			CallbackWrapper::addToArray($this->eventHandlers[$e], $cb);
119
		}
120
		return $this;
121
	}
122
123
	/**
124
	 * Bind event or events
125
	 * @alias EventHandlers::bind
126
	 * @param string|array $event Event name
127
	 * @param callable     $cb    Callback
128
	 * @return this
0 ignored issues
show
Documentation introduced by
Should the return type not be EventHandlers?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
129
	 */
130
	public function on($event, $cb) {
131
		return $this->bind($event, $cb);
132
	}
133
134
	/**
135
	 * Unbind event(s) or callback from event(s)
136
	 * @param string|array $event Event name
137
	 * @param callable     $cb    Callback, optional
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
138
	 * @return this
0 ignored issues
show
Documentation introduced by
Should the return type not be EventHandlers?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
139
	 */
140
	public function unbind($event, $cb = null) {
141
		if ($cb !== null) {
142
			$cb = CallbackWrapper::wrap($cb);
143
		}
144
		is_array($event) or $event = [$event];
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
145
		$success = true;
0 ignored issues
show
Unused Code introduced by
$success is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
146
		foreach ($event as $e) {
0 ignored issues
show
Bug introduced by
The expression $event of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
147
			if (!isset($this->eventHandlers[$e])) {
148
				$success = false;
0 ignored issues
show
Unused Code introduced by
$success is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
149
				continue;
150
			}
151
			if ($cb === null) {
152
				unset($this->eventHandlers[$e]);
153
				continue;
154
			}
155
			CallbackWrapper::removeFromArray($this->eventHandlers[$e], $cb);
156
		}
157
		return $this;
158
	}
159
160
	/**
161
	 * Unbind event(s) or callback from event(s)
162
	 * @alias EventHandlers::unbind
163
	 * @param string|array $event Event name
164
	 * @param callable     $cb    Callback, optional
165
	 * @return this
0 ignored issues
show
Documentation introduced by
Should the return type not be EventHandlers?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
166
	 */
167
	public function off($event, $cb) {
168
		return $this->unbind($event, $cb);
169
	}
170
171
	/**
172
	 * Clean up all events
173
	 * @return void
174
	 */
175
	protected function cleanupEventHandlers() {
176
		$this->eventHandlers = [];
177
		//Daemon::log('clean up event handlers '.get_class($this). ' -- '.$this->attrs->server['REQUEST_URI']. PHP_EOL .Debug::backtrace());
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 134 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
178
	}
179
}
180