Completed
Push — master ( 1d8fed...863918 )
by lan tian
12s
created

Sms::file()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 3
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 2
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 2
        }
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 2
        }
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 2
        }
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 2
        }
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 10
            }
233 15
            $result = $agent->result();
234 15
            if ($result['success']) {
235 15
                $driver->success();
236 10
            }
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 16
            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 4
            } else {
294
                throw new PhpSmsException("Not support agent `$name`.");
295
            }
296 4
        }
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 4
        }
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 4
            }
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 2
                }
339 2
            }
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 4
                    self::getAgent("$name")->config([], true);
390 2
                }
391 4
            }
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 4
        }
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 2
        }
419 9
    }
420
421
    /**
422
     * Validate the name of agent.
423
     *
424
     * @param string $name
425
     *
426
     * @throws PhpSmsException
427
     */
428 12
    protected static function validateAgentName($name)
429
    {
430 12
        if (empty($name) || !is_string($name) || preg_match('/^[0-9]+$/', $name)) {
431
            throw new PhpSmsException('Expected the name of agent to be a string which except the digital string.');
432
        }
433 12
    }
434
435
    /**
436
     * Tear down scheme.
437
     */
438 6
    public static function cleanScheme()
439
    {
440 6
        self::scheme([], true);
441 6
    }
442
443
    /**
444
     * Tear down config information.
445
     */
446 6
    public static function cleanConfig()
447
    {
448 6
        self::config([], true);
449 6
    }
450
451
    /**
452
     * Create a instance for send sms.
453
     *
454
     * @param mixed $agentName
455
     * @param mixed $tempId
456
     *
457
     * @return Sms
458
     */
459
    public static function make($agentName = null, $tempId = null)
460
    {
461
        $sms = new self();
462
        $sms->type(self::TYPE_SMS);
463
        if (is_array($agentName)) {
464
            $sms->template($agentName);
465
        } elseif ($agentName && is_string($agentName)) {
466
            if ($tempId === null) {
467
                $sms->content($agentName);
468
            } elseif (is_string($tempId) || is_int($tempId)) {
469
                $sms->template($agentName, "$tempId");
470
            }
471
        }
472
473
        return $sms;
474
    }
475
476
    /**
477
     * Create a instance for send voice.
478
     *
479
     * @param int|string|null $code
480
     *
481
     * @return Sms
482
     */
483 3
    public static function voice($code = null)
484
    {
485 3
        $sms = new self();
486 3
        $sms->type(self::TYPE_VOICE);
487 3
        $sms->code($code);
488
489 3
        return $sms;
490
    }
491
492
    /**
493
     * Set whether to use the queue system,
494
     * and define how to use it.
495
     *
496
     * @param bool|\Closure|null $enable
497
     * @param \Closure|null      $handler
498
     *
499
     * @return bool
500
     */
501 3
    public static function queue($enable = null, $handler = null)
502
    {
503 3
        if ($enable === null && $handler === null) {
504 3
            return self::$enableQueue;
505
        }
506 3
        if (is_callable($enable)) {
507 3
            $handler = $enable;
508 3
            $enable = true;
509 2
        }
510 3
        self::$enableQueue = (bool) $enable;
511 3
        if (is_callable($handler)) {
512 3
            self::$howToUseQueue = $handler;
513 2
        }
514
515 3
        return self::$enableQueue;
516
    }
517
518
    /**
519
     * Set the type of Sms instance.
520
     *
521
     * @param $type
522
     *
523
     * @throws PhpSmsException
524
     *
525
     * @return $this
526
     */
527 3
    public function type($type)
528
    {
529 3
        if ($type !== self::TYPE_SMS && $type !== self::TYPE_VOICE) {
530
            throw new PhpSmsException('Expected the parameter equals to `Sms::TYPE_SMS` or `Sms::TYPE_VOICE`.');
531
        }
532 3
        $this->smsData['type'] = $type;
533
534 3
        return $this;
535
    }
536
537
    /**
538
     * Set the recipient`s mobile number.
539
     *
540
     * @param string|array $mobile
541
     *
542
     * @return $this
543
     */
544 6
    public function to($mobile)
545
    {
546 6
        if (is_string($mobile)) {
547 6
            $mobile = trim($mobile);
548 4
        }
549 6
        $this->smsData['to'] = $mobile;
550
551 6
        return $this;
552
    }
553
554
    /**
555
     * Set the sms content.
556
     *
557
     * @param string $content
558
     *
559
     * @return $this
560
     */
561 3
    public function content($content)
562
    {
563 3
        $this->smsData['content'] = trim((string) $content);
564
565 3
        return $this;
566
    }
567
568
    /**
569
     * Set the template ids.
570
     *
571
     * @param mixed $name
572
     * @param mixed $tempId
573
     *
574
     * @return $this
575
     */
576 3
    public function template($name, $tempId = null)
577
    {
578 3
        Util::operateArray($this->smsData['templates'], $name, $tempId);
579
580 3
        return $this;
581
    }
582
583
    /**
584
     * Set the template data.
585
     *
586
     * @param mixed $key
587
     * @param mixed $value
588
     *
589
     * @return $this
590
     */
591 3
    public function data($key, $value = null)
592
    {
593 3
        Util::operateArray($this->smsData['data'], $key, $value);
594
595 3
        return $this;
596
    }
597
598
    /**
599
     * Set the voice code.
600
     *
601
     * @param string|int $code
602
     *
603
     * @return $this
604
     */
605 3
    public function code($code)
606
    {
607 3
        $this->smsData['code'] = $code;
608
609 3
        return $this;
610
    }
611
612
    /**
613
     * Set voice file.
614
     *
615
     * @param string|array $name
616
     * @param string|int   $id
617
     *
618
     * @return $this
619
     */
620
    public function file($name, $id = null)
621
    {
622
        Util::operateArray($this->smsData['files'], $name, $id);
623
624
        return $this;
625
    }
626
627
    /**
628
     * Set params of agent.
629
     *
630
     * @param string|array    $name
631
     * @param array|bool|null $params
632
     * @param bool            $override
633
     *
634
     * @return $this
635
     */
636
    public function params($name, $params = null, $override = false)
637
    {
638
        $overrideAll = (is_array($name) && is_bool($params)) ? $params : false;
639
        Util::operateArray($this->smsData['params'], $name, $params, [], function ($name, array $params) use ($override) {
640
            if (!isset($this->smsData['params'][$name])) {
641
                $this->smsData['params'][$name] = [];
642
            }
643
            $target = &$this->smsData['params'][$name];
644
            if ($override) {
645
                $target = $params;
646
            } else {
647
                $target = array_merge($target, $params);
648
            }
649
        }, $overrideAll);
650
651
        return $this;
652
    }
653
654
    /**
655
     * Set the first agent.
656
     *
657
     * @param string $name
658
     *
659
     * @throws PhpSmsException
660
     *
661
     * @return $this
662
     */
663 3
    public function agent($name)
664
    {
665 3
        if (!is_string($name) || empty($name)) {
666
            throw new PhpSmsException('Expected the parameter to be non-empty string.');
667
        }
668 3
        $this->firstAgent = $name;
669
670 3
        return $this;
671
    }
672
673
    /**
674
     * Start send.
675
     *
676
     * If call with a `true` parameter, this system will immediately start request to send sms whatever whether to use the queue.
677
     * if the current instance has pushed to the queue, you can recall this method in queue system without any parameter,
678
     * so this mechanism in order to make you convenient to use this method in queue system.
679
     *
680
     * @param bool $immediately
681
     *
682
     * @return mixed
683
     */
684 18
    public function send($immediately = false)
685
    {
686 18
        if (!self::$enableQueue || $this->pushedToQueue) {
687 18
            $immediately = true;
688 12
        }
689 18
        if ($immediately) {
690 18
            return self::$task->data($this->all())->run($this->firstAgent);
691
        }
692
693 3
        return $this->push();
694
    }
695
696
    /**
697
     * Push to the queue system.
698
     *
699
     * @throws \Exception | PhpSmsException
700
     *
701
     * @return mixed
702
     */
703 3
    public function push()
704
    {
705 3
        if (!is_callable(self::$howToUseQueue)) {
706
            throw new PhpSmsException('Expected define how to use the queue system by methods `queue`.');
707
        }
708
        try {
709 3
            $this->pushedToQueue = true;
710
711 3
            return call_user_func_array(self::$howToUseQueue, [$this, $this->all()]);
712
        } catch (\Exception $e) {
713
            $this->pushedToQueue = false;
714
            throw $e;
715
        }
716
    }
717
718
    /**
719
     * Get all of the data.
720
     *
721
     * @param null|string $key
722
     *
723
     * @return mixed
724
     */
725 36
    public function all($key = null)
726
    {
727 36
        if ($key !== null) {
728 6
            return isset($this->smsData[$key]) ? $this->smsData[$key] : null;
729
        }
730
731 33
        return $this->smsData;
732
    }
733
734
    /**
735
     * Define the static hook methods by overload static method.
736
     *
737
     * @param string $name
738
     * @param array  $args
739
     *
740
     * @throws PhpSmsException
741
     */
742 9
    public static function __callStatic($name, $args)
743
    {
744 9
        $name = $name === 'beforeSend' ? 'beforeRun' : $name;
745 9
        $name = $name === 'afterSend' ? 'afterRun' : $name;
746 9
        $name = $name === 'beforeAgentSend' ? 'beforeDriverRun' : $name;
747 9
        $name = $name === 'afterAgentSend' ? 'afterDriverRun' : $name;
748 9
        if (!in_array($name, self::$availableHooks)) {
749
            throw new PhpSmsException("Not found methods `$name`.");
750
        }
751 9
        $handler = $args[0];
752 9
        $override = isset($args[1]) ? (bool) $args[1] : false;
753 9
        self::getTask()->hook($name, $handler, $override);
754 9
    }
755
756
    /**
757
     * Define the hook methods by overload method.
758
     *
759
     * @param string $name
760
     * @param array  $args
761
     *
762
     * @throws PhpSmsException
763
     * @throws \Exception
764
     */
765 3
    public function __call($name, $args)
766
    {
767
        try {
768 3
            $this->__callStatic($name, $args);
769 2
        } catch (\Exception $e) {
770
            throw $e;
771
        }
772 3
    }
773
774
    /**
775
     * Serialize magic method.
776
     *
777
     * @return array
778
     */
779 3
    public function __sleep()
780
    {
781
        try {
782 3
            $this->state['scheme'] = self::toggleSerializeScheme(self::scheme());
783 3
            $this->state['agentsConfig'] = self::config();
784 3
            $this->state['handlers'] = self::serializeHandlers();
785 2
        } catch (\Exception $e) {
786
            //swallow exception
787
        }
788
789 3
        return ['smsData', 'firstAgent', 'pushedToQueue', 'state'];
790
    }
791
792
    /**
793
     * Deserialize magic method.
794
     */
795 3
    public function __wakeup()
796
    {
797 3
        if (empty($this->state)) {
798
            return;
799
        }
800 3
        self::$scheme = self::toggleSerializeScheme($this->state['scheme']);
801 3
        self::$agentsConfig = $this->state['agentsConfig'];
802 3
        self::reinstallHandlers($this->state['handlers']);
803 3
    }
804
805
    /**
806
     * Serialize or deserialize the scheme.
807
     *
808
     * @param array $scheme
809
     *
810
     * @return array
811
     */
812 3
    protected static function toggleSerializeScheme(array $scheme)
813
    {
814 3
        foreach ($scheme as $name => &$options) {
815 3
            if (is_array($options)) {
816 3
                foreach (ParasiticAgent::methods() as $method) {
817 3
                    self::toggleSerializeClosure($options, $method);
818 2
                }
819 2
            }
820 2
        }
821
822 3
        return $scheme;
823
    }
824
825
    /**
826
     * Serialize the hooks' handlers.
827
     *
828
     * @return array
829
     */
830 3
    protected static function serializeHandlers()
831
    {
832 3
        $hooks = (array) self::getTask()->handlers;
833 3
        foreach ($hooks as &$handlers) {
834 3
            foreach (array_keys($handlers) as $key) {
835 3
                self::toggleSerializeClosure($handlers, $key);
836 2
            }
837 2
        }
838
839 3
        return $hooks;
840
    }
841
842
    /**
843
     * Reinstall hooks' handlers.
844
     *
845
     * @param array $handlers
846
     */
847 3
    protected static function reinstallHandlers(array $handlers)
848
    {
849 3
        $serializer = Util::getClosureSerializer();
850 3
        foreach ($handlers as $hookName => $serializedHandlers) {
851 3
            foreach ($serializedHandlers as $index => $handler) {
852 3
                if (is_string($handler)) {
853 3
                    $handler = $serializer->unserialize($handler);
854 2
                }
855 3
                self::$hookName($handler, $index === 0);
856 2
            }
857 2
        }
858 3
    }
859
860
    /**
861
     * Serialize or deserialize the specified closure and then replace the original value.
862
     *
863
     * @param array      $options
864
     * @param int|string $key
865
     */
866 3
    protected static function toggleSerializeClosure(array &$options, $key)
867
    {
868 3
        if (!isset($options[$key])) {
869 3
            return;
870
        }
871 3
        $serializer = Util::getClosureSerializer();
872 3
        if (is_callable($options[$key])) {
873 3
            $options[$key] = (string) $serializer->serialize($options[$key]);
874 3
        } elseif (is_string($options[$key])) {
875 3
            $options[$key] = $serializer->unserialize($options[$key]);
876 2
        }
877 3
    }
878
}
879