Completed
Push — master ( bad5d9...4e991e )
by Angus
03:11
created

GameOfScanlation::getFullTitleURL()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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