Completed
Push — master ( abab0f...58f85f )
by Angus
03:27
created

MangaCow::isValidChapter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 5
ccs 0
cts 0
cp 0
crap 6
rs 9.4285
c 0
b 0
f 0
1
<?php declare(strict_types=1); defined('BASEPATH') OR exit('No direct script access allowed');
2
3
class Site_Model extends CI_Model {
4 94
	public function __construct() {
5 94
		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, History_Model, KireiCake, KissManga, MangaCow, MangaFox, MangaHere, MangaPanda, MangaStream, 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 94
		$this->load->database();
8 94
	}
9
10
	public function getFullTitleURL(string $title_url) : string {}
11
12
	public function getChapterData(string $title_url, string $chapter) : array {}
13
14
	public function getTitleData(string $title_url) {}
15
16
	public function isValidTitleURL(string $title_url) : bool {}
17
	public function isValidChapter(string $chapter): bool {}
18
19 6
	protected function get_content(string $url, string $cookie_string = "", string $cookiejar_path = "", bool $follow_redirect = FALSE){
20 6
		$ch = curl_init();
21 6
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
22 6
		curl_setopt($ch, CURLOPT_ENCODING , "gzip");
23
24 6
		if($follow_redirect)        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
25
26 6
		if(!empty($cookie_string))  curl_setopt($ch, CURLOPT_COOKIE, $cookie_string);
27 6
		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 6
		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 6
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); //FIXME: This isn't safe, but it allows us to grab SSL URLs
33
34 6
		curl_setopt($ch, CURLOPT_URL, $url);
35 6
		$data = curl_exec($ch);
36 6
		curl_close($ch);
37 6
		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
53 94
	public function __construct() {
54 94
		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, History_Model, KireiCake, KissManga, MangaCow, MangaFox, MangaHere, MangaPanda, MangaStream, 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...
55
56 94
		$this->MangaFox         = new MangaFox();
57 94
		$this->MangaHere        = new MangaHere();
58 94
		$this->Batoto           = new Batoto();
59 94
		$this->DynastyScans     = new DynastyScans();
60 94
		$this->MangaPanda       = new MangaPanda();
61 94
		$this->MangaStream      = new MangaStream();
62 94
		$this->WebToons         = new WebToons();
63 94
		$this->KissManga        = new KissManga();
64 94
		$this->KireiCake        = new KireiCake();
65 94
		$this->GameOfScanlation = new GameOfScanlation();
66 94
		$this->MangaCow         = new MangaCow();
67 94
	}
68
}
69
70
class MangaFox extends Site_Model {
71
	public function getFullTitleURL(string $title_url) : string {
72
		return "http://mangafox.me/manga/{$title_url}/";
73
	}
74
75
	public function isValidTitleURL(string $title_url) : bool {
76
		$success = (bool) preg_match('/^[a-z0-9_]+$/', $title_url);
77
		if(!$success) log_message('error', "Invalid Title URL (MangaFox): {$title_url}");
78
		return $success;
79
	}
80
	public function isValidChapter(string $chapter) : bool {
81
		$success = (bool) preg_match('/^(?:v[0-9a-zA-Z]+\/)?c[0-9\.]+$/', $chapter);
82
		if(!$success) log_message('error', 'Invalid Chapter (MangaFox): '.$chapter);
83
		return $success;
84
	}
85
86
	public function getChapterData(string $title_url, string $chapter) : array {
87
		return [
88
			'url'    => "http://mangafox.me/manga/{$title_url}/{$chapter}/",
89
			'number' => $chapter
90
		];
91
	}
92
93 1
	public function getTitleData(string $title_url) {
94 1
		$titleData = [];
95
96 1
		$fullURL = "http://mangafox.me/manga/{$title_url}";
97
98 1
		$data = $this->get_content($fullURL);
99 1
		if($data !== 'Can\'t find the manga series.') {
100
			//$data = preg_replace('/^[\S\s]*(<body id="body">[\S\s]*<\/body>)[\S\s]*$/', '$1', $data);
101
102 1
			$dom = new DOMDocument();
103 1
			libxml_use_internal_errors(true);
104 1
			$dom->loadHTML($data);
105 1
			libxml_use_internal_errors(false);
106
107 1
			$xpath = new DOMXPath($dom);
108
109 1
			$nodes_title = $xpath->query("//meta[@property='og:title']");
110 1
			$nodes_row   = $xpath->query("//body/div[@id='page']/div[@class='left']/div[@id='chapters']/ul[1]/li[1]");
111 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
112
				//This seems to be be the only viable way to grab the title...
113 1
				$titleData['title'] = html_entity_decode(substr($nodes_title[0]->getAttribute('content'), 0, -6));
114
115 1
				$nodes_latest  = $xpath->query("div/span[@class='date']", $nodes_row[0]);
116 1
				$nodes_chapter = $xpath->query("div/h3/a", $nodes_row[0]);
117
118 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...
119 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...
120 1
				$titleData['latest_chapter'] = $chapterURLSegments[5] . (isset($chapterURLSegments[6]) && !empty($chapterURLSegments[6]) ? "/{$chapterURLSegments[6]}" : "");
121 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...
122
			}
123
		} 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...
124
			//TODO: Throw ERRORS;
125
		}
126
127 1
		return (!empty($titleData) ? $titleData : NULL);
128
	}
129
}
130
131
class MangaHere extends Site_Model {
132
	public function getFullTitleURL(string $title_url) : string {
133
		return "http://www.mangahere.co/manga/{$title_url}/";
134
	}
135
136
	public function isValidTitleURL(string $title_url) : bool {
137
		$success = (bool) preg_match('/^[a-z0-9_]+$/', $title_url);
138
		if(!$success) log_message('error', "Invalid Title URL (MangaFox): {$title_url}");
139
		return $success;
140
	}
141
	public function isValidChapter(string $chapter) : bool {
142
		$success = (bool) preg_match('/^(?:v[0-9]+\/)?c[0-9]+(?:\.[0-9]+)?$/', $chapter);
143
		if(!$success) log_message('error', 'Invalid Chapter (MangaFox): '.$chapter);
144
		return $success;
145
	}
146
147
	public function getChapterData(string $title, string $chapter) : array {
148
		return [
149
			'url'    => "http://www.mangahere.co/manga/{$title}/{$chapter}/",
150
			'number' => $chapter
151
		];
152
	}
153
154 1
	public function getTitleData(string $title_url) {
155 1
		$titleData = [];
156
157 1
		$fullURL = "http://www.mangahere.co/manga/{$title_url}/";
158
159 1
		$data = $this->get_content($fullURL);
160 1
		if($data !== 'Can\'t find the manga series.') {
161
			//$data = preg_replace('/^[\S\s]*(<body id="body">[\S\s]*<\/body>)[\S\s]*$/', '$1', $data);
162
163 1
			$dom = new DOMDocument();
164 1
			libxml_use_internal_errors(true);
165 1
			$dom->loadHTML($data);
166 1
			libxml_use_internal_errors(false);
167
168 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...
169 1
			$nodes_title = $xpath->query("//meta[@property='og:title']");
170 1
			$nodes_row   = $xpath->query("//body/section/article/div/div[@class='manga_detail']/div[@class='detail_list']/ul[1]/li[1]");
171 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
172
				//This seems to be be the only viable way to grab the title...
173 1
				$titleData['title'] = $nodes_title[0]->getAttribute('content');
174
175 1
				$nodes_latest  = $xpath->query("span[@class='right']", $nodes_row[0]);
176 1
				$nodes_chapter = $xpath->query("span[@class='left']/a", $nodes_row[0]);
177
178 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...
179 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...
180 1
				$titleData['latest_chapter'] = $chapterURLSegments[5] . (isset($chapterURLSegments[6]) && !empty($chapterURLSegments[6]) ? "/{$chapterURLSegments[6]}" : "");
181 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...
182
			}
183
		} 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...
184
			//TODO: Throw ERRORS;
185
		}
186 1
		return (!empty($titleData) ? $titleData : NULL);
187
	}
188
}
189
190
class Batoto extends Site_Model {
191
	//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.
192
	//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.
193
	//title_url is stored like: "TITLE_URL:--:LANGUAGE"
194
	//chapter_urls are stored like "CHAPTER_ID:--:CHAPTER_NUMBER"
195
196
	public function getFullTitleURL(string $title_string) : string {
197
		//FIXME: This does not point to the language specific title page. Should ask if it is possible to set LANG as arg?
198
		//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.
199
		$title_parts = explode(':--:', $title_string);
200
		return "http://bato.to/comic/_/comics/-r".$title_parts[0];
201
	}
202
203
	public function isValidTitleURL(string $title_url) : bool {
204
		$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);
205
		if(!$success) log_message('error', "Invalid Title URL (Batoto): {$title_url}");
206
		return $success;
207
	}
208
	public function isValidChapter(string $chapter) : bool {
209
		//FIXME: We're not validating the chapter name since we don't know what all the possible valid characters can be
210
		//       Preferably we'd just use /^[0-9a-z]+:--:(v[0-9]+\/)?c[0-9]+(\.[0-9]+)?$/
211
212
		$success = (bool) preg_match('/^[0-9a-z]+:--:.+$/', $chapter);
213
		if(!$success) log_message('error', 'Invalid Chapter (Batoto): '.$chapter);
214
		return $success;
215
	}
216
217 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...
218
		//$title_string isn't used here.
219
220
		$chapter_parts = explode(':--:', $chapter);
221
		return [
222
			'url'    => "http://bato.to/reader#" . $chapter_parts[0],
223
			'number' => $chapter_parts[1]
224
		];
225
	}
226
227
	public function getTitleData(string $title_string) {
228
		$title_parts = explode(':--:', $title_string);
229
		$title_url   = $this->getFullTitleURL($title_string);
230
		$title_lang  = $title_parts[1];
231
		//TODO: Validate title_lang from array?
232
233
		$titleData = [];
234
235
		//Bato.to is annoying and locks stuff behind auth. See: https://github.com/DakuTree/manga-tracker/issues/14#issuecomment-233830855
236
		$cookies = [
237
			"lang_option={$title_lang}",
238
			"member_id=" . $this->config->item('batoto_cookie_member_id'),
239
			"pass_hash=" . $this->config->item('batoto_cookie_pass_hash')
240
		];
241
		$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...
242
		if(!$data) {
243
			log_message('error', "Batoto: Couldn't successfully grab URL ({$title_url})");
244
			return NULL;
245
		}
246
247
		$data = preg_replace('/^[\s\S]+<!-- ::: CONTENT ::: -->/', '<!-- ::: CONTENT ::: -->', $data);
248
		$data = preg_replace('/<!-- end mainContent -->[\s\S]+$/', '<!-- end mainContent -->', $data);
249
		$data = preg_replace('/<div id=\'commentsStart\' class=\'ipsBox\'>[\s\S]+$/', '</div></div><!-- end mainContent -->', $data);
250
		if(strpos($data, '>Register now<') === FALSE) {
251
			//Auth was successful
252
			$dom = new DOMDocument();
253
			libxml_use_internal_errors(true);
254
			$dom->loadHTML($data);
255
			libxml_use_internal_errors(false);
256
257
			$xpath = new DOMXPath($dom);
258
			$nodes = $xpath->query("(//div/div)[last()]/table/tbody/tr[2]");
259
			if($nodes->length === 1) {
260
				$node = $nodes[0];
261
262
				$nodes_chapter = $xpath->query('td/a[contains(@href,\'reader\')]', $node);
263
				$nodes_updated = $xpath->query('td[last()]', $node);
264
				if($nodes_chapter->length === 1 && $nodes_updated->length === 1) {
265
					$chapter_element = $nodes_chapter->item(0);
266
					$updated_element = $nodes_updated->item(0);
267
268
					preg_match('/^(?:Vol\.(?<volume>\S+) )?(?:Ch.(?<chapter>[^\s:]+)):?.*/', trim($chapter_element->nodeValue), $text);
269
270
					$titleData['title']          = html_entity_decode(trim($xpath->query('//h1[@class="ipsType_pagetitle"]')->item(0)->nodeValue));
271
					$titleData['latest_chapter'] = substr($chapter_element->getAttribute('href'), 22) . ':--:' . ((!empty($text['volume']) ? 'v'.$text['volume'].'/' : '') . 'c'.$text['chapter']);
272
273
					$dateString = $updated_element->nodeValue;
274
					if($dateString == 'An hour ago') {
275
						$dateString = '1 hour ago';
276
					}
277
					$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...
278
				} else {
279
					log_message('error', "Batoto: Regex missing <td> ({$title_url})");
280
					return NULL;
281
				}
282
			} else {
283
				log_message('error', "Batoto: Regex missing <tr> ({$title_url})");
284
				return NULL;
285
			}
286
		} else {
287
			//Auth was not successful. Alert the admin / Try to login.
288
			log_message('error', "Batoto: Auth not successful ({$title_url})");
289
			return NULL;
290
		}
291
		return (!empty($titleData) ? $titleData : NULL);
292
	}
293
}
294
295
class DynastyScans extends Site_Model {
296
	//FIXME: This has some major issues. SEE: https://github.com/DakuTree/manga-tracker/issues/58
297
	public function getFullTitleURL(string $title_string) : string {
298
		$title_parts = explode(':--:', $title_string);
299
		$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...
300
301
		return 'http://dynasty-scans.com/'.$url_type.'/'.$title_parts[0];
302
	}
303
304
	public function isValidTitleURL(string $title_url) : bool {
305
		$success = (bool) preg_match('/^[a-z0-9_]+:--:(?:0|1)$/', $title_url);
306
		if(!$success) log_message('error', "Invalid Title URL (DynastyScans): {$title_url}");
307
		return $success;
308
	}
309
	public function isValidChapter(string $chapter) : bool {
310
		$success = (bool) preg_match('/^[0-9a-z_]+$/', $chapter);
311
		if(!$success) log_message('error', 'Invalid Chapter (DynastyScans): '.$chapter);
312
		return $success;
313
	}
314
315
	public function getChapterData(string $title_string, string $chapter) : array {
316
		$title_parts = explode(':--:', $title_string);
317
		/* Known chapter url formats (# is numbers):
318
		       chapters_#A_#B - Ch#A-#B
319
		       ch_#A          - Ch#A
320
		       ch_#A_#B       - Ch#A.#B
321
		       <NOTHING>      - Oneshot (This is passed as "oneshot")
322
		*/
323
324
		$chapterData = [
325
			'url'    => 'http://dynasty-scans.com/chapters/' . $title_parts[0].'_'.$chapter,
326
			'number' => ''
327
		];
328
329
		if($chapter == 'oneshot') {
330
			$chapterData['number'] = 'oneshot';
331
		} else {
332
			$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...
333
			$chapterSegments = explode('_', $chapter);
334
			switch($chapterSegments[0]) {
335
				case 'ch':
336
					$chapterData['number'] = 'c'.$chapterSegments[1].(isset($chapterSegments[2]) && !empty($chapterSegments[2]) ? '.'.$chapterSegments[2] : '');
337
					break;
338
339
				case 'chapters':
340
					//This is barely ever used, but I have seen it.
341
					$chapterData['number'] = 'c'.$chapterSegments[1].'-'.$chapterSegments[2];
342
					break;
343
344
				default:
345
					//TODO: FALLBACK, ALERT ADMIN?
346
					$chapterData['number'] = $chapter;
347
					break;
348
			}
349
		}
350
		return $chapterData;
351
	}
352
353 1
	public function getTitleData(string $title_string) {
354 1
		$title_parts = explode(':--:', $title_string);
355 1
		$title_url   = $title_parts[0];
356
357 1
		$titleData = [];
358
		//FIXME: Using regex here is probably a terrible idea, but we're doing it anyway....
359
		//FIXME (ASAP): All the regex here should be checked to see if it even returns something, and we should probably error if possible.
360 1
		if($title_parts[1] == '0') {
361 1
			$data = $this->get_content('http://dynasty-scans.com/series/'.$title_url);
362
363 1
			preg_match('/<b>.*<\/b>/', $data, $matchesT);
364 1
			preg_match('/\/doujins\/[^"]+">(.+)?(?=<\/a>)<\/a>/', $data, $matchesD);
365 1
			$titleData['title'] = (!empty($matchesD) ? (substr($matchesD[1], 0, -7) !== 'Original' ? substr($matchesD[1], 0, -7).' - ' : '') : '') . substr($matchesT[0], 3, -4);
366
367 1
			$data = preg_replace('/^[\S\s]*(<dl class=\'chapter-list\'>[\S\s]*<\/dl>)[\S\s]*$/', '$1', $data);
368 1
			preg_match_all('/<dd>[\s\S]+?(?=<\/dd>)<\/dd>/', $data, $matches);
369 1
			$latest_chapter_html = array_pop($matches[0]);
370
371 1
			preg_match('/\/chapters\/([^"]+)/', $latest_chapter_html, $matches);
372 1
			$titleData['latest_chapter'] = substr($matches[1], strlen($title_url)+1);
373
			//FIXME: THIS IS A TEMP FIX, SEE https://github.com/DakuTree/manga-tracker/issues/58
374 1
			if(!$titleData['latest_chapter']) {
375
				log_message('error', 'DynastyScans::getTitleData cannot parse title properly as it contains oneshot. || URL: '.$title_url);
376
				return NULL;
377
			}
378
379 1
			preg_match('/<small>released (.*)<\/small>/', $latest_chapter_html, $matches);
380 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...
381
		} elseif($title_parts[1] == '1') {
382
			$data = $this->get_content('http://dynasty-scans.com/chapters/'.$title_url);
383
384
			preg_match('/<b>.*<\/b>/', $data, $matchesT);
385
			preg_match('/\/doujins\/[^"]+">(.+)?(?=<\/a>)<\/a>/', $data, $matchesD);
386
			$titleData['title'] = (!empty($matchesD) ? ($matchesD[1] !== 'Original' ? $matchesD[1].' - ' : '') : '') . substr($matchesT[0], 3, -4);
387
388
			$titleData['latest_chapter'] = 'oneshot'; //This will never change
389
390
			preg_match('/<i class="icon-calendar"><\/i> (.*)<\/span>/', $data, $matches);
391
			$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...
392
393
			//Oneshots are special, and really shouldn't need to be re-tracked
394
			//FIXME: We need to have a specific "no-track" complete param.
395
			$titleData['complete'] = 'Y';
396
		} 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...
397
			//FIXME: WTF?
398
		}
399 1
		return (!empty($titleData) ? $titleData : NULL);
400
	}
401
}
402
403 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...
404
	public function getFullTitleURL(string $title_url) : string {
405
		return "http://www.mangapanda.com/{$title_url}";
406
	}
407
408
	public function getChapterData(string $title_url, string $chapter) : array {
409
		return [
410
			'url'    => "http://www.mangapanda.com/{$title_url}/{$chapter}/",
411
			'number' => 'c'.$chapter
412
		];
413
	}
414
415
	public function isValidTitleURL(string $title_url) : bool {
416
		$success = (bool) preg_match('/^[a-z0-9-]+$/', $title_url);
417
		if(!$success) log_message('error', "Invalid Title URL (MangaPanda): {$title_url}");
418
		return $success;
419
	}
420
	public function isValidChapter(string $chapter) : bool {
421
		$success = (bool) preg_match('/^[0-9]+$/', $chapter);
422
		if(!$success) log_message('error', 'Invalid Chapter (MangaPanda): '.$chapter);
423
		return $success;
424
	}
425
426 1
	public function getTitleData(string $title_url) {
427 1
		$titleData = [];
428
429 1
		$fullURL = "http://www.mangapanda.com/{$title_url}";
430
431 1
		$data = $this->get_content($fullURL);
432 1
		if($data !== 'Can\'t find the manga series.') {
433
			//$data = preg_replace('/^[\S\s]*(<body id="body">[\S\s]*<\/body>)[\S\s]*$/', '$1', $data);
434
435 1
			$dom = new DOMDocument();
436 1
			libxml_use_internal_errors(true);
437 1
			$dom->loadHTML($data);
438 1
			libxml_use_internal_errors(false);
439
440 1
			$xpath = new DOMXPath($dom);
441
442 1
			$nodes_title = $xpath->query("//h2[@class='aname']");
443 1
			$nodes_row   = $xpath->query("(//table[@id='listing']/tr)[last()]");
444 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
445
				//This seems to be be the only viable way to grab the title...
446 1
				$titleData['title'] = $nodes_title[0]->nodeValue;
447
448 1
				$nodes_latest  = $xpath->query("td[2]", $nodes_row[0]);
449 1
				$nodes_chapter = $xpath->query("td[1]/a", $nodes_row[0]);
450
451 1
				$titleData['latest_chapter'] = preg_replace('/^.*\/([0-9]+)$/', '$1', (string) $nodes_chapter[0]->getAttribute('href'));
452 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...
453
			}
454
		} 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...
455
			//TODO: Throw ERRORS;
456
		}
457
458 1
		return (!empty($titleData) ? $titleData : NULL);
459
	}
460
}
461
462 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...
463
	public function getFullTitleURL(string $title_url) : string {
464
		return "https://mangastream.com/manga/{$title_url}/";
465
	}
466
467
	public function isValidTitleURL(string $title_url) : bool {
468
		$success = (bool) preg_match('/^[a-z0-9_]+$/', $title_url);
469
		if(!$success) log_message('error', "Invalid Title URL (MangaStream): {$title_url}");
470
		return $success;
471
	}
472
	public function isValidChapter(string $chapter) : bool {
473
		$success = (bool) preg_match('/^(.*?)\/[0-9]+$/', $chapter);
474
		if(!$success) log_message('error', 'Invalid Chapter (MangaStream): '.$chapter);
475
		return $success;
476
	}
477
478
	public function getChapterData(string $title_url, string $chapter) : array {
479
		return [
480
			'url'    => "https://mangastream.com/r/{$title_url}/{$chapter}",
481
			'number' => 'c'.explode('/', $chapter)[0]
482
		];
483
	}
484
485
	public function getTitleData(string $title_url) {
486
		$titleData = [];
487
488
		$fullURL = $this->getFullTitleURL($title_url);
489
490
		$data = $this->get_content($fullURL);
491
		if($data !== 'Can\'t find the manga series.') {
492
			//$data = preg_replace('/^[\S\s]*(<body id="body">[\S\s]*<\/body>)[\S\s]*$/', '$1', $data);
493
494
			$dom = new DOMDocument();
495
			libxml_use_internal_errors(true);
496
			$dom->loadHTML($data);
497
			libxml_use_internal_errors(false);
498
499
			$xpath = new DOMXPath($dom);
500
501
			$nodes_title = $xpath->query("//div[contains(@class, 'content')]/div[1]/h1");
502
			$nodes_row   = $xpath->query("//div[contains(@class, 'content')]/div[1]/table/tr[2]"); //Missing tbody here..
503
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
504
				$titleData['title'] = $nodes_title[0]->nodeValue;
505
506
				$nodes_latest  = $xpath->query("td[2]", $nodes_row[0]);
507
				$nodes_chapter = $xpath->query("td[1]/a", $nodes_row[0]);
508
509
				$titleData['latest_chapter'] = preg_replace('/^.*\/(.*?\/[0-9]+)\/[0-9]+$/', '$1', (string) $nodes_chapter[0]->getAttribute('href'));
510
				$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...
511
			}
512
		} 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...
513
			//TODO: Throw ERRORS;
514
		}
515
516
		return (!empty($titleData) ? $titleData : NULL);
517
	}
518
}
519
520
class WebToons extends Site_Model {
521
	/* Webtoons.com has a very weird and pointless URL format.
522
	   TITLE URL:   /#LANG#/#GENRE#/#TITLE#/list?title_no=#TITLEID#
523
	   RSS URL:     /#LANG#/#GENRE#/#TITLE#/rss?title_no=#TITLEID#
524
	   CHAPTER URL: /#LANG#/#GENRE#/#TITLE#/#CHAPTER#/viewer?title_no=#TITLEID#&episode_no=#CHAPTERID#
525
526
	   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).
527
	   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.
528
	   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.
529
530
	   FORMATS:
531
	   TITLE_URL: ID:--:LANG:--:TITLE:--:GENRE
532
	   CHAPTER:   ID:--:CHAPTER_N
533
	*/
534
	//private $validLang = ['en', 'zh-hant', 'zh-hans', 'th', 'id'];
535
536
	public function getFullTitleURL(string $title_url) : string {
537
		$title_parts = explode(':--:', $title_url);
538
		return "http://www.webtoons.com/{$title_parts[1]}/{$title_parts[3]}/{$title_parts[2]}/list?title_no={$title_parts[0]}/";
539
	}
540
541
	public function isValidTitleURL(string $title_url) : bool {
542
		$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);
543
		if(!$success) log_message('error', "Invalid Title URL (WebToons): {$title_url}");
544
		return $success;
545
	}
546
	public function isValidChapter(string $chapter) : bool {
547
		$success = (bool) preg_match('/^[0-9]+:--:.*$/', $chapter);
548
		if(!$success) log_message('error', 'Invalid Chapter (WebToons): '.$chapter);
549
		return $success;
550
	}
551
552
	public function getChapterData(string $title_url, string $chapter) : array {
553
		$title_parts   = explode(':--:', $title_url);
554
		$chapter_parts = explode(':--:', $chapter);
555
556
		return [
557
			'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]}",
558
			'number' => $chapter_parts[1] //TODO: Possibly replace certain formats in here? Since webtoons doesn't have a standard chapter format
559
		];
560
	}
561
562 1
	public function getTitleData(string $title_url) {
563 1
		$titleData = [];
564
565 1
		$title_parts = explode(':--:', $title_url);
566 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...
567
568 1
		$data = $this->get_content($fullURL);
569 1
		if($data !== 'Can\'t find the manga series.') {
570 1
			$xml = simplexml_load_string($data) or die("Error: Cannot create object");
571 1
			if(isset($xml->channel->item[0])) {
572 1
				$titleData['title'] = trim((string) $xml->channel->title);
573
574 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...
575 1
				$titleData['latest_chapter'] = preg_replace('/^.*?([0-9]+)$/', '$1', $chapterURLSegments[7]) . ':--:' . $chapterURLSegments[6];
576 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...
577
			}
578
		} 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...
579
			//TODO: Throw ERRORS;
580
		}
581
582 1
		return (!empty($titleData) ? $titleData : NULL);
583
	}
584
}
585
586
class KissManga extends Site_Model {
587
	/* 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.
588
	   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.
589
590
	   To generate this cookie, we need three variables. Two are static, but the other is generated by randomly generated JS on the page.
591
	   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.
592
	   The other option is using regex, but that is a rabbit hole I don't want to touch with a ten-foot pole.
593
594
	   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.
595
	   The cookie has a length of 1 year, but I don't think it actually lasts that long, so we update every 6hours instead.
596
	   I should probably also mention that the cookie generated also uses your user-agent, so if it changes the cookie will break.
597
	*/
598
599
	public function getFullTitleURL(string $title_url) : string {
600
		return "http://kissmanga.com/Manga/{$title_url}";
601
	}
602
603
	public function isValidTitleURL(string $title_url) : bool {
604
		$success = (bool) preg_match('/^[A-Za-z0-9-]+/', $title_url);
605
		if(!$success) log_message('error', "Invalid Title URL (KissManga): {$title_url}");
606
		return $success;
607
	}
608
	public function isValidChapter(string $chapter) : bool {
609
		$success = (bool) preg_match('/^.*?:--:[0-9]+$/', $chapter);
610
		if(!$success) log_message('error', 'Invalid Chapter (KissManga): '.$chapter);
611
		return $success;
612
	}
613
614 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...
615
		$chapter_parts = explode(':--:', $chapter);
616
617
		return [
618
			'url'    => "http://kissmanga.com/Manga/{$title_url}/{$chapter_parts[0]}?id={$chapter_parts[1]}",
619
			//FIXME: KM has an extremely inconsistant chapter format which makes it difficult to parse.
620
			'number' => /*preg_replace('/--.*?$/', '', */$chapter_parts[0]/*)*/
621
		];
622
	}
623
624
	public function getTitleData(string $title_url) {
625
		$titleData = [];
626
627
		//Check if cookiejar is a day old (so we can know if something went wrong)
628
		$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...
629
		$cookie_last_updated = filemtime($cookiejar_path);
630
		if($cookie_last_updated && ((time() - 86400) < $cookie_last_updated)) {
631
632
			$fullURL = $this->getFullTitleURL($title_url);
633
			$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...
634
			if(strpos($data, 'containerRoot') !== FALSE) {
635
				//FIXME: For whatever reason, we can't grab the entire div without simplexml shouting at us
636
				$data = preg_replace('/^[\S\s]*(<div id="leftside">[\S\s]*)<div id="rightside">[\S\s]*$/', '$1', $data);
637
638
				$dom = new DOMDocument();
639
				libxml_use_internal_errors(true);
640
				$dom->loadHTML($data);
641
				libxml_use_internal_errors(false);
642
643
				$xpath = new DOMXPath($dom);
644
645
				$nodes_title = $xpath->query("//a[@class='bigChar']");
646
				$nodes_row   = $xpath->query("//table[@class='listing']/tr[3]");
647
				if($nodes_title->length === 1 && $nodes_row->length === 1) {
648
					$titleData['title'] = $nodes_title[0]->textContent;
649
650
					$nodes_latest  = $xpath->query("td[2]", $nodes_row[0]);
651
					$nodes_chapter = $xpath->query("td[1]/a", $nodes_row[0]);
652
653
					$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...
654
					$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...
655
					$titleData['latest_chapter'] = $chapterURLSegments[3] . ':--:' . preg_replace('/.*?([0-9]+)$/', '$1', $link);
656
					$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...
657
				}
658
			} 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...
659
				//TODO: Throw ERRORS;
660
			}
661
		} 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...
662
			//Do nothing, wait until next update.
663
			//TODO: NAG ADMIN??
664
		}
665
666
		return (!empty($titleData) ? $titleData : NULL);
667
	}
668
}
669
670
class KireiCake extends Site_Model {
671 1
	public function getFullTitleURL(string $title_url) : string {
672 1
		return "https://reader.kireicake.com/series/{$title_url}";
673
	}
674
675
	public function isValidTitleURL(string $title_url) : bool {
676
		$success = (bool) preg_match('/^[a-z0-9_]+/', $title_url);
677
		if(!$success) log_message('error', "Invalid Title URL (KireiCake): {$title_url}");
678
		return $success;
679
	}
680
	public function isValidChapter(string $chapter) : bool {
681
		$success = (bool) preg_match('/^en\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+)?)?)?$/', $chapter);
682
		if(!$success) log_message('error', 'Invalid Chapter (KireiCake): '.$chapter);
683
		return $success;
684
	}
685
686
	public function getChapterData(string $title_url, string $chapter) : array {
687
		//LANG/VOLUME/CHAPTER/CHAPTER_EXTRA(/page/)
688
		$chapter_parts = explode('/', $chapter);
689
		return [
690
			'url'    => "https://reader.kireicake.com/read/{$title_url}/{$chapter}",
691
			'number' => ($chapter_parts[1] !== '0' ? "v{$chapter_parts[1]}/" : '') . "c{$chapter_parts[2]}" . (isset($chapter_parts[3]) ? ".{$chapter_parts[3]}" : '')/*)*/
692
		];
693
	}
694
695 1
	public function getTitleData(string $title_url) {
696 1
		$titleData = [];
697
698 1
		$fullURL = $this->getFullTitleURL($title_url);
699 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...
700 1
		if(strpos($data, '404 Page Not Found') === FALSE) {
701
			//FIXME: For whatever reason, we can't grab the entire div without simplexml shouting at us
702 1
			$data = preg_replace('/^[\S\s]*(<article>[\S\s]*)<\/article>[\S\s]*$/', '$1', $data);
703
704 1
			$dom = new DOMDocument();
705 1
			libxml_use_internal_errors(true);
706 1
			$dom->loadHTML($data);
707 1
			libxml_use_internal_errors(false);
708
709 1
			$xpath = new DOMXPath($dom);
710
711 1
			$nodes_title = $xpath->query("//div[@class='large comic']/h1[@class='title']");
712 1
			$nodes_row   = $xpath->query("//div[@class='list']/div[@class='element'][1]");
713 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
714 1
				$titleData['title'] = trim($nodes_title[0]->textContent);
715
716
717 1
				$nodes_latest  = $xpath->query("div[@class='meta_r']", $nodes_row[0]);
718 1
				$nodes_chapter = $xpath->query("div[@class='title']/a", $nodes_row[0]);
719
720 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...
721 1
				$titleData['latest_chapter'] = preg_replace('/.*\/read\/.*?\/(.*?)\/$/', '$1', $link);
722 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...
723
			}
724
		} 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...
725
			//TODO: Throw ERRORS;
726
		}
727
728 1
		return (!empty($titleData) ? $titleData : NULL);
729
	}
730
}
731
732
class GameOfScanlation extends Site_Model {
733
	public function getFullTitleURL(string $title_url) : string {
734
		return "https://gameofscanlation.moe/forums/{$title_url}/";
735
	}
736
737
	public function isValidTitleURL(string $title_url) : bool {
738
		$success = (bool) preg_match('/^[a-z0-9-]+/', $title_url);
739
		if(!$success) log_message('error', "Invalid Title URL (GameOfScanlation): {$title_url}");
740
		return $success;
741
	}
742
	public function isValidChapter(string $chapter) : bool {
743
		$success = (bool) preg_match('/^[a-z0-9\.-]+$/', $chapter);
744
		if(!$success) log_message('error', 'Invalid Chapter (GameOfScanlation): '.$chapter);
745
		return $success;
746
	}
747
748
	public function getChapterData(string $title_url, string $chapter) : array {
749
		return [
750
			'url'    => "https://gameofscanlation.moe/projects/".preg_replace("/\\.[0-9]+$/", "", $title_url).'/'.$chapter.'/',
751
			'number' => preg_replace("/chapter-/", "c", preg_replace("/\\.[0-9]+$/", "", $chapter))
752
		];
753
	}
754
755
	public function getTitleData(string $title_url) {
756
		$titleData = [];
757
758
		$fullURL = $this->getFullTitleURL($title_url);
759
		$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...
760
		if(strpos($data, '404 Page Not Found') === FALSE) {
761
			//$data = preg_replace('/^[\S\s]*(<ol[\S\s]*)<\/ol>[\S\s]*$/', '$1', $data);
762
763
			$dom = new DOMDocument();
764
			libxml_use_internal_errors(true);
765
			$dom->loadHTML($data);
766
			libxml_use_internal_errors(false);
767
768
			$xpath = new DOMXPath($dom);
769
770
			$nodes_title = $xpath->query("//meta[@property='og:title']");
771
			$nodes_row   = $xpath->query("//ol[@class='discussionListItems']/li[1]/div[@class='home_list']/ul/li/div[@class='list_press_text']");
772
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
773
				$titleData['title'] = html_entity_decode($nodes_title[0]->getAttribute('content'));
774
775
				$nodes_latest  = $xpath->query("p[@class='author']/span|p[@class='author']/abbr", $nodes_row[0]);
776
				$nodes_chapter = $xpath->query("p[@class='text_work']/a", $nodes_row[0]);
777
778
				$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...
779
				$titleData['latest_chapter'] = preg_replace('/^projects\/.*?\/(.*?)\/$/', '$1', $link);
780
				$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...
781
			} else {
782
				log_message('error', "GameOfScanlation: Unable to find nodes.");
783
				return NULL;
784
			}
785
		} 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...
786
			//TODO: Throw ERRORS;
787
		}
788
789
		return (!empty($titleData) ? $titleData : NULL);
790
	}
791
}
792
793
class MangaCow extends Site_Model {
794
	public function getFullTitleURL(string $title_url) : string {
795
		return "http://mngcow.co/{$title_url}/";
796
	}
797
798
	public function isValidTitleURL(string $title_url) : bool {
799
		$success = (bool) preg_match('/^[a-zA-Z0-9_]+/', $title_url);
800
		if(!$success) log_message('error', "Invalid Title URL (MangaCow): {$title_url}");
801
		return $success;
802
	}
803
	public function isValidChapter(string $chapter) : bool {
804
		$success = (bool) preg_match('/^[0-9]+$/', $chapter);
805
		if(!$success) log_message('error', 'Invalid Chapter (MangaCow): '.$chapter);
806
		return $success;
807
	}
808
809
	public function getChapterData(string $title_url, string $chapter) : array {
810
		return [
811
			'url'    => $this->getFullTitleURL($title_url).$chapter.'/',
812
			'number' => "c{$chapter}"
813
		];
814
	}
815
816
	public function getTitleData(string $title_url) {
817
		$titleData = [];
818
819
		$fullURL = $this->getFullTitleURL($title_url);
820
		$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...
821
		if(strpos($data, '404 Page Not Found') === FALSE) {
822
			$dom = new DOMDocument();
823
			libxml_use_internal_errors(true);
824
			$dom->loadHTML($data);
825
			libxml_use_internal_errors(false);
826
827
			$xpath = new DOMXPath($dom);
828
829
			$nodes_title = $xpath->query("//h4");
830
			$nodes_row   = $xpath->query("//ul[contains(@class, 'mng_chp')]/li[1]/a[1]");
831
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
832
				$titleData['title'] = trim($nodes_title[0]->nodeValue);
833
834
				$nodes_chapter = $nodes_row;
835
				$nodes_latest  = $xpath->query("b[@class='dte']", $nodes_row[0]);
836
837
				$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...
838
				$titleData['latest_chapter'] = preg_replace('/^.*\/([0-9]+)\/$/', '$1', $link);
839
				$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...
840
			} else {
841
				log_message('error', "MangaCow: Unable to find nodes.");
842
				return NULL;
843
			}
844
		} 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...
845
			//TODO: Throw ERRORS;
846
		}
847
848
		return (!empty($titleData) ? $titleData : NULL);
849
	}
850
}
851