Completed
Pull Request — master (#125)
by lan tian
05:28
created

Sms::all()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 4
nc 3
nop 1
crap 3
1
<?php
2
3
namespace Toplan\PhpSms;
4
5
use Toplan\TaskBalance\Driver;
6
use Toplan\TaskBalance\Task;
7
8
/**
9
 * Class Sms
10
 *
11
 * @author toplan<[email protected]>
12
 */
13
class Sms
14
{
15
    const TYPE_SMS = 1;
16
    const TYPE_VOICE = 2;
17
18
    /**
19
     * Task instance.
20
     *
21
     * @var Task
22
     */
23
    protected static $task = null;
24
25
    /**
26
     * Agent instances.
27
     *
28
     * @var Agent[]
29
     */
30
    protected static $agents = [];
31
32
    /**
33
     * Dispatch scheme of agents.
34
     *
35
     * @var array
36
     */
37
    protected static $scheme = [];
38
39
    /**
40
     * Configuration information of agents.
41
     *
42
     * @var array
43
     */
44
    protected static $agentsConfig = [];
45
46
    /**
47
     * Whether to use the queue system.
48
     *
49
     * @var bool
50
     */
51
    protected static $enableQueue = false;
52
53
    /**
54
     * How to use the queue system.
55
     *
56
     * @var \Closure
57
     */
58
    protected static $howToUseQueue = null;
59
60
    /**
61
     * Available hooks.
62
     *
63
     * @var string[]
64
     */
65
    protected static $availableHooks = [
66
        'beforeRun',
67
        'beforeDriverRun',
68
        'afterDriverRun',
69
        'afterRun',
70
    ];
71
72
    /**
73
     * Data container.
74
     *
75
     * @var array
76
     */
77
    protected $smsData = [
78
        'type'      => self::TYPE_SMS,
79
        'to'        => null,
80
        'templates' => [],
81
        'data'      => [],
82
        'content'   => null,
83
        'code'      => null,
84
        'files'     => [],
85
        'params'    => [],
86
    ];
87
88
    /**
89
     * The name of first agent.
90
     *
91
     * @var string
92
     */
93
    protected $firstAgent = null;
94
95
    /**
96
     * Whether pushed to the queue system.
97
     *
98
     * @var bool
99
     */
100
    protected $pushedToQueue = false;
101
102
    /**
103
     * State container.
104
     *
105
     * @var array
106
     */
107
    protected $state = [];
108
109
    /**
110
     * Constructor
111
     *
112
     * @param bool $autoBoot
113
     */
114 6
    public function __construct($autoBoot = true)
115
    {
116 6
        if ($autoBoot) {
117 3
            self::bootTask();
118 3
        }
119 6
    }
120
121
    /**
122
     * Bootstrap the task.
123
     */
124 3
    public static function bootTask()
125
    {
126 3
        if (!self::isTaskBooted()) {
127
            self::configure();
128
            foreach (self::scheme() as $name => $scheme) {
129
                self::registerDriver($name, $scheme);
130
            }
131
        }
132 3
    }
133
134
    /**
135
     * Is task has been booted.
136
     *
137
     * @return bool
138
     */
139 15
    protected static function isTaskBooted()
140
    {
141 15
        return !empty(self::getTask()->drivers);
142
    }
143
144
    /**
145
     * Get the task instance.
146
     *
147
     * @return Task
148
     */
149 24
    public static function getTask()
150
    {
151 24
        if (empty(self::$task)) {
152 3
            self::$task = new Task();
153 3
        }
154
155 24
        return self::$task;
156
    }
157
158
    /**
159
     * Configure.
160
     *
161
     * @throws PhpSmsException
162
     */
163 3
    protected static function configure()
164
    {
165 3
        $config = [];
166 3
        if (!count(self::scheme())) {
167 3
            self::initScheme($config);
168 3
        }
169 3
        $diff = array_diff_key(self::scheme(), self::$agentsConfig);
170 3
        self::initAgentsConfig(array_keys($diff), $config);
171 3
        if (!count(self::scheme())) {
172
            throw new PhpSmsException('Expected at least one agent in scheme.');
173
        }
174 3
    }
175
176
    /**
177
     * Initialize the dispatch scheme.
178
     *
179
     * @param array $config
180
     */
181 3
    protected static function initScheme(array &$config)
182
    {
183 3
        $config = empty($config) ? include __DIR__ . '/../config/phpsms.php' : $config;
184 3
        $scheme = isset($config['scheme']) ? $config['scheme'] : [];
185 3
        self::scheme($scheme);
186 3
    }
187
188
    /**
189
     * Initialize the configuration information.
190
     *
191
     * @param array $agents
192
     * @param array $config
193
     */
194 3
    protected static function initAgentsConfig(array $agents, array &$config)
195
    {
196 3
        if (empty($agents)) {
197
            return;
198
        }
199 3
        $config = empty($config) ? include __DIR__ . '/../config/phpsms.php' : $config;
200 3
        $agentsConfig = isset($config['agents']) ? $config['agents'] : [];
201 3
        foreach ($agents as $name) {
202 3
            $agentConfig = isset($agentsConfig[$name]) ? $agentsConfig[$name] : [];
203 3
            self::config($name, $agentConfig);
204 3
        }
205 3
    }
206
207
    /**
208
     * register driver.
209
     *
210
     * @param string       $name
211
     * @param string|array $scheme
212
     */
213 15
    protected static function registerDriver($name, $scheme)
214
    {
215
        // parse higher-order scheme
216
        $settings = [];
217
        if (is_array($scheme)) {
218
            $settings = self::parseScheme($scheme);
219
            $scheme = $settings['scheme'];
220
        }
221
        // register
222
        self::getTask()->driver("$name $scheme")->work(function (Driver $driver) use ($settings) {
223 15
            $agent = self::getAgent($driver->name, $settings);
224 15
            extract($driver->getTaskData());
0 ignored issues
show
Bug introduced by
$driver->getTaskData() cannot be passed to extract() as the parameter $var_array expects a reference.
Loading history...
225 15
            $template = isset($templates[$driver->name]) ? $templates[$driver->name] : null;
226 15
            $file = isset($files[$driver->name]) ? $files[$driver->name] : null;
227 15
            $params = isset($params[$driver->name]) ? $params[$driver->name] : [];
228 15
            if ($type === self::TYPE_VOICE) {
229
                $agent->sendVoice($to, $content, $template, $data, $code, $file, $params);
230 15
            } elseif ($type === self::TYPE_SMS) {
231 15
                $agent->sendSms($to, $content, $template, $data, $params);
232 15
            }
233 15
            $result = $agent->result();
234 15
            if ($result['success']) {
235 15
                $driver->success();
236 15
            }
237 15
            unset($result['success']);
238
239 15
            return $result;
240
        });
241
    }
242
243
    /**
244
     * Parse the higher-order dispatch scheme.
245
     *
246
     * @param array $options
247
     *
248
     * @return array
249
     */
250
    protected static function parseScheme(array $options)
251
    {
252
        $weight = Util::pullFromArray($options, 'weight');
253
        $backup = Util::pullFromArray($options, 'backup') ? 'backup' : '';
254
        $props = array_filter(array_values($options), function ($prop) {
255
            return is_numeric($prop) || is_string($prop);
256
        });
257
258
        $options['scheme'] = implode(' ', $props) . " $weight $backup";
259
260
        return $options;
261
    }
262
263
    /**
264
     * Get the agent instance by name.
265
     *
266
     * @param string $name
267
     * @param array  $options
268
     *
269
     * @throws PhpSmsException
270
     *
271
     * @return Agent
272
     */
273 24
    public static function getAgent($name, array $options = [])
274
    {
275 24
        if (!self::hasAgent($name)) {
276 6
            $scheme = self::scheme($name);
277 6
            $config = self::config($name);
278 6
            if (is_array($scheme) && empty($options)) {
279
                $options = self::parseScheme($scheme);
280
            }
281 6
            if (isset($options['scheme'])) {
282
                unset($options['scheme']);
283
            }
284 6
            $className = "Toplan\\PhpSms\\{$name}Agent";
285 6
            if (isset($options['agentClass'])) {
286
                $className = $options['agentClass'];
287
                unset($options['agentClass']);
288
            }
289 21
            if (!empty($options)) {
290
                self::$agents[$name] = new ParasiticAgent($config, $options);
291 6
            } elseif (class_exists($className)) {
292 6
                self::$agents[$name] = new $className($config);
293 6
            } else {
294
                throw new PhpSmsException("Not support agent `$name`.");
295
            }
296 6
        }
297
298 24
        return self::$agents[$name];
299
    }
300
301
    /**
302
     * Whether has the specified agent.
303
     *
304
     * @param string $name
305
     *
306
     * @return bool
307
     */
308 33
    public static function hasAgent($name)
309
    {
310 33
        return isset(self::$agents[$name]);
311
    }
312
313
    /**
314
     * Set or get the dispatch scheme.
315
     *
316
     * @param string|array|null      $name
317
     * @param string|array|bool|null $scheme
318
     * @param bool                   $override
319
     *
320
     * @return mixed
321
     */
322 18
    public static function scheme($name = null, $scheme = null, $override = false)
323
    {
324 18
        if (is_array($name) && is_bool($scheme)) {
325 6
            $override = $scheme;
326 6
        }
327
328
        return Util::operateArray(self::$scheme, $name, $scheme, null, function ($key, $value) {
329 6
            if (is_string($key)) {
330 3
                self::modifyScheme($key, is_array($value) ? $value : "$value");
331 6
            } elseif (is_int($key)) {
332 6
                self::modifyScheme($value, '');
333 6
            }
334
        }, $override, function (array $origin) {
335 6
            if (self::isTaskBooted()) {
336 3
                foreach (array_keys($origin) as $name) {
337 3
                    self::getTask()->removeDriver($name);
338 3
                }
339 3
            }
340 18
        });
341
    }
342
343
    /**
344
     * Modify the dispatch scheme of agent.
345
     *
346
     * @param string       $name
347
     * @param string|array $scheme
348
     *
349
     * @throws PhpSmsException
350
     */
351 6
    protected static function modifyScheme($name, $scheme)
352
    {
353 6
        self::validateAgentName($name);
354 6
        self::$scheme[$name] = $scheme;
355 6
        if (self::isTaskBooted()) {
356
            $driver = self::getTask()->getDriver($name);
357
            if ($driver) {
358
                if (is_array($scheme)) {
359
                    $higherOrderScheme = self::parseScheme($scheme);
360
                    $scheme = $higherOrderScheme['scheme'];
361
                }
362
                $driver->reset($scheme);
363
            } else {
364
                self::registerDriver($name, $scheme);
365
            }
366
        }
367 6
    }
368
369
    /**
370
     * Set or get the configuration information.
371
     *
372
     * @param string|array|null $name
373
     * @param array|bool|null   $config
374
     * @param bool              $override
375
     *
376
     * @throws PhpSmsException
377
     *
378
     * @return array
379
     */
380 18
    public static function config($name = null, $config = null, $override = false)
381
    {
382 18
        $overrideAll = (is_array($name) && is_bool($config)) ? $config : false;
383
384
        return Util::operateArray(self::$agentsConfig, $name, $config, [], function ($name, array $config) use ($override) {
385 9
            self::modifyConfig($name, $config, $override);
386
        }, $overrideAll, function (array $origin) {
387 6
            foreach (array_keys($origin) as $name) {
388 6
                if (self::hasAgent("$name")) {
389 3
                    self::getAgent("$name")->config([], true);
390 3
                }
391 6
            }
392 18
        });
393
    }
394
395
    /**
396
     * Modify the configuration information.
397
     *
398
     * @param string $name
399
     * @param array  $config
400
     * @param bool   $override
401
     *
402
     * @throws PhpSmsException
403
     */
404 9
    protected static function modifyConfig($name, array $config, $override = false)
405
    {
406 9
        self::validateAgentName($name);
407 9
        if (!isset(self::$agentsConfig[$name])) {
408 6
            self::$agentsConfig[$name] = [];
409 6
        }
410 9
        $target = &self::$agentsConfig[$name];
411 9
        if ($override) {
412
            $target = $config;
413
        } else {
414 9
            $target = array_merge($target, $config);
415
        }
416 9
        if (self::hasAgent($name)) {
417 3
            self::getAgent($name)->config($target);
418 3
        }
419 9
    }
420
421
    /**
422
     * Validate the agent name.
423
     * Expected type is string, except the string of number.
424
     *
425
     * @param string $name
426
     *
427
     * @throws PhpSmsException
428
     */
429 12
    protected static function validateAgentName($name)
430
    {
431 12
        if (empty($name) || !is_string($name) || preg_match('/^[0-9]+$/', $name)) {
432
            throw new PhpSmsException('Expected the parameter to be string which except the string of number.');
433
        }
434 12
    }
435
436
    /**
437
     * Tear down scheme.
438
     */
439 6
    public static function cleanScheme()
440
    {
441 6
        self::scheme([], true);
442 6
    }
443
444
    /**
445
     * Tear down config information.
446
     */
447 6
    public static function cleanConfig()
448
    {
449 6
        self::config([], true);
450 6
    }
451
452
    /**
453
     * Create a instance for send sms.
454
     *
455
     * @param mixed $agentName
456
     * @param mixed $tempId
457
     *
458
     * @return Sms
459
     */
460
    public static function make($agentName = null, $tempId = null)
461
    {
462
        $sms = new self();
463
        $sms->type(self::TYPE_SMS);
464
        if (is_array($agentName)) {
465
            $sms->template($agentName);
466
        } elseif ($agentName && is_string($agentName)) {
467
            if ($tempId === null) {
468
                $sms->content($agentName);
469
            } elseif (is_string($tempId) || is_int($tempId)) {
470
                $sms->template($agentName, "$tempId");
471
            }
472
        }
473
474
        return $sms;
475
    }
476
477
    /**
478
     * Create a instance for send voice.
479
     *
480
     * @param int|string|null $code
481
     *
482
     * @return Sms
483
     */
484 3
    public static function voice($code = null)
485
    {
486 3
        $sms = new self();
487 3
        $sms->type(self::TYPE_VOICE);
488 3
        $sms->code($code);
489
490 3
        return $sms;
491
    }
492
493
    /**
494
     * Set whether to use the queue system,
495
     * and define how to use it.
496
     *
497
     * @param bool|\Closure|null $enable
498
     * @param \Closure|null      $handler
499
     *
500
     * @return bool
501
     */
502 3
    public static function queue($enable = null, $handler = null)
503
    {
504 3
        if ($enable === null && $handler === null) {
505 3
            return self::$enableQueue;
506
        }
507 3
        if (is_callable($enable)) {
508 3
            $handler = $enable;
509 3
            $enable = true;
510 3
        }
511 3
        self::$enableQueue = (bool) $enable;
512 3
        if (is_callable($handler)) {
513 3
            self::$howToUseQueue = $handler;
514 3
        }
515
516 3
        return self::$enableQueue;
517
    }
518
519
    /**
520
     * Set the type of Sms instance.
521
     *
522
     * @param $type
523
     *
524
     * @throws PhpSmsException
525
     *
526
     * @return $this
527
     */
528 3
    public function type($type)
529
    {
530 3
        if ($type !== self::TYPE_SMS && $type !== self::TYPE_VOICE) {
531
            throw new PhpSmsException('Expected the parameter equals to `Sms::TYPE_SMS` or `Sms::TYPE_VOICE`.');
532
        }
533 3
        $this->smsData['type'] = $type;
534
535 3
        return $this;
536
    }
537
538
    /**
539
     * Set the recipient`s mobile number.
540
     *
541
     * @param string|array $mobile
542
     *
543
     * @return $this
544
     */
545 6
    public function to($mobile)
546
    {
547 6
        if (is_string($mobile)) {
548 6
            $mobile = trim($mobile);
549 6
        }
550 6
        $this->smsData['to'] = $mobile;
551
552 6
        return $this;
553
    }
554
555
    /**
556
     * Set the sms content.
557
     *
558
     * @param string $content
559
     *
560
     * @return $this
561
     */
562 3
    public function content($content)
563
    {
564 3
        $this->smsData['content'] = trim((string) $content);
565
566 3
        return $this;
567
    }
568
569
    /**
570
     * Set the template ids.
571
     *
572
     * @param mixed $name
573
     * @param mixed $tempId
574
     *
575
     * @return $this
576
     */
577 3
    public function template($name, $tempId = null)
578
    {
579 3
        Util::operateArray($this->smsData['templates'], $name, $tempId);
580
581 3
        return $this;
582
    }
583
584
    /**
585
     * Set the template data.
586
     *
587
     * @param mixed $key
588
     * @param mixed $value
589
     *
590
     * @return $this
591
     */
592 3
    public function data($key, $value = null)
593
    {
594 3
        Util::operateArray($this->smsData['data'], $key, $value);
595
596 3
        return $this;
597
    }
598
599
    /**
600
     * Set the voice code.
601
     *
602
     * @param string|int $code
603
     *
604
     * @return $this
605
     */
606 3
    public function code($code)
607
    {
608 3
        $this->smsData['code'] = $code;
609
610 3
        return $this;
611
    }
612
613
    /**
614
     * Set voice files.
615
     *
616
     * @param string|array $name
617
     * @param string|int   $id
618
     *
619
     * @return $this
620
     */
621
    public function files($name, $id = null)
622
    {
623
        Util::operateArray($this->smsData['files'], $name, $id);
624
625
        return $this;
626
    }
627
628
    /**
629
     * Set params of agent.
630
     *
631
     * @param string|array    $name
632
     * @param array|bool|null $params
633
     * @param bool            $override
634
     *
635
     * @return $this
636
     */
637
    public function params($name, $params = null, $override = false)
638
    {
639
        $overrideAll = (is_array($name) && is_bool($params)) ? $params : false;
640
        Util::operateArray($this->smsData['params'], $name, $params, [], function ($name, array $params) use ($override) {
641
            if (!isset($this->smsData['params'][$name])) {
642
                $this->smsData['params'][$name] = [];
643
            }
644
            $target = &$this->smsData['params'][$name];
645
            if ($override) {
646
                $target = $params;
647
            } else {
648
                $target = array_merge($target, $params);
649
            }
650
        }, $overrideAll);
651
652
        return $this;
653
    }
654
655
    /**
656
     * Set the first agent.
657
     *
658
     * @param string $name
659
     *
660
     * @throws PhpSmsException
661
     *
662
     * @return $this
663
     */
664 3
    public function agent($name)
665
    {
666 3
        if (!is_string($name) || empty($name)) {
667
            throw new PhpSmsException('Expected the parameter to be non-empty string.');
668
        }
669 3
        $this->firstAgent = $name;
670
671 3
        return $this;
672
    }
673
674
    /**
675
     * Start send.
676
     *
677
     * If call with a `true` parameter, this system will immediately start request to send sms whatever whether to use the queue.
678
     * if the current instance has pushed to the queue, you can recall this method in queue system without any parameter,
679
     * so this mechanism in order to make you convenient to use this method in queue system.
680
     *
681
     * @param bool $immediately
682
     *
683
     * @return mixed
684
     */
685 18
    public function send($immediately = false)
686
    {
687 18
        if (!self::$enableQueue || $this->pushedToQueue) {
688 18
            $immediately = true;
689 18
        }
690 18
        if ($immediately) {
691 18
            return self::$task->data($this->all())->run($this->firstAgent);
692
        }
693
694 3
        return $this->push();
695
    }
696
697
    /**
698
     * Push to the queue system.
699
     *
700
     * @throws \Exception | PhpSmsException
701
     *
702
     * @return mixed
703
     */
704 3
    public function push()
705
    {
706 3
        if (!is_callable(self::$howToUseQueue)) {
707
            throw new PhpSmsException('Expected define how to use the queue system by methods `queue`.');
708
        }
709
        try {
710 3
            $this->pushedToQueue = true;
711
712 3
            return call_user_func_array(self::$howToUseQueue, [$this, $this->all()]);
713
        } catch (\Exception $e) {
714
            $this->pushedToQueue = false;
715
            throw $e;
716
        }
717
    }
718
719
    /**
720
     * Get all of the data.
721
     *
722
     * @param null|string $key
723
     *
724
     * @return mixed
725
     */
726 36
    public function all($key = null)
727
    {
728 36
        if ($key !== null) {
729 6
            return isset($this->smsData[$key]) ? $this->smsData[$key] : null;
730
        }
731
732 33
        return $this->smsData;
733
    }
734
735
    /**
736
     * Define the static hook methods by overload static method.
737
     *
738
     * @param string $name
739
     * @param array  $args
740
     *
741
     * @throws PhpSmsException
742
     */
743 9
    public static function __callStatic($name, $args)
744
    {
745 9
        $name = $name === 'beforeSend' ? 'beforeRun' : $name;
746 9
        $name = $name === 'afterSend' ? 'afterRun' : $name;
747 9
        $name = $name === 'beforeAgentSend' ? 'beforeDriverRun' : $name;
748 9
        $name = $name === 'afterAgentSend' ? 'afterDriverRun' : $name;
749 9
        if (!in_array($name, self::$availableHooks)) {
750
            throw new PhpSmsException("Not found methods `$name`.");
751
        }
752 9
        $handler = $args[0];
753 9
        $override = isset($args[1]) ? (bool) $args[1] : false;
754 9
        self::getTask()->hook($name, $handler, $override);
755 9
    }
756
757
    /**
758
     * Define the hook methods by overload method.
759
     *
760
     * @param string $name
761
     * @param array  $args
762
     *
763
     * @throws PhpSmsException
764
     * @throws \Exception
765
     */
766 3
    public function __call($name, $args)
767
    {
768
        try {
769 3
            $this->__callStatic($name, $args);
770 3
        } catch (\Exception $e) {
771
            throw $e;
772
        }
773 3
    }
774
775
    /**
776
     * Serialize magic method.
777
     *
778
     * @return array
779
     */
780 3
    public function __sleep()
781
    {
782
        try {
783 3
            $this->state['scheme'] = self::toggleSerializeScheme(self::scheme());
784 3
            $this->state['agentsConfig'] = self::config();
785 3
            $this->state['handlers'] = self::serializeHandlers();
786 3
        } catch (\Exception $e) {
787
            //swallow exception
788
        }
789
790 3
        return ['smsData', 'firstAgent', 'pushedToQueue', 'state'];
791
    }
792
793
    /**
794
     * Deserialize magic method.
795
     */
796 3
    public function __wakeup()
797
    {
798 3
        if (empty($this->state)) {
799
            return;
800
        }
801 3
        self::$scheme = self::toggleSerializeScheme($this->state['scheme']);
802 3
        self::$agentsConfig = $this->state['agentsConfig'];
803 3
        self::reinstallHandlers($this->state['handlers']);
804 3
    }
805
806
    /**
807
     * Serialize or deserialize the scheme.
808
     *
809
     * @param array $scheme
810
     *
811
     * @return array
812
     */
813 3
    protected static function toggleSerializeScheme(array $scheme)
814
    {
815 3
        foreach ($scheme as $name => &$options) {
816 3
            if (is_array($options)) {
817 3
                foreach (ParasiticAgent::methods() as $method) {
818 3
                    self::toggleSerializeClosure($options, $method);
819 3
                }
820 3
            }
821 3
        }
822
823 3
        return $scheme;
824
    }
825
826
    /**
827
     * Serialize the hooks' handlers.
828
     *
829
     * @return array
830
     */
831 3
    protected static function serializeHandlers()
832
    {
833 3
        $hooks = (array) self::getTask()->handlers;
834 3
        foreach ($hooks as &$handlers) {
835 3
            foreach (array_keys($handlers) as $key) {
836 3
                self::toggleSerializeClosure($handlers, $key);
837 3
            }
838 3
        }
839
840 3
        return $hooks;
841
    }
842
843
    /**
844
     * Reinstall hooks' handlers.
845
     *
846
     * @param array $handlers
847
     */
848 3
    protected static function reinstallHandlers(array $handlers)
849
    {
850 3
        $serializer = Util::getClosureSerializer();
851 3
        foreach ($handlers as $hookName => $serializedHandlers) {
852 3
            foreach ($serializedHandlers as $index => $handler) {
853 3
                if (is_string($handler)) {
854 3
                    $handler = $serializer->unserialize($handler);
855 3
                }
856 3
                self::$hookName($handler, $index === 0);
857 3
            }
858 3
        }
859 3
    }
860
861
    /**
862
     * Serialize or deserialize the specified closure and then replace the original value.
863
     *
864
     * @param array      $options
865
     * @param int|string $key
866
     */
867 3
    protected static function toggleSerializeClosure(array &$options, $key)
868
    {
869 3
        if (!isset($options[$key])) {
870 3
            return;
871
        }
872 3
        $serializer = Util::getClosureSerializer();
873 3
        if (is_callable($options[$key])) {
874 3
            $options[$key] = (string) $serializer->serialize($options[$key]);
875 3
        } elseif (is_string($options[$key])) {
876 3
            $options[$key] = $serializer->unserialize($options[$key]);
877 3
        }
878 3
    }
879
}
880