Total Complexity | 52 |
Total Lines | 374 |
Duplicated Lines | 0 % |
Changes | 6 | ||
Bugs | 0 | Features | 0 |
Complex classes like AuditHelper 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 AuditHelper, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
12 | class AuditHelper |
||
13 | { |
||
14 | /** |
||
15 | * @var \DH\DoctrineAuditBundle\AuditConfiguration |
||
16 | */ |
||
17 | private $configuration; |
||
18 | |||
19 | /** |
||
20 | * @param AuditConfiguration $configuration |
||
21 | */ |
||
22 | public function __construct(AuditConfiguration $configuration) |
||
23 | { |
||
24 | $this->configuration = $configuration; |
||
25 | } |
||
26 | |||
27 | /** |
||
28 | * @return \DH\DoctrineAuditBundle\AuditConfiguration |
||
29 | */ |
||
30 | public function getConfiguration(): AuditConfiguration |
||
31 | { |
||
32 | return $this->configuration; |
||
33 | } |
||
34 | |||
35 | /** |
||
36 | * Returns the primary key value of an entity. |
||
37 | * |
||
38 | * @param EntityManagerInterface $em |
||
39 | * @param object $entity |
||
40 | * |
||
41 | * @throws \Doctrine\DBAL\DBALException |
||
42 | * @throws \Doctrine\ORM\Mapping\MappingException |
||
43 | * |
||
44 | * @return mixed |
||
45 | */ |
||
46 | public function id(EntityManagerInterface $em, $entity) |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * Computes a usable diff. |
||
79 | * |
||
80 | * @param EntityManagerInterface $em |
||
81 | * @param object $entity |
||
82 | * @param array $ch |
||
83 | * |
||
84 | * @throws \Doctrine\DBAL\DBALException |
||
85 | * @throws \Doctrine\ORM\Mapping\MappingException |
||
86 | * |
||
87 | * @return array |
||
88 | */ |
||
89 | public function diff(EntityManagerInterface $em, $entity, array $ch): array |
||
90 | { |
||
91 | /** @var ClassMetadata $meta */ |
||
92 | $meta = $em->getClassMetadata(\get_class($entity)); |
||
93 | $diff = []; |
||
94 | |||
95 | foreach ($ch as $fieldName => list($old, $new)) { |
||
96 | $o = null; |
||
97 | $n = null; |
||
98 | |||
99 | if ( |
||
100 | $meta->hasField($fieldName) && |
||
101 | !isset($meta->embeddedClasses[$fieldName]) && |
||
102 | $this->configuration->isAuditedField($entity, $fieldName) |
||
103 | ) { |
||
104 | $mapping = $meta->fieldMappings[$fieldName]; |
||
105 | $type = Type::getType($mapping['type']); |
||
106 | $o = $this->value($em, $type, $old); |
||
107 | $n = $this->value($em, $type, $new); |
||
108 | } elseif ( |
||
109 | $meta->hasAssociation($fieldName) && |
||
110 | $meta->isSingleValuedAssociation($fieldName) && |
||
111 | $this->configuration->isAuditedField($entity, $fieldName) |
||
112 | ) { |
||
113 | $o = $this->summarize($em, $old); |
||
114 | $n = $this->summarize($em, $new); |
||
115 | } |
||
116 | |||
117 | if ($o !== $n) { |
||
118 | $diff[$fieldName] = [ |
||
119 | 'old' => $o, |
||
120 | 'new' => $n, |
||
121 | ]; |
||
122 | } |
||
123 | } |
||
124 | ksort($diff); |
||
125 | |||
126 | return $diff; |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * Blames an audit operation. |
||
131 | * |
||
132 | * @return array |
||
133 | */ |
||
134 | public function blame(): array |
||
135 | { |
||
136 | $user_id = null; |
||
137 | $username = null; |
||
138 | $client_ip = null; |
||
139 | $user_fqdn = null; |
||
140 | $user_firewall = null; |
||
141 | |||
142 | $request = $this->configuration->getRequestStack()->getCurrentRequest(); |
||
143 | if (null !== $request) { |
||
144 | $client_ip = $request->getClientIp(); |
||
145 | $user_firewall = null === $this->configuration->getFirewallMap()->getFirewallConfig($request) ? null : $this->configuration->getFirewallMap()->getFirewallConfig($request)->getName(); |
||
146 | } |
||
147 | |||
148 | $user = null === $this->configuration->getUserProvider() ? null : $this->configuration->getUserProvider()->getUser(); |
||
149 | if ($user instanceof UserInterface) { |
||
150 | $user_id = $user->getId(); |
||
151 | $username = $user->getUsername(); |
||
152 | $user_fqdn = \get_class($user); |
||
153 | } |
||
154 | |||
155 | return [ |
||
156 | 'user_id' => $user_id, |
||
157 | 'username' => $username, |
||
158 | 'client_ip' => $client_ip, |
||
159 | 'user_fqdn' => $user_fqdn, |
||
160 | 'user_firewall' => $user_firewall, |
||
161 | ]; |
||
162 | } |
||
163 | |||
164 | /** |
||
165 | * Returns an array describing an entity. |
||
166 | * |
||
167 | * @param EntityManagerInterface $em |
||
168 | * @param object $entity |
||
169 | * @param mixed $id |
||
170 | * |
||
171 | * @throws \Doctrine\DBAL\DBALException |
||
172 | * @throws \Doctrine\ORM\Mapping\MappingException |
||
173 | * |
||
174 | * @return array |
||
175 | */ |
||
176 | public function summarize(EntityManagerInterface $em, $entity = null, $id = null): ?array |
||
203 | ]; |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * Return columns of audit tables. |
||
208 | * |
||
209 | * @return array |
||
210 | */ |
||
211 | public function getAuditTableColumns(): array |
||
212 | { |
||
213 | return [ |
||
214 | 'id' => [ |
||
215 | 'type' => class_exists('DoctrineDBALTypesTypes', false) ? Types::INTEGER : Type::INTEGER, |
||
|
|||
216 | 'options' => [ |
||
217 | 'autoincrement' => true, |
||
218 | 'unsigned' => true, |
||
219 | ], |
||
220 | ], |
||
221 | 'type' => [ |
||
222 | 'type' => class_exists('DoctrineDBALTypesTypes', false) ? Types::STRING : Type::STRING, |
||
223 | 'options' => [ |
||
224 | 'notnull' => true, |
||
225 | 'length' => 10, |
||
226 | ], |
||
227 | ], |
||
228 | 'object_id' => [ |
||
229 | 'type' => class_exists('DoctrineDBALTypesTypes', false) ? Types::STRING : Type::STRING, |
||
230 | 'options' => [ |
||
231 | 'notnull' => true, |
||
232 | ], |
||
233 | ], |
||
234 | 'discriminator' => [ |
||
235 | 'type' => class_exists('DoctrineDBALTypesTypes', false) ? Types::STRING : Type::STRING, |
||
236 | 'options' => [ |
||
237 | 'default' => null, |
||
238 | 'notnull' => false, |
||
239 | ], |
||
240 | ], |
||
241 | 'transaction_hash' => [ |
||
242 | 'type' => class_exists('DoctrineDBALTypesTypes', false) ? Types::STRING : Type::STRING, |
||
243 | 'options' => [ |
||
244 | 'notnull' => false, |
||
245 | 'length' => 40, |
||
246 | ], |
||
247 | ], |
||
248 | 'diffs' => [ |
||
249 | 'type' => class_exists('DoctrineDBALTypesTypes', false) ? Types::JSON : Type::JSON, |
||
250 | 'options' => [ |
||
251 | 'default' => null, |
||
252 | 'notnull' => false, |
||
253 | ], |
||
254 | ], |
||
255 | 'blame_id' => [ |
||
256 | 'type' => class_exists('DoctrineDBALTypesTypes', false) ? Types::STRING : Type::STRING, |
||
257 | 'options' => [ |
||
258 | 'default' => null, |
||
259 | 'notnull' => false, |
||
260 | ], |
||
261 | ], |
||
262 | 'blame_user' => [ |
||
263 | 'type' => class_exists('DoctrineDBALTypesTypes', false) ? Types::STRING : Type::STRING, |
||
264 | 'options' => [ |
||
265 | 'default' => null, |
||
266 | 'notnull' => false, |
||
267 | 'length' => 255, |
||
268 | ], |
||
269 | ], |
||
270 | 'blame_user_fqdn' => [ |
||
271 | 'type' => class_exists('DoctrineDBALTypesTypes', false) ? Types::STRING : Type::STRING, |
||
272 | 'options' => [ |
||
273 | 'default' => null, |
||
274 | 'notnull' => false, |
||
275 | 'length' => 255, |
||
276 | ], |
||
277 | ], |
||
278 | 'blame_user_firewall' => [ |
||
279 | 'type' => class_exists('DoctrineDBALTypesTypes', false) ? Types::STRING : Type::STRING, |
||
280 | 'options' => [ |
||
281 | 'default' => null, |
||
282 | 'notnull' => false, |
||
283 | 'length' => 100, |
||
284 | ], |
||
285 | ], |
||
286 | 'ip' => [ |
||
287 | 'type' => class_exists('DoctrineDBALTypesTypes', false) ? Types::STRING : Type::STRING, |
||
288 | 'options' => [ |
||
289 | 'default' => null, |
||
290 | 'notnull' => false, |
||
291 | 'length' => 45, |
||
292 | ], |
||
293 | ], |
||
294 | 'created_at' => [ |
||
295 | 'type' => class_exists('DoctrineDBALTypesTypes', false) ? Types::DATETIME_IMMUTABLE : Type::DATETIME_IMMUTABLE, |
||
296 | 'options' => [ |
||
297 | 'notnull' => true, |
||
298 | ], |
||
299 | ], |
||
300 | ]; |
||
301 | } |
||
302 | |||
303 | public function getAuditTableIndices(string $tablename): array |
||
304 | { |
||
305 | return [ |
||
306 | 'id' => [ |
||
307 | 'type' => 'primary', |
||
308 | ], |
||
309 | 'type' => [ |
||
310 | 'type' => 'index', |
||
311 | 'name' => 'type_'.md5($tablename).'_idx', |
||
312 | ], |
||
313 | 'object_id' => [ |
||
314 | 'type' => 'index', |
||
315 | 'name' => 'object_id_'.md5($tablename).'_idx', |
||
316 | ], |
||
317 | 'discriminator' => [ |
||
318 | 'type' => 'index', |
||
319 | 'name' => 'discriminator_'.md5($tablename).'_idx', |
||
320 | ], |
||
321 | 'transaction_hash' => [ |
||
322 | 'type' => 'index', |
||
323 | 'name' => 'transaction_hash_'.md5($tablename).'_idx', |
||
324 | ], |
||
325 | 'blame_id' => [ |
||
326 | 'type' => 'index', |
||
327 | 'name' => 'blame_id_'.md5($tablename).'_idx', |
||
328 | ], |
||
329 | 'created_at' => [ |
||
330 | 'type' => 'index', |
||
331 | 'name' => 'created_at_'.md5($tablename).'_idx', |
||
332 | ], |
||
333 | ]; |
||
334 | } |
||
335 | |||
336 | public static function paramToNamespace(string $entity): string |
||
337 | { |
||
338 | return str_replace('-', '\\', $entity); |
||
339 | } |
||
340 | |||
341 | public static function namespaceToParam(string $entity): string |
||
344 | } |
||
345 | |||
346 | /** |
||
347 | * Type converts the input value and returns it. |
||
348 | * |
||
349 | * @param EntityManagerInterface $em |
||
350 | * @param Type $type |
||
351 | * @param mixed $value |
||
352 | * |
||
353 | * @throws \Doctrine\DBAL\DBALException |
||
354 | * |
||
355 | * @return mixed |
||
356 | */ |
||
357 | private function value(EntityManagerInterface $em, Type $type, $value) |
||
386 | } |
||
387 | } |
||
388 |
This class constant has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.