1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Contains the BaseProxy class. |
7
|
|
|
* |
8
|
|
|
* @copyright Copyright (c) 2017 Attila Fulop |
9
|
|
|
* @author Attila Fulop |
10
|
|
|
* @license MIT |
11
|
|
|
* @since 2017-05-24 |
12
|
|
|
* |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace Konekt\Concord\Proxies; |
16
|
|
|
|
17
|
|
|
use Konekt\Concord\Contracts\Concord; |
18
|
|
|
use LogicException; |
19
|
|
|
|
20
|
|
|
abstract class BaseProxy |
21
|
|
|
{ |
22
|
|
|
/** @var Concord */ |
23
|
|
|
public $concord; |
24
|
|
|
|
25
|
|
|
/** @var string */ |
26
|
|
|
protected $contract; |
27
|
|
|
|
28
|
|
|
/** @var array */ |
29
|
|
|
protected static $instances = []; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Repository constructor. |
33
|
|
|
* |
34
|
|
|
* @param Concord $concord |
35
|
|
|
*/ |
36
|
|
|
public function __construct(Concord $concord = null) |
37
|
|
|
{ |
38
|
|
|
$this->concord = $concord ?: app('concord'); |
|
|
|
|
39
|
|
|
|
40
|
|
|
if (empty($this->contract)) { |
41
|
|
|
$this->contract = $this->guessContract(); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
if (!interface_exists($this->contract)) { |
45
|
|
|
throw new LogicException( |
46
|
|
|
sprintf( |
47
|
|
|
'The proxy %s has a non-existent contract class: `%s`', |
48
|
|
|
static::class, |
49
|
|
|
$this->contract |
50
|
|
|
) |
51
|
|
|
); |
52
|
|
|
} |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* Resets the proxy by removing the class instance. |
57
|
|
|
* Shouldn't be used in application code. |
58
|
|
|
* |
59
|
|
|
*/ |
60
|
|
|
public static function __reset() |
61
|
|
|
{ |
62
|
|
|
// This is only needed to ensure that in the rare case when |
63
|
|
|
// the app instance gets replaced along with the Concord |
64
|
|
|
// singleton in runtime, no stale concord survives it |
65
|
|
|
if (isset(static::$instances[static::class])) { |
66
|
|
|
unset(static::$instances[static::class]); |
67
|
|
|
} |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @param $method |
72
|
|
|
* @param $parameters |
73
|
|
|
* |
74
|
|
|
* @return mixed |
75
|
|
|
*/ |
76
|
|
|
public static function __callStatic($method, $parameters) |
77
|
|
|
{ |
78
|
|
|
return call_user_func(static::getInstance()->targetClass() . '::' . $method, ...$parameters); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* This is a method where the dark word 'static' has 7 occurrences |
83
|
|
|
* |
84
|
|
|
* @return BaseProxy |
85
|
|
|
*/ |
86
|
|
|
public static function getInstance() |
87
|
|
|
{ |
88
|
|
|
if (!isset(static::$instances[static::class])) { |
89
|
|
|
static::$instances[static::class] = new static(); |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
return static::$instances[static::class]; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* Try guessing the associated contract class for a concrete proxy class |
97
|
|
|
* |
98
|
|
|
* @return string |
99
|
|
|
*/ |
100
|
|
|
abstract protected function guessContract(); |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Returns the resolved class |
104
|
|
|
* |
105
|
|
|
* @return string |
106
|
|
|
*/ |
107
|
|
|
abstract protected function targetClass(): string; |
108
|
|
|
} |
109
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.