MovieMapper::getFilteredQuery()   C
last analyzed

Complexity

Conditions 14
Paths 35

Size

Total Lines 66
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 14.6615

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 14
eloc 41
c 1
b 0
f 0
nc 35
nop 2
dl 0
loc 66
ccs 34
cts 40
cp 0.85
crap 14.6615
rs 6.2666

How to fix   Long Method    Complexity   

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 mQueue\Model;
4
5
use Zend_Date;
6
use Zend_Db_Expr;
7
use Zend_Db_Table_Select;
8
9
abstract class MovieMapper extends AbstractMapper
10
{
11
    /**
12
     * Returns a movie by its ID
13
     *
14
     * @param int $id
15
     *
16
     * @return null|Movie
17
     */
18 16
    public static function find($id)
19
    {
20 16
        $result = self::getDbTable()->find([$id]);
21
22 16
        return $result->current();
23
    }
24
25
    /**
26
     * Returns all movies
27
     *
28
     * @return Movie[]
29
     */
30
    public static function fetchAll()
31
    {
32
        $resultSet = self::getDbTable()->fetchAll();
33
34
        return $resultSet;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $resultSet returns the type Zend_Db_Table_Rowset_Abstract which is incompatible with the documented return type mQueue\Model\Movie[].
Loading history...
35
    }
36
37
    /**
38
     * Returns movies for search
39
     *
40
     * @return Movie[]
41
     */
42
    public static function findAllForSearch()
43
    {
44
        $futureYears = [];
45
        $date = Zend_Date::now();
46
        for ($i = 0; $i < 10; ++$i) {
47
            $date->addYear(1);
48
            $futureYears[] = $date->get(Zend_Date::YEAR_8601);
49
        }
50
51
        $select = self::getDbTable()->select()->setIntegrityCheck(false)
52
            ->from('movie')
53
            ->join('status', 'status.idMovie = movie.id AND status.isLatest AND rating = ' . Status::Need, [])
54
            ->where('source IS NULL')
55
            ->where('dateSearch IS NULL OR dateSearch < DATE_SUB(NOW(), INTERVAL searchCount MONTH)')// Search for same movie with an incrementally longer interval (1 month, 2 month, 3 month, etc.)
56
            ->where('dateRelease IS NOT NULL')// Movie must be released ...
57
            ->where('dateRelease < DATE_SUB(NOW(), INTERVAL 1 MONTH)')// ...at least released one month ago, or longer
58
            ->group('movie.id')
59
            ->order('COUNT(movie.id) DESC')// First, order by popularity, so get the most needed first
60
            ->order('RAND() ASC')// Then, randomize a little bit so we don't always look for the same movies
61
            ->limit(5);
62
63
        $records = self::getDbTable()->fetchAll($select);
64
65
        return $records;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $records returns the type Zend_Db_Table_Rowset_Abstract which is incompatible with the documented return type mQueue\Model\Movie[].
Loading history...
66
    }
67
68
    /**
69
     * Returns movies for data fetching
70
     *
71
     * @param int $limit
72
     *
73
     * @return Movie[]
74
     */
75
    public static function findAllForFetching($limit = null)
76
    {
77
        $select = self::getDbTable()->select()->setIntegrityCheck(false)
78
            ->from('movie')
79
            ->where('dateUpdate IS NULL OR dateUpdate < DATE_SUB(NOW(), INTERVAL 1 MONTH)')// Don't fetch data for movies, more than once a month
80
            ->order('RAND()'); // Randomize order, so we don't watch only old movies
81
82
        if ($limit) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $limit of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
83
            $select->limit(20);
84
        }
85
86
        $records = self::getDbTable()->fetchAll($select);
87
88
        return $records;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $records returns the type Zend_Db_Table_Rowset_Abstract which is incompatible with the documented return type mQueue\Model\Movie[].
Loading history...
89
    }
90
91
    /**
92
     * Returns a query filtered according to parameters. This query may be used with paginator.
93
     *
94
     * @param array $filters
95
     * @param string $orderBy valid SQL sorting snippet
96
     *
97
     * @return Zend_Db_Table_Select
98
     */
99 1
    public static function getFilteredQuery(array $filters, string $orderBy)
100
    {
101 1
        $orderBy = preg_replace('/^(status\d+)(.*)/', '\\1.rating\\2', $orderBy);
102
103 1
        $select = self::getDbTable()->select()->setIntegrityCheck(false)
104 1
            ->from('movie')
105 1
            ->order($orderBy);
106
107 1
        $i = 0;
108 1
        $maxDate = '';
109 1
        $filtersDone = [];
110 1
        foreach ($filters as $key => $filter) {
111 1
            if (!is_array($filter)) {
112 1
                continue;
113
            }
114
115 1
            $filterUniqueId = $filter['user'];
116 1
            if (!preg_match('/^filter\d+$/', $key) || in_array($filterUniqueId, $filtersDone)) {
117
                continue;
118
            }
119
120 1
            $filtersDone[] = $filterUniqueId;
121 1
            $showNoRating = in_array(0, $filter['status']);
122 1
            $alias = 'status' . $i++;
123 1
            $allowNull = ' OR ' . $alias . '.idUser IS NULL';
124 1
            if ($filter['condition'] === 'is') {
125 1
                $condition = '';
126 1
                $allowNull = $showNoRating ? $allowNull : '';
127
            } else {
128
                $condition = 'NOT ';
129
                $allowNull = !$showNoRating ? $allowNull : '';
130
            }
131 1
            $select->joinLeft([$alias => 'status'], '(movie.id = ' . $alias . '.idMovie AND ' . $alias . '.idUser = ' . $filter['user'] . ')' . $allowNull, []);
132
133 1
            $select->where($alias . '.isLatest = 1 OR ' . $alias . '.isLatest IS NULL');
134
135
            // Filter by status
136 1
            $select->where($alias . '.rating ' . $condition . 'IN (?)' . $allowNull, $filter['status']);
137
138
            // Filter by title
139 1
            if (isset($filter['title'])) {
140 1
                $title = $filter['title'];
141 1
                $id = Movie::extractId($title);
142 1
                $titles = explode(' ', trim($title));
143 1
                foreach ($titles as $part) {
144 1
                    if ($part) {
145
                        $select->where('movie.title LIKE ? OR movie.id = "' . $id . '"', '%' . $part . '%');
146
                    }
147
                }
148
            }
149
150
            // Filter by presence of source
151 1
            if (isset($filter['withSource']) && $filter['withSource']) {
152
                $select->where('movie.source IS NOT NULL');
153
            }
154
155 1
            if ($maxDate) {
156
                $maxDate = 'IF(`' . $alias . '`.`dateUpdate` IS NULL OR `' . $alias . '`.`dateUpdate` < ' . $maxDate . ', ' . $maxDate . ', `' . $alias . '`.`dateUpdate`)';
157
            } else {
158 1
                $maxDate = '`' . $alias . '`.`dateUpdate`';
159
            }
160
        }
161
162 1
        $select->columns(['date' => new Zend_Db_Expr($maxDate)]);
163
164 1
        return $select;
165
    }
166
167
    /**
168
     * Delete obsolete sources for all movies.
169
     * An obsolete source is either a source older than 3 months, or
170
     * a source which is not needed anymore (nobody need the movie anymore)
171
     */
172
    public static function deleteObsoleteSources(): void
173
    {
174
        $db = self::getDbTable()->getAdapter();
175
        $update = 'UPDATE `movie` SET dateUpdate = dateUpdate, dateSearch = NULL, searchCount = 0, identity = 0, quality = 0, score = 0, source = NULL';
176
177
        // Delete sources older than 6 months
178
        $db->query($update . ' WHERE `source` IS NOT NULL AND `dateSearch` < DATE_SUB(NOW(), INTERVAL 6 MONTH)');
179
180
        // Delete non-needed sources
181
        $db->query($update . ' WHERE `movie`.`id` NOT IN (SELECT `status`.`idMovie` FROM `status` WHERE `rating` = ? AND `isLatest`)', [Status::Need]);
182
    }
183
}
184