Completed
Push — master ( 13cabb...9cf391 )
by lan tian
6s
created

Sms::__wakeup()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2.004

Importance

Changes 7
Bugs 1 Features 0
Metric Value
c 7
b 1
f 0
dl 0
loc 12
ccs 9
cts 10
cp 0.9
rs 9.4285
cc 2
eloc 9
nc 2
nop 0
crap 2.004
1
<?php
2
3
namespace Toplan\PhpSms;
4
5
use SuperClosure\Serializer;
6
use Toplan\TaskBalance\Balancer;
7
use Toplan\TaskBalance\Task;
8
9
/**
10
 * Class Sms
11
 *
12
 * @author toplan<[email protected]>
13
 */
14
class Sms
15
{
16
    const TASK_NAME = 'PhpSms';
17
    const TYPE_SMS = 1;
18
    const TYPE_VOICE = 2;
19
20
    /**
21
     * The instances of Agent.
22
     *
23
     * @var array
24
     */
25
    protected static $agents = [];
26
27
    /**
28
     * Agent use scheme, and these agents are available.
29
     * example:
30
     * [
31
     *   'Agent1' => '10 backup',
32
     *   'Agent2' => '20 backup',
33
     * ]
34
     *
35
     * @var array
36
     */
37
    protected static $scheme = [];
38
39
    /**
40
     * The configuration information of agents.
41
     *
42
     * @var array
43
     */
44
    protected static $agentsConfig = [];
45
46
    /**
47
     * Whether to use the queue.
48
     *
49
     * @var bool
50
     */
51
    protected static $enableQueue = false;
52
53
    /**
54
     * How to use the queue.
55
     *
56
     * @var \Closure
57
     */
58
    protected static $howToUseQueue = null;
59
60
    /**
61
     * The available hooks for balancing task.
62
     *
63
     * @var array
64
     */
65
    protected static $availableHooks = [
66
        'beforeRun',
67
        'beforeDriverRun',
68
        'afterDriverRun',
69
        'afterRun',
70
    ];
71
72
    /**
73
     * An instance of class [SuperClosure\Serializer] use for serialization closures.
74
     *
75
     * @var Serializer
76
     */
77
    protected static $serializer = null;
78
79
    /**
80
     * The data container of SMS/voice verify.
81
     *
82
     * @var array
83
     */
84
    protected $smsData = [
85
        'type'         => self::TYPE_SMS,
86
        'to'           => null,
87
        'templates'    => [],
88
        'templateData' => [],
89
        'content'      => null,
90
        'voiceCode'    => null,
91
    ];
92
93
    /**
94
     * The name of first agent.
95
     *
96
     * @var string|null
97
     */
98
    protected $firstAgent = null;
99
100
    /**
101
     * Whether the current instance has already pushed to the queue system.
102
     *
103
     * @var bool
104
     */
105
    protected $pushedToQueue = false;
106
107
    /**
108
     * Status container,
109
     * store some configuration information before serialize current instance(before enqueue).
110
     *
111
     * @var array
112
     */
113
    protected $_status_before_enqueue_ = [];
114
115
    /**
116
     * Constructor
117
     *
118
     * @param bool $autoBoot
119
     */
120 6
    public function __construct($autoBoot = true)
121
    {
122 6
        if ($autoBoot) {
123 3
            self::bootstrap();
124 2
        }
125 6
    }
126
127
    /**
128
     * Boot balancing task for send SMS/voice verify.
129
     *
130
     * Note: 判断drivers是否为空不能用'empty',因为在TaskBalance库的中Task类的drivers属性是受保护的(不可访问),
131
     * 虽然通过魔术方法可以获取到其值,但在其目前版本(v0.4.2)其内部却并没有使用'__isset'魔术方法对'empty'或'isset'函数进行逻辑补救.
132
     */
133 6
    public static function bootstrap()
134
    {
135 6
        $task = self::getTask();
136 6
        if (!count($task->drivers)) {
137 3
            self::configuration();
138 3
            self::createDrivers($task);
139 2
        }
140 6
    }
141
142
    /**
143
     * Get or generate a balancing task instance for send SMS/voice verify.
144
     *
145
     * @return Task
146
     */
147 15
    public static function getTask()
148
    {
149 15
        if (!Balancer::hasTask(self::TASK_NAME)) {
150 3
            Balancer::task(self::TASK_NAME);
151 2
        }
152
153 15
        return Balancer::getTask(self::TASK_NAME);
154
    }
155
156
    /**
157
     * Configuration.
158
     */
159 6
    protected static function configuration()
160
    {
161 6
        $config = [];
162 6
        if (empty(self::$scheme)) {
163 3
            self::initScheme($config);
164 2
        }
165 6
        $diff = array_diff_key(self::$scheme, self::$agentsConfig);
166 6
        self::initAgentsConfig(array_keys($diff), $config);
167 6
        self::validateConfig();
168 6
    }
169
170
    /**
171
     * Try to read agent use scheme from config file.
172
     *
173
     * @param array $config
174
     */
175 3
    protected static function initScheme(array &$config)
176
    {
177 3
        $config = empty($config) ? include __DIR__ . '/../config/phpsms.php' : $config;
178 3
        $scheme = isset($config['scheme']) ? $config['scheme'] : [];
179 3
        self::scheme($scheme);
180 3
    }
181
182
    /**
183
     * Try to initialize the specified agents` configuration information.
184
     *
185
     * @param array $agents
186
     * @param array $config
187
     */
188 6
    protected static function initAgentsConfig(array $agents, array &$config)
189
    {
190 6
        if (empty($agents)) {
191 3
            return;
192
        }
193 3
        $config = empty($config) ? include __DIR__ . '/../config/phpsms.php' : $config;
194 3
        $agentsConfig = isset($config['agents']) ? $config['agents'] : [];
195 3
        foreach ($agents as $name) {
196 3
            $agentConfig = isset($agentsConfig[$name]) ? $agentsConfig[$name] : [];
197 3
            self::config($name, $agentConfig);
198 2
        }
199 3
    }
200
201
    /**
202
     * validate configuration.
203
     *
204
     * @throws PhpSmsException
205
     */
206 6
    protected static function validateConfig()
207
    {
208 6
        if (empty(self::$scheme)) {
209
            throw new PhpSmsException('Please configure at least one agent');
210
        }
211 6
    }
212
213
    /**
214
     * Create drivers for the balancing task.
215
     *
216
     * @param Task $task
217
     */
218 18
    protected static function createDrivers(Task $task)
219
    {
220 3
        foreach (self::$scheme as $name => $scheme) {
221
            //获取代理器配置
222 3
            $configData = self::config($name);
223
224
            //解析代理器数组模式的调度配置
225 3
            if (is_array($scheme)) {
226 3
                $data = self::parseScheme($scheme);
227 3
                $configData = array_merge($configData, $data);
228 3
                $scheme = $data['scheme'];
229 2
            }
230 3
            $scheme = is_string($scheme) ? $scheme : '';
231
232
            //创建任务驱动器
233 3
            $task->driver("$name $scheme")->data($configData)
234 18
                 ->work(function ($driver) {
235 18
                     $configData = $driver->getDriverData();
236 18
                     $agent = self::getAgent($driver->name, $configData);
237 18
                     $smsData = $driver->getTaskData();
238 18
                     extract($smsData);
239 18
                     $template = isset($templates[$driver->name]) ? $templates[$driver->name] : 0;
240 18
                     if ($type === self::TYPE_VOICE) {
241
                         $agent->voiceVerify($to, $voiceCode, $template, $templateData);
242 18
                     } elseif ($type === self::TYPE_SMS) {
243 18
                         $agent->sendSms($to, $content, $template, $templateData);
244 12
                     }
245 18
                     $result = $agent->result();
246 18
                     if ($result['success']) {
247 18
                         $driver->success();
248 12
                     }
249 18
                     unset($result['success']);
250
251 18
                     return $result;
252 3
                 });
253 2
        }
254 3
    }
255
256
    /**
257
     * Parsing scheduling configuration.
258
     * 解析代理器的数组模式的调度配置
259
     *
260
     * @param array $options
261
     *
262
     * @return array
263
     */
264 3
    protected static function parseScheme(array $options)
265
    {
266 3
        $agentClass = self::pullOptionOutOfArrayByKey($options, 'agentClass');
267 3
        $sendSms = self::pullOptionOutOfArrayByKey($options, 'sendSms');
268 3
        $voiceVerify = self::pullOptionOutOfArrayByKey($options, 'voiceVerify');
269 3
        $backup = self::pullOptionOutOfArrayByKey($options, 'backup') ? 'backup' : '';
270 3
        $scheme = implode(' ', array_values($options)) . " $backup";
271
272 3
        return compact('agentClass', 'sendSms', 'voiceVerify', 'scheme');
273
    }
274
275
    /**
276
     * Pull the value out of the specified array by key.
277
     *
278
     * @param array      $options
279
     * @param int|string $key
280
     *
281
     * @return mixed
282
     */
283 3
    protected static function pullOptionOutOfArrayByKey(array &$options, $key)
284
    {
285 3
        if (!isset($options[$key])) {
286 3
            return;
287
        }
288 3
        $value = $options[$key];
289 3
        unset($options[$key]);
290
291 3
        return $value;
292
    }
293
294
    /**
295
     * Get a sms agent instance by agent name,
296
     * if null, will try to create a new agent instance.
297
     *
298
     * @param string $name
299
     * @param array  $configData
300
     *
301
     * @throws PhpSmsException
302
     *
303
     * @return mixed
304
     */
305 21
    public static function getAgent($name, array $configData)
306
    {
307 21
        if (!isset(self::$agents[$name])) {
308 6
            $configData['name'] = $name;
309 6
            $className = isset($configData['agentClass']) ? $configData['agentClass'] : ('Toplan\\PhpSms\\' . $name . 'Agent');
310 6
            if ((isset($configData['sendSms']) && is_callable($configData['sendSms'])) ||
311 6
                (isset($configData['voiceVerify']) && is_callable($configData['voiceVerify']))) {
312
                //创建寄生代理器
313 3
                $configData['agentClass'] = '';
314 3
                self::$agents[$name] = new ParasiticAgent($configData);
315 5
            } elseif (class_exists($className)) {
316
                //创建新代理器
317 3
                self::$agents[$name] = new $className($configData);
318 2
            } else {
319
                //无代理器可用
320
                throw new PhpSmsException("Dont support [$name] agent.");
321
            }
322 4
        }
323
324 21
        return self::$agents[$name];
325
    }
326
327
    /**
328
     * Set or get agent use scheme by agent name.
329
     *
330
     * @param mixed $agentName
331
     * @param mixed $scheme
332
     *
333
     * @return mixed
334
     */
335 12
    public static function scheme($agentName = null, $scheme = null)
336
    {
337 12 View Code Duplication
        if (($agentName === null || is_string($agentName)) && $scheme === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
338 12
            return $agentName === null ? self::$scheme :
339 12
                (isset(self::$scheme[$agentName]) ? self::$scheme[$agentName] : null);
340
        }
341 6
        if (is_array($agentName)) {
342 6
            foreach ($agentName as $name => $value) {
343 6
                self::scheme($name, $value);
344 4
            }
345 6
        } elseif ($agentName && is_string($agentName)) {
346 3
            self::$scheme["$agentName"] = is_array($scheme) ? $scheme : "$scheme";
347 6
        } elseif (is_int($agentName) && $scheme && is_string($scheme)) {
348 6
            self::$scheme["$scheme"] = '';
349 4
        }
350
351 6
        return self::$scheme;
352
    }
353
354
    /**
355
     * Set or get configuration information by agent name.
356
     *
357
     * @param mixed $agentName
358
     * @param mixed $config
359
     *
360
     * @throws PhpSmsException
361
     *
362
     * @return array
363
     */
364 12
    public static function config($agentName = null, $config = null)
365
    {
366 12 View Code Duplication
        if (($agentName === null || is_string($agentName)) && $config === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
367 12
            return $agentName === null ? self::$agentsConfig :
368 12
                (isset(self::$agentsConfig[$agentName]) ? self::$agentsConfig[$agentName] : []);
369
        }
370 6
        if (is_array($agentName)) {
371 3
            foreach ($agentName as $name => $value) {
372 3
                self::config($name, $value);
373 2
            }
374 6
        } elseif ($agentName && is_array($config)) {
375 6
            if (preg_match('/^[0-9]+$/', $agentName)) {
376
                throw new PhpSmsException("Agent name [$agentName] must be string, can not be a pure digital");
377
            }
378 6
            self::$agentsConfig["$agentName"] = $config;
379 4
        }
380
381 6
        return self::$agentsConfig;
382
    }
383
384
    /**
385
     * Tear down agent use scheme and prepare to create and start a new balancing task,
386
     * so before do it must destroy old task instance.
387
     */
388 6
    public static function cleanScheme()
389
    {
390 6
        Balancer::destroy(self::TASK_NAME);
391 6
        self::$scheme = [];
392 6
    }
393
394
    /**
395
     * Tear down all the configuration information of agent.
396
     */
397 3
    public static function cleanConfig()
398
    {
399 3
        self::$agentsConfig = [];
400 3
    }
401
402
    /**
403
     * Create a sms instance send SMS,
404
     * your can also set SMS templates or content at the same time.
405
     *
406
     * @param mixed $agentName
407
     * @param mixed $tempId
408
     *
409
     * @return Sms
410
     */
411
    public static function make($agentName = null, $tempId = null)
412
    {
413
        $sms = new self();
414
        $sms->smsData['type'] = self::TYPE_SMS;
415
        if (is_array($agentName)) {
416
            $sms->template($agentName);
417
        } elseif ($agentName && is_string($agentName)) {
418
            if ($tempId === null) {
419
                $sms->content($agentName);
420
            } elseif (is_string("$tempId")) {
421
                $sms->template($agentName, $tempId);
422
            }
423
        }
424
425
        return $sms;
426
    }
427
428
    /**
429
     * Create a sms instance send voice verify,
430
     * your can also set verify code at the same time.
431
     *
432
     * @param int|string|null $code
433
     *
434
     * @return Sms
435
     */
436 3
    public static function voice($code = null)
437
    {
438 3
        $sms = new self();
439 3
        $sms->smsData['type'] = self::TYPE_VOICE;
440 3
        $sms->smsData['voiceCode'] = $code;
441
442 3
        return $sms;
443
    }
444
445
    /**
446
     * Set whether to use the queue system, and define how to use it.
447
     *
448
     * @param mixed $enable
449
     * @param mixed $handler
450
     *
451
     * @return bool
452
     */
453 3
    public static function queue($enable = null, $handler = null)
454
    {
455 3
        if ($enable === null && $handler === null) {
456 3
            return self::$enableQueue;
457
        }
458 3
        if (is_callable($enable)) {
459 3
            $handler = $enable;
460 3
            $enable = true;
461 2
        }
462 3
        self::$enableQueue = (bool) $enable;
463 3
        if (is_callable($handler)) {
464 3
            self::$howToUseQueue = $handler;
0 ignored issues
show
Documentation Bug introduced by
It seems like $handler of type callable is incompatible with the declared type object<Closure> of property $howToUseQueue.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
465 2
        }
466
467 3
        return self::$enableQueue;
468
    }
469
470
    /**
471
     * Set the recipient`s mobile number.
472
     *
473
     * @param string $mobile
474
     *
475
     * @return $this
476
     */
477 6
    public function to($mobile)
478
    {
479 6
        $this->smsData['to'] = $mobile;
480
481 6
        return $this;
482
    }
483
484
    /**
485
     * Set the content for content SMS.
486
     *
487
     * @param string $content
488
     *
489
     * @return $this
490
     */
491 3
    public function content($content)
492
    {
493 3
        $this->smsData['content'] = trim((string) $content);
494
495 3
        return $this;
496
    }
497
498
    /**
499
     * Set the template id for template SMS.
500
     *
501
     * @param mixed $agentName
502
     * @param mixed $tempId
503
     *
504
     * @return $this
505
     */
506 3
    public function template($agentName, $tempId = null)
507
    {
508 3
        if (is_array($agentName)) {
509 3
            foreach ($agentName as $k => $v) {
510 3
                $this->template($k, $v);
511 2
            }
512 3
        } elseif ($agentName && $tempId) {
513 3
            if (!isset($this->smsData['templates']) || !is_array($this->smsData['templates'])) {
514
                $this->smsData['templates'] = [];
515
            }
516 3
            $this->smsData['templates']["$agentName"] = $tempId;
517 2
        }
518
519 3
        return $this;
520
    }
521
522
    /**
523
     * Set the template data for template SMS.
524
     *
525
     * @param array $data
526
     *
527
     * @return $this
528
     */
529 3
    public function data(array $data)
530
    {
531 3
        $this->smsData['templateData'] = $data;
532
533 3
        return $this;
534
    }
535
536
    /**
537
     * Set the first agent by name.
538
     *
539
     * @param string $name
540
     *
541
     * @return $this
542
     */
543 3
    public function agent($name)
544
    {
545 3
        $this->firstAgent = (string) $name;
546
547 3
        return $this;
548
    }
549
550
    /**
551
     * Start send SMS/voice verify.
552
     *
553
     * If give a true parameter, this system will immediately start request to send SMS/voice verify whatever whether to use the queue.
554
     * if you are already pushed sms instance to the queue, you can recall the method `send()` in queue system without `true` parameter,
555
     * so this mechanism in order to make you convenient use the method `send()` in queue system.
556
     *
557
     * @param bool $immediately
558
     *
559
     * @return mixed
560
     */
561 18
    public function send($immediately = false)
562
    {
563 18
        if (!self::$enableQueue || $this->pushedToQueue) {
564 18
            $immediately = true;
565 12
        }
566 18
        if ($immediately) {
567 18
            $result = Balancer::run(self::TASK_NAME, [
568 18
                'data'   => $this->getData(),
569 18
                'driver' => $this->firstAgent,
570 12
            ]);
571 12
        } else {
572 3
            $result = $this->push();
573
        }
574
575 18
        return $result;
576
    }
577
578
    /**
579
     * Push to the queue by a custom method.
580
     *
581
     * @throws \Exception | PhpSmsException
582
     *
583
     * @return mixed
584
     */
585 3
    public function push()
586
    {
587 3
        if (is_callable(self::$howToUseQueue)) {
588
            try {
589 3
                $this->pushedToQueue = true;
590
591 3
                return call_user_func_array(self::$howToUseQueue, [$this, $this->smsData]);
592
            } catch (\Exception $e) {
593
                $this->pushedToQueue = false;
594
                throw $e;
595
            }
596
        } else {
597
            throw new PhpSmsException('Please define how to use queue by method `queue($available, $handler)`');
598
        }
599
    }
600
601
    /**
602
     * Get all the data of SMS/voice verify.
603
     *
604
     * @param null|string $name
605
     *
606
     * @return mixed
607
     */
608 36
    public function getData($name = null)
609
    {
610 36
        if (is_string($name) && isset($this->smsData["$name"])) {
611 3
            return $this->smsData[$name];
612
        }
613
614 36
        return $this->smsData;
615
    }
616
617
    /**
618
     * Overload static method.
619
     *
620
     * @param string $name
621
     * @param array  $args
622
     *
623
     * @throws PhpSmsException
624
     */
625 9
    public static function __callStatic($name, $args)
626
    {
627 9
        $name = $name === 'beforeSend' ? 'beforeRun' : $name;
628 9
        $name = $name === 'afterSend' ? 'afterRun' : $name;
629 9
        $name = $name === 'beforeAgentSend' ? 'beforeDriverRun' : $name;
630 9
        $name = $name === 'afterAgentSend' ? 'afterDriverRun' : $name;
631 9
        if (in_array($name, self::$availableHooks)) {
632 9
            $handler = $args[0];
633 9
            $override = isset($args[1]) ? (bool) $args[1] : false;
634 9
            if (is_callable($handler)) {
635 9
                $task = self::getTask();
636 9
                $task->hook($name, $handler, $override);
637 6
            } else {
638 3
                throw new PhpSmsException("Please give method $name() a callable parameter");
639
            }
640 6
        } else {
641
            throw new PhpSmsException("Dont find method $name()");
642
        }
643 9
    }
644
645
    /**
646
     * Overload method.
647
     *
648
     * @param string $name
649
     * @param array  $args
650
     *
651
     * @throws PhpSmsException
652
     * @throws \Exception
653
     */
654 3
    public function __call($name, $args)
655
    {
656
        try {
657 3
            $this->__callStatic($name, $args);
658 2
        } catch (\Exception $e) {
659
            throw $e;
660
        }
661 3
    }
662
663
    /**
664
     * Serialize magic method.
665
     *
666
     * @return array
667
     */
668 3
    public function __sleep()
669
    {
670
        try {
671 3
            $this->_status_before_enqueue_['scheme'] = self::serializeOrDeserializeScheme(self::scheme());
672 3
            $this->_status_before_enqueue_['agentsConfig'] = self::config();
673 3
            $this->_status_before_enqueue_['handlers'] = self::serializeHandlers();
674 2
        } catch (\Exception $e) {
675
            //swallow exception
676
        }
677
678 3
        return ['smsData', 'firstAgent', 'pushedToQueue', '_status_before_enqueue_'];
679
    }
680
681
    /**
682
     * Deserialize magic method.
683
     */
684 3
    public function __wakeup()
685
    {
686 3
        if (empty($this->_status_before_enqueue_)) {
687
            return;
688
        }
689 3
        $status = $this->_status_before_enqueue_;
690 3
        self::$scheme = self::serializeOrDeserializeScheme($status['scheme']);
691 3
        self::$agentsConfig = $status['agentsConfig'];
692 3
        Balancer::destroy(self::TASK_NAME);
693 3
        self::bootstrap();
694 3
        self::reinstallHandlers($status['handlers']);
695 3
    }
696
697
    /**
698
     * Get a closure serializer.
699
     *
700
     * @return Serializer
701
     */
702 3
    protected static function getSerializer()
703
    {
704 3
        if (!self::$serializer) {
705 3
            self::$serializer = new Serializer();
706 2
        }
707
708 3
        return self::$serializer;
709
    }
710
711
    /**
712
     * Serialize or deserialize the agent use scheme.
713
     *
714
     * @param array $scheme
715
     *
716
     * @return array
717
     */
718 3
    protected static function serializeOrDeserializeScheme(array $scheme)
719
    {
720 3
        foreach ($scheme as $name => &$options) {
721 3
            if (is_array($options)) {
722 3
                self::serializeOrDeserializeClosureAndReplace($options, 'sendSms');
723 3
                self::serializeOrDeserializeClosureAndReplace($options, 'voiceVerify');
724 2
            }
725 2
        }
726
727 3
        return $scheme;
728
    }
729
730
    /**
731
     * Serialize the hooks` handlers of balancing task
732
     *
733
     * @return array
734
     */
735 3
    protected static function serializeHandlers()
736
    {
737 3
        $task = self::getTask();
738 3
        $hooks = $task->handlers;
739 3
        foreach ($hooks as &$handlers) {
740 3
            foreach (array_keys($handlers) as $key) {
741 3
                self::serializeOrDeserializeClosureAndReplace($handlers, $key);
742 2
            }
743 2
        }
744
745 3
        return $hooks;
746
    }
747
748
    /**
749
     * Reinstall hooks` handlers for balancing task.
750
     *
751
     * @param array $handlers
752
     */
753 3
    protected static function reinstallHandlers(array $handlers)
754
    {
755 3
        $serializer = self::getSerializer();
756 3
        foreach ($handlers as $hookName => $serializedHandlers) {
757 3
            foreach ($serializedHandlers as $index => $handler) {
758 3
                if (is_string($handler)) {
759 3
                    $handler = $serializer->unserialize($handler);
760 2
                }
761 3
                self::$hookName($handler, $index === 0);
762 2
            }
763 2
        }
764 3
    }
765
766
    /**
767
     * Serialize/deserialize the specified closure and replace the origin value.
768
     *
769
     * @param array      $options
770
     * @param int|string $key
771
     */
772 3
    protected static function serializeOrDeserializeClosureAndReplace(array &$options, $key)
773
    {
774 3
        if (!isset($options[$key])) {
775 3
            return;
776
        }
777 3
        $serializer = self::getSerializer();
778 3
        if (is_callable($options[$key])) {
779 3
            $options[$key] = (string) $serializer->serialize($options[$key]);
780 3
        } elseif (is_string($options[$key])) {
781 3
            $options[$key] = $serializer->unserialize($options[$key]);
782 2
        }
783 3
    }
784
}
785