1: <?php
2: /*
3: * SimpleID
4: *
5: * Copyright (C) Kelvin Mo 2021-2025
6: *
7: * This program is free software; you can redistribute it and/or
8: * modify it under the terms of the GNU General Public
9: * License as published by the Free Software Foundation; either
10: * version 2 of the License, or (at your option) any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public
18: * License along with this program; if not, write to the Free
19: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20: *
21: */
22:
23: namespace SimpleID\Util\Events;
24:
25: /**
26: * A generic event used to collect data.
27: *
28: * This class implements f3-event-dispatcher's GenericEventInterface, and
29: * therefore the event name is specified by the `$eventName` parameter
30: * passed in the constructor.
31: *
32: * Listeners add data by calling the {@link addResult()} method. How
33: * this is added to the existing data depends on the merge strategy:
34: *
35: * - If the merge strategy is `MERGE_APPEND`, then the result
36: * is appended to the existing data
37: * - If the merge strategy is `MERGE_PLAIN`, then the result
38: * is merged to the existing data using `array_merge`
39: * - If the merge strategy is `MERGE_RECURSIVE`, then the result
40: * is merged to the existing data using `array_merge_recursive`
41: * - If the merge strategy is `MERGE_DEFAULT`, then the result is
42: * appended if it is a scalar, or merged if it is an array
43: *
44: * The emitter can retrieve the collected data by calling the
45: * {@link getResults()} method.
46: */
47: class BaseDataCollectionEvent extends BaseEvent implements \GenericEventInterface {
48: use GenericEventTrait;
49:
50: public const MERGE_DEFAULT = 0;
51: public const MERGE_APPEND = 1;
52: public const MERGE_PLAIN = 2;
53: public const MERGE_RECURSIVE = 3;
54:
55: // alias
56: public const MERGE_MERGE = self::MERGE_PLAIN;
57:
58: /** @var array<mixed> */
59: protected $results = [];
60:
61: /** @var int */
62: protected $mergeStrategy;
63:
64: /**
65: * Creates a data collection event
66: *
67: * @param string $eventName the name of the event, or the null to use the
68: * name of this class
69: * @param int $mergeStrategy whether the merge will be mergeStrategy
70: */
71: public function __construct($eventName = null, $mergeStrategy = self::MERGE_DEFAULT) {
72: $this->setEventName($eventName);
73: $this->mergeStrategy = $mergeStrategy;
74: }
75:
76:
77: /**
78: * Adds data to the event.
79: *
80: * If the data to be added is an array, it is merged with the existing data.
81: * If the data to be added is a scalar, it is appended to the existing data.
82: *
83: * @param mixed $result the data to add
84: * @return void
85: */
86: public function addResult($result) {
87: if ($this->isEmpty($result)) return;
88:
89: // If recursive, result must be an array
90: if (($this->mergeStrategy == self::MERGE_RECURSIVE) && !is_array($result))
91: throw new \InvalidArgumentException('result must be an array if recursive merge');
92:
93: if ($this->mergeStrategy == self::MERGE_DEFAULT) {
94: $merge_strategy = (is_array($result)) ? self::MERGE_PLAIN : self::MERGE_APPEND;
95: } else {
96: $merge_strategy = $this->mergeStrategy;
97: }
98:
99: switch ($merge_strategy) {
100: case self::MERGE_APPEND:
101: $this->results[] = $result;
102: break;
103: case self::MERGE_PLAIN:
104: $this->results = array_merge($this->results, $result);
105: break;
106: case self::MERGE_RECURSIVE:
107: $this->results = array_merge_recursive($this->results, $result);
108: break;
109: }
110: }
111:
112: /**
113: * Retrieves the data collected from the event.
114: *
115: * If no data is collected, an empty array is returned.
116: *
117: * @return array<mixed>
118: */
119: public function getResults() {
120: return $this->results;
121: }
122:
123: /**
124: * Returns whether any data have been collected by the
125: * event.
126: *
127: * @return bool true if data have been collected
128: */
129: public function hasResults() {
130: return (count($this->results) > 0);
131: }
132:
133: /**
134: * Returns whether a variable is "empty".
135: *
136: * A variable is empty if it is null or is a zero-length array.
137: *
138: * @param mixed $x the variable
139: * @return bool true if the variable is empty
140: */
141: protected function isEmpty($x) {
142: return (($x == null) || (is_array($x) && (count($x) == 0)));
143: }
144: }
145:
146: ?>