1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Spiral Framework. |
4
|
|
|
* |
5
|
|
|
* @license MIT |
6
|
|
|
* @author Anton Titov (Wolfy-J) |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
namespace Spiral\ORM\Entities; |
10
|
|
|
|
11
|
|
|
use Spiral\Core\Component; |
12
|
|
|
use Spiral\Core\Exceptions\SugarException; |
13
|
|
|
use Spiral\Core\Traits\SaturateTrait; |
14
|
|
|
use Spiral\Models\SourceInterface; |
15
|
|
|
use Spiral\ORM\Exceptions\SourceException; |
16
|
|
|
use Spiral\ORM\ORM; |
17
|
|
|
use Spiral\ORM\ORMInterface; |
18
|
|
|
use Spiral\ORM\RecordEntity; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Source class associated to one or multiple (default implementation) ORM models. Source can be |
22
|
|
|
* used to write your own custom find method or change default selection. |
23
|
|
|
*/ |
24
|
|
|
class RecordSource extends Component implements SourceInterface, \Countable |
25
|
|
|
{ |
26
|
|
|
use SaturateTrait; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Linked document model. ORM can automatically index and link user sources to models based on |
30
|
|
|
* value of this constant. |
31
|
|
|
*/ |
32
|
|
|
const RECORD = null; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Associated document class. |
36
|
|
|
* |
37
|
|
|
* @var string |
38
|
|
|
*/ |
39
|
|
|
private $class = null; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @var RecordSelector |
43
|
|
|
*/ |
44
|
|
|
private $selector = null; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @invisible |
48
|
|
|
* |
49
|
|
|
* @var ORM |
50
|
|
|
*/ |
51
|
|
|
protected $orm = null; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @param string $class |
55
|
|
|
* @param ORMInterface $orm |
56
|
|
|
* |
57
|
|
|
* @throws SugarException |
58
|
|
|
*/ |
59
|
|
View Code Duplication |
public function __construct($class = null, ORMInterface $orm = null) |
|
|
|
|
60
|
|
|
{ |
61
|
|
|
if (empty($class)) { |
62
|
|
|
if (empty(static::RECORD)) { |
63
|
|
|
throw new SourceException('Unable to create source without associated class'); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
$class = static::RECORD; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
$this->class = $class; |
70
|
|
|
$this->orm = $this->saturate($orm, ORMInterface::class); |
71
|
|
|
$this->setSelector($this->orm->selector($this->class)); |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Create new Record based on set of provided fields. |
76
|
|
|
* |
77
|
|
|
* @final Change static method of entity, not this one. |
78
|
|
|
* |
79
|
|
|
* @param array $fields |
80
|
|
|
* |
81
|
|
|
* @return RecordEntity |
82
|
|
|
*/ |
83
|
|
|
final public function create($fields = []) |
84
|
|
|
{ |
85
|
|
|
//Letting entity to create itself (needed |
86
|
|
|
return call_user_func([$this->class, 'create'], $fields, $this->orm); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* Find record by it's primary key. |
91
|
|
|
* |
92
|
|
|
* @see findOne() |
93
|
|
|
* |
94
|
|
|
* @param string|int $id Primary key value. |
95
|
|
|
* |
96
|
|
|
* @return RecordEntity|null |
97
|
|
|
*/ |
98
|
|
|
public function findByPK($id) |
99
|
|
|
{ |
100
|
|
|
return $this->find()->findByPK($id); |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Select one record from mongo collection. |
105
|
|
|
* |
106
|
|
|
* @param array $where Where conditions in array form. |
107
|
|
|
* @param array $orderBy In a form of [key => direction]. |
108
|
|
|
* |
109
|
|
|
* @return RecordEntity|null |
110
|
|
|
*/ |
111
|
|
|
public function findOne(array $where = [], array $orderBy = []) |
112
|
|
|
{ |
113
|
|
|
return $this->find()->orderBy($orderBy)->findOne($where); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Get associated record selection with pre-configured query (if any). |
118
|
|
|
* |
119
|
|
|
* @param array $where Where conditions in array form. |
120
|
|
|
* |
121
|
|
|
* @return RecordSelector |
122
|
|
|
*/ |
123
|
|
|
public function find(array $where = []) |
124
|
|
|
{ |
125
|
|
|
return $this->selector()->where($where); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* {@inheritdoc} |
130
|
|
|
*/ |
131
|
|
|
public function count() |
132
|
|
|
{ |
133
|
|
|
return $this->find()->count(); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* @return RecordSelector |
138
|
|
|
*/ |
139
|
|
|
final protected function selector() |
140
|
|
|
{ |
141
|
|
|
//Has to be cloned every time to prevent query collisions |
142
|
|
|
return clone $this->selector; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* @param RecordSelector $selector |
147
|
|
|
*/ |
148
|
|
|
protected function setSelector(RecordSelector $selector) |
149
|
|
|
{ |
150
|
|
|
$this->selector = $selector; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* {@inheritdoc} |
155
|
|
|
*/ |
156
|
|
|
protected function container() |
157
|
|
|
{ |
158
|
|
|
if ($this->orm instanceof Component) { |
159
|
|
|
return $this->orm->container(); |
|
|
|
|
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
return parent::container(); |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
|
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.