8000 WIP - Progress to an extendable TypeCaster and Factory · laravel/framework@3d891e7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3d891e7

Browse files
author
Aden Fraser
committed
WIP - Progress to an extendable TypeCaster and Factory
1 parent 6ee8c3a commit 3d891e7

File tree

5 files changed

+315
-0
lines changed

5 files changed

+315
-0
lines changed
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Illuminate\Contracts\Database\TypeCaster;
4+
5+
interface TypeCaster
6+
{
7+
/**
8+
* Register a custom Type Caster extension.
9+
*
10+
* @param string $rule
11+
* @param \Closure|string $fromDatabase
12+
* @param \Closure|string|null $toDatabase
13+
* @return void
14+
*/
15+
public function extend($rule, $fromDatabase, $toDatabase = null);
16+
}

src/Illuminate/Database/DatabaseServiceProvider.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Illuminate\Database\Eloquent\QueueEntityResolver;
1010
use Illuminate\Database\Connectors\ConnectionFactory;
1111
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
12+
use Illuminate\Database\Eloquent\TypeCaster as TypeCasterFactory;
1213

1314
class DatabaseServiceProvider extends ServiceProvider
1415
{
@@ -37,6 +38,8 @@ public function register()
3738

3839
$this->registerQueueableEntityResolver();
3940

41+
$this->registerTypeCasterFactory();
42+
4043
// The connection factory is used to create the actual connection instances on
4144
// the database. We will inject the factory into the manager so that it may
4245
// make the connections while they are actually needed and not of before.
@@ -85,4 +88,29 @@ protected function registerQueueableEntityResolver()
8588
return new QueueEntityResolver;
8689
});
8790
}
91+
92+
/**
93+
* Register the Type Caster factory.
94+
*
95+
* @return void
96+
*/
97+
protected function registerTypeCasterFactory()
98+
{
99+
$this->app->singleton('typecaster', function ($app) {
100+
return new TypeCasterFactory($app);
101+
});
102+
}
103+
104+
/**
105+
* Get the services provided by the provider.
106+
*
107+
* @return array
108+
*/
109+
public function provides()
110+
{
111+
return [
112+
'typecaster',
113+
];
114+
}
88115
}
116+
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
namespace Illuminate\Database\Eloquent\TypeCaster;
4+
5+
use Closure;
6+
use Illuminate\Database\Eloquent\Model;
7+
use Illuminate\Contracts\Container\Container;
8+
use Illuminate\Contracts\Database\TypeCaster\Factory as FactoryContract;
9+
10+
class Factory implements FactoryContract
11+
{
12+
/**
13+
* The IoC container instance.
14+
*
15+
* @var \Illuminate\Contracts\Container\Container
16+
*/
17+
protected $container;
18+
19+
/**
20+
* All of the custom Type Caster extensions.
21+
*
22+
* @var array
23+
*/
24+
protected $extensions = [];
25+
26+
/**
27+
* Create a new Type Caster factory instance.
28+
*
29+
* @param \Illuminate\Contracts\Container\Container $container
30+
* @return void
31+
*/
32+
public function __construct(Container $container = null)
33+
{
34+
$this->container = $container;
35+
}
36+
37+
/**
38+
* Create a new Type Caster instance.
39+
*
40+
* @param \Illuminate\Database\Eloquent\Model $model
41+
* @return \Illuminate\Database\Eloquent\TypeCaster\TypeCaster
42+
*/
43+
public function make(Model $model)
44+
{
45+
$typecaster = new TypeCaster($model);
46+
47+
// Next we'll set the IoC container instance of the type caster, which is used
48+
// to resolve out class based type casting extensions. If it is not set then
49+
// these extension types wont be possible on these type caster instances.
50+
if (! is_null($this->container)) {
51+
$typecaster->setContainer($this->container);
52+
}
53+
54+
$typecaster->addExtensions($this->extensions);
55+
56+
return $typecaster;
57+
}
58+
59+
/**
60+
* Register a custom Type Caster extension.
61+
*
62+
* @param string $rule
63+
* @param \Closure|string $fromDatabase
64+
* @param \Closure|string|null $toDatabase
65+
* @return void
66+
*/
67+
public function extend($rule, $fromDatabase, $toDatabase = null)
68+
{
69+
$this->extensions[$rule] = [
70+
'from' => $fromDatabase,
71+
'to' => $toDatabase,
72+
];
73+
}
74+
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
<?php
2+
3+
namespace Illuminate\Database\Eloquent\TypeCaster;
4+
5+
use Str;
6+
use Closure;
7+
use BadMethodCallException;
8+
use Illuminate\Database\Eloquent\Model;
9+
use Illuminate\Contracts\Container\Container;
10+
11+
class TypeCaster
12+
{
13+
/**
14+
* The container instance.
15+
*
16+
* @var \Illuminate\Contracts\Container\Container
17+
*/
18+
protected $container;
19+
20+
/**
21+
* The Model to perform Type Casting on.
22+
*
23+
* @var array
24+
*/
25+
protected $model;
26+
27+
/**
28+
* All of the custom Type Casting extensions.
29+
*
30+
* @var array
31+
*/
32+
protected $extensions = [];
33+
34+
/**
35+
* Create a new Type Caster instance.
36+
*
37+
* @param \Illuminate\Database\Eloquent\Model $model
38+
* @return void
39+
*/
40+
public function __construct(Model $data)
41+
{
42+
$this->model = $model;
43+
}
44+
45+
/**
46+
* Run the Type Caster's rule against an attribute.
47+
*
48+
* @return void
49+
*/
50+
public function cast()
51+
{
52+
53+
}
54+
55+
/**
56+
* Determine if an cast has been set on an attribute.
57+
*
58+
* @param string $attribute
59+
* @return bool
60+
*/
61+
public function hasCast($attribute)
62+
{
63+
return ! is_null($this->getCast($attribute));
64+
}
65+
66+
/**
67+
* Get a cast type and its parameters for a given attribute.
68+
*
69+
* @param string $attribute
70+
* @return array|null
71+
*/
72+
protected function getCast($attribute)
73+
{
74+
75+
}
76+
77+
/**
78+
* Get the array of the custom Type Caster extensions.
79+
*
80+
* @return array
81+
*/
82+
public function getExtensions()
83+
{
84+
return $this->extensions;
85+
}
86+
87+
/**
88+
* Register an array of custom Type Caster extensions.
89+
*
90+
* @param array $extensions
91+
* @return void
92+
*/
93+
public function addExtensions(array $extensions)
94+
{
95+
if ($extensions) {
96+
$keys = array_map('\Illuminate\Support\Str::snake', array_keys($extensions));
97+
98+
$extensions = array_combine($keys, array_values($extensions));
99+
}
100+
101+
$this->extensions = array_merge($this->extensions, $extensions);
102+
}
103+
104+
/**
105+
* Register a custom Type Caster extension.
106+
*
107+
* @param string $rule
108+
* @param \Closure|string $extension
109+
* @return void
110+
*/
111+
public function addExtension($rule, $extension)
112+
{
113+
$this->extensions[Str::snake($rule)] = $extension;
114+
}
115+
116+
/**
117+
* Set the IoC container instance.
118+
*
119+
* @param \Illuminate\Contracts\Container\Container $container
120+
* @return void
121+
*/
122+
public function setContainer(Container $container)
123+
{
124+
$this->container = $container;
125+
}
126+
127+
/**
128+
* Call a custom validator extension.
129+
*
130+
* @param string $rule
131+
* @param array $parameters
132+
* @return bool|null
133+
*/
134+
protected function callExtension($rule, $parameters)
135+
{
136+
$callback = $this->extensions[$rule];
137+
138+
if ($callback instanceof Closure) {
139+
return call_user_func_array($callback, $parameters);
140+
} elseif (is_string($callback)) {
141+
return $this->callClassBasedExtension($callback, $parameters);
142+
}
143+
}
144+
145+
/**
146+
* Call a class based validator extension.
147+
*
148+
* @param string $callback
149+
* @param array $parameters
150+
* @return bool
151+
*/
152+
protected function callClassBasedExtension($callback, $parameters)
153+
{
154+
list($class, $method) = explode('@', $callback);
155+
156+
return call_user_func_array([$this->container->make($class), $method], $parameters);
157+
}
158+
159+
/**
160+
* Handle dynamic calls to class methods.
161+
*
162+
* @param string $method
163+
* @param array $parameters
164+
* @return mixed
165+
*
166+
* @throws \BadMethodCallException
167+
*/
168+
public function __call($method, $parameters)
169+
{
170+
$rule = Str::snake(substr($method, 8));
171+
172+
if (isset($this->extensions[$rule])) {
173+
return $this->callExtension($rule, $parameters);
174+
}
175+
176+
throw new BadMethodCallException("Method [$method] does not exist.");
177+
}
178+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Illuminate\Support\Facades;
4+
5+
/**
6+
* @see \Illuminate\Database\Eloquent\TypeCaster\Factory
7+
*/
8+
class TypeCaster extends Facade
9+
{
10+
/**
11+
* Get the registered name of the component.
12+
*
13+
* @return string
14+
*/
15+
protected static function getFacadeAccessor()
16+
{
17+
return 'typecaster';
18+
}
19+
}

0 commit comments

Comments
 (0)
0