Failed Conditions
Push — master ( 2b3b32...674f38 )
by Adrien
03:18
created

Movie::setStatus()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 5
ccs 0
cts 3
cp 0
rs 10
cc 1
nc 1
nop 2
crap 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 1
    public static function extractId(string $string): ?string
23
    {
24 1
        $string = str_pad($string, 7, '0', STR_PAD_LEFT);
25 1
        preg_match_all("/(\d{7,})/", $string, $r);
26 1
        if (isset($r[1][0])) {
27 1
            return $r[1][0];
28
        }
29
30
        return null;
31
    }
32
33
    /**
34
     * Returns the title, if needed fetch the title from IMDb
35
     *
36
     * @return string
37
     */
38 1
    public function getTitle()
39
    {
40
        // If we didn't get the title yet, fetch it and save in our database
41 1
        if (!($this->title)) {
42
            $this->fetchData();
43
        }
44
45 1
        return $this->title;
46
    }
47
48
    /**
49
     * Fetch data from IMDb and store in database (possibly overwriting)
50
     */
51
    public function fetchData(): void
52
    {
53
        $ch = curl_init($this->getImdbUrl());
54
        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

54
        curl_setopt(/** @scrutinizer ignore-type */ $ch, CURLOPT_HTTPHEADER, ['Accept-Language: en-US,en;q=0.8']);
Loading history...
55
        curl_setopt($ch, CURLOPT_HEADER, false);
56
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
57
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
58
59
        $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

59
        $file = curl_exec(/** @scrutinizer ignore-type */ $ch);
Loading history...
60
        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

60
        curl_close(/** @scrutinizer ignore-type */ $ch);
Loading history...
61
62
        $document = new DOMDocument();
63
        @$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

63
        /** @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...
64
        $xpath = new DOMXPath($document);
65
66
        // Extract title
67
        $titleEntries = $xpath->evaluate('//meta[contains(@property, "og:title")]/@content');
68
        if ($titleEntries->length == 1) {
69
            $rawTitle = $titleEntries->item(0)->value;
70
            $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...
71
        } else {
72
            $this->title = '[title not available, could not fetch from IMDb]';
73
74
            return; // If there is not even title give up everything
75
        }
76
77
        // Extract release date
78
        $jsonLd = $xpath->evaluate('//script[@type="application/ld+json"]/text()');
79
        if ($jsonLd->length == 1) {
80
            $json = json_decode($jsonLd->item(0)->data, true);
81
            $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...
82
        } else {
83
            $this->dateRelease = null;
84
        }
85
86
        $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...
87
        $this->setReadOnly(false); // If the movie is coming from a joined query, we need to set non-readonly before saving
88
        $this->save();
89
    }
90
91
    /**
92
     * Sets the ID for the movie from any string containing a valid ID
93
     *
94
     * @param string $id
95
     *
96
     * @return \mQueue\Model\Movie
97
     */
98
    public function setId($id)
99
    {
100
        $extractedId = self::extractId($id);
101
        if (!$extractedId) {
102
            throw new Exception(sprintf('Invalid Id for movie. Given "%1$s", extracted "%2$s"', $id, $extractedId));
103
        }
104
105
        $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...
106
107
        return $this;
108
    }
109
110
    /**
111
     * Returns the IMDb url for the movie
112
     *
113
     * @return string
114
     */
115
    public function getImdbUrl()
116
    {
117
        return 'https://www.imdb.com/title/tt' . str_pad($this->id, 7, '0', STR_PAD_LEFT) . '/';
118
    }
119
120
    /**
121
     * Returns the status for this movie and the specified user
122
     *
123
     * @param \mQueue\Model\User $user
124
     *
125
     * @return \mQueue\Model\Status
126
     */
127
    public function getStatus(User $user = null)
128
    {
129
        return StatusMapper::find($this->id, $user);
130
    }
131
132
    /**
133
     * Set the status for the specified user
134
     *
135
     * @param \mQueue\Model\User $user
136
     * @param int $rating @see \mQueue\Model\Status
137
     *
138
     * @return \mQueue\Model\Status
139
     */
140
    public function setStatus(User $user, $rating)
141
    {
142
        $status = StatusMapper::set($this, $user, $rating);
143
144
        return $status;
145
    }
146
147
    /**
148
     * Set the source for the movie if any. In any case record the search date and count
149
     *
150
     * @param array|false $source
151
     */
152
    public function setSource($source): void
153
    {
154
        $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...
155
        ++$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...
156
        if ($source && @$source['score']) {
157
            $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...
158
            $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...
159
            $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...
160
            $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...
161
        }
162
    }
163
}
164