Completed
Push — master ( 898de0...1a66a2 )
by Benedikt
04:39
created

RankingSystemService::recalculateRankingSystems()   B

Complexity

Conditions 9
Paths 1

Size

Total Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 51
c 0
b 0
f 0
cc 9
nc 1
nop 0
rs 7.5135

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
/**
4
 * Created by PhpStorm.
5
 * User: benedikt
6
 * Date: 1/4/18
7
 * Time: 4:09 PM
8
 */
9
10
namespace Tfboe\FmLib\Service;
11
12
13
use Doctrine\DBAL\LockMode;
14
use Doctrine\ORM\EntityManager;
15
use Doctrine\ORM\EntityManagerInterface;
16
use Tfboe\FmLib\Entity\Helpers\TournamentHierarchyInterface;
17
use Tfboe\FmLib\Entity\LastRecalculationInterface;
18
use Tfboe\FmLib\Entity\RankingSystemInterface;
19
use Tfboe\FmLib\Entity\TournamentInterface;
20
21
/**
22
 * Class RankingSystemService
23
 * @package Tfboe\FmLib\Service
24
 */
25
class RankingSystemService implements RankingSystemServiceInterface
26
{
27
//<editor-fold desc="Fields">
28
  /**
29
   * @var DynamicServiceLoadingServiceInterface
30
   */
31
  private $dsls;
32
33
  /** @var EntityManagerInterface */
34
  private $entityManager;
35
//</editor-fold desc="Fields">
36
37
//<editor-fold desc="Constructor">
38
39
  /**
40
   * RankingSystemService constructor.
41
   * @param DynamicServiceLoadingServiceInterface $dsls
42
   * @param EntityManagerInterface $entityManager
43
   */
44
  public function __construct(DynamicServiceLoadingServiceInterface $dsls, EntityManagerInterface $entityManager)
45
  {
46
    $this->dsls = $dsls;
47
    $this->entityManager = $entityManager;
48
  }
49
//</editor-fold desc="Constructor">
50
51
//<editor-fold desc="Public Methods">
52
  /**
53
   * @inheritDoc
54
   */
55
  public function adaptOpenSyncFromValues(TournamentInterface $tournament, array $oldInfluences): void
56
  {
57
    $earliestInfluences = $this->getRankingSystemsEarliestInfluences($tournament);
58
    foreach ($oldInfluences as $id => $arr) {
59
      if (array_key_exists($id, $earliestInfluences)) {
60
        if ($oldInfluences[$id]["earliestInfluence"] < $earliestInfluences[$id]["earliestInfluence"]) {
61
          $earliestInfluences[$id]["earliestInfluence"] = $oldInfluences[$id]["earliestInfluence"];
62
        }
63
      } else {
64
        $earliestInfluences[$id] = $oldInfluences[$id];
65
      }
66
    }
67
    foreach ($earliestInfluences as $arr) {
68
      /** @var RankingSystemInterface $ranking */
69
      $ranking = $arr["rankingSystem"];
70
      $earliestInfluence = $arr["earliestInfluence"];
71
      if ($ranking->getOpenSyncFrom() === null || $ranking->getOpenSyncFrom() > $earliestInfluence) {
72
        $ranking->setOpenSyncFrom($earliestInfluence);
73
      }
74
    }
75
  }
76
77
  /**
78
   * @inheritDoc
79
   */
80
  public function applyRankingSystems(TournamentInterface $tournament, array $earliestInfluences): void
81
  {
82
    $rankingSystems = $this->getRankingSystems($tournament);
83
    foreach ($rankingSystems as $sys) {
84
      if (!array_key_exists($sys->getId(), $earliestInfluences)) {
85
        $earliestInfluences[$sys->getId()] = [
86
          "rankingSystem" => $sys,
87
          "earliestInfluence" => null
88
        ];
89
      }
90
    }
91
    foreach ($earliestInfluences as $arr) {
92
      /** @var RankingSystemInterface $ranking */
93
      $ranking = $arr["rankingSystem"];
94
      $earliestInfluence = $arr["earliestInfluence"];
95
      $service = $this->dsls->loadRankingSystemService($ranking->getServiceName());
96
      $service->updateRankingForTournament($ranking, $tournament, $earliestInfluence);
97
    }
98
  }
99
100
  /**
101
   * @inheritDoc
102
   */
103
  public function getRankingSystemsEarliestInfluences(TournamentInterface $tournament): array
104
  {
105
    $rankingSystems = $this->getRankingSystems($tournament);
106
107
    $result = [];
108
    //compute earliest influences
109
    foreach ($rankingSystems as $sys) {
110
      $service = $this->dsls->loadRankingSystemService($sys->getServiceName());
111
      $result[$sys->getId()] = [
112
        "rankingSystem" => $sys,
113
        "earliestInfluence" => $service->getEarliestInfluence($sys, $tournament)
114
      ];
115
    }
116
117
    return $result;
118
  }
119
120
  /**
121
   * @inheritDoc
122
   */
123
  public function recalculateRankingSystems(): void
124
  {
125
    //clear entityManager to save memory
126
    $this->entityManager->flush();
127
    $this->entityManager->clear();
128
    $rankingSystemOpenSyncFroms = [];
129
    /** @var RankingSystemInterface[] $rankingSystems */
130
    $rankingSystems = [];
131
    $this->entityManager->transactional(
132
      function (EntityManager $em) use (&$rankingSystems, &$rankingSystemOpenSyncFroms) {
133
        $em->find(LastRecalculationInterface::class, 1, LockMode::PESSIMISTIC_WRITE);
134
        $query = $em->createQueryBuilder();
135
        $query
136
          ->from(RankingSystemInterface::class, 's')
137
          ->select('s')
138
          ->where($query->expr()->isNotNull('s.openSyncFrom'))
139
          ->orWhere($query->expr()->isNotNull('s.openSyncFromInProcess'));
140
        /** @var RankingSystemInterface[] $rankingSystems */
141
        $rankingSystems = $query->getQuery()->setLockMode(LockMode::PESSIMISTIC_WRITE)->getResult();
142
        foreach ($rankingSystems as $rankingSystem) {
143
          if ($rankingSystem->getOpenSyncFrom() !== null && ($rankingSystem->getOpenSyncFromInProcess() === null ||
144
              $rankingSystem->getOpenSyncFrom() < $rankingSystem->getOpenSyncFromInProcess())) {
145
            $rankingSystemOpenSyncFroms[$rankingSystem->getId()] = $rankingSystem->getOpenSyncFrom();
146
            $rankingSystem->setOpenSyncFrom(null);
147
          }
148
        }
149
      }
150
    );
151
152
    $this->entityManager->transactional(
153
      function (EntityManager $em) use (&$rankingSystems, &$rankingSystemOpenSyncFroms) {
154
        /** @var LastRecalculationInterface $lastRecalculation */
155
        $lastRecalculation = $em->find(LastRecalculationInterface::class, 1, LockMode::PESSIMISTIC_WRITE);
156
        foreach ($rankingSystems as $rankingSystem) {
157
          if (array_key_exists($rankingSystem->getId(), $rankingSystemOpenSyncFroms) &&
158
            $rankingSystemOpenSyncFroms[$rankingSystem->getId()] < $rankingSystem->getOpenSyncFromInProcess()) {
159
            $rankingSystem->setOpenSyncFromInProcess($rankingSystemOpenSyncFroms[$rankingSystem->getId()]);
160
          }
161
        }
162
        $em->flush();
163
        $lastRecalculation->setStartTime(new \DateTime());
164
        foreach ($rankingSystems as $rankingSystem) {
165
          $service = $this->dsls->loadRankingSystemService($rankingSystem->getServiceName());
166
          $service->updateRankingFrom($rankingSystem, $rankingSystem->getOpenSyncFrom());
0 ignored issues
show
Bug introduced by
It seems like $rankingSystem->getOpenSyncFrom() can be null; however, updateRankingFrom() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
167
          $rankingSystem->setOpenSyncFromInProcess(null);
168
        }
169
        $lastRecalculation->setEndTime(new \DateTime());
170
        $lastRecalculation->setVersion($lastRecalculation->getVersion() + 1);
171
      }
172
    );
173
  }
174
//</editor-fold desc="Public Methods">
175
176
//<editor-fold desc="Private Methods">
177
  /**
178
   * @param TournamentHierarchyInterface $entity
179
   * @return RankingSystemInterface[]
180
   */
181
  private function getRankingSystems(TournamentHierarchyInterface $entity): array
182
  {
183
    $result = $entity->getRankingSystems()->toArray();
184
    foreach ($entity->getChildren() as $child) {
185
      $result = array_merge($result, $this->getRankingSystems($child));
186
    }
187
    return $result;
188
  }
189
//</editor-fold desc="Private Methods">
190
}