Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Database\Eloquent\Concerns;
4
 
5
use Illuminate\Contracts\Events\Dispatcher;
6
use Illuminate\Events\NullDispatcher;
7
use Illuminate\Support\Arr;
8
use InvalidArgumentException;
9
 
10
trait HasEvents
11
{
12
    /**
13
     * The event map for the model.
14
     *
15
     * Allows for object-based events for native Eloquent events.
16
     *
17
     * @var array
18
     */
19
    protected $dispatchesEvents = [];
20
 
21
    /**
22
     * User exposed observable events.
23
     *
24
     * These are extra user-defined events observers may subscribe to.
25
     *
26
     * @var array
27
     */
28
    protected $observables = [];
29
 
30
    /**
31
     * Register observers with the model.
32
     *
33
     * @param  object|array|string  $classes
34
     * @return void
35
     *
36
     * @throws \RuntimeException
37
     */
38
    public static function observe($classes)
39
    {
40
        $instance = new static;
41
 
42
        foreach (Arr::wrap($classes) as $class) {
43
            $instance->registerObserver($class);
44
        }
45
    }
46
 
47
    /**
48
     * Register a single observer with the model.
49
     *
50
     * @param  object|string  $class
51
     * @return void
52
     *
53
     * @throws \RuntimeException
54
     */
55
    protected function registerObserver($class)
56
    {
57
        $className = $this->resolveObserverClassName($class);
58
 
59
        // When registering a model observer, we will spin through the possible events
60
        // and determine if this observer has that method. If it does, we will hook
61
        // it into the model's event system, making it convenient to watch these.
62
        foreach ($this->getObservableEvents() as $event) {
63
            if (method_exists($class, $event)) {
64
                static::registerModelEvent($event, $className.'@'.$event);
65
            }
66
        }
67
    }
68
 
69
    /**
70
     * Resolve the observer's class name from an object or string.
71
     *
72
     * @param  object|string  $class
73
     * @return string
74
     *
75
     * @throws \InvalidArgumentException
76
     */
77
    private function resolveObserverClassName($class)
78
    {
79
        if (is_object($class)) {
80
            return get_class($class);
81
        }
82
 
83
        if (class_exists($class)) {
84
            return $class;
85
        }
86
 
87
        throw new InvalidArgumentException('Unable to find observer: '.$class);
88
    }
89
 
90
    /**
91
     * Get the observable event names.
92
     *
93
     * @return array
94
     */
95
    public function getObservableEvents()
96
    {
97
        return array_merge(
98
            [
99
                'retrieved', 'creating', 'created', 'updating', 'updated',
100
                'saving', 'saved', 'restoring', 'restored', 'replicating',
399 lars 101
                'deleting', 'deleted', 'forceDeleting', 'forceDeleted',
148 lars 102
            ],
103
            $this->observables
104
        );
105
    }
106
 
107
    /**
108
     * Set the observable event names.
109
     *
110
     * @param  array  $observables
111
     * @return $this
112
     */
113
    public function setObservableEvents(array $observables)
114
    {
115
        $this->observables = $observables;
116
 
117
        return $this;
118
    }
119
 
120
    /**
121
     * Add an observable event name.
122
     *
123
     * @param  array|mixed  $observables
124
     * @return void
125
     */
126
    public function addObservableEvents($observables)
127
    {
128
        $this->observables = array_unique(array_merge(
129
            $this->observables, is_array($observables) ? $observables : func_get_args()
130
        ));
131
    }
132
 
133
    /**
134
     * Remove an observable event name.
135
     *
136
     * @param  array|mixed  $observables
137
     * @return void
138
     */
139
    public function removeObservableEvents($observables)
140
    {
141
        $this->observables = array_diff(
142
            $this->observables, is_array($observables) ? $observables : func_get_args()
143
        );
144
    }
145
 
146
    /**
147
     * Register a model event with the dispatcher.
148
     *
149
     * @param  string  $event
150
     * @param  \Illuminate\Events\QueuedClosure|\Closure|string|array  $callback
151
     * @return void
152
     */
153
    protected static function registerModelEvent($event, $callback)
154
    {
155
        if (isset(static::$dispatcher)) {
156
            $name = static::class;
157
 
158
            static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);
159
        }
160
    }
161
 
162
    /**
163
     * Fire the given event for the model.
164
     *
165
     * @param  string  $event
166
     * @param  bool  $halt
167
     * @return mixed
168
     */
169
    protected function fireModelEvent($event, $halt = true)
170
    {
171
        if (! isset(static::$dispatcher)) {
172
            return true;
173
        }
174
 
175
        // First, we will get the proper method to call on the event dispatcher, and then we
176
        // will attempt to fire a custom, object based event for the given event. If that
177
        // returns a result we can return that result, or we'll call the string events.
178
        $method = $halt ? 'until' : 'dispatch';
179
 
180
        $result = $this->filterModelEventResults(
181
            $this->fireCustomModelEvent($event, $method)
182
        );
183
 
184
        if ($result === false) {
185
            return false;
186
        }
187
 
188
        return ! empty($result) ? $result : static::$dispatcher->{$method}(
189
            "eloquent.{$event}: ".static::class, $this
190
        );
191
    }
192
 
193
    /**
194
     * Fire a custom model event for the given event.
195
     *
196
     * @param  string  $event
197
     * @param  string  $method
198
     * @return mixed|null
199
     */
200
    protected function fireCustomModelEvent($event, $method)
201
    {
202
        if (! isset($this->dispatchesEvents[$event])) {
203
            return;
204
        }
205
 
206
        $result = static::$dispatcher->$method(new $this->dispatchesEvents[$event]($this));
207
 
208
        if (! is_null($result)) {
209
            return $result;
210
        }
211
    }
212
 
213
    /**
214
     * Filter the model event results.
215
     *
216
     * @param  mixed  $result
217
     * @return mixed
218
     */
219
    protected function filterModelEventResults($result)
220
    {
221
        if (is_array($result)) {
222
            $result = array_filter($result, function ($response) {
223
                return ! is_null($response);
224
            });
225
        }
226
 
227
        return $result;
228
    }
229
 
230
    /**
231
     * Register a retrieved model event with the dispatcher.
232
     *
233
     * @param  \Illuminate\Events\QueuedClosure|\Closure|string|array  $callback
234
     * @return void
235
     */
236
    public static function retrieved($callback)
237
    {
238
        static::registerModelEvent('retrieved', $callback);
239
    }
240
 
241
    /**
242
     * Register a saving model event with the dispatcher.
243
     *
244
     * @param  \Illuminate\Events\QueuedClosure|\Closure|string|array  $callback
245
     * @return void
246
     */
247
    public static function saving($callback)
248
    {
249
        static::registerModelEvent('saving', $callback);
250
    }
251
 
252
    /**
253
     * Register a saved model event with the dispatcher.
254
     *
255
     * @param  \Illuminate\Events\QueuedClosure|\Closure|string|array  $callback
256
     * @return void
257
     */
258
    public static function saved($callback)
259
    {
260
        static::registerModelEvent('saved', $callback);
261
    }
262
 
263
    /**
264
     * Register an updating model event with the dispatcher.
265
     *
266
     * @param  \Illuminate\Events\QueuedClosure|\Closure|string|array  $callback
267
     * @return void
268
     */
269
    public static function updating($callback)
270
    {
271
        static::registerModelEvent('updating', $callback);
272
    }
273
 
274
    /**
275
     * Register an updated model event with the dispatcher.
276
     *
277
     * @param  \Illuminate\Events\QueuedClosure|\Closure|string|array  $callback
278
     * @return void
279
     */
280
    public static function updated($callback)
281
    {
282
        static::registerModelEvent('updated', $callback);
283
    }
284
 
285
    /**
286
     * Register a creating model event with the dispatcher.
287
     *
288
     * @param  \Illuminate\Events\QueuedClosure|\Closure|string|array  $callback
289
     * @return void
290
     */
291
    public static function creating($callback)
292
    {
293
        static::registerModelEvent('creating', $callback);
294
    }
295
 
296
    /**
297
     * Register a created model event with the dispatcher.
298
     *
299
     * @param  \Illuminate\Events\QueuedClosure|\Closure|string|array  $callback
300
     * @return void
301
     */
302
    public static function created($callback)
303
    {
304
        static::registerModelEvent('created', $callback);
305
    }
306
 
307
    /**
308
     * Register a replicating model event with the dispatcher.
309
     *
310
     * @param  \Illuminate\Events\QueuedClosure|\Closure|string|array  $callback
311
     * @return void
312
     */
313
    public static function replicating($callback)
314
    {
315
        static::registerModelEvent('replicating', $callback);
316
    }
317
 
318
    /**
319
     * Register a deleting model event with the dispatcher.
320
     *
321
     * @param  \Illuminate\Events\QueuedClosure|\Closure|string|array  $callback
322
     * @return void
323
     */
324
    public static function deleting($callback)
325
    {
326
        static::registerModelEvent('deleting', $callback);
327
    }
328
 
329
    /**
330
     * Register a deleted model event with the dispatcher.
331
     *
332
     * @param  \Illuminate\Events\QueuedClosure|\Closure|string|array  $callback
333
     * @return void
334
     */
335
    public static function deleted($callback)
336
    {
337
        static::registerModelEvent('deleted', $callback);
338
    }
339
 
340
    /**
341
     * Remove all the event listeners for the model.
342
     *
343
     * @return void
344
     */
345
    public static function flushEventListeners()
346
    {
347
        if (! isset(static::$dispatcher)) {
348
            return;
349
        }
350
 
351
        $instance = new static;
352
 
353
        foreach ($instance->getObservableEvents() as $event) {
354
            static::$dispatcher->forget("eloquent.{$event}: ".static::class);
355
        }
356
 
357
        foreach (array_values($instance->dispatchesEvents) as $event) {
358
            static::$dispatcher->forget($event);
359
        }
360
    }
361
 
362
    /**
363
     * Get the event dispatcher instance.
364
     *
365
     * @return \Illuminate\Contracts\Events\Dispatcher
366
     */
367
    public static function getEventDispatcher()
368
    {
369
        return static::$dispatcher;
370
    }
371
 
372
    /**
373
     * Set the event dispatcher instance.
374
     *
375
     * @param  \Illuminate\Contracts\Events\Dispatcher  $dispatcher
376
     * @return void
377
     */
378
    public static function setEventDispatcher(Dispatcher $dispatcher)
379
    {
380
        static::$dispatcher = $dispatcher;
381
    }
382
 
383
    /**
384
     * Unset the event dispatcher for models.
385
     *
386
     * @return void
387
     */
388
    public static function unsetEventDispatcher()
389
    {
390
        static::$dispatcher = null;
391
    }
392
 
393
    /**
394
     * Execute a callback without firing any model events for any model type.
395
     *
396
     * @param  callable  $callback
397
     * @return mixed
398
     */
399
    public static function withoutEvents(callable $callback)
400
    {
401
        $dispatcher = static::getEventDispatcher();
402
 
403
        if ($dispatcher) {
404
            static::setEventDispatcher(new NullDispatcher($dispatcher));
405
        }
406
 
407
        try {
408
            return $callback();
409
        } finally {
410
            if ($dispatcher) {
411
                static::setEventDispatcher($dispatcher);
412
            }
413
        }
414
    }
415
}