Completed
Push — master ( 8be713...a37140 )
by Angus
02:57
created

SenseScans::getFullTitleURL()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 3
Ratio 100 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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

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

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

Loading history...
859 1
	public function getFullTitleURL(string $title_url) : string {
860 1
		return "http://reader.seaotterscans.com/series/{$title_url}";
861
	}
862
863
	public function isValidTitleURL(string $title_url) : bool {
864
		$success = (bool) preg_match('/^[a-z0-9_]+/', $title_url);
865
		if(!$success) log_message('error', "Invalid Title URL (SeaOtterScans): {$title_url}");
866
		return $success;
867
	}
868
	public function isValidChapter(string $chapter) : bool {
869
		$success = (bool) preg_match('/^en\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+)?)?)?$/', $chapter);
870
		if(!$success) log_message('error', 'Invalid Chapter (SeaOtterScans): '.$chapter);
871
		return $success;
872
	}
873
874
	public function getChapterData(string $title_url, string $chapter) : array {
875
		//LANG/VOLUME/CHAPTER/CHAPTER_EXTRA(/page/)
876
		$chapter_parts = explode('/', $chapter);
877
		return [
878
			'url'    => "https://reader.seaotterscans.com/read/{$title_url}/{$chapter}",
879
			'number' => ($chapter_parts[1] !== '0' ? "v{$chapter_parts[1]}/" : '') . "c{$chapter_parts[2]}" . (isset($chapter_parts[3]) ? ".{$chapter_parts[3]}" : '')/*)*/
880
		];
881
	}
882
883 1
	public function getTitleData(string $title_url) {
884 1
		$titleData = [];
885
886 1
		$fullURL = $this->getFullTitleURL($title_url);
887 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...
888 1
		if(strpos($data, '404 Page Not Found') === FALSE) {
889
			//FIXME: For whatever reason, we can't grab the entire div without simplexml shouting at us
890 1
			$data = preg_replace('/^[\S\s]*(<article[\S\s]*)<\/article>[\S\s]*$/', '$1', $data);
891
892 1
			$dom = new DOMDocument();
893 1
			libxml_use_internal_errors(true);
894 1
			$dom->loadHTML($data);
895 1
			libxml_use_internal_errors(false);
896
897 1
			$xpath = new DOMXPath($dom);
898
899 1
			$nodes_title = $xpath->query("//div[@class='large comic']/h1[@class='title']");
900
901
			//SOO sometimes uses volume groups which are above recent chapters (if they haven't been grouped yet), so make sure we check for both.
902 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...
903 1
			if($nodes_row->length !== 1) {
904 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...
905
			}
906 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
907 1
				$titleData['title'] = trim($nodes_title[0]->textContent);
908
909
910 1
				$nodes_latest  = $xpath->query("div[@class='meta_r']", $nodes_row[0]);
911 1
				$nodes_chapter = $xpath->query("div[@class='title']/a", $nodes_row[0]);
912
913 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...
914 1
				$titleData['latest_chapter'] = preg_replace('/.*\/read\/.*?\/(.*?)\/$/', '$1', $link);
915 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...
916
			}
917
		} 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...
918
			//TODO: Throw ERRORS;
919
		}
920
921 1
		return (!empty($titleData) ? $titleData : NULL);
922
	}
923
}
924
925 View Code Duplication
class HelveticaScans extends Site_Model {
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

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

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

Loading history...
926 1
	public function getFullTitleURL(string $title_url) : string {
927 1
		return "http://helveticascans.com/reader/series/{$title_url}";
928
	}
929
930
	public function isValidTitleURL(string $title_url) : bool {
931
		$success = (bool) preg_match('/^[a-z0-9_]+/', $title_url);
932
		if(!$success) log_message('error', "Invalid Title URL (HelveticaScans): {$title_url}");
933
		return $success;
934
	}
935
	public function isValidChapter(string $chapter) : bool {
936
		$success = (bool) preg_match('/^en\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+)?)?)?$/', $chapter);
937
		if(!$success) log_message('error', 'Invalid Chapter (HelveticaScans): '.$chapter);
938
		return $success;
939
	}
940
941
	public function getChapterData(string $title_url, string $chapter) : array {
942
		//LANG/VOLUME/CHAPTER/CHAPTER_EXTRA(/page/)
943
		$chapter_parts = explode('/', $chapter);
944
		return [
945
			'url'    => "http://helveticascans.com/reader/read/{$title_url}/{$chapter}",
946
			'number' => ($chapter_parts[1] !== '0' ? "v{$chapter_parts[1]}/" : '') . "c{$chapter_parts[2]}" . (isset($chapter_parts[3]) ? ".{$chapter_parts[3]}" : '')/*)*/
947
		];
948
	}
949
950 1
	public function getTitleData(string $title_url) {
951 1
		$titleData = [];
952
953 1
		$fullURL = $this->getFullTitleURL($title_url);
954 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...
955 1
		if(strpos($data, '404 Page Not Found') === FALSE) {
956
			//FIXME: For whatever reason, we can't grab the entire div without simplexml shouting at us
957 1
			$data = preg_replace('/^[\S\s]*(<article[\S\s]*)<\/article>[\S\s]*$/', '$1', $data);
958
959 1
			$dom = new DOMDocument();
960 1
			libxml_use_internal_errors(true);
961 1
			$dom->loadHTML($data);
962 1
			libxml_use_internal_errors(false);
963
964 1
			$xpath = new DOMXPath($dom);
965
966 1
			$nodes_title = $xpath->query("//div[@class='large comic']/h1[@class='title']");
967 1
			$nodes_row   = $xpath->query("//div[@class='list']/div[@class='group']/div[@class='title' and text() = 'Chapters']/following-sibling::div[@class='element'][1]");
968 1
			if($nodes_row->length !== 1) {
969
				$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...
970
			}
971 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
972 1
				$titleData['title'] = trim($nodes_title[0]->textContent);
973
974
975 1
				$nodes_latest  = $xpath->query("div[@class='meta_r']", $nodes_row[0]);
976 1
				$nodes_chapter = $xpath->query("div[@class='title']/a", $nodes_row[0]);
977
978 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...
979 1
				$titleData['latest_chapter'] = preg_replace('/.*\/read\/.*?\/(.*?)\/$/', '$1', $link);
980 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...
981
			}
982
		} 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...
983
			//TODO: Throw ERRORS;
984
		}
985
986 1
		return (!empty($titleData) ? $titleData : NULL);
987
	}
988
}
989 View Code Duplication
class SenseScans extends Site_Model {
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

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

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

Loading history...
990 1
	public function getFullTitleURL(string $title_url) : string {
991 1
		return "http://reader.sensescans.com/series/{$title_url}";
992
	}
993
994
	public function isValidTitleURL(string $title_url) : bool {
995
		$success = (bool) preg_match('/^[a-z0-9_]+/', $title_url);
996
		if(!$success) log_message('error', "Invalid Title URL (SenseScans): {$title_url}");
997
		return $success;
998
	}
999
	public function isValidChapter(string $chapter) : bool {
1000
		$success = (bool) preg_match('/^en\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+(?:\/[0-9]+)?)?)?$/', $chapter);
1001
		if(!$success) log_message('error', 'Invalid Chapter (SenseScans): '.$chapter);
1002
		return $success;
1003
	}
1004
1005
	public function getChapterData(string $title_url, string $chapter) : array {
1006
		//LANG/VOLUME/CHAPTER/CHAPTER_EXTRA(/page/)
1007
		$chapter_parts = explode('/', $chapter);
1008
		return [
1009
			'url'    => "http://reader.sensescans.com/read/{$title_url}/{$chapter}",
1010
			'number' => ($chapter_parts[1] !== '0' ? "v{$chapter_parts[1]}/" : '') . "c{$chapter_parts[2]}" . (isset($chapter_parts[3]) ? ".{$chapter_parts[3]}" : '')/*)*/
1011
		];
1012
	}
1013
1014 1
	public function getTitleData(string $title_url) {
1015 1
		$titleData = [];
1016
1017 1
		$fullURL = $this->getFullTitleURL($title_url);
1018 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...
1019 1
		if(strpos($data, '404 Page Not Found') === FALSE) {
1020
			//FIXME: For whatever reason, we can't grab the entire div without simplexml shouting at us
1021 1
			$data = preg_replace('/^[\S\s]*(<article[\S\s]*)<\/article>[\S\s]*$/', '$1', $data);
1022
1023 1
			$dom = new DOMDocument();
1024 1
			libxml_use_internal_errors(true);
1025 1
			$dom->loadHTML($data);
1026 1
			libxml_use_internal_errors(false);
1027
1028 1
			$xpath = new DOMXPath($dom);
1029
1030 1
			$nodes_title = $xpath->query("//div[@class='large comic']/h1[@class='title']");
1031 1
			$nodes_row   = $xpath->query("//div[@class='list']/div[@class='group']/div[@class='title' and text() = 'Chapters']/following-sibling::div[@class='element'][1]");
1032 1
			if($nodes_row->length !== 1) {
1033
				$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...
1034
			}
1035 1
			if($nodes_title->length === 1 && $nodes_row->length === 1) {
1036 1
				$titleData['title'] = trim($nodes_title[0]->textContent);
1037
1038
1039 1
				$nodes_latest  = $xpath->query("div[@class='meta_r']", $nodes_row[0]);
1040 1
				$nodes_chapter = $xpath->query("div[@class='title']/a", $nodes_row[0]);
1041
1042 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...
1043 1
				$titleData['latest_chapter'] = preg_replace('/.*\/read\/.*?\/(.*?)\/$/', '$1', $link);
1044 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...
1045
			}
1046
		} 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...
1047
			//TODO: Throw ERRORS;
1048
		}
1049
1050 1
		return (!empty($titleData) ? $titleData : NULL);
1051
	}
1052
}
1053