Completed
Push — master ( 79d43d...8be713 )
by Angus
03:47
created

HelveticaScans::getTitleData()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 38
Code Lines 24

Duplication

Lines 38
Ratio 100 %

Code Coverage

Tests 22
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 24
nc 10
nop 1
dl 38
loc 38
ccs 22
cts 22
cp 1
crap 6
rs 8.439
c 0
b 0
f 0
1
<?php declare(strict_types=1); defined('BASEPATH') OR exit('No direct script access allowed');
2
3
abstract class Site_Model extends CI_Model {
4 97
	public function __construct() {
5 97
		parent::__construct();
1 ignored issue
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class CI_Model as the method __construct() does only exist in the following sub-classes of CI_Model: Auth_Model, Batoto, DynastyScans, GameOfScanlation, HelveticaScans, History_Model, KireiCake, KissManga, MangaCow, MangaFox, MangaHere, MangaPanda, MangaStream, SeaOtterScans, Site_Model, Sites_Model, Tracker_Model, User_Model, User_Options_Model, WebToons. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
6
7 97
		$this->load->database();
8 97
	}
9
10
	abstract public function getFullTitleURL(string $title_url) : string;
11
12
	abstract public function getChapterData(string $title_url, string $chapter) : array;
13
14
	abstract public function getTitleData(string $title_url);
15
16
	abstract public function isValidTitleURL(string $title_url) : bool;
17
	abstract public function isValidChapter(string $chapter) : bool;
18
19 9
	protected function get_content(string $url, string $cookie_string = "", string $cookiejar_path = "", bool $follow_redirect = FALSE){
20 9
		$ch = curl_init();
21 9
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
22 9
		curl_setopt($ch, CURLOPT_ENCODING , "gzip");
23
24 9
		if($follow_redirect)        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
25
26 9
		if(!empty($cookie_string))  curl_setopt($ch, CURLOPT_COOKIE, $cookie_string);
27 9
		if(!empty($cookiejar_path)) curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiejar_path);
28
29
		//Some sites check the useragent for stuff, use a pre-defined user-agent to avoid stuff.
30 9
		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2824.0 Safari/537.36');
31
32 9
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); //FIXME: This isn't safe, but it allows us to grab SSL URLs
33
34 9
		curl_setopt($ch, CURLOPT_URL, $url);
35 9
		$data = curl_exec($ch);
36 9
		curl_close($ch);
37 9
		return $data;
38
	}
39
}
40
class Sites_Model extends CI_Model {
41
	public $MangaFox;
42
	public $MangaHere;
43
	public $Batoto;
44
	public $DynastyScans;
45
	public $MangaPanda;
46
	public $MangaStream;
47
	public $WebToons;
48
	public $KissManga;
49
	public $KireiCake;
50
	public $GameOfScanlation;
51
	public $MangaCow;
52
	public $SeaOtterScans;
53
	public $HelveticaScans;
54
55 97
	public function __construct() {
56 97
		parent::__construct();
1 ignored issue
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class CI_Model as the method __construct() does only exist in the following sub-classes of CI_Model: Auth_Model, Batoto, DynastyScans, GameOfScanlation, HelveticaScans, History_Model, KireiCake, KissManga, MangaCow, MangaFox, MangaHere, MangaPanda, MangaStream, SeaOtterScans, Site_Model, Sites_Model, Tracker_Model, User_Model, User_Options_Model, WebToons. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
57
58 97
		$this->MangaFox         = new MangaFox();
59 97
		$this->MangaHere        = new MangaHere();
60 97
		$this->Batoto           = new Batoto();
61 97
		$this->DynastyScans     = new DynastyScans();
62 97
		$this->MangaPanda       = new MangaPanda();
63 97
		$this->MangaStream      = new MangaStream();
64 97
		$this->WebToons         = new WebToons();
65 97
		$this->KissManga        = new KissManga();
66 97
		$this->KireiCake        = new KireiCake();
67 97
		$this->GameOfScanlation = new GameOfScanlation();
68 97
		$this->MangaCow         = new MangaCow();
69 97
		$this->SeaOtterScans    = new SeaOtterScans();
70 97
		$this->HelveticaScans   = new HelveticaScans();
71 97
	}
72
}
73
74
class MangaFox extends Site_Model {
75
	public function getFullTitleURL(string $title_url) : string {
76
		return "http://mangafox.me/manga/{$title_url}/";
77
	}
78
79
	public function isValidTitleURL(string $title_url) : bool {
80
		$success = (bool) preg_match('/^[a-z0-9_]+$/', $title_url);
81
		if(!$success) log_message('error', "Invalid Title URL (MangaFox): {$title_url}");
82
		return $success;
83
	}
84
	public function isValidChapter(string $chapter) : bool {
85
		$success = (bool) preg_match('/^(?:v[0-9a-zA-Z]+\/)?c[0-9\.]+$/', $chapter);
86
		if(!$success) log_message('error', 'Invalid Chapter (MangaFox): '.$chapter);
87
		return $success;
88
	}
89
90
	public function getChapterData(string $title_url, string $chapter) : array {
91
		return [
92
			'url'    => "http://mangafox.me/manga/{$title_url}/{$chapter}/",
93
			'number' => $chapter
94
		];
95
	}
96
97 1
	public function getTitleData(string $title_url) {
98 1
		$titleData = [];
99
100 1
		$fullURL = "http://mangafox.me/manga/{$title_url}";
101
102 1
		$data = $this->get_content($fullURL);
103 1
		if($data !== 'Can\'t find the manga series.') {
104
			//$data = preg_replace('/^[\S\s]*(<body id="body">[\S\s]*<\/body>)[\S\s]*$/', '$1', $data);
105
106 1
			$dom = new DOMDocument();
107 1
			libxml_use_internal_errors(true);
108 1
			$dom->loadHTML($data);
109 1
			libxml_use_internal_errors(false);
110
111 1
			$xpath = new DOMXPath($dom);
112
113 1
			$nodes_title = $xpath->query("//meta[@property='og:title']");
114 1
			$nodes_row   = $xpath->query("//body/div[@id='page']/div[@class='left']/div[@id='chapters']/ul[1]/li[1]");
115 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
116
				//This seems to be be the only viable way to grab the title...
117 1
				$titleData['title'] = html_entity_decode(substr($nodes_title[0]->getAttribute('content'), 0, -6));
118
119 1
				$nodes_latest  = $xpath->query("div/span[@class='date']", $nodes_row[0]);
120 1
				$nodes_chapter = $xpath->query("div/h3/a", $nodes_row[0]);
121
122 1
				$link = preg_replace('/^(.*\/)(?:[0-9]+\.html)?$/', '$1', (string) $nodes_chapter[0]->getAttribute('href'));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 24 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
123 1
				$chapterURLSegments = explode('/', $link);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 10 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
124 1
				$titleData['latest_chapter'] = $chapterURLSegments[5] . (isset($chapterURLSegments[6]) && !empty($chapterURLSegments[6]) ? "/{$chapterURLSegments[6]}" : "");
125 1
				$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) $nodes_latest[0]->nodeValue));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
126
			}
127
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
128
			//TODO: Throw ERRORS;
129
		}
130
131 1
		return (!empty($titleData) ? $titleData : NULL);
132
	}
133
}
134
135
class MangaHere extends Site_Model {
136
	public function getFullTitleURL(string $title_url) : string {
137
		return "http://www.mangahere.co/manga/{$title_url}/";
138
	}
139
140
	public function isValidTitleURL(string $title_url) : bool {
141
		$success = (bool) preg_match('/^[a-z0-9_]+$/', $title_url);
142
		if(!$success) log_message('error', "Invalid Title URL (MangaFox): {$title_url}");
143
		return $success;
144
	}
145
	public function isValidChapter(string $chapter) : bool {
146
		$success = (bool) preg_match('/^(?:v[0-9]+\/)?c[0-9]+(?:\.[0-9]+)?$/', $chapter);
147
		if(!$success) log_message('error', 'Invalid Chapter (MangaFox): '.$chapter);
148
		return $success;
149
	}
150
151
	public function getChapterData(string $title, string $chapter) : array {
152
		return [
153
			'url'    => "http://www.mangahere.co/manga/{$title}/{$chapter}/",
154
			'number' => $chapter
155
		];
156
	}
157
158 1
	public function getTitleData(string $title_url) {
159 1
		$titleData = [];
160
161 1
		$fullURL = "http://www.mangahere.co/manga/{$title_url}/";
162
163 1
		$data = $this->get_content($fullURL);
164 1
		if($data !== 'Can\'t find the manga series.') {
165
			//$data = preg_replace('/^[\S\s]*(<body id="body">[\S\s]*<\/body>)[\S\s]*$/', '$1', $data);
166
167 1
			$dom = new DOMDocument();
168 1
			libxml_use_internal_errors(true);
169 1
			$dom->loadHTML($data);
170 1
			libxml_use_internal_errors(false);
171
172 1
			$xpath = new DOMXPath($dom);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 7 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
173 1
			$nodes_title = $xpath->query("//meta[@property='og:title']");
174 1
			$nodes_row   = $xpath->query("//body/section/article/div/div[@class='manga_detail']/div[@class='detail_list']/ul[1]/li[1]");
175 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
176
				//This seems to be be the only viable way to grab the title...
177 1
				$titleData['title'] = $nodes_title[0]->getAttribute('content');
178
179 1
				$nodes_latest  = $xpath->query("span[@class='right']", $nodes_row[0]);
180 1
				$nodes_chapter = $xpath->query("span[@class='left']/a", $nodes_row[0]);
181
182 1
				$link = preg_replace('/^(.*\/)(?:[0-9]+\.html)?$/', '$1', (string) $nodes_chapter[0]->getAttribute('href'));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 24 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
183 1
				$chapterURLSegments = explode('/', $link);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 10 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
184 1
				$titleData['latest_chapter'] = $chapterURLSegments[5] . (isset($chapterURLSegments[6]) && !empty($chapterURLSegments[6]) ? "/{$chapterURLSegments[6]}" : "");
185 1
				$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) $nodes_latest[0]->nodeValue));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
186
			}
187
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
188
			//TODO: Throw ERRORS;
189
		}
190 1
		return (!empty($titleData) ? $titleData : NULL);
191
	}
192
}
193
194
class Batoto extends Site_Model {
195
	//Batoto is a bit tricky to track. Unlike MangaFox and MangaHere, it doesn't store anything in the title_url, which means we have to get the data via other methods.
196
	//One problem we have though, is the tracker must support multiple sites, so this means we need to do some weird things to track Batoto.
197
	//title_url is stored like: "TITLE_URL:--:LANGUAGE"
198
	//chapter_urls are stored like "CHAPTER_ID:--:CHAPTER_NUMBER"
199
200
	public function getFullTitleURL(string $title_string) : string {
201
		//FIXME: This does not point to the language specific title page. Should ask if it is possible to set LANG as arg?
202
		//FIXME: This points to a generic URL which will redirect according to the ID. Preferably we'd try and get the exact URL from the title, but we can't pass it here.
203
		$title_parts = explode(':--:', $title_string);
204
		return "http://bato.to/comic/_/comics/-r".$title_parts[0];
205
	}
206
207
	public function isValidTitleURL(string $title_url) : bool {
208
		$success = (bool) preg_match('/^[0-9]+:--:(?:English|Spanish|French|German|Portuguese|Turkish|Indonesian|Greek|Filipino|Italian|Polish|Thai|Malay|Hungarian|Romanian|Arabic|Hebrew|Russian|Vietnamese|Dutch)$/', $title_url);
209
		if(!$success) log_message('error', "Invalid Title URL (Batoto): {$title_url}");
210
		return $success;
211
	}
212
	public function isValidChapter(string $chapter) : bool {
213
		//FIXME: We're not validating the chapter name since we don't know what all the possible valid characters can be
214
		//       Preferably we'd just use /^[0-9a-z]+:--:(v[0-9]+\/)?c[0-9]+(\.[0-9]+)?$/
215
216
		$success = (bool) preg_match('/^[0-9a-z]+:--:.+$/', $chapter);
217
		if(!$success) log_message('error', 'Invalid Chapter (Batoto): '.$chapter);
218
		return $success;
219
	}
220
221 View Code Duplication
	public function getChapterData(string $title_string, string $chapter) : array {
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
222
		//$title_string isn't used here.
223
224
		$chapter_parts = explode(':--:', $chapter);
225
		return [
226
			'url'    => "http://bato.to/reader#" . $chapter_parts[0],
227
			'number' => $chapter_parts[1]
228
		];
229
	}
230
231
	public function getTitleData(string $title_string) {
232
		$title_parts = explode(':--:', $title_string);
233
		$title_url   = $this->getFullTitleURL($title_string);
234
		$title_lang  = $title_parts[1];
235
		//TODO: Validate title_lang from array?
236
237
		$titleData = [];
238
239
		//Bato.to is annoying and locks stuff behind auth. See: https://github.com/DakuTree/manga-tracker/issues/14#issuecomment-233830855
240
		$cookies = [
241
			"lang_option={$title_lang}",
242
			"member_id=" . $this->config->item('batoto_cookie_member_id'),
243
			"pass_hash=" . $this->config->item('batoto_cookie_pass_hash')
244
		];
245
		$data = $this->get_content($title_url, implode("; ", $cookies), "", TRUE);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
246
		if(!$data) {
247
			log_message('error', "Batoto: Couldn't successfully grab URL ({$title_url})");
248
			return NULL;
249
		}
250
251
		$data = preg_replace('/^[\s\S]+<!-- ::: CONTENT ::: -->/', '<!-- ::: CONTENT ::: -->', $data);
252
		$data = preg_replace('/<!-- end mainContent -->[\s\S]+$/', '<!-- end mainContent -->', $data);
253
		$data = preg_replace('/<div id=\'commentsStart\' class=\'ipsBox\'>[\s\S]+$/', '</div></div><!-- end mainContent -->', $data);
254
		if(strpos($data, '>Register now<') === FALSE) {
255
			//Auth was successful
256
			$dom = new DOMDocument();
257
			libxml_use_internal_errors(true);
258
			$dom->loadHTML($data);
259
			libxml_use_internal_errors(false);
260
261
			$xpath = new DOMXPath($dom);
262
			$nodes = $xpath->query("(//div/div)[last()]/table/tbody/tr[2]");
263
			if($nodes->length === 1) {
264
				$node = $nodes[0];
265
266
				$nodes_chapter = $xpath->query('td/a[contains(@href,\'reader\')]', $node);
267
				$nodes_updated = $xpath->query('td[last()]', $node);
268
				if($nodes_chapter->length === 1 && $nodes_updated->length === 1) {
269
					$chapter_element = $nodes_chapter->item(0);
270
					$updated_element = $nodes_updated->item(0);
271
272
					preg_match('/^(?:Vol\.(?<volume>\S+) )?(?:Ch.(?<chapter>[^\s:]+)):?.*/', trim($chapter_element->nodeValue), $text);
273
274
					$titleData['title']          = html_entity_decode(trim($xpath->query('//h1[@class="ipsType_pagetitle"]')->item(0)->nodeValue));
275
					$titleData['latest_chapter'] = substr($chapter_element->getAttribute('href'), 22) . ':--:' . ((!empty($text['volume']) ? 'v'.$text['volume'].'/' : '') . 'c'.$text['chapter']);
276
277
					$dateString = $updated_element->nodeValue;
278
					if($dateString == 'An hour ago') {
279
						$dateString = '1 hour ago';
280
					}
281
					$titleData['last_updated']   = date("Y-m-d H:i:s", strtotime(preg_replace('/ (-|\[A\]).*$/', '', $dateString)));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 3 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
282
				} else {
283
					log_message('error', "Batoto: Regex missing <td> ({$title_url})");
284
					return NULL;
285
				}
286
			} else {
287
				log_message('error', "Batoto: Regex missing <tr> ({$title_url})");
288
				return NULL;
289
			}
290
		} else {
291
			//Auth was not successful. Alert the admin / Try to login.
292
			log_message('error', "Batoto: Auth not successful ({$title_url})");
293
			return NULL;
294
		}
295
		return (!empty($titleData) ? $titleData : NULL);
296
	}
297
}
298
299
class DynastyScans extends Site_Model {
300
	//FIXME: This has some major issues. SEE: https://github.com/DakuTree/manga-tracker/issues/58
301
	public function getFullTitleURL(string $title_string) : string {
302
		$title_parts = explode(':--:', $title_string);
303
		$url_type = ($title_parts[1] == '0' ? 'series' : 'chapters');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
304
305
		return 'http://dynasty-scans.com/'.$url_type.'/'.$title_parts[0];
306
	}
307
308
	public function isValidTitleURL(string $title_url) : bool {
309
		$success = (bool) preg_match('/^[a-z0-9_]+:--:(?:0|1)$/', $title_url);
310
		if(!$success) log_message('error', "Invalid Title URL (DynastyScans): {$title_url}");
311
		return $success;
312
	}
313
	public function isValidChapter(string $chapter) : bool {
314
		$success = (bool) preg_match('/^[0-9a-z_]+$/', $chapter);
315
		if(!$success) log_message('error', 'Invalid Chapter (DynastyScans): '.$chapter);
316
		return $success;
317
	}
318
319
	public function getChapterData(string $title_string, string $chapter) : array {
320
		$title_parts = explode(':--:', $title_string);
321
		/* Known chapter url formats (# is numbers):
322
		       chapters_#A_#B - Ch#A-#B
323
		       ch_#A          - Ch#A
324
		       ch_#A_#B       - Ch#A.#B
325
		       <NOTHING>      - Oneshot (This is passed as "oneshot")
326
		*/
327
328
		$chapterData = [
329
			'url'    => 'http://dynasty-scans.com/chapters/' . $title_parts[0].'_'.$chapter,
330
			'number' => ''
331
		];
332
333
		if($chapter == 'oneshot') {
334
			$chapterData['number'] = 'oneshot';
335
		} else {
336
			$chapter = preg_replace("/^([a-zA-Z]+)/", '$1_', $chapter);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 9 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
337
			$chapterSegments = explode('_', $chapter);
338
			switch($chapterSegments[0]) {
339
				case 'ch':
340
					$chapterData['number'] = 'c'.$chapterSegments[1].(isset($chapterSegments[2]) && !empty($chapterSegments[2]) ? '.'.$chapterSegments[2] : '');
341
					break;
342
343
				case 'chapters':
344
					//This is barely ever used, but I have seen it.
345
					$chapterData['number'] = 'c'.$chapterSegments[1].'-'.$chapterSegments[2];
346
					break;
347
348
				default:
349
					//TODO: FALLBACK, ALERT ADMIN?
350
					$chapterData['number'] = $chapter;
351
					break;
352
			}
353
		}
354
		return $chapterData;
355
	}
356
357 1
	public function getTitleData(string $title_string) {
358 1
		$title_parts = explode(':--:', $title_string);
359 1
		$title_url   = $title_parts[0];
360
361 1
		$titleData = [];
362
		//FIXME: Using regex here is probably a terrible idea, but we're doing it anyway....
363
		//FIXME (ASAP): All the regex here should be checked to see if it even returns something, and we should probably error if possible.
364 1
		if($title_parts[1] == '0') {
365 1
			$data = $this->get_content('http://dynasty-scans.com/series/'.$title_url);
366
367 1
			preg_match('/<b>.*<\/b>/', $data, $matchesT);
368 1
			preg_match('/\/doujins\/[^"]+">(.+)?(?=<\/a>)<\/a>/', $data, $matchesD);
369 1
			$titleData['title'] = (!empty($matchesD) ? (substr($matchesD[1], 0, -7) !== 'Original' ? substr($matchesD[1], 0, -7).' - ' : '') : '') . substr($matchesT[0], 3, -4);
370
371 1
			$data = preg_replace('/^[\S\s]*(<dl class=\'chapter-list\'>[\S\s]*<\/dl>)[\S\s]*$/', '$1', $data);
372 1
			preg_match_all('/<dd>[\s\S]+?(?=<\/dd>)<\/dd>/', $data, $matches);
373 1
			$latest_chapter_html = array_pop($matches[0]);
374
375 1
			preg_match('/\/chapters\/([^"]+)/', $latest_chapter_html, $matches);
376 1
			$titleData['latest_chapter'] = substr($matches[1], strlen($title_url)+1);
377
			//FIXME: THIS IS A TEMP FIX, SEE https://github.com/DakuTree/manga-tracker/issues/58
378 1
			if(!$titleData['latest_chapter']) {
379
				log_message('error', 'DynastyScans::getTitleData cannot parse title properly as it contains oneshot. || URL: '.$title_url);
380
				return NULL;
381
			}
382
383 1
			preg_match('/<small>released (.*)<\/small>/', $latest_chapter_html, $matches);
384 1
			$titleData['last_updated']   = date("Y-m-d H:i:s", strtotime(str_replace('\'', '', $matches[1])));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 3 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
385
		} elseif($title_parts[1] == '1') {
386
			$data = $this->get_content('http://dynasty-scans.com/chapters/'.$title_url);
387
388
			preg_match('/<b>.*<\/b>/', $data, $matchesT);
389
			preg_match('/\/doujins\/[^"]+">(.+)?(?=<\/a>)<\/a>/', $data, $matchesD);
390
			$titleData['title'] = (!empty($matchesD) ? ($matchesD[1] !== 'Original' ? $matchesD[1].' - ' : '') : '') . substr($matchesT[0], 3, -4);
391
392
			$titleData['latest_chapter'] = 'oneshot'; //This will never change
393
394
			preg_match('/<i class="icon-calendar"><\/i> (.*)<\/span>/', $data, $matches);
395
			$titleData['last_updated']   = date("Y-m-d H:i:s", strtotime($matches[1]));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 3 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
396
397
			//Oneshots are special, and really shouldn't need to be re-tracked
398
			//FIXME: We need to have a specific "no-track" complete param.
399
			$titleData['complete'] = 'Y';
400
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
401
			//FIXME: WTF?
402
		}
403 1
		return (!empty($titleData) ? $titleData : NULL);
404
	}
405
}
406
407 View Code Duplication
class MangaPanda extends Site_Model {
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
408
	public function getFullTitleURL(string $title_url) : string {
409
		return "http://www.mangapanda.com/{$title_url}";
410
	}
411
412
	public function getChapterData(string $title_url, string $chapter) : array {
413
		return [
414
			'url'    => "http://www.mangapanda.com/{$title_url}/{$chapter}/",
415
			'number' => 'c'.$chapter
416
		];
417
	}
418
419
	public function isValidTitleURL(string $title_url) : bool {
420
		$success = (bool) preg_match('/^[a-z0-9-]+$/', $title_url);
421
		if(!$success) log_message('error', "Invalid Title URL (MangaPanda): {$title_url}");
422
		return $success;
423
	}
424
	public function isValidChapter(string $chapter) : bool {
425
		$success = (bool) preg_match('/^[0-9]+$/', $chapter);
426
		if(!$success) log_message('error', 'Invalid Chapter (MangaPanda): '.$chapter);
427
		return $success;
428
	}
429
430 1
	public function getTitleData(string $title_url) {
431 1
		$titleData = [];
432
433 1
		$fullURL = "http://www.mangapanda.com/{$title_url}";
434
435 1
		$data = $this->get_content($fullURL);
436 1
		if($data !== 'Can\'t find the manga series.') {
437
			//$data = preg_replace('/^[\S\s]*(<body id="body">[\S\s]*<\/body>)[\S\s]*$/', '$1', $data);
438
439 1
			$dom = new DOMDocument();
440 1
			libxml_use_internal_errors(true);
441 1
			$dom->loadHTML($data);
442 1
			libxml_use_internal_errors(false);
443
444 1
			$xpath = new DOMXPath($dom);
445
446 1
			$nodes_title = $xpath->query("//h2[@class='aname']");
447 1
			$nodes_row   = $xpath->query("(//table[@id='listing']/tr)[last()]");
448 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
449
				//This seems to be be the only viable way to grab the title...
450 1
				$titleData['title'] = $nodes_title[0]->nodeValue;
451
452 1
				$nodes_latest  = $xpath->query("td[2]", $nodes_row[0]);
453 1
				$nodes_chapter = $xpath->query("td[1]/a", $nodes_row[0]);
454
455 1
				$titleData['latest_chapter'] = preg_replace('/^.*\/([0-9]+)$/', '$1', (string) $nodes_chapter[0]->getAttribute('href'));
456 1
				$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) $nodes_latest[0]->nodeValue));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
457
			}
458
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
459
			//TODO: Throw ERRORS;
460
		}
461
462 1
		return (!empty($titleData) ? $titleData : NULL);
463
	}
464
}
465
466 View Code Duplication
class MangaStream extends Site_Model {
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
467
	public function getFullTitleURL(string $title_url) : string {
468
		return "https://mangastream.com/manga/{$title_url}/";
469
	}
470
471
	public function isValidTitleURL(string $title_url) : bool {
472
		$success = (bool) preg_match('/^[a-z0-9_]+$/', $title_url);
473
		if(!$success) log_message('error', "Invalid Title URL (MangaStream): {$title_url}");
474
		return $success;
475
	}
476
	public function isValidChapter(string $chapter) : bool {
477
		$success = (bool) preg_match('/^(.*?)\/[0-9]+$/', $chapter);
478
		if(!$success) log_message('error', 'Invalid Chapter (MangaStream): '.$chapter);
479
		return $success;
480
	}
481
482
	public function getChapterData(string $title_url, string $chapter) : array {
483
		return [
484
			'url'    => "https://mangastream.com/r/{$title_url}/{$chapter}",
485
			'number' => 'c'.explode('/', $chapter)[0]
486
		];
487
	}
488
489
	public function getTitleData(string $title_url) {
490
		$titleData = [];
491
492
		$fullURL = $this->getFullTitleURL($title_url);
493
494
		$data = $this->get_content($fullURL);
495
		if($data !== 'Can\'t find the manga series.') {
496
			//$data = preg_replace('/^[\S\s]*(<body id="body">[\S\s]*<\/body>)[\S\s]*$/', '$1', $data);
497
498
			$dom = new DOMDocument();
499
			libxml_use_internal_errors(true);
500
			$dom->loadHTML($data);
501
			libxml_use_internal_errors(false);
502
503
			$xpath = new DOMXPath($dom);
504
505
			$nodes_title = $xpath->query("//div[contains(@class, 'content')]/div[1]/h1");
506
			$nodes_row   = $xpath->query("//div[contains(@class, 'content')]/div[1]/table/tr[2]"); //Missing tbody here..
507
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
508
				$titleData['title'] = $nodes_title[0]->nodeValue;
509
510
				$nodes_latest  = $xpath->query("td[2]", $nodes_row[0]);
511
				$nodes_chapter = $xpath->query("td[1]/a", $nodes_row[0]);
512
513
				$titleData['latest_chapter'] = preg_replace('/^.*\/(.*?\/[0-9]+)\/[0-9]+$/', '$1', (string) $nodes_chapter[0]->getAttribute('href'));
514
				$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) $nodes_latest[0]->nodeValue));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
515
			}
516
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
517
			//TODO: Throw ERRORS;
518
		}
519
520
		return (!empty($titleData) ? $titleData : NULL);
521
	}
522
}
523
524
class WebToons extends Site_Model {
525
	/* Webtoons.com has a very weird and pointless URL format.
526
	   TITLE URL:   /#LANG#/#GENRE#/#TITLE#/list?title_no=#TITLEID#
527
	   RSS URL:     /#LANG#/#GENRE#/#TITLE#/rss?title_no=#TITLEID#
528
	   CHAPTER URL: /#LANG#/#GENRE#/#TITLE#/#CHAPTER#/viewer?title_no=#TITLEID#&episode_no=#CHAPTERID#
529
530
	   For both the title and chapter URLs, only the TITLEID and CHAPTERID are needed. Everything else can be anything at all (Well, alphanumeric at least).
531
	   The RSS URL however, requires everything to be exactly correct. I have no idea why this is, but it does mean we need to store all that info too.
532
	   We <could> not use the RSS url, and just parse via the title url, but rss is much better in the long run as it shouldn't change much.
533
534
	   FORMATS:
535
	   TITLE_URL: ID:--:LANG:--:TITLE:--:GENRE
536
	   CHAPTER:   ID:--:CHAPTER_N
537
	*/
538
	//private $validLang = ['en', 'zh-hant', 'zh-hans', 'th', 'id'];
539
540
	public function getFullTitleURL(string $title_url) : string {
541
		$title_parts = explode(':--:', $title_url);
542
		return "http://www.webtoons.com/{$title_parts[1]}/{$title_parts[3]}/{$title_parts[2]}/list?title_no={$title_parts[0]}/";
543
	}
544
545
	public function isValidTitleURL(string $title_url) : bool {
546
		$success = (bool) preg_match('/^[0-9]+:--:(?:en|zh-hant|zh-hans|th|id):--:[a-z0-9-]+:--:(?:drama|fantasy|comedy|action|slice-of-life|romance|superhero|thriller|sports|sci-fi)$/', $title_url);
547
		if(!$success) log_message('error', "Invalid Title URL (WebToons): {$title_url}");
548
		return $success;
549
	}
550
	public function isValidChapter(string $chapter) : bool {
551
		$success = (bool) preg_match('/^[0-9]+:--:.*$/', $chapter);
552
		if(!$success) log_message('error', 'Invalid Chapter (WebToons): '.$chapter);
553
		return $success;
554
	}
555
556
	public function getChapterData(string $title_url, string $chapter) : array {
557
		$title_parts   = explode(':--:', $title_url);
558
		$chapter_parts = explode(':--:', $chapter);
559
560
		return [
561
			'url'    => "http://www.webtoons.com/{$title_parts[1]}/{$title_parts[3]}/{$title_parts[2]}/{$chapter_parts[1]}/viewer?title_no={$title_parts[0]}&episode_no={$chapter_parts[0]}",
562
			'number' => $chapter_parts[1] //TODO: Possibly replace certain formats in here? Since webtoons doesn't have a standard chapter format
563
		];
564
	}
565
566 1
	public function getTitleData(string $title_url) {
567 1
		$titleData = [];
568
569 1
		$title_parts = explode(':--:', $title_url);
570 1
		$fullURL = "http://www.webtoons.com/{$title_parts[1]}/{$title_parts[3]}/{$title_parts[2]}/rss?title_no={$title_parts[0]}";
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
571
572 1
		$data = $this->get_content($fullURL);
573 1
		if($data !== 'Can\'t find the manga series.') {
574 1
			$xml = simplexml_load_string($data) or die("Error: Cannot create object");
575 1
			if(isset($xml->channel->item[0])) {
576 1
				$titleData['title'] = trim((string) $xml->channel->title);
577
578 1
				$chapterURLSegments = explode('/', ((string) $xml->channel->item[0]->link));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 10 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
579 1
				$titleData['latest_chapter'] = preg_replace('/^.*?([0-9]+)$/', '$1', $chapterURLSegments[7]) . ':--:' . $chapterURLSegments[6];
580 1
				$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) $xml->channel->item[0]->pubDate));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
581
			}
582
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
583
			//TODO: Throw ERRORS;
584
		}
585
586 1
		return (!empty($titleData) ? $titleData : NULL);
587
	}
588
}
589
590
class KissManga extends Site_Model {
591
	/* This site is a massive pain in the ass. The only reason I'm supporting it is it's one of the few aggregator sites which actually support more risqué manga.
592
	   The main problem with this site is it has some form of bot protection. To view any part of the site normally, you need a cookie set by the bot protection.
593
594
	   To generate this cookie, we need three variables. Two are static, but the other is generated by randomly generated JS on the page.
595
	   The randomly generated JS is the troublesome part. We can't easily parse this with PHP. Both V8JS & SpiderMonkey refuse to build properly for me, so that rules that out.
596
	   The other option is using regex, but that is a rabbit hole I don't want to touch with a ten-foot pole.
597
598
	   To make the entire site work, I've built a python script to handle grabbing this cookie. This is grabbed & updated at the same time the manga are updated. The script saves the cookiejar which the PHP later reads.
599
	   The cookie has a length of 1 year, but I don't think it actually lasts that long, so we update every 6hours instead.
600
	   I should probably also mention that the cookie generated also uses your user-agent, so if it changes the cookie will break.
601
	*/
602
603
	public function getFullTitleURL(string $title_url) : string {
604
		return "http://kissmanga.com/Manga/{$title_url}";
605
	}
606
607
	public function isValidTitleURL(string $title_url) : bool {
608
		$success = (bool) preg_match('/^[A-Za-z0-9-]+/', $title_url);
609
		if(!$success) log_message('error', "Invalid Title URL (KissManga): {$title_url}");
610
		return $success;
611
	}
612
	public function isValidChapter(string $chapter) : bool {
613
		$success = (bool) preg_match('/^.*?:--:[0-9]+$/', $chapter);
614
		if(!$success) log_message('error', 'Invalid Chapter (KissManga): '.$chapter);
615
		return $success;
616
	}
617
618 View Code Duplication
	public function getChapterData(string $title_url, string $chapter) : array {
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
619
		$chapter_parts = explode(':--:', $chapter);
620
621
		return [
622
			'url'    => "http://kissmanga.com/Manga/{$title_url}/{$chapter_parts[0]}?id={$chapter_parts[1]}",
623
			//FIXME: KM has an extremely inconsistant chapter format which makes it difficult to parse.
624
			'number' => /*preg_replace('/--.*?$/', '', */$chapter_parts[0]/*)*/
625
		];
626
	}
627
628
	public function getTitleData(string $title_url) {
629
		$titleData = [];
630
631
		//Check if cookiejar is a day old (so we can know if something went wrong)
632
		$cookiejar_path = str_replace("public/", "_scripts/cookiejar", FCPATH);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
633
		$cookie_last_updated = filemtime($cookiejar_path);
634
		if($cookie_last_updated && ((time() - 86400) < $cookie_last_updated)) {
635
636
			$fullURL = $this->getFullTitleURL($title_url);
637
			$data = $this->get_content($fullURL, '', $cookiejar_path);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
638
			if(strpos($data, 'containerRoot') !== FALSE) {
639
				//FIXME: For whatever reason, we can't grab the entire div without simplexml shouting at us
640
				$data = preg_replace('/^[\S\s]*(<div id="leftside">[\S\s]*)<div id="rightside">[\S\s]*$/', '$1', $data);
641
642
				$dom = new DOMDocument();
643
				libxml_use_internal_errors(true);
644
				$dom->loadHTML($data);
645
				libxml_use_internal_errors(false);
646
647
				$xpath = new DOMXPath($dom);
648
649
				$nodes_title = $xpath->query("//a[@class='bigChar']");
650
				$nodes_row   = $xpath->query("//table[@class='listing']/tr[3]");
651
				if($nodes_title->length === 1 && $nodes_row->length === 1) {
652
					$titleData['title'] = $nodes_title[0]->textContent;
653
654
					$nodes_latest  = $xpath->query("td[2]", $nodes_row[0]);
655
					$nodes_chapter = $xpath->query("td[1]/a", $nodes_row[0]);
656
657
					$link = (string) $nodes_chapter[0]->getAttribute('href');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 24 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
658
					$chapterURLSegments = explode('/', preg_replace('/\?.*$/', '', $link));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 10 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
659
					$titleData['latest_chapter'] = $chapterURLSegments[3] . ':--:' . preg_replace('/.*?([0-9]+)$/', '$1', $link);
660
					$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) $nodes_latest[0]->textContent));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
661
				}
662
			} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
663
				//TODO: Throw ERRORS;
664
			}
665
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
666
			//Do nothing, wait until next update.
667
			//TODO: NAG ADMIN??
668
		}
669
670
		return (!empty($titleData) ? $titleData : NULL);
671
	}
672
}
673
674
class KireiCake extends Site_Model {
675 1
	public function getFullTitleURL(string $title_url) : string {
676 1
		return "https://reader.kireicake.com/series/{$title_url}";
677
	}
678
679
	public function isValidTitleURL(string $title_url) : bool {
680
		$success = (bool) preg_match('/^[a-z0-9_]+/', $title_url);
681
		if(!$success) log_message('error', "Invalid Title URL (KireiCake): {$title_url}");
682
		return $success;
683
	}
684
	public function isValidChapter(string $chapter) : bool {
685
		$success = (bool) preg_match('/^en\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+)?)?)?$/', $chapter);
686
		if(!$success) log_message('error', 'Invalid Chapter (KireiCake): '.$chapter);
687
		return $success;
688
	}
689
690
	public function getChapterData(string $title_url, string $chapter) : array {
691
		//LANG/VOLUME/CHAPTER/CHAPTER_EXTRA(/page/)
692
		$chapter_parts = explode('/', $chapter);
693
		return [
694
			'url'    => "https://reader.kireicake.com/read/{$title_url}/{$chapter}",
695
			'number' => ($chapter_parts[1] !== '0' ? "v{$chapter_parts[1]}/" : '') . "c{$chapter_parts[2]}" . (isset($chapter_parts[3]) ? ".{$chapter_parts[3]}" : '')/*)*/
696
		];
697
	}
698
699 1
	public function getTitleData(string $title_url) {
700 1
		$titleData = [];
701
702 1
		$fullURL = $this->getFullTitleURL($title_url);
703 1
		$data = $this->get_content($fullURL);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
704 1
		if(strpos($data, '404 Page Not Found') === FALSE) {
705
			//FIXME: For whatever reason, we can't grab the entire div without simplexml shouting at us
706 1
			$data = preg_replace('/^[\S\s]*(<article>[\S\s]*)<\/article>[\S\s]*$/', '$1', $data);
707
708 1
			$dom = new DOMDocument();
709 1
			libxml_use_internal_errors(true);
710 1
			$dom->loadHTML($data);
711 1
			libxml_use_internal_errors(false);
712
713 1
			$xpath = new DOMXPath($dom);
714
715 1
			$nodes_title = $xpath->query("//div[@class='large comic']/h1[@class='title']");
716 1
			$nodes_row   = $xpath->query("//div[@class='list']/div[@class='element'][1]");
717 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
718 1
				$titleData['title'] = trim($nodes_title[0]->textContent);
719
720
721 1
				$nodes_latest  = $xpath->query("div[@class='meta_r']", $nodes_row[0]);
722 1
				$nodes_chapter = $xpath->query("div[@class='title']/a", $nodes_row[0]);
723
724 1
				$link = (string) $nodes_chapter[0]->getAttribute('href');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 24 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
725 1
				$titleData['latest_chapter'] = preg_replace('/.*\/read\/.*?\/(.*?)\/$/', '$1', $link);
726 1
				$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) str_replace('.', '', explode(',', $nodes_latest[0]->textContent)[1])));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
727
			}
728
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
729
			//TODO: Throw ERRORS;
730
		}
731
732 1
		return (!empty($titleData) ? $titleData : NULL);
733
	}
734
}
735
736
class GameOfScanlation extends Site_Model {
737
	public function getFullTitleURL(string $title_url) : string {
738
		return "https://gameofscanlation.moe/forums/{$title_url}/";
739
	}
740
741
	public function isValidTitleURL(string $title_url) : bool {
742
		$success = (bool) preg_match('/^[a-z0-9-]+/', $title_url);
743
		if(!$success) log_message('error', "Invalid Title URL (GameOfScanlation): {$title_url}");
744
		return $success;
745
	}
746
	public function isValidChapter(string $chapter) : bool {
747
		$success = (bool) preg_match('/^[a-z0-9\.-]+$/', $chapter);
748
		if(!$success) log_message('error', 'Invalid Chapter (GameOfScanlation): '.$chapter);
749
		return $success;
750
	}
751
752
	public function getChapterData(string $title_url, string $chapter) : array {
753
		return [
754
			'url'    => "https://gameofscanlation.moe/projects/".preg_replace("/\\.[0-9]+$/", "", $title_url).'/'.$chapter.'/',
755
			'number' => preg_replace("/chapter-/", "c", preg_replace("/\\.[0-9]+$/", "", $chapter))
756
		];
757
	}
758
759
	public function getTitleData(string $title_url) {
760
		$titleData = [];
761
762
		$fullURL = $this->getFullTitleURL($title_url);
763
		$data = $this->get_content($fullURL);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
764
		if(strpos($data, '404 Page Not Found') === FALSE) {
765
			//$data = preg_replace('/^[\S\s]*(<ol[\S\s]*)<\/ol>[\S\s]*$/', '$1', $data);
766
767
			$dom = new DOMDocument();
768
			libxml_use_internal_errors(true);
769
			$dom->loadHTML($data);
770
			libxml_use_internal_errors(false);
771
772
			$xpath = new DOMXPath($dom);
773
774
			$nodes_title = $xpath->query("//meta[@property='og:title']");
775
			$nodes_row   = $xpath->query("//ol[@class='discussionListItems']/li[1]/div[@class='home_list']/ul/li/div[@class='list_press_text']");
776
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
777
				$titleData['title'] = html_entity_decode($nodes_title[0]->getAttribute('content'));
778
779
				$nodes_latest  = $xpath->query("p[@class='author']/span|p[@class='author']/abbr", $nodes_row[0]);
780
				$nodes_chapter = $xpath->query("p[@class='text_work']/a", $nodes_row[0]);
781
782
				$link = (string) $nodes_chapter[0]->getAttribute('href');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 24 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
783
				$titleData['latest_chapter'] = preg_replace('/^projects\/.*?\/(.*?)\/$/', '$1', $link);
784
				$titleData['last_updated'] =  date("Y-m-d H:i:s", (int) $nodes_latest[0]->getAttribute('data-time'));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
785
			} else {
786
				log_message('error', "GameOfScanlation: Unable to find nodes.");
787
				return NULL;
788
			}
789
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
790
			//TODO: Throw ERRORS;
791
		}
792
793
		return (!empty($titleData) ? $titleData : NULL);
794
	}
795
}
796
797
class MangaCow extends Site_Model {
798 1
	public function getFullTitleURL(string $title_url) : string {
799 1
		return "http://mngcow.co/{$title_url}/";
800
	}
801
802
	public function isValidTitleURL(string $title_url) : bool {
803
		$success = (bool) preg_match('/^[a-zA-Z0-9_]+/', $title_url);
804
		if(!$success) log_message('error', "Invalid Title URL (MangaCow): {$title_url}");
805
		return $success;
806
	}
807
	public function isValidChapter(string $chapter) : bool {
808
		$success = (bool) preg_match('/^[0-9]+$/', $chapter);
809
		if(!$success) log_message('error', 'Invalid Chapter (MangaCow): '.$chapter);
810
		return $success;
811
	}
812
813
	public function getChapterData(string $title_url, string $chapter) : array {
814
		return [
815
			'url'    => $this->getFullTitleURL($title_url).$chapter.'/',
816
			'number' => "c{$chapter}"
817
		];
818
	}
819
820 1
	public function getTitleData(string $title_url) {
821 1
		$titleData = [];
822
823 1
		$fullURL = $this->getFullTitleURL($title_url);
824 1
		$data = $this->get_content($fullURL);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
825 1
		if(strpos($data, '404 Page Not Found') === FALSE) {
826 1
			$dom = new DOMDocument();
827 1
			libxml_use_internal_errors(true);
828 1
			$dom->loadHTML($data);
829 1
			libxml_use_internal_errors(false);
830
831 1
			$xpath = new DOMXPath($dom);
832
833 1
			$nodes_title = $xpath->query("//h4");
834 1
			$nodes_row   = $xpath->query("//ul[contains(@class, 'mng_chp')]/li[1]/a[1]");
835 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
836 1
				$titleData['title'] = trim($nodes_title[0]->nodeValue);
837
838 1
				$nodes_chapter = $nodes_row;
839 1
				$nodes_latest  = $xpath->query("b[@class='dte']", $nodes_row[0]);
840
841 1
				$link = (string) $nodes_chapter[0]->getAttribute('href');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 24 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
842 1
				$titleData['latest_chapter'] = preg_replace('/^.*\/([0-9]+)\/$/', '$1', $link);
843 1
				$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) substr($nodes_latest[0]->getAttribute('title'), 13)));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
844
			} else {
845
				log_message('error', "MangaCow: Unable to find nodes.");
846 1
				return NULL;
847
			}
848
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
849
			//TODO: Throw ERRORS;
850
		}
851
852 1
		return (!empty($titleData) ? $titleData : NULL);
853
	}
854
}
855
856 View Code Duplication
class SeaOtterScans extends Site_Model {
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
857 1
	public function getFullTitleURL(string $title_url) : string {
858 1
		return "http://reader.seaotterscans.com/series/{$title_url}";
859
	}
860
861
	public function isValidTitleURL(string $title_url) : bool {
862
		$success = (bool) preg_match('/^[a-z0-9_]+/', $title_url);
863
		if(!$success) log_message('error', "Invalid Title URL (SeaOtterScans): {$title_url}");
864
		return $success;
865
	}
866
	public function isValidChapter(string $chapter) : bool {
867
		$success = (bool) preg_match('/^en\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+)?)?)?$/', $chapter);
868
		if(!$success) log_message('error', 'Invalid Chapter (SeaOtterScans): '.$chapter);
869
		return $success;
870
	}
871
872
	public function getChapterData(string $title_url, string $chapter) : array {
873
		//LANG/VOLUME/CHAPTER/CHAPTER_EXTRA(/page/)
874
		$chapter_parts = explode('/', $chapter);
875
		return [
876
			'url'    => "https://reader.seaotterscans.com/read/{$title_url}/{$chapter}",
877
			'number' => ($chapter_parts[1] !== '0' ? "v{$chapter_parts[1]}/" : '') . "c{$chapter_parts[2]}" . (isset($chapter_parts[3]) ? ".{$chapter_parts[3]}" : '')/*)*/
878
		];
879
	}
880
881 1
	public function getTitleData(string $title_url) {
882 1
		$titleData = [];
883
884 1
		$fullURL = $this->getFullTitleURL($title_url);
885 1
		$data = $this->get_content($fullURL);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
886 1
		if(strpos($data, '404 Page Not Found') === FALSE) {
887
			//FIXME: For whatever reason, we can't grab the entire div without simplexml shouting at us
888 1
			$data = preg_replace('/^[\S\s]*(<article[\S\s]*)<\/article>[\S\s]*$/', '$1', $data);
889
890 1
			$dom = new DOMDocument();
891 1
			libxml_use_internal_errors(true);
892 1
			$dom->loadHTML($data);
893 1
			libxml_use_internal_errors(false);
894
895 1
			$xpath = new DOMXPath($dom);
896
897 1
			$nodes_title = $xpath->query("//div[@class='large comic']/h1[@class='title']");
898
899
			//SOO sometimes uses volume groups which are above recent chapters (if they haven't been grouped yet), so make sure we check for both.
900 1
			$nodes_row   = $xpath->query("//div[@class='list']/div[@class='group']/div[@class='title' and text() = 'Chapters']/following-sibling::div[@class='element'][1]");
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 3 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
901 1
			if($nodes_row->length !== 1) {
902 1
				$nodes_row   = $xpath->query("//div[@class='list']/div[@class='group'][1]/div[@class='element'][1]");
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 3 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
903
			}
904 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
905 1
				$titleData['title'] = trim($nodes_title[0]->textContent);
906
907
908 1
				$nodes_latest  = $xpath->query("div[@class='meta_r']", $nodes_row[0]);
909 1
				$nodes_chapter = $xpath->query("div[@class='title']/a", $nodes_row[0]);
910
911 1
				$link = (string) $nodes_chapter[0]->getAttribute('href');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 24 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
912 1
				$titleData['latest_chapter'] = preg_replace('/.*\/read\/.*?\/(.*?)\/$/', '$1', $link);
913 1
				$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) str_replace('.', '', explode(',', $nodes_latest[0]->textContent)[1])));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
914
			}
915
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
916
			//TODO: Throw ERRORS;
917
		}
918
919 1
		return (!empty($titleData) ? $titleData : NULL);
920
	}
921
}
922
923 View Code Duplication
class HelveticaScans extends Site_Model {
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
924 1
	public function getFullTitleURL(string $title_url) : string {
925 1
		return "http://helveticascans.com/reader/series/{$title_url}";
926
	}
927
928
	public function isValidTitleURL(string $title_url) : bool {
929
		$success = (bool) preg_match('/^[a-z0-9_]+/', $title_url);
930
		if(!$success) log_message('error', "Invalid Title URL (HelveticaScans): {$title_url}");
931
		return $success;
932
	}
933
	public function isValidChapter(string $chapter) : bool {
934
		$success = (bool) preg_match('/^en\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+)?)?)?$/', $chapter);
935
		if(!$success) log_message('error', 'Invalid Chapter (HelveticaScans): '.$chapter);
936
		return $success;
937
	}
938
939
	public function getChapterData(string $title_url, string $chapter) : array {
940
		//LANG/VOLUME/CHAPTER/CHAPTER_EXTRA(/page/)
941
		$chapter_parts = explode('/', $chapter);
942
		return [
943
			'url'    => "http://helveticascans.com/reader/read/{$title_url}/{$chapter}",
944
			'number' => ($chapter_parts[1] !== '0' ? "v{$chapter_parts[1]}/" : '') . "c{$chapter_parts[2]}" . (isset($chapter_parts[3]) ? ".{$chapter_parts[3]}" : '')/*)*/
945
		];
946
	}
947
948 1
	public function getTitleData(string $title_url) {
949 1
		$titleData = [];
950
951 1
		$fullURL = $this->getFullTitleURL($title_url);
952 1
		$data = $this->get_content($fullURL);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
953 1
		if(strpos($data, '404 Page Not Found') === FALSE) {
954
			//FIXME: For whatever reason, we can't grab the entire div without simplexml shouting at us
955 1
			$data = preg_replace('/^[\S\s]*(<article[\S\s]*)<\/article>[\S\s]*$/', '$1', $data);
956
957 1
			$dom = new DOMDocument();
958 1
			libxml_use_internal_errors(true);
959 1
			$dom->loadHTML($data);
960 1
			libxml_use_internal_errors(false);
961
962 1
			$xpath = new DOMXPath($dom);
963
964 1
			$nodes_title = $xpath->query("//div[@class='large comic']/h1[@class='title']");
965 1
			$nodes_row   = $xpath->query("//div[@class='list']/div[@class='group']/div[@class='title' and text() = 'Chapters']/following-sibling::div[@class='element'][1]");
966 1
			if($nodes_row->length !== 1) {
967
				$nodes_row   = $xpath->query("//div[@class='list']/div[@class='group'][1]/div[@class='element'][1]");
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 3 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
968
			}
969 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
970 1
				$titleData['title'] = trim($nodes_title[0]->textContent);
971
972
973 1
				$nodes_latest  = $xpath->query("div[@class='meta_r']", $nodes_row[0]);
974 1
				$nodes_chapter = $xpath->query("div[@class='title']/a", $nodes_row[0]);
975
976 1
				$link = (string) $nodes_chapter[0]->getAttribute('href');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 24 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
977 1
				$titleData['latest_chapter'] = preg_replace('/.*\/read\/.*?\/(.*?)\/$/', '$1', $link);
978 1
				$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) str_replace('.', '', explode(',', $nodes_latest[0]->textContent)[1])));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
979
			}
980
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
981
			//TODO: Throw ERRORS;
982
		}
983
984 1
		return (!empty($titleData) ? $titleData : NULL);
985
	}
986
}
987