Completed
Push — master ( 4b1131...dbc6d3 )
by Jean-Christophe
01:37
created

OrmUtils::getJoinColumnName()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
cc 2
nc 2
nop 2
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 getAllFields($class){
250
		return \array_keys(self::getAnnotationInfo($class, "#fieldNames"));
251
	}
252
	
253
	public static function getFormAllFields($class){
254
		$result=self::getSerializableFields($class);
255 View Code Duplication
		if ($manyToOne=self::getAnnotationInfo($class, "#manyToOne")) {
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...
256
			foreach ($manyToOne as $member){
257
				$joinColumn = OrmUtils::getAnnotationInfoMember ( $class, "#joinColumn", $member );
258
				$result[]=$joinColumn["name"];
259
			}
260
		}
261 View Code Duplication
		if ($manyToMany=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...
262
			$manyToMany=array_keys($manyToMany);
263
			foreach ($manyToMany as $member){
264
				$result[]=$member . "Ids";
265
			}
266
		}
267
		return $result;
268
	}
269
	
270
	public static function setFieldToMemberNames(&$fields,$relFields){
271
		foreach ($fields as $index=>$field){
272
			if(isset($relFields[$field])){
273
				$fields[$index]=$relFields[$field];
274
			}
275
		}
276
	}
277
278
	public static function getFieldsInRelations($class) {
279
		$result=[ ];
280
		
281
		if ($manyToOne=self::getAnnotationInfo($class, "#manyToOne")) {
282
			$result=\array_merge($result, $manyToOne);
283
		}
284
		if ($oneToMany=self::getAnnotationInfo($class, "#oneToMany")) {
285
			$result=\array_merge($result, \array_keys($oneToMany));
286
		}
287
		if ($manyToMany=self::getAnnotationInfo($class, "#manyToMany")) {
288
			$result=\array_merge($result, \array_keys($manyToMany));
289
		}
290
		return $result;
291
	}
292
	
293
	public static function getFieldsInRelations_($class) {
294
		return self::getFieldsInRelationsForUpdate_($class)["relations"];
295
	}
296
	
297
	public static function getFieldsInRelationsForUpdate_($class) {
298
		$result=[ ];
299 View Code Duplication
		if ($manyToOne=self::getAnnotationInfo($class, "#manyToOne")) {
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...
300
			foreach ($manyToOne as $member){
301
				$joinColumn = OrmUtils::getAnnotationInfoMember ( $class, "#joinColumn", $member );
302
				$result[$joinColumn["name"]]=$member;
303
			}
304
		}
305 View Code Duplication
		if ($manyToMany=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...
306
			$manyToMany=array_keys($manyToMany);
307
			foreach ($manyToMany as $member){
308
				$result[$member . "Ids"]=$member;
309
			}
310
		}
311 View Code Duplication
		if ($oneToMany=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...
312
			$oneToMany=array_keys($oneToMany);
313
			foreach ($oneToMany as $member){
314
				$result[$member . "Ids"]=$member;
315
			}
316
		}
317
		return ["relations"=>$result,"manyToOne"=>$manyToOne,"manyToMany"=>$manyToMany,"oneToMany"=>$oneToMany];
318
	}
319
	
320
	public static function getAnnotFieldsInRelations($class) {
321
		$result=[ ];
322
		if ($manyToOnes=self::getAnnotationInfo($class, "#manyToOne")) {
323
			$joinColumns=self::getAnnotationInfo($class, "#joinColumn");
324
			foreach ($manyToOnes as $manyToOne ){
325
				if(isset($joinColumns[$manyToOne])){
326
					$result[$manyToOne]=["type"=>"manyToOne","value"=>$joinColumns[$manyToOne]];
327
				}
328
			}
329
		}
330 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...
331
			foreach ($oneToManys as $field=>$oneToMany){
332
				$result[$field]=["type"=>"oneToMany","value"=>$oneToMany];
333
			}
334
		}
335 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...
336
			foreach ($manyToManys as $field=>$manyToMany){
337
				$result[$field]=["type"=>"manyToMany","value"=>$manyToMany];
338
			}
339
		}
340
		return $result;
341
	}
342
	
343
	public static function getUJoinSQL($model,$arrayAnnot,$field,&$aliases){
344
		$type=$arrayAnnot["type"];$annot=$arrayAnnot["value"];
345
		$table=self::getTableName($model);
346
		$tableAlias=(isset($aliases[$table]))?$aliases[$table]:$table;
347
		if($type==="manyToOne"){
348
			$fkClass=$annot["className"];
349
			$fkTable=OrmUtils::getTableName($fkClass);
350
			$fkField=$annot["name"];
351
			$pkField=self::getFirstKey($fkClass);
352
			$alias=self::getJoinAlias($table, $fkTable);
353
			$result="INNER JOIN `{$fkTable}` `{$alias}` ON `{$tableAlias}`.`{$fkField}`=`{$alias}`.`{$pkField}`";
354
		}elseif($type==="oneToMany"){
355
			$fkClass=$annot["className"];
356
			$fkAnnot=OrmUtils::getAnnotationInfoMember($fkClass, "#joinColumn", $annot["mappedBy"]);
357
			$fkTable=OrmUtils::getTableName($fkClass);
358
			$fkField=$fkAnnot["name"];
359
			$pkField=self::getFirstKey($model);
360
			$alias=self::getJoinAlias($table, $fkTable);
361
			$result="INNER JOIN `{$fkTable}` `{$alias}` ON `{$tableAlias}`.`{$pkField}`=`{$alias}`.`{$fkField}`";
362
		}else{
363
			$parser=new ManyToManyParser($model,$field);
364
			$parser->init($annot);
365
			$fkTable=$parser->getTargetEntityTable();
366
			$fkClass=$parser->getTargetEntityClass();
367
			$alias=self::getJoinAlias($table, $fkTable);
368
			$result=$parser->getSQL($alias,$aliases);
369
		}
370
		
371
		if(array_search($alias, $aliases)!==false){
372
			$result="";
373
		}
374
		$aliases[$fkTable]=$alias;
375
		return ["class"=>$fkClass,"table"=>$fkTable,"sql"=>$result,"alias"=>$alias];
376
	}
377
	
378
	private static function getJoinAlias($table,$fkTable){
379
		return uniqid($fkTable.'_'.$table[0]);
380
	}
381
	
382
	public static function getOneToManyFields($class) {
383
		return self::getAnnotationInfo($class, "#oneToMany");
384
	}
385
386
	public static function getManyToOneFields($class) {
387
		return self::getAnnotationInfo($class, "#manyToOne");
388
	}
389
390
	public static function getManyToManyFields($class) {
391
		$result=self::getAnnotationInfo($class, "#manyToMany");
392
		if($result!==false)
393
			return \array_keys($result);
394
		return [];
395
	}
396
397
	public static function getDefaultFk($classname) {
398
		return "id" . \ucfirst(self::getTableName($classname));
399
	}
400
401
	public static function getMemberJoinColumns($instance,$member,$metaDatas=NULL){
402
		if(!isset($metaDatas)){
403
			$class=get_class($instance);
404
			$metaDatas=self::getModelMetadata($class);
405
		}
406
		$invertedJoinColumns=$metaDatas["#invertedJoinColumn"];
407
		foreach ($invertedJoinColumns as $field=>$invertedJoinColumn){
408
			if($invertedJoinColumn["member"]===$member){
409
				return [$field,$invertedJoinColumn];
410
			}
411
		}
412
		return null;
413
	}
414
	
415
	public static function objectAsJSON($instance){
416
		$formatter=new ResponseFormatter();
417
		$datas=$formatter->cleanRestObject($instance);
418
		return $formatter->format(["pk"=>self::getFirstKeyValue($instance),"object"=>$datas]);
419
	}
420
}
421