Completed
Push — master ( 5510c9...ea618d )
by Angus
06:00
created

SeaOtterScans::getFullTitleURL()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
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 96
	public function __construct() {
5 96
		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, SeaOtterScans, Site_Model, Sites_Model, Tracker_Model, User_Model, User_Options_Model, WebToons. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

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

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

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

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

Available Fixes

  1. Change the type-hint for the parameter:

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

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

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
6
7 96
		$this->load->database();
8 96
	}
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 8
	protected function get_content(string $url, string $cookie_string = "", string $cookiejar_path = "", bool $follow_redirect = FALSE){
20 8
		$ch = curl_init();
21 8
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
22 8
		curl_setopt($ch, CURLOPT_ENCODING , "gzip");
23
24 8
		if($follow_redirect)        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
25
26 8
		if(!empty($cookie_string))  curl_setopt($ch, CURLOPT_COOKIE, $cookie_string);
27 8
		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 8
		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 8
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); //FIXME: This isn't safe, but it allows us to grab SSL URLs
33
34 8
		curl_setopt($ch, CURLOPT_URL, $url);
35 8
		$data = curl_exec($ch);
36 8
		curl_close($ch);
37 8
		return $data;
38
	}
39
}
40
class Sites_Model extends CI_Model {
41
	public $MangaFox;
42
	public $MangaHere;
43
	public $Batoto;
44
	public $DynastyScans;
45
	public $MangaPanda;
46
	public $MangaStream;
47
	public $WebToons;
48
	public $KissManga;
49
	public $KireiCake;
50
	public $GameOfScanlation;
51
	public $MangaCow;
52
	public $SeaOtterScans;
53
54 96
	public function __construct() {
55 96
		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, SeaOtterScans, Site_Model, Sites_Model, Tracker_Model, User_Model, User_Options_Model, WebToons. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

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

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

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

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

Available Fixes

  1. Change the type-hint for the parameter:

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

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

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

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

To visualize

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

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

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

will produce no issues.

Loading history...
842
			} else {
843
				log_message('error', "MangaCow: Unable to find nodes.");
844 1
				return NULL;
845
			}
846
		} 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...
847
			//TODO: Throw ERRORS;
848
		}
849
850 1
		return (!empty($titleData) ? $titleData : NULL);
851
	}
852
}
853
854
855
class SeaOtterScans extends Site_Model {
856 1
	public function getFullTitleURL(string $title_url) : string {
857 1
		return "http://reader.seaotterscans.com//series/{$title_url}";
858
	}
859
860
	public function isValidTitleURL(string $title_url) : bool {
861
		$success = (bool) preg_match('/^[a-z0-9_]+/', $title_url);
862
		if(!$success) log_message('error', "Invalid Title URL (SeaOtterScans): {$title_url}");
863
		return $success;
864
	}
865
	public function isValidChapter(string $chapter) : bool {
866
		$success = (bool) preg_match('/^en\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+)?)?)?$/', $chapter);
867
		if(!$success) log_message('error', 'Invalid Chapter (SeaOtterScans): '.$chapter);
868
		return $success;
869
	}
870
871 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...
872
		//LANG/VOLUME/CHAPTER/CHAPTER_EXTRA(/page/)
873
		$chapter_parts = explode('/', $chapter);
874
		return [
875
			'url'    => "https://reader.seaotterscans.com/read/{$title_url}/{$chapter}",
876
			'number' => ($chapter_parts[1] !== '0' ? "v{$chapter_parts[1]}/" : '') . "c{$chapter_parts[2]}" . (isset($chapter_parts[3]) ? ".{$chapter_parts[3]}" : '')/*)*/
877
		];
878
	}
879
880 1
	public function getTitleData(string $title_url) {
881 1
		$titleData = [];
882
883 1
		$fullURL = $this->getFullTitleURL($title_url);
884 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...
885 1
		if(strpos($data, '404 Page Not Found') === FALSE) {
886
			//FIXME: For whatever reason, we can't grab the entire div without simplexml shouting at us
887 1
			$data = preg_replace('/^[\S\s]*(<article[\S\s]*)<\/article>[\S\s]*$/', '$1', $data);
888
889 1
			$dom = new DOMDocument();
890 1
			libxml_use_internal_errors(true);
891 1
			$dom->loadHTML($data);
892 1
			libxml_use_internal_errors(false);
893
894 1
			$xpath = new DOMXPath($dom);
895
896 1
			$nodes_title = $xpath->query("//div[@class='large comic']/h1[@class='title']");
897
898
			//SOO sometimes uses volume groups which are above recent chapters (if they haven't been grouped yet), so make sure we check for both.
899 1
			$nodes_row   = $xpath->query("//div[@class='list']/div[@class='group']/div[@class='title' and text() = 'Chapters']/following-sibling::div[@class='element'][1]");
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 3 spaces

This check looks for improperly formatted assignments.

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

To illustrate:

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

will have no issues, while

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

will report issues in lines 1 and 2.

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

This check looks for improperly formatted assignments.

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

To illustrate:

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

will have no issues, while

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

will report issues in lines 1 and 2.

Loading history...
902
			}
903 1 View Code Duplication
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across 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...
904 1
				$titleData['title'] = trim($nodes_title[0]->textContent);
905
906
907 1
				$nodes_latest  = $xpath->query("div[@class='meta_r']", $nodes_row[0]);
908 1
				$nodes_chapter = $xpath->query("div[@class='title']/a", $nodes_row[0]);
909
910 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...
911 1
				$titleData['latest_chapter'] = preg_replace('/.*\/read\/.*?\/(.*?)\/$/', '$1', $link);
912 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...
913
			}
914
		} 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...
915
			//TODO: Throw ERRORS;
916
		}
917
918 1
		return (!empty($titleData) ? $titleData : NULL);
919
	}
920
}
921