Completed
Push — master ( a4295f...ead2e4 )
by Angus
03:30
created

MangaFox::getTitleData()   B

Complexity

Conditions 5
Paths 10

Size

Total Lines 26
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 19
nc 10
nop 1
dl 0
loc 26
ccs 17
cts 17
cp 1
crap 5
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
	public $site          = '';
5
	public $titleFormat   = '';
6
	public $chapterFormat = '';
7
8 102
	public function __construct() {
9 102
		parent::__construct();
10
11 102
		$this->load->database();
12 102
	}
13
14
	abstract public function getFullTitleURL(string $title_url) : string;
15
16
	abstract public function getChapterData(string $title_url, string $chapter) : array;
17
18
	//TODO: When ci-phpunit-test supports PHP Parser 3.x, add " : ?array"
19
	abstract public function getTitleData(string $title_url);
20
21
	public function isValidTitleURL(string $title_url, string $regex) : bool {
22
		$success = (bool) preg_match($regex, $title_url);
23
		if(!$success) log_message('error', "Invalid Title URL ({$this->site}): {$title_url}");
24
		return $success;
25
	}
26
	public function isValidChapter(string $chapter, string $regex) : bool {
27
		$success = (bool) preg_match($regex, $chapter);
28
		if(!$success) log_message('error', "Invalid Chapter ({$this->site}): {$chapter}");
29
		return $success;
30
	}
31
32 14
	final protected function get_content(string $url, string $cookie_string = "", string $cookiejar_path = "", bool $follow_redirect = FALSE) {
33 14
		$ch = curl_init();
34 14
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
35 14
		curl_setopt($ch, CURLOPT_ENCODING , "gzip");
36
		//curl_setopt($ch, CURLOPT_VERBOSE, 1);
37 14
		curl_setopt($ch, CURLOPT_HEADER, 1);
38
39 14
		if($follow_redirect)        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
40
41 14
		if(!empty($cookie_string))  curl_setopt($ch, CURLOPT_COOKIE, $cookie_string);
42 14
		if(!empty($cookiejar_path)) curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiejar_path);
43
44
		//Some sites check the useragent for stuff, use a pre-defined user-agent to avoid stuff.
45 14
		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');
46
47
		//TODO: Check in a while if this being enabled still causes issues
48
		//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); //FIXME: This isn't safe, but it allows us to grab SSL URLs
49
50 14
		curl_setopt($ch, CURLOPT_URL, $url);
51 14
		$response = curl_exec($ch);
52 14
		if($response === FALSE) {
53
			log_message('error', "curl failed with error: ".curl_errno($ch)." | ".curl_error($ch));
54
			return FALSE;
55
		}
56
57 14
		$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
58 14
		$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
59 14
		$header      = http_parse_headers(substr($response, 0, $header_size));
60 14
		$body        = substr($response, $header_size);
61 14
		curl_close($ch);
62
63
		return [
64 14
			'headers'     => $header,
65 14
			'status_code' => $status_code,
66 14
			'body'        => $body
67
		];
68
	}
69
70
	/**
71
	 * @param array  $content
72
	 * @param string $site
73
	 * @param string $title_url
74
	 * @param string $node_title_string
75
	 * @param string $node_row_string
76
	 * @param string $node_latest_string
77
	 * @param string $node_chapter_string
78
	 * @param string $failure_string
79
	 *
80
	 * @return DOMElement[]|false
81
	 */
82 11
	final protected function parseTitleDataDOM(
83
		array $content, string $site, string $title_url,
84
		string $node_title_string, string $node_row_string,
85
		string $node_latest_string, string $node_chapter_string,
86
		string $failure_string = "") {
87
		//list('headers' => $headers, 'status_code' => $status_code, 'body' => $data) = $content; //TODO: PHP 7.1
88 11
		$headers     = $content['headers'];
0 ignored issues
show
Unused Code introduced by
$headers is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
89 11
		$status_code = $content['status_code'];
90 11
		$data        = $content['body'];
91
92 11
		if(!($status_code >= 200 && $status_code < 300)) {
93 3
			log_message('error', "{$site} : {$title_url} | Bad Status Code ({$status_code})");
94 8
		} else if(empty($data)) {
95
			log_message('error', "{$site} : {$title_url} | Data is empty? (Status code: {$status_code})");
96 8
		} else if($failure_string !== "" && strpos($data, $failure_string) !== FALSE) {
97 1
			log_message('error', "{$site} : {$title_url} | Failure string matched");
98
		} else {
99 7
			$data = $this->cleanTitleDataDOM($data); //This allows us to clean the DOM prior to parsing. It's faster to grab the only part we need THEN parse it.
100
101 7
			$dom = new DOMDocument();
102 7
			libxml_use_internal_errors(TRUE);
103 7
			$dom->loadHTML($data);
104 7
			libxml_use_internal_errors(FALSE);
105
106 7
			$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...
107 7
			$nodes_title = $xpath->query($node_title_string);
108 7
			$nodes_row   = $xpath->query($node_row_string);
109 7
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
110 7
				$firstRow      = $nodes_row->item(0);
111 7
				$nodes_latest  = $xpath->query($node_latest_string,  $firstRow);
112 7
				$nodes_chapter = $xpath->query($node_chapter_string, $firstRow);
113
114 7
				if($nodes_latest->length === 1 && $nodes_chapter->length === 1) {
115
					return [
116 7
						'nodes_title'   => $nodes_title->item(0),
117 7
						'nodes_latest'  => $nodes_latest->item(0),
118 7
						'nodes_chapter' => $nodes_chapter->item(0)
119
					];
120
				} else {
121
					log_message('error', "{$site} : {$title_url} | Invalid amount of nodes (LATEST: {$nodes_latest->length} | CHAPTER: {$nodes_chapter->length})");
122
				}
123
			} else {
124
				log_message('error', "{$site} : {$title_url} | Invalid amount of nodes (TITLE: {$nodes_title->length} | ROW: {$nodes_row->length})");
125
			}
126
		}
127 4
		return FALSE;
128
	}
129
130 7
	public function cleanTitleDataDOM(string $data) : string {
131 7
		return $data;
132
	}
133
134
	//This has it's own function due to FoOlSlide being used a lot by fan translation sites, and the code being pretty much the same across all of them.
135 4
	final public function parseFoolSlide(string $fullURL, string $title_url) {
136 4
		$titleData = [];
137
138 4
		$content         = $this->get_content($fullURL);
139 4
		$content['body'] = preg_replace('/^[\S\s]*(<article[\S\s]*)<\/article>[\S\s]*$/', '$1', $content['body']);
140
141 4
		$data = $this->parseTitleDataDOM(
142
			$content,
0 ignored issues
show
Security Bug introduced by
It seems like $content defined by $this->get_content($fullURL) on line 138 can also be of type false; however, Site_Model::parseTitleDataDOM() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
143 4
			$this->site,
144
			$title_url,
145 4
			"//div[@class='large comic']/h1[@class='title']",
146 4
			"(//div[@class='list']/div[@class='group']/div[@class='title' and text() = 'Chapters']/following-sibling::div[@class='element'][1] | //div[@class='list']/div[@class='element'][1] | //div[@class='list']/div[@class='group'][1]/div[@class='element'][1])[1]",
147 4
			"div[@class='meta_r']",
148 4
			"div[@class='title']/a"
149
		);
150 4
		if($data) {
151 4
			$titleData['title'] = trim($data['nodes_title']->textContent);
152
153 4
			$link = (string) $data['nodes_chapter']->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...
154 4
			$titleData['latest_chapter'] = preg_replace('/.*\/read\/.*?\/(.*?)\/$/', '$1', $link);
155
156 4
			$titleData['last_updated']   = date("Y-m-d H:i:s", strtotime((string) str_replace('.', '', explode(',', $data['nodes_latest']->nodeValue)[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...
157
		}
158
159 4
		return (!empty($titleData) ? $titleData : NULL);
160
	}
161
}
162
class Sites_Model extends CI_Model {
163
	public $MangaFox;
164
	public $MangaHere;
165
	public $Batoto;
166
	public $DynastyScans;
167
	public $MangaPanda;
168
	public $MangaStream;
169
	public $WebToons;
170
	public $KissManga;
171
	public $KireiCake;
172
	public $GameOfScanlation;
173
	public $MangaCow;
174
	public $SeaOtterScans;
175
	public $HelveticaScans;
176
	public $SenseScans;
177
178 102
	public function __construct() {
179 102
		parent::__construct();
180
181 102
		$this->MangaFox         = new MangaFox();
182 102
		$this->MangaHere        = new MangaHere();
183 102
		$this->Batoto           = new Batoto();
184 102
		$this->DynastyScans     = new DynastyScans();
185 102
		$this->MangaPanda       = new MangaPanda();
186 102
		$this->MangaStream      = new MangaStream();
187 102
		$this->WebToons         = new WebToons();
188 102
		$this->KissManga        = new KissManga();
189 102
		$this->KireiCake        = new KireiCake();
190 102
		$this->GameOfScanlation = new GameOfScanlation();
191 102
		$this->MangaCow         = new MangaCow();
192 102
		$this->SeaOtterScans    = new SeaOtterScans();
193 102
		$this->HelveticaScans   = new HelveticaScans();
194 102
		$this->SenseScans       = new SenseScans();
195 102
	}
196
}
197
198
class MangaFox extends Site_Model {
199
	public $site          = 'MangaFox';
200
	public $titleFormat   = '/^[a-z0-9_]+$/';
201
	public $chapterFormat = '/^(?:v[0-9a-zA-Z]+\/)?c[0-9\.]+$/';
202
203 2
	public function getFullTitleURL(string $title_url) : string {
204 2
		return "http://mangafox.me/manga/{$title_url}/";
205
	}
206
207
	public function getChapterData(string $title_url, string $chapter) : array {
208
		return [
209
			'url'    => "http://mangafox.me/manga/{$title_url}/{$chapter}/",
210
			'number' => $chapter
211
		];
212
	}
213
214 2
	public function getTitleData(string $title_url) {
215 2
		$titleData = [];
216
217 2
		$fullURL = $this->getFullTitleURL($title_url);
218 2
		$content = $this->get_content($fullURL);
219
220 2
		$data = $this->parseTitleDataDOM(
221
			$content,
0 ignored issues
show
Security Bug introduced by
It seems like $content defined by $this->get_content($fullURL) on line 218 can also be of type false; however, Site_Model::parseTitleDataDOM() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
222 2
			'MangaFox',
223
			$title_url,
224 2
			"//meta[@property='og:title']/@content",
225 2
			"//body/div[@id='page']/div[@class='left']/div[@id='chapters']/ul[1]/li[1]",
226 2
			"div/span[@class='date']",
227 2
			"div/h3/a"
228
		);
229 2
		if($data) {
230 1
			$titleData['title'] = html_entity_decode(substr($data['nodes_title']->textContent, 0, -6));
231
232 1
			$link = preg_replace('/^(.*\/)(?:[0-9]+\.html)?$/', '$1', (string) $data['nodes_chapter']->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...
233 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...
234 1
			$titleData['latest_chapter'] = $chapterURLSegments[5] . (isset($chapterURLSegments[6]) && !empty($chapterURLSegments[6]) ? "/{$chapterURLSegments[6]}" : "");
235 1
			$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) $data['nodes_latest']->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...
236
		}
237
238 2
		return (!empty($titleData) ? $titleData : NULL);
239
	}
240
}
241
242
class MangaHere extends Site_Model {
243
	public $site          = 'MangaHere';
244
	public $titleFormat   = '/^[a-z0-9_]+$/';
245
	public $chapterFormat = '/^(?:v[0-9]+\/)?c[0-9]+(?:\.[0-9]+)?$/';
246
247 2
	public function getFullTitleURL(string $title_url) : string {
248 2
		return "http://www.mangahere.co/manga/{$title_url}/";
249
	}
250
251
	public function getChapterData(string $title, string $chapter) : array {
252
		return [
253
			'url'    => "http://www.mangahere.co/manga/{$title}/{$chapter}/",
254
			'number' => $chapter
255
		];
256
	}
257
258 2
	public function getTitleData(string $title_url) {
259 2
		$titleData = [];
260
261 2
		$fullURL = $this->getFullTitleURL($title_url);
262 2
		$content = $this->get_content($fullURL);
263
264 2
		$data = $this->parseTitleDataDOM(
265
			$content,
0 ignored issues
show
Security Bug introduced by
It seems like $content defined by $this->get_content($fullURL) on line 262 can also be of type false; however, Site_Model::parseTitleDataDOM() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
266 2
			'MangaHere',
267
			$title_url,
268 2
			"//meta[@property='og:title']/@content",
269 2
			"//body/section/article/div/div[@class='manga_detail']/div[@class='detail_list']/ul[1]/li[1]",
270 2
			"span[@class='right']",
271 2
			"span[@class='left']/a",
272 2
			"<div class=\"error_text\">Sorry, the page you have requested can’t be found."
273
		);
274 2
		if($data) {
275 1
			$titleData['title'] = $data['nodes_title']->textContent;
276
277 1
			$link = preg_replace('/^(.*\/)(?:[0-9]+\.html)?$/', '$1', (string) $data['nodes_chapter']->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...
278 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...
279 1
			$titleData['latest_chapter'] = $chapterURLSegments[5] . (isset($chapterURLSegments[6]) && !empty($chapterURLSegments[6]) ? "/{$chapterURLSegments[6]}" : "");
280 1
			$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) $data['nodes_latest']->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...
281
		}
282
283 2
		return (!empty($titleData) ? $titleData : NULL);
284
	}
285
}
286
287
class Batoto extends Site_Model {
288
	//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.
289
	//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.
290
	//title_url is stored like: "TITLE_URL:--:LANGUAGE"
291
	//chapter_urls are stored like "CHAPTER_ID:--:CHAPTER_NUMBER"
292
293
	public $site          = 'Batoto';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 8 spaces but found 10 spaces

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...
294
	public $titleFormat   = '/^[0-9]+:--:(?:English|Spanish|French|German|Portuguese|Turkish|Indonesian|Greek|Filipino|Italian|Polish|Thai|Malay|Hungarian|Romanian|Arabic|Hebrew|Russian|Vietnamese|Dutch)$/';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 1 space but found 3 spaces

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...
295
	//FIXME: We're not validating the chapter name since we don't know what all the possible valid characters can be
296
	//       Preferably we'd just use /^[0-9a-z]+:--:(v[0-9]+\/)?c[0-9]+(\.[0-9]+)?$/
297
	public $chapterFormat = '/^[0-9a-z]+:--:.+$/';
298
299 1
	public function getFullTitleURL(string $title_string) : string {
300
		//FIXME: This does not point to the language specific title page. Should ask if it is possible to set LANG as arg?
301
		//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.
302 1
		$title_parts = explode(':--:', $title_string);
303 1
		return "http://bato.to/comic/_/comics/-r".$title_parts[0];
304
	}
305
306 View Code Duplication
	public function getChapterData(string $title_string, string $chapter) : array {
307
		//$title_string isn't used here.
308
309
		$chapter_parts = explode(':--:', $chapter);
310
		return [
311
			'url'    => "http://bato.to/reader#" . $chapter_parts[0],
312
			'number' => $chapter_parts[1]
313
		];
314
	}
315
316 1
	public function getTitleData(string $title_url) {
317 1
		$titleData = [];
318
319 1
		$title_parts = explode(':--:', $title_url);
320 1
		$fullURL     = $this->getFullTitleURL($title_url);
321 1
		$lang        = $title_parts[1]; //TODO: Validate title_lang from array?
322
323
324
		//Bato.to is annoying and locks stuff behind auth. See: https://github.com/DakuTree/manga-tracker/issues/14#issuecomment-233830855
325
		$cookies = [
326 1
			"lang_option={$lang}",
327 1
			"member_id={$this->config->item('batoto_cookie_member_id')}",
328 1
			"pass_hash={$this->config->item('batoto_cookie_pass_hash')}"
329
		];
330 1
		$content = $this->get_content($fullURL, implode("; ", $cookies), "", TRUE);
331
332 1
		$data = $this->parseTitleDataDOM(
333
			$content,
0 ignored issues
show
Security Bug introduced by
It seems like $content defined by $this->get_content($full...', $cookies), '', TRUE) on line 330 can also be of type false; however, Site_Model::parseTitleDataDOM() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
334 1
			'Batoto',
335
			$title_url,
336 1
			"//h1[@class='ipsType_pagetitle']",
337 1
			"//table[contains(@class, 'chapters_list')]/tbody/tr[2]",
338 1
			"td[last()]",
339 1
			"td/a[contains(@href,'reader')]",
340 1
			">Register now<"
341
		);
342 1
		if($data) {
343
			$titleData['title'] = html_entity_decode(trim($data['nodes_title']->textContent));
344
345
			///^(?:Vol\.(?<volume>\S+) )?(?:Ch.(?<chapter>[^\s:]+)(?:\s?-\s?(?<extra>[0-9]+))?):?.*/
346
			preg_match('/^(?:Vol\.(?<volume>\S+) )?(?:Ch.(?<chapter>[^\s:]+)(?:\s?-\s?(?<extra>[0-9]+))?):?.*/', trim($data['nodes_chapter']->nodeValue), $text);
347
			$titleData['latest_chapter'] = substr($data['nodes_chapter']->getAttribute('href'), 22) . ':--:' . ((!empty($text['volume']) ? 'v'.$text['volume'].'/' : '') . 'c'.$text['chapter'] . (!empty($text['extra']) ? '-'.$text['extra'] : ''));
348
349
			$dateString = $data['nodes_latest']->nodeValue;
350
			if($dateString == 'An hour ago') {
351
				$dateString = '1 hour ago';
352
			}
353
			$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...
354
		}
355
356 1
		return (!empty($titleData) ? $titleData : NULL);
357
	}
358
359
	public function cleanTitleDataDOM(string $data) : string {
360
		$data = preg_replace('/^[\s\S]+<!-- ::: CONTENT ::: -->/', '<!-- ::: CONTENT ::: -->', $data);
361
		$data = preg_replace('/<!-- end mainContent -->[\s\S]+$/', '<!-- end mainContent -->', $data);
362
		$data = preg_replace('/<div id=\'commentsStart\' class=\'ipsBox\'>[\s\S]+$/', '</div></div><!-- end mainContent -->', $data);
363
364
		return $data;
365
	}
366
}
367
368
class DynastyScans extends Site_Model {
369
	//FIXME: This has some major issues. SEE: https://github.com/DakuTree/manga-tracker/issues/58
370
371
	public $site          = 'DynastyScans';
372
	public $titleFormat   = '/^[a-z0-9_]+:--:(?:0|1)$/';
373
	public $chapterFormat = '/^[0-9a-z_]+$/';
374
375
	public function getFullTitleURL(string $title_string) : string {
376
		$title_parts = explode(':--:', $title_string);
377
		$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...
378
379
		return 'http://dynasty-scans.com/'.$url_type.'/'.$title_parts[0];
380
	}
381
382
	public function getChapterData(string $title_string, string $chapter) : array {
383
		$title_parts = explode(':--:', $title_string);
384
		/* Known chapter url formats (# is numbers):
385
		       chapters_#A_#B - Ch#A-#B
386
		       ch_#A          - Ch#A
387
		       ch_#A_#B       - Ch#A.#B
388
		       <NOTHING>      - Oneshot (This is passed as "oneshot")
389
		*/
390
391
		$chapterData = [
392
			'url'    => 'http://dynasty-scans.com/chapters/' . $title_parts[0].'_'.$chapter,
393
			'number' => ''
394
		];
395
396
		if($chapter == 'oneshot') {
397
			$chapterData['number'] = 'oneshot';
398
		} else {
399
			$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...
400
			$chapterSegments = explode('_', $chapter);
401
			switch($chapterSegments[0]) {
402
				case 'ch':
403
					$chapterData['number'] = 'c'.$chapterSegments[1].(isset($chapterSegments[2]) && !empty($chapterSegments[2]) ? '.'.$chapterSegments[2] : '');
404
					break;
405
406
				case 'chapters':
407
					//This is barely ever used, but I have seen it.
408
					$chapterData['number'] = 'c'.$chapterSegments[1].'-'.$chapterSegments[2];
409
					break;
410
411
				default:
412
					//TODO: FALLBACK, ALERT ADMIN?
413
					$chapterData['number'] = $chapter;
414
					break;
415
			}
416
		}
417
		return $chapterData;
418
	}
419
420 1
	public function getTitleData(string $title_string) {
421 1
		$title_parts = explode(':--:', $title_string);
422 1
		$title_url   = $title_parts[0];
423
424 1
		$titleData = [];
425
		//FIXME: Using regex here is probably a terrible idea, but we're doing it anyway....
426
		//FIXME (ASAP): All the regex here should be checked to see if it even returns something, and we should probably error if possible.
427 1
		if($title_parts[1] == '0') {
428 1
			$content = $this->get_content('http://dynasty-scans.com/series/'.$title_url);
429 1
			$data = $content['body'];
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...
430
431 1
			preg_match('/<b>.*<\/b>/', $data, $matchesT);
432 1
			preg_match('/\/doujins\/[^"]+">(.+)?(?=<\/a>)<\/a>/', $data, $matchesD);
433 1
			$titleData['title'] = (!empty($matchesD) ? (substr($matchesD[1], 0, -7) !== 'Original' ? substr($matchesD[1], 0, -7).' - ' : '') : '') . substr($matchesT[0], 3, -4);
434
435 1
			$data = preg_replace('/^[\S\s]*(<dl class=\'chapter-list\'>[\S\s]*<\/dl>)[\S\s]*$/', '$1', $data);
436 1
			preg_match_all('/<dd>[\s\S]+?(?=<\/dd>)<\/dd>/', $data, $matches);
437 1
			$latest_chapter_html = array_pop($matches[0]);
438
439 1
			preg_match('/\/chapters\/([^"]+)/', $latest_chapter_html, $matches);
440 1
			$titleData['latest_chapter'] = substr($matches[1], strlen($title_url)+1);
441
			//FIXME: THIS IS A TEMP FIX, SEE https://github.com/DakuTree/manga-tracker/issues/58
442 1
			if(!$titleData['latest_chapter']) {
443
				log_message('error', 'DynastyScans::getTitleData cannot parse title properly as it contains oneshot. || URL: '.$title_url);
444
				return NULL;
445
			}
446
447 1
			preg_match('/<small>released (.*)<\/small>/', $latest_chapter_html, $matches);
448 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...
449
		} elseif($title_parts[1] == '1') {
450
			$content = $this->get_content('http://dynasty-scans.com/chapters/'.$title_url);
451
			$data = $content['body'];
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...
452
453
			preg_match('/<b>.*<\/b>/', $data, $matchesT);
454
			preg_match('/\/doujins\/[^"]+">(.+)?(?=<\/a>)<\/a>/', $data, $matchesD);
455
			$titleData['title'] = (!empty($matchesD) ? ($matchesD[1] !== 'Original' ? $matchesD[1].' - ' : '') : '') . substr($matchesT[0], 3, -4);
456
457
			$titleData['latest_chapter'] = 'oneshot'; //This will never change
458
459
			preg_match('/<i class="icon-calendar"><\/i> (.*)<\/span>/', $data, $matches);
460
			$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...
461
462
			//Oneshots are special, and really shouldn't need to be re-tracked
463
			//FIXME: We need to have a specific "no-track" complete param.
464
			$titleData['complete'] = 'Y';
465
		} 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...
466
			//FIXME: WTF?
467
		}
468 1
		return (!empty($titleData) ? $titleData : NULL);
469
	}
470
}
471
472
class MangaPanda extends Site_Model {
473
	public $site          = 'MangaPanda';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 10 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...
474
	//NOTE: MangaPanda has manga pages under the root URL, so we need to filter out pages we know that aren't manga.
475
	public $titleFormat   = '/^(?!(?:latest|search|popular|random|alphabetical|privacy)$)([a-z0-9-]+)$/';
476
	public $chapterFormat = '/^[0-9]+$/';
477
478 2
	public function getFullTitleURL(string $title_url) : string {
479 2
		return "http://www.mangapanda.com/{$title_url}";
480
	}
481
482
	public function getChapterData(string $title_url, string $chapter) : array {
483
		return [
484
			'url'    => "http://www.mangapanda.com/{$title_url}/{$chapter}/",
485
			'number' => 'c'.$chapter
486
		];
487
	}
488
489 2 View Code Duplication
	public function getTitleData(string $title_url) {
490 2
		$titleData = [];
491
492 2
		$fullURL = $this->getFullTitleURL($title_url);
493 2
		$content = $this->get_content($fullURL);
494
495 2
		$data = $this->parseTitleDataDOM(
496
			$content,
0 ignored issues
show
Security Bug introduced by
It seems like $content defined by $this->get_content($fullURL) on line 493 can also be of type false; however, Site_Model::parseTitleDataDOM() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
497 2
			'MangaPanda',
498
			$title_url,
499 2
			"//h2[@class='aname']",
500 2
			"(//table[@id='listing']/tr)[last()]",
501 2
			"td[2]",
502 2
			"td[1]/a"
503
		);
504 2
		if($data) {
505 1
			$titleData['title'] = $data['nodes_title']->textContent;
506
507 1
			$titleData['latest_chapter'] = preg_replace('/^.*\/([0-9]+)$/', '$1', (string) $data['nodes_chapter']->getAttribute('href'));
508
509 1
			$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) $data['nodes_latest']->nodeValue));
510
		}
511
512 2
		return (!empty($titleData) ? $titleData : NULL);
513
	}
514
}
515
516
class MangaStream extends Site_Model {
517
	public $site          = 'MangaPanda';
518
	public $titleFormat   = '/^[a-z0-9_]+$/';
519
	public $chapterFormat = '/^(.*?)\/[0-9]+$/';
520
521
	public function getFullTitleURL(string $title_url) : string {
522
		return "https://mangastream.com/manga/{$title_url}/";
523
	}
524
525
	public function getChapterData(string $title_url, string $chapter) : array {
526
		return [
527
			'url'    => "https://mangastream.com/r/{$title_url}/{$chapter}",
528
			'number' => 'c'.explode('/', $chapter)[0]
529
		];
530
	}
531
532 View Code Duplication
	public function getTitleData(string $title_url) {
533
		$titleData = [];
534
535
		$fullURL = $this->getFullTitleURL($title_url);
536
		$content = $this->get_content($fullURL);
537
538
		$data = $this->parseTitleDataDOM(
539
			$content,
0 ignored issues
show
Security Bug introduced by
It seems like $content defined by $this->get_content($fullURL) on line 536 can also be of type false; however, Site_Model::parseTitleDataDOM() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
540
			'MangaStream',
541
			$title_url,
542
			"//div[contains(@class, 'content')]/div[1]/h1",
543
			"//div[contains(@class, 'content')]/div[1]/table/tr[2]",
544
			"td[2]",
545
			"td[1]/a",
546
			"<h1>Page Not Found</h1>"
547
		);
548
		if($data) {
549
			$titleData['title'] = $data['nodes_title']->textContent;
550
551
			$titleData['latest_chapter'] = preg_replace('/^.*\/(.*?\/[0-9]+)\/[0-9]+$/', '$1', (string) $data['nodes_chapter']->getAttribute('href'));
552
553
			$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) $data['nodes_latest']->nodeValue));
554
		}
555
556
		return (!empty($titleData) ? $titleData : NULL);
557
	}
558
}
559
560
class WebToons extends Site_Model {
561
	/* Webtoons.com has a very weird and pointless URL format.
562
	   TITLE URL:   /#LANG#/#GENRE#/#TITLE#/list?title_no=#TITLEID#
563
	   RSS URL:     /#LANG#/#GENRE#/#TITLE#/rss?title_no=#TITLEID#
564
	   CHAPTER URL: /#LANG#/#GENRE#/#TITLE#/#CHAPTER#/viewer?title_no=#TITLEID#&episode_no=#CHAPTERID#
565
566
	   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).
567
	   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.
568
	   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.
569
570
	   FORMATS:
571
	   TITLE_URL: ID:--:LANG:--:TITLE:--:GENRE
572
	   CHAPTER:   ID:--:CHAPTER_N
573
	*/
574
	//private $validLang = ['en', 'zh-hant', 'zh-hans', 'th', 'id'];
575
576
	public $site          = 'WebToons';
577
	public $titleFormat   = '/^[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)$/';
578
	public $chapterFormat = '/^[0-9]+:--:.*$/';
579
580
	public function getFullTitleURL(string $title_url) : string {
581
		$title_parts = explode(':--:', $title_url);
582
		return "http://www.webtoons.com/{$title_parts[1]}/{$title_parts[3]}/{$title_parts[2]}/list?title_no={$title_parts[0]}/";
583
	}
584
585
	public function getChapterData(string $title_url, string $chapter) : array {
586
		$title_parts   = explode(':--:', $title_url);
587
		$chapter_parts = explode(':--:', $chapter);
588
589
		return [
590
			'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]}",
591
			'number' => $chapter_parts[1] //TODO: Possibly replace certain formats in here? Since webtoons doesn't have a standard chapter format
592
		];
593
	}
594
595 1
	public function getTitleData(string $title_url) {
596 1
		$titleData = [];
597
598 1
		$title_parts = explode(':--:', $title_url);
599 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...
600
601 1
		$content = $this->get_content($fullURL);
602 1
		$data = $content['body'];
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...
603 1
		if($data !== 'Can\'t find the manga series.') { //FIXME: We should check for he proper error here.
604 1
			$xml = simplexml_load_string($data) or die("Error: Cannot create object");
605 1
			if(isset($xml->{'channel'}->item[0])) {
606 1
				$titleData['title'] = trim((string) $xml->{'channel'}->title);
607
608 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...
609 1
				$titleData['latest_chapter'] = preg_replace('/^.*?([0-9]+)$/', '$1', $chapterURLSegments[7]) . ':--:' . $chapterURLSegments[6];
610 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...
611
			}
612
		} else {
613
			log_message('error', "Series missing? (WebToons): {$title_url}");
614
			return NULL;
615
		}
616
617 1
		return (!empty($titleData) ? $titleData : NULL);
618
	}
619
}
620
621
class KissManga extends Site_Model {
622
	/* 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.
623
	   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.
624
625
	   To generate this cookie, we need three variables. Two are static, but the other is generated by randomly generated JS on the page.
626
	   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.
627
	   The other option is using regex, but that is a rabbit hole I don't want to touch with a ten-foot pole.
628
629
	   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.
630
	   The cookie has a length of 1 year, but I don't think it actually lasts that long, so we update every 6hours instead.
631
	   I should probably also mention that the cookie generated also uses your user-agent, so if it changes the cookie will break.
632
	*/
633
634
	public $site          = 'KissManga';
635
	public $titleFormat   = '/^[A-Za-z0-9-]+$/';
636
	public $chapterFormat = '/^.*?:--:[0-9]+$/';
637
638
	public function getFullTitleURL(string $title_url) : string {
639
		return "http://kissmanga.com/Manga/{$title_url}";
640
	}
641
642 View Code Duplication
	public function getChapterData(string $title_url, string $chapter) : array {
643
		$chapter_parts = explode(':--:', $chapter);
644
645
		return [
646
			'url'    => "http://kissmanga.com/Manga/{$title_url}/{$chapter_parts[0]}?id={$chapter_parts[1]}",
647
			//FIXME: KM has an extremely inconsistant chapter format which makes it difficult to parse.
648
			'number' => /*preg_replace('/--.*?$/', '', */$chapter_parts[0]/*)*/
649
		];
650
	}
651
652
	public function getTitleData(string $title_url) {
653
		$titleData = [];
654
655
		//Check if cookiejar is a day old (so we can know if something went wrong)
656
		$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...
657
		$cookie_last_updated = filemtime($cookiejar_path);
658
		if($cookie_last_updated && ((time() - 86400) < $cookie_last_updated)) {
659
660
			$fullURL = $this->getFullTitleURL($title_url);
661
662
			$content = $this->get_content($fullURL, '', $cookiejar_path);
663
			$data = $content['body'];
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...
664
			if(strpos($data, 'containerRoot') !== FALSE) {
665
				//FIXME: For whatever reason, we can't grab the entire div without simplexml shouting at us
666
				$data = preg_replace('/^[\S\s]*(<div id="leftside">[\S\s]*)<div id="rightside">[\S\s]*$/', '$1', $data);
667
668
				$dom = new DOMDocument();
669
				libxml_use_internal_errors(true);
670
				$dom->loadHTML($data);
671
				libxml_use_internal_errors(false);
672
673
				$xpath = new DOMXPath($dom);
674
675
				$nodes_title = $xpath->query("//a[@class='bigChar']");
676
				$nodes_row   = $xpath->query("//table[@class='listing']/tr[3]");
677
				if($nodes_title->length === 1 && $nodes_row->length === 1) {
678
					$titleData['title'] = $nodes_title->item(0)->textContent;
679
680
					$firstRow      = $nodes_row->item(0);
681
					$nodes_latest  = $xpath->query("td[2]",   $firstRow);
682
					$nodes_chapter = $xpath->query("td[1]/a", $firstRow);
683
684
					$link = (string) $nodes_chapter->item(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...
685
					$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...
686
					$titleData['latest_chapter'] = $chapterURLSegments[3] . ':--:' . preg_replace('/.*?([0-9]+)$/', '$1', $link);
687
					$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) $nodes_latest->item(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...
688
				}
689
			} 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...
690
				//TODO: Throw ERRORS;
691
			}
692
		} 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...
693
			//Do nothing, wait until next update.
694
			//TODO: NAG ADMIN??
695
		}
696
697
		return (!empty($titleData) ? $titleData : NULL);
698
	}
699
}
700
701 View Code Duplication
class KireiCake 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...
702
	public $site          = 'KireiCake';
703
	public $titleFormat   = '/^[a-z0-9_]+$/';
704
	public $chapterFormat = '/^en\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+)?)?)?$/';
705
706 1
	public function getFullTitleURL(string $title_url) : string {
707 1
		return "https://reader.kireicake.com/series/{$title_url}";
708
	}
709
710
	public function getChapterData(string $title_url, string $chapter) : array {
711
		//LANG/VOLUME/CHAPTER/CHAPTER_EXTRA(/page/)
712
		$chapter_parts = explode('/', $chapter);
713
		return [
714
			'url'    => "https://reader.kireicake.com/read/{$title_url}/{$chapter}/",
715
			'number' => ($chapter_parts[1] !== '0' ? "v{$chapter_parts[1]}/" : '') . "c{$chapter_parts[2]}" . (isset($chapter_parts[3]) ? ".{$chapter_parts[3]}" : '')/*)*/
716
		];
717
	}
718
719 1
	public function getTitleData(string $title_url) {
720 1
		$fullURL = $this->getFullTitleURL($title_url);
721 1
		return $this->parseFoolSlide($fullURL, $title_url);
722
	}
723
}
724
725
class GameOfScanlation extends Site_Model {
726
	public $site          = 'GameOfScanlation';
727
	public $titleFormat   = '/^[a-z0-9-]+$/';
728
	public $chapterFormat = '/^[a-z0-9\.-]+$/';
729
730
	public function getFullTitleURL(string $title_url) : string {
731
		return "https://gameofscanlation.moe/forums/{$title_url}/";
732
	}
733
734
	public function getChapterData(string $title_url, string $chapter) : array {
735
		return [
736
			'url'    => "https://gameofscanlation.moe/projects/".preg_replace("/\\.[0-9]+$/", "", $title_url).'/'.$chapter.'/',
737
			'number' => preg_replace("/chapter-/", "c", preg_replace("/\\.[0-9]+$/", "", $chapter))
738
		];
739
	}
740
741
	public function getTitleData(string $title_url) {
742
		$titleData = [];
743
744
		$fullURL = $this->getFullTitleURL($title_url);
745
746
		$content = $this->get_content($fullURL);
747
		$data = $content['body'];
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...
748
		if(strpos($data, '404 Page Not Found') === FALSE) {
749
			//$data = preg_replace('/^[\S\s]*(<ol[\S\s]*)<\/ol>[\S\s]*$/', '$1', $data);
750
751
			$dom = new DOMDocument();
752
			libxml_use_internal_errors(true);
753
			$dom->loadHTML($data);
754
			libxml_use_internal_errors(false);
755
756
			$xpath = new DOMXPath($dom);
757
758
			$nodes_title = $xpath->query("//meta[@property='og:title']");
759
			$nodes_row   = $xpath->query("//ol[@class='discussionListItems']/li[1]/div[@class='home_list']/ul/li/div[@class='list_press_text']");
760
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
761
				$titleData['title'] = html_entity_decode($nodes_title->item(0)->getAttribute('content'));
762
763
				$firstRow      = $nodes_row->item(0);
764
				$nodes_latest  = $xpath->query("p[@class='author']/span|p[@class='author']/abbr", $firstRow);
765
				$nodes_chapter = $xpath->query("p[@class='text_work']/a",                         $firstRow);
766
767
				$link = (string) $nodes_chapter->item(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...
768
				$titleData['latest_chapter'] = preg_replace('/^projects\/.*?\/(.*?)\/$/', '$1', $link);
769
				$titleData['last_updated'] =  date("Y-m-d H:i:s", (int) $nodes_latest->item(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...
770
			} else {
771
				log_message('error', "GameOfScanlation: Unable to find nodes.");
772
				return NULL;
773
			}
774
		} 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...
775
			//TODO: Throw ERRORS;
776
		}
777
778
		return (!empty($titleData) ? $titleData : NULL);
779
	}
780
}
781
782
class MangaCow extends Site_Model {
783
	public $site          = 'MangaCow';
784
	public $titleFormat   = '/^[a-zA-Z0-9_]+$/';
785
	public $chapterFormat = '/^[0-9]+$/';
786
787 1
	public function getFullTitleURL(string $title_url) : string {
788 1
		return "http://mngcow.co/{$title_url}/";
789
	}
790
791
	public function getChapterData(string $title_url, string $chapter) : array {
792
		return [
793
			'url'    => $this->getFullTitleURL($title_url).$chapter.'/',
794
			'number' => "c{$chapter}"
795
		];
796
	}
797
798 1
	public function getTitleData(string $title_url) {
799 1
		$titleData = [];
800
801 1
		$fullURL = $this->getFullTitleURL($title_url);
802
803 1
		$content = $this->get_content($fullURL);
804 1
		$data = $content['body'];
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...
805 1
		if(strpos($data, '404 Page Not Found') === FALSE) {
806 1
			$dom = new DOMDocument();
807 1
			libxml_use_internal_errors(true);
808 1
			$dom->loadHTML($data);
809 1
			libxml_use_internal_errors(false);
810
811 1
			$xpath = new DOMXPath($dom);
812
813 1
			$nodes_title = $xpath->query("//h4");
814 1
			$nodes_row   = $xpath->query("//ul[contains(@class, 'mng_chp')]/li[1]/a[1]");
815 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
816 1
				$titleData['title'] = trim($nodes_title->item(0)->nodeValue);
817
818 1
				$nodes_chapter = $nodes_row;
819 1
				$nodes_latest  = $xpath->query("b[@class='dte']", $nodes_row->item(0));
820
821 1
				$link = (string) $nodes_chapter->item(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...
822 1
				$titleData['latest_chapter'] = preg_replace('/^.*\/([0-9]+)\/$/', '$1', $link);
823 1
				$titleData['last_updated'] =  date("Y-m-d H:i:s", strtotime((string) substr($nodes_latest->item(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...
824
			} else {
825
				log_message('error', "MangaCow: Unable to find nodes.");
826 1
				return NULL;
827
			}
828
		} 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...
829
			//TODO: Throw ERRORS;
830
		}
831
832 1
		return (!empty($titleData) ? $titleData : NULL);
833
	}
834
}
835
836 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...
837
	public $site          = 'SeaOtterScans';
838
	public $titleFormat   = '/^[a-z0-9_]+$/';
839
	public $chapterFormat = '/^en\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+)?)?)?$/';
840
841 1
	public function getFullTitleURL(string $title_url) : string {
842 1
		return "https://reader.seaotterscans.com/series/{$title_url}";
843
	}
844
845
	public function getChapterData(string $title_url, string $chapter) : array {
846
		//LANG/VOLUME/CHAPTER/CHAPTER_EXTRA(/page/)
847
		$chapter_parts = explode('/', $chapter);
848
		return [
849
			'url'    => "https://reader.seaotterscans.com/read/{$title_url}/{$chapter}/",
850
			'number' => ($chapter_parts[1] !== '0' ? "v{$chapter_parts[1]}/" : '') . "c{$chapter_parts[2]}" . (isset($chapter_parts[3]) ? ".{$chapter_parts[3]}" : '')/*)*/
851
		];
852
	}
853
854 1
	public function getTitleData(string $title_url) {
855 1
		$fullURL = $this->getFullTitleURL($title_url);
856 1
		return $this->parseFoolSlide($fullURL, $title_url);
857
	}
858
}
859
860 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...
861
	public $site          = 'HelveticaScans';
862
	public $titleFormat   = '/^[a-z0-9_]+$/';
863
	public $chapterFormat = '/^en\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+)?)?)?$/';
864
865 1
	public function getFullTitleURL(string $title_url) : string {
866 1
		return "http://helveticascans.com/reader/series/{$title_url}";
867
	}
868
869
	public function getChapterData(string $title_url, string $chapter) : array {
870
		//LANG/VOLUME/CHAPTER/CHAPTER_EXTRA(/page/)
871
		$chapter_parts = explode('/', $chapter);
872
		return [
873
			'url'    => "http://helveticascans.com/reader/read/{$title_url}/{$chapter}/",
874
			'number' => ($chapter_parts[1] !== '0' ? "v{$chapter_parts[1]}/" : '') . "c{$chapter_parts[2]}" . (isset($chapter_parts[3]) ? ".{$chapter_parts[3]}" : '')/*)*/
875
		];
876
	}
877
878 1
	public function getTitleData(string $title_url) {
879 1
		$fullURL = $this->getFullTitleURL($title_url);
880 1
		return $this->parseFoolSlide($fullURL, $title_url);
881
	}
882
}
883
884 View Code Duplication
class SenseScans 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...
885
	public $site          = 'SenseScans';
886
	public $titleFormat   = '/^[a-z0-9_]+$/';
887
	public $chapterFormat = '/^en\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+)?)?)?$/';
888
889 1
	public function getFullTitleURL(string $title_url) : string {
890 1
		return "http://reader.sensescans.com/series/{$title_url}";
891
	}
892
893
	public function getChapterData(string $title_url, string $chapter) : array {
894
		//LANG/VOLUME/CHAPTER/CHAPTER_EXTRA(/page/)
895
		$chapter_parts = explode('/', $chapter);
896
		return [
897
			'url'    => "http://reader.sensescans.com/read/{$title_url}/{$chapter}/",
898
			'number' => ($chapter_parts[1] !== '0' ? "v{$chapter_parts[1]}/" : '') . "c{$chapter_parts[2]}" . (isset($chapter_parts[3]) ? ".{$chapter_parts[3]}" : '')/*)*/
899
		];
900
	}
901
902 1
	public function getTitleData(string $title_url) {
903 1
		$fullURL = $this->getFullTitleURL($title_url);
904 1
		return $this->parseFoolSlide($fullURL, $title_url);
905
	}
906
}
907