Passed
Pull Request — development (#389)
by Mirko
23:21
created

FieldNoteService::importFromFile()   B

Complexity

Conditions 8
Paths 11

Size

Total Lines 53
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 33
nc 11
nop 3
dl 0
loc 53
rs 7.1199
c 0
b 0
f 0

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
3
namespace AppBundle\Service;
4
5
use AppBundle\Entity\FieldNote;
6
use AppBundle\Exception\WrongDateFormatException;
7
use AppBundle\Exception\WrongFileFormatException;
8
use AppBundle\Service\Interfaces\FieldNoteServiceInterface;
9
use AppBundle\Service\Traits\ErrorTrait;
10
use AppBundle\Util\ArrayUtil;
11
use AppBundle\Util\DateUtil;
12
use DateTime;
13
use DateTimeZone;
14
use Doctrine\ORM\EntityManagerInterface;
15
use Symfony\Component\Translation\TranslatorInterface;
16
17
class FieldNoteService implements FieldNoteServiceInterface
18
{
19
    use ErrorTrait;
20
21
    /**
22
     * @var \Doctrine\ORM\EntityManagerInterface
23
     */
24
    protected $entityManager;
25
26
    /**
27
     * @var \Symfony\Component\Translation\TranslatorInterface
28
     */
29
    protected $translator;
30
31
    /**
32
     * FieldNoteService constructor.
33
     *
34
     * @param \Doctrine\ORM\EntityManagerInterface $entityManager
35
     * @param \Symfony\Component\Translation\TranslatorInterface $translator
36
     */
37
    public function __construct(EntityManagerInterface $entityManager, TranslatorInterface $translator)
38
    {
39
        $this->entityManager = $entityManager;
40
        $this->translator = $translator;
41
    }
42
43
    /**
44
     * @param string $fileName
45
     * @param int $userId
46
     * @param null|\DateTime $ignoreBeforeDate
47
     *
48
     * @return bool
49
     * @throws \AppBundle\Exception\WrongDateFormatException
50
     * @throws \AppBundle\Exception\WrongFileFormatException
51
     */
52
    public function importFromFile($fileName, $userId, DateTime $ignoreBeforeDate = null)
53
    {
54
        $content = file_get_contents($fileName);
55
        $content = mb_convert_encoding($content, 'UTF-8', 'UCS-2LE');
56
        $rows = ArrayUtil::trimExplode("\n", $content);
57
        foreach ($rows as $row) {
58
            $data = str_getcsv($row, ',', '"', '""');
59
            if (count($data) !== 4) {
60
                throw new WrongFileFormatException(
61
                    $this->translator->trans('field_notes.error.wrong_file_format')
62
                );
63
            }
64
65
            $date = $this->getDate($data[1]);
66
67
            if ($ignoreBeforeDate !== null && $date < $ignoreBeforeDate) {
68
                continue;
69
            }
70
71
            if (!array_key_exists($data[2], self::LOG_TYPE)) {
72
                $this->addError(
73
                    /** @Desc("Log type ""%type%"" is not implemented.") */
74
                    $this->translator->trans('field_notes.error.log_type_not_implemented', ['%type%' => $data[2]])
75
                );
76
                continue;
77
            }
78
            $type = self::LOG_TYPE[$data[2]];
79
            
80
            $geocache = $this->entityManager->getRepository('AppBundle:Geocache')->findOneBy(['wpOc' => $data[0]]);
81
            if (!$geocache) {
82
                $this->addError(
83
                    /** @Desc("Geocache ""%code%"" not found.") */
84
                    $this->translator->trans('field_notes.error.geocache_not_found', ['%code%' => $data[0]])
85
                );
86
                continue;
87
            }
88
89
            $fieldNote = new FieldNote();
90
            $fieldNote->setUser($this->entityManager->getReference('AppBundle:User', $userId));
91
            $fieldNote->setGeocache($geocache);
92
            $fieldNote->setDate($date);
93
            $fieldNote->setType($type);
94
            $fieldNote->setText($data[3]);
95
            $this->entityManager->persist($fieldNote);
96
        }
97
        $this->entityManager->flush();
98
99
        if ($this->hasErrors()) {
100
            return false;
101
        }
102
103
        return true;
104
    }
105
106
    /**
107
     * @param int $userId
108
     *
109
     * @return \DateTime|null
110
     */
111
    public function getLatestFieldNoteOrLogDate($userId)
112
    {
113
        $maxFieldNote = $this->getMaxDateFromEntityByUserId('AppBundle:FieldNote', $userId);
114
        $maxLog = $this->getMaxDateFromEntityByUserId('AppBundle:GeocacheLog', $userId);
115
116
        return max($maxFieldNote, $maxLog);
117
    }
118
119
    /**
120
     * @param string $entityName
121
     * @param int $userId
122
     *
123
     * @return \DateTime|null
124
     */
125
    protected function getMaxDateFromEntityByUserId($entityName, $userId)
126
    {
127
        $max = null;
128
        $query = $this->entityManager->createQueryBuilder();
129
        $query
130
            ->select('MAX(e.date) AS max_date')
131
            ->from($entityName, 'e')
132
            ->where('e.user = :user_id')
133
                ->setParameter('user_id', $userId)
134
            ->setMaxResults(1);
135
        $result = $query->getQuery()->getResult();
136
        if ($result && isset($result[0]['max_date'])) {
137
            $max = DateUtil::dateTimeFromMySqlFormat($result[0]['max_date']);
138
        }
139
140
        return $max;
141
    }
142
143
    /**
144
     * @param string $dateString
145
     *
146
     * @throws \AppBundle\Exception\WrongDateFormatException
147
     * @return \DateTime
148
     */
149
    protected function getDate($dateString)
150
    {
151
        $format = null;
152
        if (preg_match('/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}Z/', $dateString)) {
153
            $format = self::FIELD_NOTE_DATETIME_FORMAT_SHORT;
154
        } elseif (preg_match('/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z/', $dateString)) {
155
            $format = self::FIELD_NOTE_DATETIME_FORMAT;
156
        }
157
158
        if ($format === null) {
159
            throw new WrongDateFormatException(
160
                $this->translator->trans('field_notes.error.wrong_date_format')
161
            );
162
        }
163
164
        $date = DateTime::createFromFormat(
165
            $format,
166
            $dateString,
167
            new DateTimeZone('UTC')
168
        );
169
170
        return $date;
171
    }
172
}
173