How to use Closure class

Best Mockery code snippet using .Closure

Run Mockery automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

ClosureParserTest.php

Source: ClosureParserTest.php Github

copy
1<?php
2
3namespace Jeremeamia\SuperClosure\Test;
4
5use Jeremeamia\SuperClosure\ClosureParser;
6
7class ClosureParserTest extends \PHPUnit_Framework_TestCase
8{
9    /**
10     * @covers \Jeremeamia\SuperClosure\ClosureParser::__construct
11     * @covers \Jeremeamia\SuperClosure\ClosureParser::getReflection
12     */
13    public function testCanGetReflectionBackFromParser()
14    {
15        $closure = function () {};
16        $reflection = new \ReflectionFunction($closure);
17        $parser = new ClosureParser($reflection);
18
19        $this->assertSame($reflection, $parser->getReflection());
20    }
21
22    /**
23     * @covers \Jeremeamia\SuperClosure\ClosureParser::fromClosure
24     */
25    public function testCanUseFactoryMethodToCreateParser()
26    {
27        $parser = ClosureParser::fromClosure(function () {});
28
29        $this->assertInstanceOf('Jeremeamia\SuperClosure\ClosureParser', $parser);
30    }
31
32    /**
33     * @covers \Jeremeamia\SuperClosure\ClosureParser::__construct
34     */
35    public function testRaisesErrorWhenNonClosureIsProvided()
36    {
37        $this->setExpectedException('InvalidArgumentException');
38
39        $reflection = new \ReflectionFunction('strpos');
40        $parser = new ClosureParser($reflection);
41    }
42
43    /**
44     * @covers \Jeremeamia\SuperClosure\ClosureParser::getCode
45     */
46    public function testCanGetCodeFromParser()
47    {
48        $closure = function () {};
49        $expectedCode = "function () {\n    \n};";
50        $parser = new ClosureParser(new \ReflectionFunction($closure));
51        $actualCode = $parser->getCode();
52
53        $this->assertEquals($expectedCode, $actualCode);
54    }
55
56    /**
57     * @covers \Jeremeamia\SuperClosure\ClosureParser::getUsedVariables
58     */
59    public function testCanGetUsedVariablesFromParser()
60    {
61        $foo = 1;
62        $bar = 2;
63        $closure = function () use ($foo, $bar) {};
64        $expectedVars = array('foo' => 1, 'bar' => 2);
65        $parser = new ClosureParser(new \ReflectionFunction($closure));
66        $actualVars = $parser->getUsedVariables();
67
68        $this->assertEquals($expectedVars, $actualVars);
69    }
70
71    /**
72     * @covers \Jeremeamia\SuperClosure\ClosureParser::getUsedVariables
73     */
74    public function testCanGetUsedVariablesWhenOneIsNullFromParser()
75    {
76        $foo = null;
77        $bar = 2;
78        $closure = function () use ($foo, $bar) {};
79        $expectedVars = array('foo' => null, 'bar' => 2);
80        $parser = new ClosureParser(new \ReflectionFunction($closure));
81        $actualVars = $parser->getUsedVariables();
82
83        $this->assertEquals($expectedVars, $actualVars);
84    }
85
86    /**
87     * @covers \Jeremeamia\SuperClosure\ClosureParser::clearCache
88     */
89    public function testCanClearCache()
90    {
91        $parserClass = 'Jeremeamia\SuperClosure\ClosureParser';
92
93        $p = new \ReflectionProperty($parserClass, 'cache');
94        $p->setAccessible(true);
95        $p->setValue(null, array('foo' => 'bar'));
96
97        $this->assertEquals(array('foo' => 'bar'), $this->readAttribute($parserClass, 'cache'));
98
99        ClosureParser::clearCache();
100
101        $this->assertEquals(array(), $this->readAttribute($parserClass, 'cache'));
102    }
103
104    /**
105     * @covers \Jeremeamia\SuperClosure\ClosureParser::getClosureAbstractSyntaxTree
106     * @covers \Jeremeamia\SuperClosure\ClosureParser::getFileAbstractSyntaxTree
107     */
108    public function testCanGetClosureAst()
109    {
110        $closure = function () {};
111        $parser = new ClosureParser(new \ReflectionFunction($closure));
112        $ast = $parser->getClosureAbstractSyntaxTree();
113        $this->assertInstanceOf('PHPParser_Node_Expr_Closure', $ast);
114    }
115}
116
Full Screen

SerializableClosure.php

Source: SerializableClosure.php Github

copy
1<?php namespace SuperClosure;
2
3use Closure;
4use SuperClosure\Exception\ClosureUnserializationException;
5
6/**
7 * This class acts as a wrapper for a closure, and allows it to be serialized.
8 *
9 * With the combined power of the Reflection API, code parsing, and the infamous
10 * `eval()` function, you can serialize a closure, unserialize it somewhere
11 * else (even a different PHP process), and execute it.
12 */
13class SerializableClosure implements \Serializable
14{
15    /**
16     * The closure being wrapped for serialization.
17     *
18     * @var Closure
19     */
20    private $closure;
21
22    /**
23     * The serializer doing the serialization work.
24     *
25     * @var SerializerInterface
26     */
27    private $serializer;
28
29    /**
30     * The data from unserialization.
31     *
32     * @var array
33     */
34    private $data;
35
36    /**
37     * Create a new serializable closure instance.
38     *
39     * @param Closure                  $closure
40     * @param SerializerInterface|null $serializer
41     */
42    public function __construct(
43        \Closure $closure,
44        SerializerInterface $serializer = null
45    ) {
46        $this->closure = $closure;
47        $this->serializer = $serializer ?: new Serializer;
48    }
49
50    /**
51     * Return the original closure object.
52     *
53     * @return Closure
54     */
55    public function getClosure()
56    {
57        return $this->closure;
58    }
59
60    /**
61     * Delegates the closure invocation to the actual closure object.
62     *
63     * Important Notes:
64     *
65     * - `ReflectionFunction::invokeArgs()` should not be used here, because it
66     *   does not work with closure bindings.
67     * - Args passed-by-reference lose their references when proxied through
68     *   `__invoke()`. This is an unfortunate, but understandable, limitation
69     *   of PHP that will probably never change.
70     *
71     * @return mixed
72     */
73    public function __invoke()
74    {
75        return call_user_func_array($this->closure, func_get_args());
76    }
77
78    /**
79     * Clones the SerializableClosure with a new bound object and class scope.
80     *
81     * The method is essentially a wrapped proxy to the Closure::bindTo method.
82     *
83     * @param mixed $newthis  The object to which the closure should be bound,
84     *                        or NULL for the closure to be unbound.
85     * @param mixed $newscope The class scope to which the closure is to be
86     *                        associated, or 'static' to keep the current one.
87     *                        If an object is given, the type of the object will
88     *                        be used instead. This determines the visibility of
89     *                        protected and private methods of the bound object.
90     *
91     * @return SerializableClosure
92     * @link http://www.php.net/manual/en/closure.bindto.php
93     */
94    public function bindTo($newthis, $newscope = 'static')
95    {
96        return new self(
97            $this->closure->bindTo($newthis, $newscope),
98            $this->serializer
99        );
100    }
101
102    /**
103     * Serializes the code, context, and binding of the closure.
104     *
105     * @return string|null
106     * @link http://php.net/manual/en/serializable.serialize.php
107     */
108    public function serialize()
109    {
110        try {
111            $this->data = $this->data ?: $this->serializer->getData($this->closure, true);
112            return serialize($this->data);
113        } catch (\Exception $e) {
114            trigger_error(
115                'Serialization of closure failed: ' . $e->getMessage(),
116                E_USER_NOTICE
117            );
118            // Note: The serialize() method of Serializable must return a string
119            // or null and cannot throw exceptions.
120            return null;
121        }
122    }
123
124    /**
125     * Unserializes the closure.
126     *
127     * Unserializes the closure's data and recreates the closure using a
128     * simulation of its original context. The used variables (context) are
129     * extracted into a fresh scope prior to redefining the closure. The
130     * closure is also rebound to its former object and scope.
131     *
132     * @param string $serialized
133     *
134     * @throws ClosureUnserializationException
135     * @link http://php.net/manual/en/serializable.unserialize.php
136     */
137    public function unserialize($serialized)
138    {
139        // Unserialize the closure data and reconstruct the closure object.
140        $this->data = unserialize($serialized);
141        $this->closure = __reconstruct_closure($this->data);
142
143        // Throw an exception if the closure could not be reconstructed.
144        if (!$this->closure instanceof Closure) {
145            throw new ClosureUnserializationException(
146                'The closure is corrupted and cannot be unserialized.'
147            );
148        }
149
150        // Rebind the closure to its former binding and scope.
151        if ($this->data['binding'] || $this->data['isStatic']) {
152            $this->closure = $this->closure->bindTo(
153                $this->data['binding'],
154                $this->data['scope']
155            );
156        }
157    }
158
159    /**
160     * Returns closure data for `var_dump()`.
161     *
162     * @return array
163     */
164    public function __debugInfo()
165    {
166        return $this->data ?: $this->serializer->getData($this->closure, true);
167    }
168}
169
170/**
171 * Reconstruct a closure.
172 *
173 * HERE BE DRAGONS!
174 *
175 * The infamous `eval()` is used in this method, along with the error
176 * suppression operator, and variable variables (i.e., double dollar signs) to
177 * perform the unserialization logic. I'm sorry, world!
178 *
179 * This is also done inside a plain function instead of a method so that the
180 * binding and scope of the closure are null.
181 *
182 * @param array $__data Unserialized closure data.
183 *
184 * @return Closure|null
185 * @internal
186 */
187function __reconstruct_closure(array $__data)
188{
189    // Simulate the original context the closure was created in.
190    foreach ($__data['context'] as $__var_name => &$__value) {
191        if ($__value instanceof SerializableClosure) {
192            // Unbox any SerializableClosures in the context.
193            $__value = $__value->getClosure();
194        } elseif ($__value === Serializer::RECURSION) {
195            // Track recursive references (there should only be one).
196            $__recursive_reference = $__var_name;
197        }
198
199        // Import the variable into this scope.
200        ${$__var_name} = $__value;
201    }
202
203    // Evaluate the code to recreate the closure.
204    try {
205        if (isset($__recursive_reference)) {
206            // Special handling for recursive closures.
207            @eval("\${$__recursive_reference} = {$__data['code']};");
208            $__closure = ${$__recursive_reference};
209        } else {
210            @eval("\$__closure = {$__data['code']};");
211        }
212    } catch (\ParseError $e) {
213        // Discard the parse error.
214    }
215
216    return isset($__closure) ? $__closure : null;
217}
218
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Most used methods in Closure

Run Selenium Automation Tests on LambdaTest Cloud Grid

Trigger Selenium automation tests on a cloud-based Grid of 3000+ real browsers and operating systems.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)