1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Ubiquity\orm\traits; |
4
|
|
|
|
5
|
|
|
use Ubiquity\db\SqlUtils; |
6
|
|
|
use Ubiquity\events\DAOEvents; |
7
|
|
|
use Ubiquity\events\EventsManager; |
8
|
|
|
use Ubiquity\log\Logger; |
9
|
|
|
use Ubiquity\orm\OrmUtils; |
10
|
|
|
use Ubiquity\orm\parser\ConditionParser; |
11
|
|
|
use Ubiquity\orm\parser\Reflexion; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* Core Trait for DAO class. |
15
|
|
|
* Ubiquity\orm\traits$DAOCoreTrait |
16
|
|
|
* This class is part of Ubiquity |
17
|
|
|
* |
18
|
|
|
* @author jcheron <[email protected]> |
19
|
|
|
* @version 1.0.5 |
20
|
|
|
* |
21
|
|
|
* @property \Ubiquity\db\Database $db |
22
|
|
|
* @property boolean $useTransformers |
23
|
|
|
* @property string $transformerOp |
24
|
|
|
* |
25
|
|
|
*/ |
26
|
|
|
trait DAOCoreTrait { |
27
|
|
|
protected static $accessors = [ ]; |
28
|
|
|
protected static $fields = [ ]; |
29
|
|
|
|
30
|
|
|
abstract protected static function _affectsRelationObjects($className, $classPropKey, $manyToOneQueries, $oneToManyQueries, $manyToManyParsers, $objects, $included, $useCache); |
31
|
|
|
|
32
|
|
|
abstract protected static function prepareManyToMany(&$ret, $instance, $member, $annot = null); |
33
|
|
|
|
34
|
|
|
abstract protected static function prepareManyToOne(&$ret, $instance, $value, $fkField, $annotationArray); |
35
|
|
|
|
36
|
|
|
abstract protected static function prepareOneToMany(&$ret, $instance, $member, $annot = null); |
37
|
|
|
|
38
|
|
|
abstract protected static function _initRelationFields($included, $metaDatas, &$invertedJoinColumns, &$oneToManyFields, &$manyToManyFields); |
39
|
|
|
|
40
|
|
|
abstract protected static function getIncludedForStep($included); |
41
|
33 |
|
|
42
|
33 |
|
private static function _getOneToManyFromArray(&$ret, $array, $fkv, $elementAccessor, $prop) { |
43
|
29 |
|
foreach ( $array as $element ) { |
44
|
29 |
|
$elementRef = $element->$elementAccessor (); |
45
|
29 |
|
if (($elementRef == $fkv) || (is_object ( $elementRef ) && Reflexion::getPropValue ( $elementRef, $prop ) == $fkv)) { |
46
|
|
|
$ret [] = $element; |
47
|
|
|
} |
48
|
33 |
|
} |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
private static function getManyToManyFromArray($instance, $array, $class, $parser) { |
52
|
|
|
$ret = [ ]; |
53
|
|
|
$continue = true; |
54
|
|
|
$accessorToMember = "get" . ucfirst ( $parser->getInversedBy () ); |
55
|
|
|
$myPkAccessor = "get" . ucfirst ( $parser->getMyPk () ); |
56
|
|
|
$pk = self::getFirstKeyValue_ ( $instance ); |
57
|
|
|
|
58
|
|
|
if (sizeof ( $array ) > 0) { |
59
|
|
|
$continue = method_exists ( current ( $array ), $accessorToMember ); |
60
|
|
|
} |
61
|
|
|
if ($continue) { |
62
|
|
|
foreach ( $array as $targetEntityInstance ) { |
63
|
|
|
$instances = $targetEntityInstance->$accessorToMember (); |
64
|
|
|
if (is_array ( $instances )) { |
65
|
|
|
foreach ( $instances as $inst ) { |
66
|
|
|
if ($inst->$myPkAccessor () == $pk) |
67
|
|
|
array_push ( $ret, $targetEntityInstance ); |
68
|
|
|
} |
69
|
|
|
} |
70
|
|
|
} |
71
|
|
|
} else { |
72
|
|
|
Logger::warn ( "DAO", "L'accesseur au membre " . $parser->getInversedBy () . " est manquant pour " . $parser->getTargetEntity (), "ManyToMany" ); |
73
|
|
|
} |
74
|
|
|
return $ret; |
75
|
|
|
} |
76
|
15 |
|
|
77
|
15 |
|
protected static function getClass_($instance) { |
78
|
12 |
|
if (is_object ( $instance )) { |
79
|
|
|
return get_class ( $instance ); |
80
|
3 |
|
} |
81
|
|
|
return $instance [0]; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
protected static function getInstance_($instance) { |
85
|
|
|
if (is_object ( $instance )) { |
86
|
|
|
return $instance; |
87
|
|
|
} |
88
|
|
|
return $instance [0]; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
protected static function getValue_($instance, $member) { |
92
|
|
|
if (is_object ( $instance )) { |
93
|
|
|
return Reflexion::getMemberValue ( $instance, $member ); |
94
|
|
|
} |
95
|
|
|
return $instance [1]; |
96
|
|
|
} |
97
|
11 |
|
|
98
|
11 |
|
protected static function getFirstKeyValue_($instance) { |
99
|
9 |
|
if (is_object ( $instance )) { |
100
|
|
|
return OrmUtils::getFirstKeyValue ( $instance ); |
101
|
2 |
|
} |
102
|
|
|
return $instance [1]; |
103
|
|
|
} |
104
|
35 |
|
|
105
|
35 |
|
protected static function _getOne($className, ConditionParser $conditionParser, $included, $useCache) { |
106
|
35 |
|
$conditionParser->limitOne (); |
107
|
35 |
|
$included = self::getIncludedForStep ( $included ); |
108
|
3 |
|
$object = null; |
109
|
|
|
$invertedJoinColumns = null; |
110
|
35 |
|
$oneToManyFields = null; |
111
|
35 |
|
$manyToManyFields = null; |
112
|
35 |
|
|
113
|
|
|
$metaDatas = OrmUtils::getModelMetadata ( $className ); |
114
|
|
|
$tableName = $metaDatas ["#tableName"]; |
115
|
|
|
$hasIncluded = $included || (\is_array ( $included ) && \sizeof ( $included ) > 0); |
116
|
|
|
if ($hasIncluded) { |
117
|
|
|
self::_initRelationFields ( $included, $metaDatas, $invertedJoinColumns, $oneToManyFields, $manyToManyFields ); |
118
|
|
|
} |
119
|
|
|
$transformers = $metaDatas ["#transformers"] [self::$transformerOp] ?? [ ]; |
120
|
|
|
$query = self::$db->prepareAndExecute ( $tableName, SqlUtils::checkWhere ( $conditionParser->getCondition () ), self::getFieldList ( $tableName, $metaDatas ), $conditionParser->getParams (), $useCache ); |
121
|
|
|
if ($query && \sizeof ( $query ) > 0) { |
|
|
|
|
122
|
|
|
$oneToManyQueries = [ ]; |
123
|
58 |
|
$manyToOneQueries = [ ]; |
124
|
58 |
|
$manyToManyParsers = [ ]; |
125
|
58 |
|
$accessors = $metaDatas ["#accessors"]; |
126
|
58 |
|
$object = self::loadObjectFromRow ( \current ( $query ), $className, $invertedJoinColumns, $manyToOneQueries, $oneToManyFields, $manyToManyFields, $oneToManyQueries, $manyToManyParsers, $accessors, $transformers ); |
127
|
58 |
|
if ($hasIncluded) { |
128
|
58 |
|
self::_affectsRelationObjects ( $className, OrmUtils::getFirstPropKey ( $className ), $manyToOneQueries, $oneToManyQueries, $manyToManyParsers, [ $object ], $included, $useCache ); |
129
|
|
|
} |
130
|
58 |
|
EventsManager::trigger ( DAOEvents::GET_ONE, $object, $className ); |
131
|
58 |
|
} |
132
|
58 |
|
return $object; |
133
|
58 |
|
} |
134
|
41 |
|
|
135
|
|
|
/** |
136
|
58 |
|
* |
137
|
58 |
|
* @param string $className |
138
|
58 |
|
* @param ConditionParser $conditionParser |
139
|
58 |
|
* @param boolean|array $included |
140
|
58 |
|
* @param boolean|null $useCache |
141
|
58 |
|
* @return array |
142
|
58 |
|
*/ |
143
|
58 |
|
protected static function _getAll($className, ConditionParser $conditionParser, $included = true, $useCache = NULL) { |
144
|
58 |
|
$included = self::getIncludedForStep ( $included ); |
145
|
58 |
|
$objects = array (); |
146
|
58 |
|
$invertedJoinColumns = null; |
147
|
58 |
|
$oneToManyFields = null; |
148
|
58 |
|
$manyToManyFields = null; |
149
|
|
|
|
150
|
58 |
|
$metaDatas = OrmUtils::getModelMetadata ( $className ); |
151
|
41 |
|
$tableName = $metaDatas ["#tableName"]; |
152
|
41 |
|
$hasIncluded = $included || (\is_array ( $included ) && \sizeof ( $included ) > 0); |
153
|
|
|
if ($hasIncluded) { |
154
|
58 |
|
self::_initRelationFields ( $included, $metaDatas, $invertedJoinColumns, $oneToManyFields, $manyToManyFields ); |
155
|
58 |
|
} |
156
|
|
|
$transformers = $metaDatas ["#transformers"] [self::$transformerOp] ?? [ ]; |
157
|
|
|
$query = self::$db->prepareAndExecute ( $tableName, SqlUtils::checkWhere ( $conditionParser->getCondition () ), self::getFieldList ( $tableName, $metaDatas ), $conditionParser->getParams (), $useCache ); |
158
|
|
|
$oneToManyQueries = [ ]; |
159
|
|
|
$manyToOneQueries = [ ]; |
160
|
|
|
$manyToManyParsers = [ ]; |
161
|
|
|
$propsKeys = OrmUtils::getPropKeys ( $className ); |
162
|
|
|
$accessors = $metaDatas ["#accessors"]; |
163
|
|
|
foreach ( $query as $row ) { |
164
|
|
|
$object = self::loadObjectFromRow ( $row, $className, $invertedJoinColumns, $manyToOneQueries, $oneToManyFields, $manyToManyFields, $oneToManyQueries, $manyToManyParsers, $accessors, $transformers ); |
165
|
|
|
$key = OrmUtils::getPropKeyValues ( $object, $propsKeys ); |
166
|
|
|
$objects [$key] = $object; |
167
|
58 |
|
} |
168
|
58 |
|
if ($hasIncluded) { |
169
|
58 |
|
self::_affectsRelationObjects ( $className, OrmUtils::getFirstPropKey ( $className ), $manyToOneQueries, $oneToManyQueries, $manyToManyParsers, $objects, $included, $useCache ); |
170
|
8 |
|
} |
171
|
4 |
|
EventsManager::trigger ( DAOEvents::GET_ALL, $objects, $className ); |
172
|
4 |
|
return $objects; |
173
|
|
|
} |
174
|
|
|
|
175
|
58 |
|
protected static function getFieldList($tableName, $metaDatas) { |
176
|
58 |
|
if (! isset ( self::$fields [$tableName] )) { |
177
|
58 |
|
$members = \array_diff ( $metaDatas ["#fieldNames"], $metaDatas ["#notSerializable"] ); |
178
|
58 |
|
self::$fields = SqlUtils::getFieldList ( $members, $tableName ); |
179
|
|
|
} |
180
|
58 |
|
return self::$fields; |
181
|
58 |
|
} |
182
|
23 |
|
|
183
|
23 |
|
/** |
184
|
46 |
|
* |
185
|
|
|
* @param array $row |
186
|
|
|
* @param string $className |
187
|
58 |
|
* @param array $invertedJoinColumns |
188
|
36 |
|
* @param array $manyToOneQueries |
189
|
33 |
|
* @param array $accessors |
190
|
|
|
* @return object |
191
|
|
|
*/ |
192
|
58 |
|
private static function loadObjectFromRow($row, $className, &$invertedJoinColumns, &$manyToOneQueries, &$oneToManyFields, &$manyToManyFields, &$oneToManyQueries, &$manyToManyParsers, &$accessors, &$transformers) { |
193
|
23 |
|
$o = new $className (); |
194
|
23 |
|
if (self::$useTransformers) { |
195
|
|
|
foreach ( $transformers as $field => $transformer ) { |
196
|
|
|
$transform = self::$transformerOp; |
197
|
58 |
|
$row [$field] = $transformer::$transform ( $row [$field] ); |
198
|
|
|
} |
199
|
|
|
} |
200
|
3 |
|
foreach ( $row as $k => $v ) { |
201
|
3 |
|
if (isset ( $accessors [$k] )) { |
202
|
3 |
|
$accesseur = $accessors [$k]; |
203
|
3 |
|
$o->$accesseur ( $v ); |
204
|
|
|
} |
205
|
|
|
$o->_rest [$k] = $v; |
206
|
3 |
|
if (isset ( $invertedJoinColumns ) && isset ( $invertedJoinColumns [$k] )) { |
207
|
|
|
$fk = "_" . $k; |
208
|
|
|
$o->$fk = $v; |
209
|
|
|
self::prepareManyToOne ( $manyToOneQueries, $o, $v, $fk, $invertedJoinColumns [$k] ); |
210
|
|
|
} |
211
|
|
|
} |
212
|
|
|
if (isset ( $oneToManyFields )) { |
213
|
|
|
foreach ( $oneToManyFields as $k => $annot ) { |
214
|
|
|
self::prepareOneToMany ( $oneToManyQueries, $o, $k, $annot ); |
215
|
|
|
} |
216
|
|
|
} |
217
|
|
|
if (isset ( $manyToManyFields )) { |
218
|
|
|
foreach ( $manyToManyFields as $k => $annot ) { |
219
|
|
|
self::prepareManyToMany ( $manyToManyParsers, $o, $k, $annot ); |
220
|
|
|
} |
221
|
|
|
} |
222
|
|
|
return $o; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
private static function parseKey(&$keyValues, $className) { |
226
|
|
|
if (! is_array ( $keyValues )) { |
227
|
|
|
if (strrpos ( $keyValues, "=" ) === false && strrpos ( $keyValues, ">" ) === false && strrpos ( $keyValues, "<" ) === false) { |
228
|
|
|
$keyValues = "`" . OrmUtils::getFirstKey ( $className ) . "`='" . $keyValues . "'"; |
229
|
|
|
} |
230
|
|
|
} |
231
|
|
|
} |
232
|
|
|
} |
233
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.