Test Failed
Push — master ( c2c60e...83ec37 )
by Alexis
14:02 queued 09:54
created

TweetRepository   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 232
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 62.5%

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 7
dl 0
loc 232
ccs 60
cts 96
cp 0.625
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A getWithUsers() 0 22 1
A getWithUsersAndMediasQuery() 0 19 1
A getWithUsersAndMedias() 0 14 2
A getTweetId() 0 19 2
A getPreviousTweetId() 0 4 1
A getNextTweetId() 0 4 1
A countPendingTweets() 0 21 2
A getLastTweet() 0 9 1
A getTweetsLessThanId() 0 21 1
A removeOrphanMedias() 0 6 2
A removeTweet() 0 18 3
A deleteAndHideTweetsLessThanId() 0 21 3
1
<?php
2
3
namespace AlexisLefebvre\Bundle\AsyncTweetsBundle\Entity;
4
5
use Doctrine\ORM\EntityRepository;
6
7
/**
8
 * TweetRepository.
9
 *
10
 * This class was generated by the Doctrine ORM. Add your own custom
11
 * repository methods below.
12
 */
13
class TweetRepository extends EntityRepository
14
{
15
    private $nbTweets = 5;
16
17 3
    public function getWithUsers($page = 1)
18
    {
19 3
        $firstResult = (($page - 1) * $this->nbTweets);
20
21 3
        $qb = $this->createQueryBuilder('t');
22
23
        $query = $qb
24 3
            ->select('t, user, rt, rt_user')
25 3
            ->innerJoin('t.user', 'user')
26 3
            ->leftJoin('t.retweeted_status', 'rt')
27 3
            ->leftJoin('rt.user', 'rt_user')
28
29
            // Ignore tweets that were only retweeted
30 3
            ->where($qb->expr()->eq('t.in_timeline', 'true'))
31
32 3
            ->orderBy('t.id', 'DESC')
33
34 3
            ->setFirstResult($firstResult)
35 3
            ->setMaxResults($this->nbTweets);
36
37 3
        return $query->getQuery()->getResult();
38
    }
39
40
    /**
41
     * @param \Doctrine\ORM\QueryBuilder $qb
42
     *
43
     * @return \Doctrine\ORM\QueryBuilder $query
44
     */
45 8
    private function getWithUsersAndMediasQuery($qb)
46
    {
47
        $query = $qb
48 8
            ->select('t, user, medias, rt, rt_user')
49 8
            ->innerJoin('t.user', 'user')
50 8
            ->leftJoin('t.medias', 'medias')
51 8
            ->leftJoin('t.retweeted_status', 'rt')
52 8
            ->leftJoin('rt.user', 'rt_user')
53
54
            // Ignore tweets that were only retweeted
55 8
            ->where($qb->expr()->eq('t.in_timeline', 'true'))
56
57 8
            ->orderBy('t.id', 'ASC')
58
59 8
            ->setFirstResult(0)
60 8
            ->setMaxResults($this->nbTweets);
61
62 8
        return $query;
63
    }
64
65 8
    public function getWithUsersAndMedias($firstTweetId = null)
66
    {
67 8
        $qb = $this->createQueryBuilder('t');
68
69 8
        $query = $this->getWithUsersAndMediasQuery($qb);
70
71 8
        if (!is_null($firstTweetId)) {
72 4
            $query = $query->andWhere(
73 4
                $qb->expr()->gte('t.id', $firstTweetId)
74
            );
75
        }
76
77 8
        return $query->getQuery()->getResult();
78
    }
79
80
    /**
81
     * @param string $condition
82
     * @param string $order
83
     * @param int    $tweetId
84
     *
85
     * @return int|null
86
     */
87 6
    private function getTweetId($condition, $order, $tweetId)
88
    {
89 6
        $qb = $this->createQueryBuilder('t')
90 6
            ->select('t.id')
91
92 6
            ->where('t.id '.$condition.' :tweetId')
93 6
            ->setParameter(':tweetId', $tweetId)
94
95 6
            ->andWhere('t.in_timeline = true')
96
97 6
            ->orderBy('t.id', $order)
98
99 6
            ->setFirstResult($this->nbTweets - 1)
100 6
            ->setMaxResults(1);
101
102 6
        $result = $qb->getQuery()->getOneOrNullResult();
103
104 6
        return is_array($result) ? $result['id'] : null;
105
    }
106
107 6
    public function getPreviousTweetId($tweetId)
108
    {
109 6
        return $this->getTweetId('<', 'DESC', $tweetId);
110
    }
111
112 6
    public function getNextTweetId($tweetId)
113
    {
114 6
        return $this->getTweetId('>', 'ASC', $tweetId);
115
    }
116
117 7
    public function countPendingTweets($lastTweetId = null): int
118
    {
119
        /** @var \Doctrine\ORM\QueryBuilder $qb */
120 7
        $qb = $this->createQueryBuilder('t');
121
122
        $query = $qb
123 7
            ->add('select', $qb->expr()->count('t.id'))
124
            // Ignore tweets that were only retweeted
125 7
            ->where(
126 7
                $qb->expr()->eq('t.in_timeline', 'true')
127
            );
128
129 7
        if (!is_null($lastTweetId)) {
130 7
            $query = $query->andWhere(
131 7
                $qb->expr()->gte('t.id', $lastTweetId)
132
            );
133
        }
134
135
        // return result of "COUNT()" query
136 7
        return $query->getQuery()->getSingleScalarResult();
137
    }
138
139 7
    public function getLastTweet(): ?Tweet
140
    {
141 7
        $qb = $this->createQueryBuilder('t')
142 7
            ->addOrderBy('t.id', 'DESC')
143 7
            ->setFirstResult(0)
144 7
            ->setMaxResults(1);
145
146 7
        return $qb->getQuery()->getOneOrNullResult();
147
    }
148
149
    /**
150
     * @param int $tweetId
151
     *
152
     * @return array
153
     */
154
    private function getTweetsLessThanId($tweetId)
155
    {
156
        $qb = $this->createQueryBuilder('t')
157
            ->select('t, m')
158
            ->leftJoin('t.medias', 'm')
159
            ->where('t.id < :tweetId')
160
            ->setParameter(':tweetId', $tweetId)
161
162
            // Get retweeted tweets (it would break foreign keys)
163
            //  http://stackoverflow.com/questions/15087933/how-to-do-left-join-in-doctrine/15088250#15088250
164
            ->leftJoin(
165
                'AsyncTweetsBundle:Tweet',
166
                't2',
167
                'WITH',
168
                't.id = t2.retweeted_status'
169
            )
170
171
            ->orderBy('t.id', 'DESC');
172
173
        return $qb->getQuery()->getResult();
174
    }
175
176
    /**
177
     * Remove Media not associated to any Tweet.
178
     *
179
     * @param Media $media
180
     */
181
    private function removeOrphanMedias(Media $media)
182
    {
183
        if (count($media->getTweets()) == 0) {
184
            $this->_em->remove($media);
185
        }
186
    }
187
188
    /**
189
     * Remove the tweet and return 1 is the deleted tweet is not a
190
     *  retweet.
191
     *
192
     * @param Tweet $tweet
193
     *
194
     * @return int
195
     */
196
    protected function removeTweet($tweet)
197
    {
198
        $count = 0;
199
200
        foreach ($tweet->getMedias() as $media) {
201
            $tweet->removeMedia($media);
202
            $this->removeOrphanMedias($media);
203
        }
204
205
        // Don't count tweets that were only retweeted
206
        if ($tweet->isInTimeline()) {
207
            $count = 1;
208
        }
209
210
        $this->_em->remove($tweet);
211
212
        return $count;
213
    }
214
215
    /**
216
     * Delete tweets and return the number of deleted tweets (excluding
217
     *  retweeted-only tweets).
218
     *
219
     * @param int $tweetId
220
     *
221
     * @return int
222
     */
223
    public function deleteAndHideTweetsLessThanId($tweetId)
224
    {
225
        $count = 0;
226
227
        $tweets = $this->getTweetsLessThanId($tweetId);
228
229
        foreach ($tweets as $tweet) {
230
            if ($tweet->mustBeKept($tweetId)) {
231
                // The Tweet is still in the timeline, it can only be hidden
232
                $tweet->setInTimeline(false);
233
                $this->_em->persist($tweet);
234
            } else {
235
                // The Tweet has not been retweeted, it can be removed
236
                $count += $this->removeTweet($tweet);
237
            }
238
        }
239
240
        $this->_em->flush();
241
242
        return $count;
243
    }
244
}
245