Passed
Push — master ( a0d60e...d9c4e6 )
by Jean-Christophe
12:17
created

DAORelationsTrait   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 219
Duplicated Lines 0 %

Test Coverage

Coverage 71.2%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 54
eloc 117
c 4
b 0
f 0
dl 0
loc 219
ccs 89
cts 125
cp 0.712
rs 6.4799

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getToManyFields() 0 4 3
B parseEncludeMember() 0 21 7
B getManyToManyFromArray() 0 24 7
A getManyToMany() 0 19 5
A getManyToOne() 0 21 6
A getInvertedJoinColumns() 0 5 3
A getOneToMany() 0 18 6
B _initRelationFields() 0 19 8
A getIncludedForStep() 0 17 6
A affectsManyToManys() 0 6 3

How to fix   Complexity   

Complex Class

Complex classes like DAORelationsTrait 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.

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 DAORelationsTrait, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Ubiquity\orm\traits;
4
5
use Ubiquity\db\Database;
6
use Ubiquity\db\SqlUtils;
7
use Ubiquity\log\Logger;
8
use Ubiquity\orm\OrmUtils;
9
use Ubiquity\orm\parser\ConditionParser;
10
use Ubiquity\orm\parser\ManyToManyParser;
11
use Ubiquity\orm\parser\Reflexion;
12
13
/**
14
 *
15
 * @author jc
16
 * @property \Ubiquity\db\Database $db
17
 */
18
trait DAORelationsTrait {
19
20
	abstract protected static function _getAll(Database $db, $className, ConditionParser $conditionParser, $included = true, $useCache = NULL);
21
22 61
	protected static function getIncludedForStep($included) {
23 61
		if (\is_bool ( $included )) {
24 61
			return $included;
25
		}
26 7
		$ret = [ ];
27 7
		if (\is_array ( $included )) {
28 7
			foreach ( $included as &$includedMember ) {
29 7
				if (\is_array ( $includedMember )) {
30
					foreach ( $includedMember as $iMember ) {
31
						self::parseEncludeMember ( $ret, $iMember );
32
					}
33
				} else {
34 7
					self::parseEncludeMember ( $ret, $includedMember );
35
				}
36
			}
37
		}
38 7
		return $ret;
39
	}
40
41 7
	private static function parseEncludeMember(&$ret, $includedMember): void {
42 7
		$array = \explode ( '.', $includedMember );
43 7
		$member = \array_shift ( $array );
44 7
		if (\sizeof ( $array ) > 0) {
45
			$newValue = \implode ( '.', $array );
46
			if ($newValue === '*') {
47
				$newValue = true;
48
			}
49
			if (isset ( $ret [$member] )) {
50
				if (! \is_array ( $ret [$member] )) {
51
					$ret [$member] = [ $ret [$member] ];
52
				}
53
				$ret [$member] [] = $newValue;
54
			} else {
55
				$ret [$member] = $newValue;
56
			}
57
		} else {
58 7
			if (isset ( $member ) && '' != $member) {
59 7
				$ret [$member] = false;
60
			} else {
61
				return;
62
			}
63
		}
64 7
	}
65
66 3
	private static function getInvertedJoinColumns($included, &$invertedJoinColumns): void {
67 3
		foreach ( $invertedJoinColumns as $column => &$annot ) {
68 3
			$member = $annot ['member'];
69 3
			if (isset ( $included [$member] ) === false) {
70 3
				unset ( $invertedJoinColumns [$column] );
71
			}
72
		}
73 3
	}
74
75 7
	private static function getToManyFields($included, &$toManyFields): void {
76 7
		foreach ( $toManyFields as $member => $annotNotUsed ) {
77 7
			if (isset ( $included [$member] ) === false) {
78 7
				unset ( $toManyFields [$member] );
79
			}
80
		}
81 7
	}
82
83 45
	protected static function _initRelationFields($included, $metaDatas, &$invertedJoinColumns, &$oneToManyFields, &$manyToManyFields): void {
84 45
		if (isset ( $metaDatas ['#invertedJoinColumn'] )) {
85 26
			$invertedJoinColumns = $metaDatas ['#invertedJoinColumn'];
86
		}
87 45
		if (isset ( $metaDatas ['#oneToMany'] )) {
88 40
			$oneToManyFields = $metaDatas ['#oneToMany'];
89
		}
90 45
		if (isset ( $metaDatas ['#manyToMany'] )) {
91 23
			$manyToManyFields = $metaDatas ['#manyToMany'];
92
		}
93 45
		if (\is_array ( $included )) {
94 7
			if (isset ( $invertedJoinColumns )) {
95 3
				self::getInvertedJoinColumns ( $included, $invertedJoinColumns );
96
			}
97 7
			if (isset ( $oneToManyFields )) {
98 7
				self::getToManyFields ( $included, $oneToManyFields );
99
			}
100 7
			if (isset ( $manyToManyFields )) {
101 3
				self::getToManyFields ( $included, $manyToManyFields );
102
			}
103
		}
104 45
	}
105
106
	private static function getManyToManyFromArray($instance, $array, $class, $parser): array {
107
		$ret = [ ];
108
		$continue = true;
109
		$accessorToMember = 'get' . \ucfirst ( $parser->getInversedBy () );
110
		$myPkAccessor = 'get' . \ucfirst ( $parser->getMyPk () );
111
		$pk = self::getFirstKeyValue_ ( $instance );
112
113
		if (sizeof ( $array ) > 0) {
114
			$continue = \method_exists ( current ( $array ), $accessorToMember );
115
		}
116
		if ($continue) {
117
			foreach ( $array as $targetEntityInstance ) {
118
				$instances = $targetEntityInstance->$accessorToMember ();
119
				if (is_array ( $instances )) {
120
					foreach ( $instances as $inst ) {
121
						if ($inst->$myPkAccessor () == $pk)
122
							\array_push ( $ret, $targetEntityInstance );
123
					}
124
				}
125
			}
126
		} else {
127
			Logger::warn ( 'DAO', "L'accesseur au membre " . $parser->getInversedBy () . ' est manquant pour ' . $parser->getTargetEntity (), 'ManyToMany' );
128
		}
129
		return $ret;
130
	}
131
132
	/**
133
	 * Loads member associated with $instance by a ManyToOne relationship
134
	 *
135
	 * @param object|array $instance The instance object or an array with [classname,id]
136
	 * @param string $member The member to load
137
	 * @param boolean|array $included if true, loads associate members with associations, if array, example : ["client.*","commands"]
138
	 * @param boolean|null $useCache
139
	 */
140 4
	public static function getManyToOne($instance, $member, $included = false, $useCache = NULL): ?object {
141 4
		$classname = self::getClass_ ( $instance );
142 4
		if (is_array ( $instance )) {
143 1
			$instance = self::getById ( $classname, $instance [1], false, $useCache );
144
		}
145 4
		$fieldAnnot = OrmUtils::getMemberJoinColumns ( $classname, $member );
146 4
		if ($fieldAnnot !== null) {
147 4
			$annotationArray = $fieldAnnot [1];
148 4
			$member = $annotationArray ['member'];
149 4
			$value = Reflexion::getMemberValue ( $instance, $member );
150 4
			$key = OrmUtils::getFirstKey ( $annotationArray ['className'] );
151 4
			$kv = array ($key => $value );
152 4
			$obj = self::getById ( $annotationArray ['className'], $kv, $included, $useCache );
153 4
			if ($obj !== null) {
154 4
				Logger::info ( 'DAO', 'Loading the member ' . $member . ' for the object ' . $classname, 'getManyToOne' );
155 4
				$accesseur = 'set' . ucfirst ( $member );
156 4
				if (\is_object ( $instance ) && \method_exists ( $instance, $accesseur )) {
157 4
					$instance->$accesseur ( $obj );
158 4
					$instance->_rest [$member] = $obj->_rest;
159
				}
160 4
				return $obj;
161
			}
162
		}
163
	}
164
165
	/**
166
	 * Assign / load the child records in the $member member of $instance.
167
	 *
168
	 * @param object|array $instance The instance object or an array with [classname,id]
169
	 * @param string $member Member on which a oneToMany annotation must be present
170
	 * @param boolean|array $included if true, loads associate members with associations, if array, example : ['client.*','commands']
171
	 * @param boolean $useCache
172
	 * @param array $annot used internally
173
	 */
174 7
	public static function getOneToMany($instance, $member, $included = true, $useCache = NULL, $annot = null): array {
175 7
		$ret = array ();
176 7
		$class = self::getClass_ ( $instance );
177 7
		if (! isset ( $annot )) {
178 7
			$annot = OrmUtils::getAnnotationInfoMember ( $class, '#oneToMany', $member );
179
		}
180 7
		if ($annot !== false) {
181 7
			$fkAnnot = OrmUtils::getAnnotationInfoMember ( $annot ['className'], '#joinColumn', $annot ['mappedBy'] );
182 7
			if ($fkAnnot !== false) {
183 7
				$fkv = self::getFirstKeyValue_ ( $instance );
184 7
				$db = self::getDb ( $annot ['className'] );
185 7
				$ret = self::_getAll ( $db, $annot ['className'], ConditionParser::simple ( $db->quote . $fkAnnot ['name'] . $db->quote . '= ?', $fkv ), $included, $useCache );
186 7
				if (is_object ( $instance ) && $modifier = self::getAccessor ( $member, $instance, 'getOneToMany' )) {
187 6
					self::setToMember ( $member, $instance, $ret, $modifier );
188
				}
189
			}
190
		}
191 7
		return $ret;
192
	}
193
194
	/**
195
	 * Assigns / loads the child records in the $member member of $instance.
196
	 * If $array is null, the records are loaded from the database
197
	 *
198
	 * @param object|array $instance The instance object or an array with [classname,id]
199
	 * @param string $member Member on which a ManyToMany annotation must be present
200
	 * @param boolean|array $included if true, loads associate members with associations, if array, example : ['client.*','commands']
201
	 * @param array $array optional parameter containing the list of possible child records
202
	 * @param boolean $useCache
203
	 */
204 4
	public static function getManyToMany($instance, $member, $included = false, $array = null, $useCache = NULL): array {
205 4
		$ret = [ ];
206 4
		$class = self::getClass_ ( $instance );
207 4
		$parser = new ManyToManyParser ( $class, $member );
208 4
		if ($parser->init ()) {
209 4
			if (\is_null ( $array )) {
210 4
				$pk = self::getFirstKeyValue_ ( $instance );
211 4
				$quote = SqlUtils::$quote;
212 4
				$condition = ' INNER JOIN ' . $quote . $parser->getJoinTable () . $quote . ' on ' . $quote . $parser->getJoinTable () . $quote . '.' . $quote . $parser->getFkField () . $quote . '=' . $quote . $parser->getTargetEntityTable () . $quote . '.' . $quote . $parser->getPk () . $quote . ' WHERE ' . $quote . $parser->getJoinTable () . $quote . '.' . $quote . $parser->getMyFkField () . $quote . '= ?';
213 4
				$targetEntityClass = $parser->getTargetEntityClass ();
214 4
				$ret = self::_getAll ( self::getDb ( $targetEntityClass ), $targetEntityClass, ConditionParser::simple ( $condition, $pk ), $included, $useCache );
215
			} else {
216
				$ret = self::getManyToManyFromArray ( $instance, $array, $class, $parser );
217
			}
218 4
			if (\is_object ( $instance ) && $modifier = self::getAccessor ( $member, $instance, 'getManyToMany' )) {
219 3
				self::setToMember ( $member, $instance, $ret, $modifier );
220
			}
221
		}
222 4
		return $ret;
223
	}
224
225
	/**
226
	 *
227
	 * @param object $instance
228
	 * @param array $array
229
	 * @param boolean $useCache
230
	 */
231
	public static function affectsManyToManys($instance, $array = NULL, $useCache = NULL) {
232
		$metaDatas = OrmUtils::getModelMetadata ( \get_class ( $instance ) );
233
		$manyToManyFields = $metaDatas ['#manyToMany'];
234
		if (\sizeof ( $manyToManyFields ) > 0) {
235
			foreach ( $manyToManyFields as $member ) {
236
				self::getManyToMany ( $instance, $member, false, $array, $useCache );
237
			}
238
		}
239
	}
240
}
241