Failed Conditions
Push — master ( 674f38...37557b )
by Adrien
03:06
created

Movie   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Test Coverage

Coverage 16.95%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 16
eloc 53
c 4
b 0
f 0
dl 0
loc 152
ccs 10
cts 59
cp 0.1695
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getTitle() 0 8 2
A setSource() 0 9 3
A getStatus() 0 3 1
A extractId() 0 13 3
A setStatus() 0 5 1
A getImdbUrl() 0 3 1
A fetchData() 0 38 3
A setId() 0 10 2
1
<?php
2
3
namespace mQueue\Model;
4
5
use DOMDocument;
6
use DOMXPath;
7
use Exception;
8
use Zend_Date;
9
10
/**
11
 * A movie
12
 */
13
class Movie extends AbstractModel
14
{
15
    /**
16
     * Extract IMDb id from URL
17
     *
18
     * @param string $string
19
     *
20
     * @return null|string the id extracted
21
     */
22 2
    public static function extractId(?string $string): ?string
23
    {
24 2
        if (!$string) {
25 2
            return null;
26
        }
27
28 1
        $string = str_pad($string, 7, '0', STR_PAD_LEFT);
29 1
        preg_match_all("/(\d{7,})/", $string, $r);
30 1
        if (isset($r[1][0])) {
31 1
            return $r[1][0];
32
        }
33
34
        return null;
35
    }
36
37
    /**
38
     * Returns the title, if needed fetch the title from IMDb
39
     *
40
     * @return string
41
     */
42 1
    public function getTitle()
43
    {
44
        // If we didn't get the title yet, fetch it and save in our database
45 1
        if (!($this->title)) {
46
            $this->fetchData();
47
        }
48
49 1
        return $this->title;
50
    }
51
52
    /**
53
     * Fetch data from IMDb and store in database (possibly overwriting)
54
     */
55
    public function fetchData(): void
56
    {
57
        $ch = curl_init($this->getImdbUrl());
58
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept-Language: en-US,en;q=0.8']);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_setopt() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

58
        curl_setopt(/** @scrutinizer ignore-type */ $ch, CURLOPT_HTTPHEADER, ['Accept-Language: en-US,en;q=0.8']);
Loading history...
59
        curl_setopt($ch, CURLOPT_HEADER, false);
60
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
61
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
62
63
        $file = curl_exec($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_exec() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

63
        $file = curl_exec(/** @scrutinizer ignore-type */ $ch);
Loading history...
64
        curl_close($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_close() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

64
        curl_close(/** @scrutinizer ignore-type */ $ch);
Loading history...
65
66
        $document = new DOMDocument();
67
        @$document->loadHTML($file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for loadHTML(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

67
        /** @scrutinizer ignore-unhandled */ @$document->loadHTML($file);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
68
        $xpath = new DOMXPath($document);
69
70
        // Extract title
71
        $titleEntries = $xpath->evaluate('//meta[contains(@property, "og:title")]/@content');
72
        if ($titleEntries->length == 1) {
73
            $rawTitle = $titleEntries->item(0)->value;
74
            $this->title = preg_replace('~ - IMDb$~', '', $rawTitle);
0 ignored issues
show
Bug Best Practice introduced by
The property title does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
75
        } else {
76
            $this->title = '[title not available, could not fetch from IMDb]';
77
78
            return; // If there is not even title give up everything
79
        }
80
81
        // Extract release date
82
        $jsonLd = $xpath->evaluate('//script[@type="application/ld+json"]/text()');
83
        if ($jsonLd->length == 1) {
84
            $json = json_decode($jsonLd->item(0)->data, true);
85
            $this->dateRelease = $json['datePublished'] ?? null;
0 ignored issues
show
Bug Best Practice introduced by
The property dateRelease does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
86
        } else {
87
            $this->dateRelease = null;
88
        }
89
90
        $this->dateUpdate = Zend_Date::now()->get(Zend_Date::ISO_8601);
0 ignored issues
show
Bug Best Practice introduced by
The property dateUpdate does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
91
        $this->setReadOnly(false); // If the movie is coming from a joined query, we need to set non-readonly before saving
92
        $this->save();
93
    }
94
95
    /**
96
     * Sets the ID for the movie from any string containing a valid ID
97
     *
98
     * @param string $id
99
     *
100
     * @return Movie
101
     */
102
    public function setId($id)
103
    {
104
        $extractedId = self::extractId($id);
105
        if (!$extractedId) {
106
            throw new Exception(sprintf('Invalid Id for movie. Given "%1$s", extracted "%2$s"', $id, $extractedId));
107
        }
108
109
        $this->id = $extractedId;
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
110
111
        return $this;
112
    }
113
114
    /**
115
     * Returns the IMDb url for the movie
116
     *
117
     * @return string
118
     */
119
    public function getImdbUrl()
120
    {
121
        return 'https://www.imdb.com/title/tt' . str_pad($this->id, 7, '0', STR_PAD_LEFT) . '/';
122
    }
123
124
    /**
125
     * Returns the status for this movie and the specified user
126
     *
127
     * @param User $user
128
     *
129
     * @return Status
130
     */
131
    public function getStatus(User $user = null)
132
    {
133
        return StatusMapper::find($this->id, $user);
134
    }
135
136
    /**
137
     * Set the status for the specified user
138
     *
139
     * @param User $user
140
     * @param int $rating @see \mQueue\Model\Status
141
     *
142
     * @return Status
143
     */
144
    public function setStatus(User $user, $rating)
145
    {
146
        $status = StatusMapper::set($this, $user, $rating);
147
148
        return $status;
149
    }
150
151
    /**
152
     * Set the source for the movie if any. In any case record the search date and count
153
     *
154
     * @param array|false $source
155
     */
156
    public function setSource($source): void
157
    {
158
        $this->dateSearch = Zend_Date::now()->get(Zend_Date::ISO_8601);
0 ignored issues
show
Bug Best Practice introduced by
The property dateSearch does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
159
        ++$this->searchCount;
0 ignored issues
show
Bug Best Practice introduced by
The property searchCount does not exist on mQueue\Model\Movie. Since you implemented __get, consider adding a @property annotation.
Loading history...
160
        if ($source && @$source['score']) {
161
            $this->identity = $source['identity'];
0 ignored issues
show
Bug Best Practice introduced by
The property identity does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
162
            $this->quality = $source['quality'];
0 ignored issues
show
Bug Best Practice introduced by
The property quality does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
163
            $this->score = $source['score'];
0 ignored issues
show
Bug Best Practice introduced by
The property score does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
164
            $this->source = $source['link'];
0 ignored issues
show
Bug Best Practice introduced by
The property source does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
165
        }
166
    }
167
}
168