Completed
Push — master ( 2d1963...3845e2 )
by Jean-Christophe
02:09
created

OrmUtils::getManyToOneFields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Ubiquity\orm;
4
5
use Ubiquity\orm\parser\Reflexion;
6
use Ubiquity\cache\CacheManager;
7
use Ubiquity\utils\base\UString;
8
use Ubiquity\utils\base\UArray;
9
use Ubiquity\controllers\rest\ResponseFormatter;
10
use Ubiquity\orm\parser\ManyToManyParser;
11
12
/**
13
 * Utilitaires de mappage Objet/relationnel
14
 * @author jc
15
 * @version 1.0.0.5
16
 */
17
class OrmUtils {
18
	private static $modelsMetadatas;
19
20
	public static function getModelMetadata($className) {
21
		if (!isset(self::$modelsMetadatas[$className])) {
22
			self::$modelsMetadatas[$className]=CacheManager::getOrmModelCache($className);
23
		}
24
		return self::$modelsMetadatas[$className];
25
	}
26
27 View Code Duplication
	public static function isSerializable($class, $member) {
28
		$ret=self::getAnnotationInfo($class, "#notSerializable");
29
		if ($ret !== false)
30
			return \array_search($member, $ret) === false;
31
		else
32
			return true;
33
	}
34
35 View Code Duplication
	public static function isNullable($class, $member) {
36
		$ret=self::getAnnotationInfo($class, "#nullable");
37
		if ($ret !== false)
38
			return \array_search($member, $ret) !== false;
39
		else
40
			return false;
41
	}
42
43
	public static function getFieldName($class, $member) {
44
		$ret=self::getAnnotationInfo($class, "#fieldNames");
45
		if ($ret === false)
46
			$ret=$member;
47
		else
48
			$ret=$ret[$member];
49
		return $ret;
50
	}
51
52
	public static function getFieldNames($model){
53
		$fields=self::getAnnotationInfo($model, "#fieldNames");
54
		$result=[];
55
		$serializables=self::getSerializableFields($model);
56
		foreach ($fields as $member=>$field){
57
			if(\array_search($member, $serializables)!==false)
58
				$result[$field]=$member;
59
		}
60
		return $result;
61
	}
62
63
	public static function getTableName($class) {
64
		if(isset(self::getModelMetadata($class)["#tableName"]))
65
		return self::getModelMetadata($class)["#tableName"];
66
	}
67
	
68
	public static function getJoinTables($class){
69
		$result=[];
70
		
71
		if(isset(self::getModelMetadata($class)["#joinTable"])){
72
			$jts=self::getModelMetadata($class)["#joinTable"];
73
			foreach ($jts as $jt){
74
				$result[]=$jt["name"];
75
			}
76
		}
77
		return $result;
78
	}
79
	
80 View Code Duplication
	public static function getAllJoinTables($models){
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
81
		$result=[];
82
		foreach ($models as $model){
83
			$result=array_merge($result,self::getJoinTables($model));
84
		}
85
		return $result;
86
	}
87
88
	public static function getKeyFieldsAndValues($instance) {
89
		$kf=self::getAnnotationInfo(get_class($instance), "#primaryKeys");
90
		return self::getMembersAndValues($instance, $kf);
91
	}
92
93
	public static function getKeyFields($instance) {
94
		if(!\is_string($instance)){
95
			$instance=\get_class($instance);
96
		}
97
		return self::getAnnotationInfo($instance, "#primaryKeys");
98
	}
99
100
	public static function getMembers($className) {
101
		$fieldNames=self::getAnnotationInfo($className, "#fieldNames");
102
		if ($fieldNames !== false)
103
			return \array_keys($fieldNames);
104
		return [ ];
105
	}
106
107
	public static function getFieldTypes($className) {
108
		$fieldTypes=self::getAnnotationInfo($className, "#fieldTypes");
109
		if ($fieldTypes !== false)
110
			return $fieldTypes;
111
		return [ ];
112
	}
113
114
	public static function getFieldType($className,$field){
115
		$types= self::getFieldTypes($className);
116
		if(isset($types[$field]))
117
			return $types[$field];
118
		return "int";
119
	}
120
121
	public static function getMembersAndValues($instance, $members=NULL) {
122
		$ret=array ();
123
		$className=get_class($instance);
124
		if (is_null($members))
125
			$members=self::getMembers($className);
126
		foreach ( $members as $member ) {
127
			if (OrmUtils::isSerializable($className, $member)) {
128
				$v=Reflexion::getMemberValue($instance, $member);
129 View Code Duplication
				if (self::isNotNullOrNullAccepted($v, $className, $member)) {
130
					$name=self::getFieldName($className, $member);
131
					$ret[$name]=$v;
132
				}
133
			}
134
		}
135
		return $ret;
136
	}
137
138
	public static function isNotNullOrNullAccepted($v, $className, $member) {
139
		$notNull=UString::isNotNull($v);
140
		return ($notNull) || (!$notNull && OrmUtils::isNullable($className, $member));
141
	}
142
143
	public static function getFirstKey($class) {
144
		$kf=self::getAnnotationInfo($class, "#primaryKeys");
145
		return \reset($kf);
146
	}
147
148
	public static function getFirstKeyValue($instance) {
149
		$fkv=self::getKeyFieldsAndValues($instance);
150
		return \reset($fkv);
151
	}
152
	
153
	public static function getKeyValues($instance) {
154
		$fkv=self::getKeyFieldsAndValues($instance);
155
		return implode("_",$fkv);
156
	}
157
158
	/**
159
	 *
160
	 * @param object $instance
161
	 * @return mixed[]
162
	 */
163
	public static function getManyToOneMembersAndValues($instance) {
164
		$ret=array ();
165
		$class=get_class($instance);
166
		$members=self::getAnnotationInfo($class, "#manyToOne");
167
		if ($members !== false) {
168
			foreach ( $members as $member ) {
169
				$memberAccessor="get" . ucfirst($member);
170
				if (method_exists($instance, $memberAccessor)) {
171
					$memberInstance=$instance->$memberAccessor();
172
					if (isset($memberInstance)) {
173
						$keyValues=self::getKeyFieldsAndValues($memberInstance);
174
						if (sizeof($keyValues) > 0) {
175
							$fkName=self::getJoinColumnName($class, $member);
176
							$ret[$fkName]=reset($keyValues);
177
						}
178
					}
179
				}
180
			}
181
		}
182
		return $ret;
183
	}
184
185
	public static function getMembersWithAnnotation($class, $annotation) {
186
		if (isset(self::getModelMetadata($class)[$annotation]))
187
			return self::getModelMetadata($class)[$annotation];
188
		return [ ];
189
	}
190
191
	/**
192
	 *
193
	 * @param object $instance
194
	 * @param string $memberKey
195
	 * @param array $array
196
	 * @return boolean
197
	 */
198
	public static function exists($instance, $memberKey, $array) {
199
		$accessor="get" . ucfirst($memberKey);
200
		if (method_exists($instance, $accessor)) {
201
			if ($array !== null) {
202
				foreach ( $array as $value ) {
203
					if ($value->$accessor() == $instance->$accessor())
204
						return true;
205
				}
206
			}
207
		}
208
		return false;
209
	}
210
211
	public static function getJoinColumnName($class, $member) {
212
		$annot=self::getAnnotationInfoMember($class, "#joinColumn", $member);
213
		if ($annot !== false) {
214
			$fkName=$annot["name"];
215
		} else {
216
			$fkName="id" . ucfirst(self::getTableName(ucfirst($member)));
217
		}
218
		return $fkName;
219
	}
220
221
	public static function getAnnotationInfo($class, $keyAnnotation) {
222
		if (isset(self::getModelMetadata($class)[$keyAnnotation]))
223
			return self::getModelMetadata($class)[$keyAnnotation];
224
		return false;
225
	}
226
227
	public static function getAnnotationInfoMember($class, $keyAnnotation, $member) {
228
		$info=self::getAnnotationInfo($class, $keyAnnotation);
229
		if ($info !== false) {
230
			if(UArray::isAssociative($info)){
231
				if (isset($info[$member])) {
232
					return $info[$member];
233
				}
234
			}else{
235
				if(\array_search($member, $info)!==false){
236
					return $member;
237
				}
238
			}
239
		}
240
		return false;
241
	}
242
243
	public static function getSerializableFields($class) {
244
		$notSerializable=self::getAnnotationInfo($class, "#notSerializable");
245
		$fieldNames=\array_keys(self::getAnnotationInfo($class, "#fieldNames"));
246
		return \array_diff($fieldNames, $notSerializable);
247
	}
248
249
	public static function getFieldsInRelations($class) {
250
		$result=[ ];
251
		if ($manyToOne=self::getAnnotationInfo($class, "#manyToOne")) {
252
			$result=\array_merge($result, $manyToOne);
253
		}
254
		if ($oneToMany=self::getAnnotationInfo($class, "#oneToMany")) {
255
			$result=\array_merge($result, \array_keys($oneToMany));
256
		}
257
		if ($manyToMany=self::getAnnotationInfo($class, "#manyToMany")) {
258
			$result=\array_merge($result, \array_keys($manyToMany));
259
		}
260
		return $result;
261
	}
262
	
263
	public static function getAnnotFieldsInRelations($class) {
264
		$result=[ ];
265
		if ($manyToOnes=self::getAnnotationInfo($class, "#manyToOne")) {
266
			$joinColumns=self::getAnnotationInfo($class, "#joinColumn");
267
			foreach ($manyToOnes as $manyToOne ){
268
				if(isset($joinColumns[$manyToOne])){
269
					$result[$manyToOne]=["type"=>"manyToOne","value"=>$joinColumns[$manyToOne]];
270
				}
271
			}
272
		}
273 View Code Duplication
		if ($oneToManys=self::getAnnotationInfo($class, "#oneToMany")) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
274
			foreach ($oneToManys as $field=>$oneToMany){
275
				$result[$field]=["type"=>"oneToMany","value"=>$oneToMany];
276
			}
277
		}
278 View Code Duplication
		if ($manyToManys=self::getAnnotationInfo($class, "#manyToMany")) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
279
			foreach ($manyToManys as $field=>$manyToMany){
280
				$result[$field]=["type"=>"manyToMany","value"=>$manyToMany];
281
			}
282
		}
283
		return $result;
284
	}
285
	
286
	public static function getUJoinSQL($model,$arrayAnnot,$field,&$aliases){
287
		$type=$arrayAnnot["type"];$annot=$arrayAnnot["value"];
288
		$table=self::getTableName($model);
289
		$tableAlias=(isset($aliases[$table]))?$aliases[$table]:$table;
290
		if($type==="manyToOne"){
291
			$fkClass=$annot["className"];
292
			$fkTable=OrmUtils::getTableName($fkClass);
293
			$fkField=$annot["name"];
294
			$pkField=self::getFirstKey($fkClass);
295
			$alias=self::getJoinAlias($table, $fkTable);
296
			$result="INNER JOIN `{$fkTable}` `{$alias}` ON `{$tableAlias}`.`{$fkField}`=`{$alias}`.`{$pkField}`";
297
		}elseif($type==="oneToMany"){
298
			$fkClass=$annot["className"];
299
			$fkAnnot=OrmUtils::getAnnotationInfoMember($fkClass, "#joinColumn", $annot["mappedBy"]);
300
			$fkTable=OrmUtils::getTableName($fkClass);
301
			$fkField=$fkAnnot["name"];
302
			$pkField=self::getFirstKey($model);
303
			$alias=self::getJoinAlias($table, $fkTable);
304
			$result="INNER JOIN `{$fkTable}` `{$alias}` ON `{$tableAlias}`.`{$pkField}`=`{$alias}`.`{$fkField}`";
305
		}else{
306
			$parser=new ManyToManyParser($model,$field);
307
			$parser->init($annot);
308
			$fkTable=$parser->getTargetEntityTable();
309
			$fkClass=$parser->getTargetEntityClass();
310
			$alias=self::getJoinAlias($table, $fkTable);
311
			$result=$parser->getSQL($alias,$aliases);
312
		}
313
		
314
		if(array_search($alias, $aliases)!==false){
315
			$result="";
316
		}
317
		$aliases[$fkTable]=$alias;
318
		return ["class"=>$fkClass,"table"=>$fkTable,"sql"=>$result,"alias"=>$alias];
319
	}
320
	
321
	private static function getJoinAlias($table,$fkTable){
322
		return uniqid($fkTable.'_'.$table[0]);
323
	}
324
325
	public static function getManyToOneFields($class) {
326
		return self::getAnnotationInfo($class, "#manyToOne");
327
	}
328
329
	public static function getManyToManyFields($class) {
330
		$result=self::getAnnotationInfo($class, "#manyToMany");
331
		if($result!==false)
332
			return \array_keys($result);
333
		return [];
334
	}
335
336
	public static function getDefaultFk($classname) {
337
		return "id" . \ucfirst(self::getTableName($classname));
338
	}
339
340
	public static function getMemberJoinColumns($instance,$member,$metaDatas=NULL){
341
		if(!isset($metaDatas)){
342
			$class=get_class($instance);
343
			$metaDatas=self::getModelMetadata($class);
344
		}
345
		$invertedJoinColumns=$metaDatas["#invertedJoinColumn"];
346
		foreach ($invertedJoinColumns as $field=>$invertedJoinColumn){
347
			if($invertedJoinColumn["member"]===$member){
348
				return [$field,$invertedJoinColumn];
349
			}
350
		}
351
		return null;
352
	}
353
	
354
	public static function objectAsJSON($instance){
355
		$formatter=new ResponseFormatter();
356
		$datas=$formatter->cleanRestObject($instance);
357
		return $formatter->format(["pk"=>self::getFirstKeyValue($instance),"object"=>$datas]);
358
	}
359
}
360