Completed
Push — master ( ac3b2a...67ef21 )
by Jean-Christophe
02:07
created

OrmUtils   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 224
Duplicated Lines 11.61 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 55
lcom 1
cbo 2
dl 26
loc 224
rs 6.8
c 0
b 0
f 0

24 Methods

Rating   Name   Duplication   Size   Complexity  
A createOrmModelCache() 0 10 2
A getCacheDirectory() 0 8 2
A startOrm() 0 6 1
A register() 0 13 1
A getModelMetadata() 0 6 2
A isSerializable() 7 7 2
A isNullable() 7 7 2
A getFieldName() 8 8 2
A getTableName() 0 3 1
A getKeyFieldsAndValues() 0 4 1
A getKeyFields() 0 3 1
A getMembers() 0 6 2
B getMembersAndValues() 4 16 9
A getFirstKey() 0 4 1
A getFirstKeyValue() 0 4 1
B getManyToOneMembersAndValues() 0 21 6
A getMembersWithAnnotation() 0 5 2
B exists() 0 12 5
A getJoinColumnName() 0 9 2
A getAnnotationInfo() 0 5 2
A getAnnotationInfoMember() 0 9 3
A getSerializableFields() 0 5 1
A getFieldsInRelations() 0 10 3
A getDefaultFk() 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like OrmUtils often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use OrmUtils, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace micro\orm;
3
4
use mindplay\annotations\Annotations;
5
use mindplay\annotations\AnnotationCache;
6
use mindplay\annotations\AnnotationManager;
7
use micro\orm\parser\ModelParser;
8
use micro\orm\parser\Reflexion;
9
10
/**
11
 * Utilitaires de mappage Objet/relationnel
12
 * @author jc
13
 * @version 1.0.0.5
14
 * @package orm
15
 */
16
class OrmUtils{
17
	public static $ormCache;
18
	private static $modelsMetadatas;
19
20
	public static function createOrmModelCache($className){
21
		$key=\str_replace("\\", DIRECTORY_SEPARATOR, $className);
22
		if(!self::$ormCache->exists($key)){
23
			$p=new ModelParser();
24
			$p->parse($className);
25
			self::$ormCache->store($key, $p->__toString());
26
		}
27
		self::$modelsMetadatas[$className]=self::$ormCache->fetch($key);
28
		return self::$modelsMetadatas[$className];
29
	}
30
31
	public static function getCacheDirectory(&$config){
32
		$cacheDirectory=@$config["ormCache"]["cacheDirectory"];
33
		if(!isset($cacheDirectory)){
34
			$config["ormCache"]=["cacheDirectory"=>"models/cache/"];
35
			$cacheDirectory=$config["ormCache"]["cacheDirectory"];
36
		}
37
		return $cacheDirectory;
38
	}
39
40
	public static function startOrm(&$config){
41
		$cacheDirectory=ROOT.DS.OrmUtils::getCacheDirectory($config);
42
		Annotations::$config['cache'] = new AnnotationCache($cacheDirectory.'/annotations');
43
		self::register(Annotations::getManager());
44
		self::$ormCache=new AnnotationCache($cacheDirectory);
45
	}
46
47
	private static function register(AnnotationManager $annotationManager){
48
		$annotationManager->registry=array_merge($annotationManager->registry,[
49
				'id' => 'micro\annotations\IdAnnotation',
50
				'manyToOne' => 'micro\annotations\ManyToOneAnnotation',
51
				'oneToMany' => 'micro\annotations\OneToManyAnnotation',
52
				'manyToMany' => 'micro\annotations\ManyToManyAnnotation',
53
				'joinColumn' => 'micro\annotations\JoinColumnAnnotation',
54
				'table' => 'micro\annotations\TableAnnotation',
55
				'transient' => 'micro\annotations\TransientAnnotation',
56
				'column' => 'micro\annotations\ColumnAnnotation',
57
				'joinTable' => 'micro\annotations\JoinTableAnnotation'
58
		]);
59
	}
60
61
	public static function getModelMetadata($className){
62
		if(!isset(self::$modelsMetadatas[$className])){
63
			self::createOrmModelCache($className);
64
		}
65
		return self::$modelsMetadatas[$className];
66
	}
67
68 View Code Duplication
	public static function isSerializable($class,$member){
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...
69
		$ret=self::getAnnotationInfo($class,"#notSerializable");
70
		if ($ret!==false)
71
			return \array_search($member, $ret)===false;
72
		else
73
			return true;
74
	}
75
76 View Code Duplication
	public static function isNullable($class,$member){
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...
77
		$ret=self::getAnnotationInfo($class,"#nullable");
78
		if ($ret!==false)
79
			return \array_search($member, $ret)!==false;
80
		else
81
			return false;
82
	}
83
84 View Code Duplication
	public static function getFieldName($class,$member){
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...
85
		$ret=self::getAnnotationInfo($class, "#fieldNames");
86
		if($ret===false)
87
			$ret=$member;
88
		else
89
			$ret=$ret[$member];
90
		return $ret;
91
	}
92
93
	public static function getTableName($class){
94
		return self::getModelMetadata($class)["#tableName"];
95
	}
96
97
	public static function getKeyFieldsAndValues($instance){
98
		$kf=self::getAnnotationInfo(get_class($instance), "#primaryKeys");
99
		return self::getMembersAndValues($instance,$kf);
100
	}
101
102
	public static function getKeyFields($instance){
103
		return self::getAnnotationInfo(get_class($instance), "#primaryKeys");
104
	}
105
106
	public function getMembers($className){
107
		$fieldNames=self::getAnnotationInfo($className, "#fieldNames");
108
		if($fieldNames!==false)
109
			return \array_keys($fieldNames);
110
		return [];
111
	}
112
113
	public static function getMembersAndValues($instance,$members=NULL){
114
		$ret=array();
115
		$className=get_class($instance);
116
		if(is_null($members))
117
			$members=self::getMembers($className);
118
		foreach ($members as $member){
119
			if(OrmUtils::isSerializable($className,$member)){
120
				$v=Reflexion::getMemberValue($instance, $member);
121 View Code Duplication
				if(($v!==null && $v!=="") || (($v===null || $v==="") && OrmUtils::isNullable($className, $member))){
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...
122
					$name=self::getFieldName($className, $member);
123
					$ret[$name]=$v;
124
				}
125
			}
126
		}
127
		return $ret;
128
	}
129
130
	public static function getFirstKey($class){
131
		$kf=self::getAnnotationInfo($class, "#primaryKeys");
132
		return \reset($kf);
133
	}
134
135
	public static function getFirstKeyValue($instance){
136
		$fkv=self::getKeyFieldsAndValues($instance);
137
		return \reset($fkv);
138
	}
139
140
	/**
141
	 * @param object $instance
142
	 * @return mixed[]
143
	 */
144
	public static function getManyToOneMembersAndValues($instance){
145
		$ret=array();
146
		$class=get_class($instance);
147
		$members=self::getAnnotationInfo($class, "#manyToOne");
148
		if($members!==false){
149
			foreach ($members as $member){
150
				$memberAccessor="get".ucfirst($member);
151
				if(method_exists($instance,$memberAccessor)){
152
					$memberInstance=$instance->$memberAccessor();
153
					if(isset($memberInstance)){
154
						$keyValues=self::getKeyFieldsAndValues($memberInstance);
155
						if(sizeof($keyValues)>0){
156
							$fkName=self::getJoinColumnName($class, $member);
157
							$ret[$fkName]=reset($keyValues);
158
						}
159
					}
160
				}
161
			}
162
		}
163
		return $ret;
164
	}
165
166
	public static function getMembersWithAnnotation($class,$annotation){
167
		if(isset(self::getModelMetadata($class)[$annotation]))
168
			return self::getModelMetadata($class)[$annotation];
169
		return [];
170
	}
171
172
173
174
	/**
175
	 * @param object $instance
176
	 * @param string $memberKey
177
	 * @param array $array
178
	 * @return boolean
179
	 */
180
	public static function exists($instance,$memberKey,$array){
181
		$accessor="get".ucfirst($memberKey);
182
		if(method_exists($instance, $accessor)){
183
			if($array!==null){
184
				foreach ($array as $value){
185
					if($value->$accessor()==$instance->$accessor())
186
						return true;
187
				}
188
			}
189
		}
190
		return false;
191
	}
192
193
	public static function getJoinColumnName($class,$member){
194
		$annot=self::getAnnotationInfoMember($class, "#joinColumn",$member);
195
		if($annot!==false){
196
			$fkName=$annot["name"];
197
		}else{
198
			$fkName="id".ucfirst(self::getTableName(ucfirst($member)));
199
		}
200
		return $fkName;
201
	}
202
203
	public static function getAnnotationInfo($class,$keyAnnotation){
204
		if(isset(self::getModelMetadata($class)[$keyAnnotation]))
205
			return self::getModelMetadata($class)[$keyAnnotation];
206
		return false;
207
	}
208
209
	public static function getAnnotationInfoMember($class,$keyAnnotation,$member){
210
		$info=self::getAnnotationInfo($class, $keyAnnotation);
211
		if($info!==false){
212
			if(isset($info[$member])){
213
				return $info[$member];
214
			}
215
		}
216
		return false;
217
	}
218
219
	public static function getSerializableFields($class){
220
		$notSerializable=self::getAnnotationInfo($class, "#notSerializable");
221
		$fieldNames=\array_keys(self::getAnnotationInfo($class, "#fieldNames"));
222
		return \array_diff($fieldNames, $notSerializable);
223
	}
224
225
	public static function getFieldsInRelations($class){
226
		$result=[];
227
		if($manyToOne=self::getAnnotationInfo($class, "#manyToOne")){
228
			$result=\array_merge($result,$manyToOne);
229
		}
230
		if($oneToMany=self::getAnnotationInfo($class, "#oneToMany")){
231
			$result=\array_merge($result,\array_keys($oneToMany));
232
		}
233
		return $result;
234
	}
235
236
	public static function getDefaultFk($classname){
237
		return "id".\ucfirst(self::getTableName($classname));
238
	}
239
}
240