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 classes like UserHandler 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 UserHandler, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 22 | class UserHandler extends AbstractHandler implements UserHandlerInterface |
||
| 23 | { |
||
| 24 | /** |
||
| 25 | * {@inheritdoc} |
||
| 26 | */ |
||
| 27 | public function create(User $user) |
||
| 37 | |||
| 38 | /** |
||
| 39 | * {@inheritdoc} |
||
| 40 | */ |
||
| 41 | View Code Duplication | public function load($userId) |
|
| 57 | |||
| 58 | /** |
||
| 59 | * {@inheritdoc} |
||
| 60 | */ |
||
| 61 | View Code Duplication | public function loadByLogin($login) |
|
| 77 | |||
| 78 | /** |
||
| 79 | * {@inheritdoc} |
||
| 80 | */ |
||
| 81 | View Code Duplication | public function loadByEmail($email) |
|
| 102 | |||
| 103 | /** |
||
| 104 | * {@inheritdoc} |
||
| 105 | */ |
||
| 106 | View Code Duplication | public function update(User $user) |
|
| 116 | |||
| 117 | /** |
||
| 118 | * {@inheritdoc} |
||
| 119 | */ |
||
| 120 | public function delete($userId) |
||
| 130 | |||
| 131 | /** |
||
| 132 | * {@inheritdoc} |
||
| 133 | */ |
||
| 134 | public function createRole(RoleCreateStruct $createStruct) |
||
| 140 | |||
| 141 | /** |
||
| 142 | * {@inheritdoc} |
||
| 143 | */ |
||
| 144 | public function createRoleDraft($roleId) |
||
| 150 | |||
| 151 | /** |
||
| 152 | * {@inheritdoc} |
||
| 153 | */ |
||
| 154 | public function loadRole($roleId, $status = Role::STATUS_DEFINED) |
||
| 155 | { |
||
| 156 | if ($status !== Role::STATUS_DEFINED) { |
||
| 157 | $this->logger->logCall(__METHOD__, array('role' => $roleId)); |
||
| 158 | |||
| 159 | return $this->persistenceHandler->userHandler()->loadRole($roleId, $status); |
||
| 160 | } |
||
| 161 | |||
| 162 | $cacheItem = $this->cache->getItem("ez-role-${roleId}"); |
||
| 163 | if ($cacheItem->isHit()) { |
||
| 164 | return $cacheItem->get(); |
||
| 165 | } |
||
| 166 | |||
| 167 | $this->logger->logCall(__METHOD__, array('role' => $roleId)); |
||
| 168 | $role = $this->persistenceHandler->userHandler()->loadRole($roleId, $status); |
||
| 169 | |||
| 170 | $cacheItem->set($role); |
||
| 171 | $cacheItem->tag(['role-' . $role->id]); |
||
| 172 | $this->cache->save($cacheItem); |
||
| 173 | |||
| 174 | return $role; |
||
| 175 | } |
||
| 176 | |||
| 177 | /** |
||
| 178 | * {@inheritdoc} |
||
| 179 | */ |
||
| 180 | public function loadRoleByIdentifier($identifier, $status = Role::STATUS_DEFINED) |
||
| 181 | { |
||
| 182 | if ($status !== Role::STATUS_DEFINED) { |
||
| 183 | $this->logger->logCall(__METHOD__, array('role' => $identifier)); |
||
| 184 | |||
| 185 | return $this->persistenceHandler->userHandler()->loadRoleByIdentifier($identifier, $status); |
||
| 186 | } |
||
| 187 | |||
| 188 | $cacheItem = $this->cache->getItem("ez-role-${identifier}-by-identifier"); |
||
| 189 | if ($cacheItem->isHit()) { |
||
| 190 | return $cacheItem->get(); |
||
| 191 | } |
||
| 192 | |||
| 193 | $this->logger->logCall(__METHOD__, array('role' => $identifier)); |
||
| 194 | $role = $this->persistenceHandler->userHandler()->loadRoleByIdentifier($identifier, $status); |
||
| 195 | |||
| 196 | $cacheItem->set($role); |
||
| 197 | $cacheItem->tag(['role-' . $role->id]); |
||
| 198 | $this->cache->save($cacheItem); |
||
| 199 | |||
| 200 | return $role; |
||
| 201 | } |
||
| 202 | |||
| 203 | /** |
||
| 204 | * {@inheritdoc} |
||
| 205 | */ |
||
| 206 | public function loadRoleDraftByRoleId($roleId) |
||
| 212 | |||
| 213 | /** |
||
| 214 | * {@inheritdoc} |
||
| 215 | */ |
||
| 216 | public function loadRoles() |
||
| 222 | |||
| 223 | /** |
||
| 224 | * {@inheritdoc} |
||
| 225 | */ |
||
| 226 | public function loadRoleAssignment($roleAssignmentId) |
||
| 227 | { |
||
| 228 | $cacheItem = $this->cache->getItem("ez-role-assignment-${roleAssignmentId}"); |
||
| 229 | if ($cacheItem->isHit()) { |
||
| 230 | return $cacheItem->get(); |
||
| 231 | } |
||
| 232 | |||
| 233 | $this->logger->logCall(__METHOD__, array('assignment' => $roleAssignmentId)); |
||
| 234 | $roleAssignment = $this->persistenceHandler->userHandler()->loadRoleAssignment($roleAssignmentId); |
||
| 235 | |||
| 236 | $cacheItem->set($roleAssignment); |
||
| 237 | $cacheItem->tag($this->getCacheTagsForRoleAssignment($roleAssignment)); |
||
| 238 | $this->cache->save($cacheItem); |
||
| 239 | |||
| 240 | return $roleAssignment; |
||
| 241 | } |
||
| 242 | |||
| 243 | /** |
||
| 244 | * {@inheritdoc} |
||
| 245 | */ |
||
| 246 | View Code Duplication | public function loadRoleAssignmentsByRoleId($roleId) |
|
| 247 | { |
||
| 248 | $cacheItem = $this->cache->getItem("ez-role-assignment-${roleId}-by-role"); |
||
| 249 | if ($cacheItem->isHit()) { |
||
| 250 | return $cacheItem->get(); |
||
| 251 | } |
||
| 252 | |||
| 253 | $this->logger->logCall(__METHOD__, array('role' => $roleId)); |
||
| 254 | $roleAssignments = $this->persistenceHandler->userHandler()->loadRoleAssignmentsByRoleId($roleId); |
||
| 255 | |||
| 256 | $cacheItem->set($roleAssignments); |
||
| 257 | $cacheTags = ['role-assignment-role-list-' . $roleId]; |
||
| 258 | foreach ($roleAssignments as $roleAssignment) { |
||
| 259 | $cacheTags = $this->getCacheTagsForRoleAssignment($roleAssignment, $cacheTags); |
||
| 260 | } |
||
| 261 | $cacheItem->tag($cacheTags); |
||
| 262 | $this->cache->save($cacheItem); |
||
| 263 | |||
| 264 | return $roleAssignments; |
||
| 265 | } |
||
| 266 | |||
| 267 | /** |
||
| 268 | * {@inheritdoc} |
||
| 269 | */ |
||
| 270 | public function loadRoleAssignmentsByGroupId($groupId, $inherit = false) |
||
| 271 | { |
||
| 272 | if ($inherit) { |
||
| 273 | $cacheItem = $this->cache->getItem("ez-role-assignment-${groupId}-by-group-inherited"); |
||
| 274 | } else { |
||
| 275 | $cacheItem = $this->cache->getItem("ez-role-assignment-${groupId}-by-group"); |
||
| 276 | } |
||
| 277 | |||
| 278 | if ($cacheItem->isHit()) { |
||
| 279 | return $cacheItem->get(); |
||
| 280 | } |
||
| 281 | |||
| 282 | $this->logger->logCall(__METHOD__, array('group' => $groupId, 'inherit' => $inherit)); |
||
| 283 | $roleAssignments = $this->persistenceHandler->userHandler()->loadRoleAssignmentsByGroupId($groupId, $inherit); |
||
| 284 | |||
| 285 | $cacheItem->set($roleAssignments); |
||
| 286 | // Tag below is for empty results, non empty it might have duplicated tags but cache will reduce those. |
||
| 287 | $cacheTags = ['role-assignment-group-list-' . $groupId]; |
||
| 288 | foreach ($roleAssignments as $roleAssignment) { |
||
| 289 | $cacheTags = $this->getCacheTagsForRoleAssignment($roleAssignment, $cacheTags); |
||
| 290 | } |
||
| 291 | |||
| 292 | // To make sure tree operations affecting this can clear the permission cache |
||
| 293 | $locations = $this->persistenceHandler->locationHandler()->loadLocationsByContent($groupId); |
||
| 294 | View Code Duplication | foreach ($locations as $location) { |
|
|
|
|||
| 295 | foreach (explode('/', trim($location->pathString, '/')) as $pathId) { |
||
| 296 | $cacheTags[] = 'location-path-' . $pathId; |
||
| 297 | } |
||
| 298 | } |
||
| 299 | |||
| 300 | $cacheItem->tag($cacheTags); |
||
| 301 | $this->cache->save($cacheItem); |
||
| 302 | |||
| 303 | return $roleAssignments; |
||
| 304 | } |
||
| 305 | |||
| 306 | /** |
||
| 307 | * {@inheritdoc} |
||
| 308 | */ |
||
| 309 | View Code Duplication | public function updateRole(RoleUpdateStruct $struct) |
|
| 316 | |||
| 317 | /** |
||
| 318 | * {@inheritdoc} |
||
| 319 | */ |
||
| 320 | public function deleteRole($roleId, $status = Role::STATUS_DEFINED) |
||
| 331 | |||
| 332 | /** |
||
| 333 | * {@inheritdoc} |
||
| 334 | */ |
||
| 335 | public function publishRoleDraft($roleDraftId) |
||
| 349 | |||
| 350 | /** |
||
| 351 | * {@inheritdoc} |
||
| 352 | */ |
||
| 353 | public function addPolicyByRoleDraft($roleId, Policy $policy) |
||
| 359 | |||
| 360 | /** |
||
| 361 | * {@inheritdoc} |
||
| 362 | */ |
||
| 363 | public function addPolicy($roleId, Policy $policy) |
||
| 372 | |||
| 373 | /** |
||
| 374 | * {@inheritdoc} |
||
| 375 | */ |
||
| 376 | View Code Duplication | public function updatePolicy(Policy $policy) |
|
| 385 | |||
| 386 | /** |
||
| 387 | * {@inheritdoc} |
||
| 388 | */ |
||
| 389 | View Code Duplication | public function deletePolicy($policyId, $roleId) |
|
| 390 | { |
||
| 391 | $this->logger->logCall(__METHOD__, array('policy' => $policyId)); |
||
| 392 | $this->persistenceHandler->userHandler()->deletePolicy($policyId, $roleId); |
||
| 393 | |||
| 394 | $this->cache->invalidateTags(['policy-' . $policyId, 'role-' . $roleId]); |
||
| 395 | } |
||
| 396 | |||
| 397 | /** |
||
| 398 | * {@inheritdoc} |
||
| 399 | */ |
||
| 400 | public function loadPoliciesByUserId($userId) |
||
| 406 | |||
| 407 | /** |
||
| 408 | * {@inheritdoc} |
||
| 409 | */ |
||
| 410 | public function assignRole($contentId, $roleId, array $limitation = null) |
||
| 419 | |||
| 420 | /** |
||
| 421 | * {@inheritdoc} |
||
| 422 | */ |
||
| 423 | View Code Duplication | public function unassignRole($contentId, $roleId) |
|
| 432 | |||
| 433 | /** |
||
| 434 | * {@inheritdoc} |
||
| 435 | */ |
||
| 436 | View Code Duplication | public function removeRoleAssignment($roleAssignmentId) |
|
| 445 | |||
| 446 | /** |
||
| 447 | * Reusable function to return relevant role assignment tags so cache can be purged reliably. |
||
| 448 | * |
||
| 449 | * @param \eZ\Publish\SPI\Persistence\User\RoleAssignment $roleAssignment |
||
| 450 | * @param array $tags Optional, can be used to specify other tags. |
||
| 451 | * |
||
| 452 | * @return array |
||
| 453 | */ |
||
| 454 | private function getCacheTagsForRoleAssignment(RoleAssignment $roleAssignment, array $tags = []) |
||
| 462 | } |
||
| 463 |
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.