Skip to content

Commit 2f7611e

Browse files
[12.x] New illuminate/reflections component from illuminate/support (#58052)
* [12.x] New `illuminate/reflections` component from `illuminate/support` Signed-off-by: Mior Muhammad Zaki <[email protected]> * formatting --------- Signed-off-by: Mior Muhammad Zaki <[email protected]> Co-authored-by: Taylor Otwell <[email protected]>
1 parent e984383 commit 2f7611e

File tree

11 files changed

+147
-133
lines changed

11 files changed

+147
-133
lines changed

bin/release.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ git tag $VERSION
5252
git push origin --tags
5353

5454
# Tag Components
55-
for REMOTE in auth broadcasting bus cache collections conditionable config console container contracts cookie database encryption events filesystem hashing http json-schema log macroable mail notifications pagination pipeline process queue redis routing session support testing translation validation view
55+
for REMOTE in auth broadcasting bus cache collections conditionable config console container contracts cookie database encryption events filesystem hashing http json-schema log macroable mail notifications pagination pipeline process queue reflection redis routing session support testing translation validation view
5656
do
5757
echo ""
5858
echo ""

bin/split.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ remote pagination [email protected]:illuminate/pagination.git
4444
remote pipeline [email protected]:illuminate/pipeline.git
4545
remote process [email protected]:illuminate/process.git
4646
remote queue [email protected]:illuminate/queue.git
47+
remote reflection [email protected]:illuminate/reflection.git
4748
remote redis [email protected]:illuminate/redis.git
4849
remote routing [email protected]:illuminate/routing.git
4950
remote session [email protected]:illuminate/session.git
@@ -79,6 +80,7 @@ split 'src/Illuminate/Pagination' pagination
7980
split 'src/Illuminate/Pipeline' pipeline
8081
split 'src/Illuminate/Process' process
8182
split 'src/Illuminate/Queue' queue
83+
split 'src/Illuminate/Reflection' reflection
8284
split 'src/Illuminate/Redis' redis
8385
split 'src/Illuminate/Routing' routing
8486
split 'src/Illuminate/Session' session

composer.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
"illuminate/pipeline": "self.version",
9191
"illuminate/process": "self.version",
9292
"illuminate/queue": "self.version",
93+
"illuminate/reflection": "self.version",
9394
"illuminate/redis": "self.version",
9495
"illuminate/routing": "self.version",
9596
"illuminate/session": "self.version",
@@ -143,6 +144,7 @@
143144
"src/Illuminate/Filesystem/functions.php",
144145
"src/Illuminate/Foundation/helpers.php",
145146
"src/Illuminate/Log/functions.php",
147+
"src/Illuminate/Reflection/helpers.php",
146148
"src/Illuminate/Support/functions.php",
147149
"src/Illuminate/Support/helpers.php"
148150
],
@@ -151,7 +153,8 @@
151153
"Illuminate\\Support\\": [
152154
"src/Illuminate/Macroable/",
153155
"src/Illuminate/Collections/",
154-
"src/Illuminate/Conditionable/"
156+
"src/Illuminate/Conditionable/",
157+
"src/Illuminate/Reflection/"
155158
]
156159
}
157160
},

src/Illuminate/Container/Container.php

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,19 @@
1313
use Illuminate\Contracts\Container\Container as ContainerContract;
1414
use Illuminate\Contracts\Container\ContextualAttribute;
1515
use Illuminate\Contracts\Container\SelfBuilding;
16+
use Illuminate\Support\Traits\ReflectsClosures;
1617
use LogicException;
1718
use ReflectionAttribute;
1819
use ReflectionClass;
1920
use ReflectionException;
2021
use ReflectionFunction;
21-
use ReflectionIntersectionType;
2222
use ReflectionParameter;
23-
use ReflectionUnionType;
2423
use TypeError;
2524

2625
class Container implements ArrayAccess, ContainerContract
2726
{
27+
use ReflectsClosures;
28+
2829
/**
2930
* The current globally available container (if any).
3031
*
@@ -563,40 +564,6 @@ protected function bindBasedOnClosureReturnTypes($abstract, $concrete = null, $s
563564
}
564565
}
565566

566-
/**
567-
* Get the class names / types of the return type of the given Closure.
568-
*
569-
* @return list<class-string>
570-
*
571-
* @throws \ReflectionException
572-
*/
573-
protected function closureReturnTypes(Closure $closure)
574-
{
575-
$reflection = new ReflectionFunction($closure);
576-
577-
if ($reflection->getReturnType() === null ||
578-
$reflection->getReturnType() instanceof ReflectionIntersectionType) {
579-
return [];
580-
}
581-
582-
$types = $reflection->getReturnType() instanceof ReflectionUnionType
583-
? $reflection->getReturnType()->getTypes()
584-
: [$reflection->getReturnType()];
585-
586-
$returnTypes = [];
587-
588-
foreach ($types as $type) {
589-
if ($type->isBuiltin() ||
590-
in_array($type->getName(), ['static', 'self'])) {
591-
continue;
592-
}
593-
594-
$returnTypes[] = $type->getName();
595-
}
596-
597-
return $returnTypes;
598-
}
599-
600567
/**
601568
* "Extend" an abstract type in the container.
602569
*

src/Illuminate/Container/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"require": {
1717
"php": "^8.2",
1818
"illuminate/contracts": "^12.0",
19+
"illuminate/reflection": "^12.0",
1920
"psr/container": "^1.1.1|^2.0.1",
2021
"symfony/polyfill-php84": "^1.33",
2122
"symfony/polyfill-php85": "^1.33"
File renamed without changes.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "illuminate/reflection",
3+
"description": "The Illuminate Reflection package.",
4+
"license": "MIT",
5+
"homepage": "https://laravel.com",
6+
"support": {
7+
"issues": "https://github.com/laravel/framework/issues",
8+
"source": "https://github.com/laravel/framework"
9+
},
10+
"authors": [
11+
{
12+
"name": "Taylor Otwell",
13+
"email": "[email protected]"
14+
}
15+
],
16+
"require": {
17+
"php": "^8.2",
18+
"illuminate/contracts": "^12.0",
19+
"illuminate/collections": "^12.0"
20+
},
21+
"autoload": {
22+
"psr-4": {
23+
"Illuminate\\Support\\": ""
24+
},
25+
"files": [
26+
"helpers.php"
27+
]
28+
},
29+
"extra": {
30+
"branch-alias": {
31+
"dev-master": "12.x-dev"
32+
}
33+
},
34+
"config": {
35+
"sort-packages": true
36+
},
37+
"minimum-stability": "dev"
38+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
use Illuminate\Support\Traits\ReflectsClosures;
4+
5+
if (! function_exists('lazy')) {
6+
/**
7+
* Create a lazy instance.
8+
*
9+
* @template TValue of object
10+
*
11+
* @param class-string<TValue>|(\Closure(TValue): mixed) $class
12+
* @param (\Closure(TValue): mixed)|int $callback
13+
* @param int $options
14+
* @param array<string, mixed> $eager
15+
* @return TValue
16+
*/
17+
function lazy($class, $callback = 0, $options = 0, $eager = [])
18+
{
19+
static $closureReflector;
20+
21+
$closureReflector ??= new class
22+
{
23+
use ReflectsClosures;
24+
25+
public function typeFromParameter($callback)
26+
{
27+
return $this->firstClosureParameterType($callback);
28+
}
29+
};
30+
31+
[$class, $callback, $options] = is_string($class)
32+
? [$class, $callback, $options]
33+
: [$closureReflector->typeFromParameter($class), $class, $callback ?: $options];
34+
35+
$reflectionClass = new ReflectionClass($class);
36+
37+
$instance = $reflectionClass->newLazyGhost(function ($instance) use ($callback) {
38+
$result = $callback($instance);
39+
40+
if (is_array($result)) {
41+
$instance->__construct(...$result);
42+
}
43+
}, $options);
44+
45+
foreach ($eager as $property => $value) {
46+
$reflectionClass->getProperty($property)->setRawValueWithoutLazyInitialization($instance, $value);
47+
}
48+
49+
return $instance;
50+
}
51+
}
52+
53+
if (! function_exists('proxy')) {
54+
/**
55+
* Create a lazy proxy instance.
56+
*
57+
* @template TValue of object
58+
*
59+
* @param class-string<TValue>|(\Closure(TValue): TValue) $class
60+
* @param (\Closure(TValue): TValue)|int $callback
61+
* @param int $options
62+
* @param array<string, mixed> $eager
63+
* @return TValue
64+
*/
65+
function proxy($class, $callback = 0, $options = 0, $eager = [])
66+
{
67+
static $closureReflector;
68+
69+
$closureReflector = new class
70+
{
71+
use ReflectsClosures;
72+
73+
public function get($callback)
74+
{
75+
return $this->closureReturnTypes($callback)[0] ?? $this->firstClosureParameterType($callback);
76+
}
77+
};
78+
79+
[$class, $callback, $options] = is_string($class)
80+
? [$class, $callback, $options]
81+
: [$closureReflector->get($class), $class, $callback ?: $options];
82+
83+
$reflectionClass = new ReflectionClass($class);
84+
85+
$proxy = $reflectionClass->newLazyProxy(function () use ($callback, $eager, &$proxy) {
86+
$instance = $callback($proxy, $eager);
87+
88+
return $instance;
89+
}, $options);
90+
91+
foreach ($eager as $property => $value) {
92+
$reflectionClass->getProperty($property)->setRawValueWithoutLazyInitialization($proxy, $value);
93+
}
94+
95+
return $proxy;
96+
}
97+
}

src/Illuminate/Support/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"illuminate/conditionable": "^12.0",
2424
"illuminate/contracts": "^12.0",
2525
"illuminate/macroable": "^12.0",
26+
"illuminate/reflection": "^12.0",
2627
"nesbot/carbon": "^3.8.4",
2728
"symfony/polyfill-php83": "^1.33",
2829
"symfony/polyfill-php85": "^1.33",

0 commit comments

Comments
 (0)