Completed
Push — master ( 1aabad...056f30 )
by Angus
02:36
created

Tracker_Admin_Model   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 225
Duplicated Lines 11.11 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 25
loc 225
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
wmc 30
lcom 1
cbo 5

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
B updateLatestChapters() 9 78 6
D updateCustom() 11 41 9
C updateTitles() 5 51 8
B getNextUpdateTime() 0 33 6

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php declare(strict_types=1); defined('BASEPATH') OR exit('No direct script access allowed');
2
3
class Tracker_Admin_Model extends Tracker_Base_Model {
4 115
	public function __construct() {
5 115
		parent::__construct();
6 115
	}
7
8
	/**
9
	 * Checks for any series that haven't updated in 16 hours and updates them.
10
	 * This is ran every 6 hours via a cron job.
11
	 */
12
	public function updateLatestChapters() {
13
		// @formatter:off
14
		$query = $this->db
15
			->select('
16
				tracker_titles.id,
17
				tracker_titles.title,
18
				tracker_titles.title_url,
19
				tracker_titles.status,
20
				tracker_sites.site,
21
				tracker_sites.site_class,
22
				tracker_sites.status,
23
				tracker_titles.latest_chapter,
24
				tracker_titles.last_updated,
25
				from_unixtime(MAX(auth_users.last_login)) AS timestamp
26
			')
27
			->from('tracker_titles')
28
			->join('tracker_sites', 'tracker_sites.id = tracker_titles.site_id', 'left')
29
			->join('tracker_chapters', 'tracker_titles.id = tracker_chapters.title_id', 'left')
30
			->join('auth_users', 'tracker_chapters.user_id = auth_users.id', 'left')
31
			->where('tracker_sites.status', 'enabled')
32
			->group_start()
33
				//Check if title is marked as on-going...
34
				->where('tracker_titles.status', 0) //TODO: Each title should have specific interval time?
35
				//AND matches one of where queries below
36
				->group_start()
37
					//Then check if it's NULL (only occurs for new series)
38
					->where('latest_chapter', NULL)
39
					//OR if it hasn't updated within the past 12 hours AND isn't a custom update site
40
					->or_group_start()
41
						->where('tracker_sites.use_custom', 'N')
42
						->where('last_checked < DATE_SUB(NOW(), INTERVAL 12 HOUR)')
43
					->group_end()
44
					//OR it is a custom update site and hasn't updated within the past 36 hours
45
					->or_where('last_checked < DATE_SUB(NOW(), INTERVAL 36 HOUR)')
46
				->group_end()
47
			->group_end()
48
			->or_group_start()
49
				//Check if title is marked as complete...
50
				->where('tracker_titles.status', 1)
51
				//Then check if it hasn't updated within the past week
52
				->where('last_checked < DATE_SUB(NOW(), INTERVAL 1 WEEK)')
53
			->group_end()
54
			//Status 2 (One-shot) & 255 (Ignore) are both not updated intentionally.
55
56
			->group_by('tracker_titles.id, tracker_chapters.active')
57
			//Check if the series is actually being tracked by someone
58
			->having('timestamp IS NOT NULL')
59
			//AND if it's currently marked as active by the user
60
			->having('tracker_chapters.active', 'Y')
61
			//AND if they have been active in the last 120 hours (5 days)
62
			->having('timestamp > DATE_SUB(NOW(), INTERVAL 120 HOUR)')
63
			->order_by('tracker_titles.title', 'ASC')
64
			->get();
65
		// @formatter:on
66
67
		if($query->num_rows() > 0) {
68
			foreach ($query->result() as $row) {
69
				print "> {$row->title} <{$row->site_class}>"; //Print this prior to doing anything so we can more easily find out if something went wrong
70
				$titleData = $this->sites->{$row->site_class}->getTitleData($row->title_url);
71
				if(is_array($titleData) && !is_null($titleData['latest_chapter'])) {
72
					//FIXME: "At the moment" we don't seem to be doing anything with TitleData['last_updated'].
73
					//       Should we even use this? Y/N
74 View Code Duplication
					if($this->Tracker->title->updateByID((int) $row->id, $titleData['latest_chapter'])) {
75
						//Make sure last_checked is always updated on successful run.
76
						//CHECK: Is there a reason we aren't just doing this in updateByID?
77
						$this->db->set('last_checked', 'CURRENT_TIMESTAMP', FALSE)
78
						         ->where('id', $row->id)
79
						         ->update('tracker_titles');
80
81
						print " - ({$titleData['latest_chapter']})\n";
82
					}
83
				} else {
84
					log_message('error', "{$row->title} failed to update successfully");
85
					print " - FAILED TO PARSE\n";
86
				}
87
			}
88
		}
89
	}
90
91
	/**
92
	 * Checks for any sites which support custom updating (usually via following lists) and updates them.
93
	 * This is run hourly.
94
	 */
95
	public function updateCustom() {
96
		$query = $this->db->select('*')
97
		                  ->from('tracker_sites')
98
		                  ->where('status', 'enabled')
99
		                  ->get();
100
101
		$sites = $query->result_array();
102
		foreach ($sites as $site) {
103
			if($titleDataList = $this->sites->{$site['site_class']}->doCustomUpdate()) {
104
				foreach ($titleDataList as $titleURL => $titleData) {
105
					print "> {$titleData['title']} <{$site['site_class']}>"; //Print this prior to doing anything so we can more easily find out if something went wrong
106
					if(is_array($titleData) && !is_null($titleData['latest_chapter'])) {
107
						if($dbTitleData = $this->Tracker->title->getID($titleURL, (int) $site['id'], FALSE, TRUE)) {
108
							if($this->sites->{$site['site_class']}->doCustomCheck($dbTitleData['latest_chapter'], $titleData['latest_chapter'])) {
109
								$titleID = $dbTitleData['id'];
110 View Code Duplication
								if($this->Tracker->title->updateByID((int) $titleID, $titleData['latest_chapter'])) {
111
									//Make sure last_checked is always updated on successful run.
112
									//CHECK: Is there a reason we aren't just doing this in updateByID?
113
									$this->db->set('last_checked', 'CURRENT_TIMESTAMP', FALSE)
114
									         ->where('id', $titleID)
115
									         ->update('tracker_titles');
116
117
									print " - ({$titleData['latest_chapter']})\n";
118
								} else {
119
									print " - Title doesn't exist? ($titleID)\n";
120
								}
121
							} else {
122
								print " - Failed Check.\n";
123
							}
124
						} else {
125
							log_message('error', "CUSTOM: {$titleData['title']} - {$site['site_class']} || Title does not exist in DB??");
126
							print " - Possibly diff language than in DB? ($titleURL)\n";
127
						}
128
					} else {
129
						log_message('error', "CUSTOM: {$titleData['title']} - {$site['site_class']} failed to custom update successfully");
130
						print " - FAILED TO PARSE\n";
131
					}
132
				}
133
			}
134
		}
135
	}
136
137
138
	/**
139
	 * Checks every series to see if title has changed, and update if so.
140
	 * This is ran once a month via a cron job
141
	 */
142
	public function updateTitles() {
143
		// @formatter:off
144
		$query = $this->db
145
			->select('
146
				tracker_titles.id,
147
				tracker_titles.title,
148
				tracker_titles.title_url,
149
				tracker_titles.status,
150
				tracker_sites.site,
151
				tracker_sites.site_class,
152
				tracker_sites.status,
153
				tracker_titles.latest_chapter,
154
				tracker_titles.last_updated
155
			')
156
			->from('tracker_titles')
157
			->join('tracker_sites', 'tracker_sites.id = tracker_titles.site_id', 'left')
158
			->where('tracker_sites.status', 'enabled')
159
160
			->group_by('tracker_titles.id')
161
			->order_by('tracker_titles.title', 'ASC')
162
			->get();
163
		// @formatter:on
164
165
		if($query->num_rows() > 0) {
166
			foreach ($query->result() as $row) {
167
				print "> {$row->title} <{$row->site_class}>"; //Print this prior to doing anything so we can more easily find out if something went wrong
168
				$titleData = $this->sites->{$row->site_class}->getTitleData($row->title_url);
169
				if($titleData['title'] && is_array($titleData) && !is_null($titleData['latest_chapter'])) {
170
					if($titleData['title'] !== $row->title) {
171
						$this->db->set('title', $titleData['title'])
172
						         ->where('id', $row->id)
173
						         ->update('tracker_titles');
174
						//TODO: Add to history somehow?
175
						print " - NEW TITLE ({$titleData['title']})\n";
176
					} else {
177
						print " - TITLE NOT CHANGED\n";
178
					}
179
180
					//We might as well try to update as well.
181 View Code Duplication
					if($this->Tracker->title->updateByID((int) $row->id, $titleData['latest_chapter'])) {
182
						$this->db->set('last_checked', 'CURRENT_TIMESTAMP', FALSE)
183
						         ->where('id', $row->id)
184
						         ->update('tracker_titles');
185
					}
186
				} else {
187
					log_message('error', "{$row->title} failed to update title successfully");
188
					print " - FAILED TO PARSE\n";
189
				}
190
			}
191
		}
192
	}
193
194
	public function getNextUpdateTime() : string {
195
		$temp_now = new DateTime();
196
		$temp_now->setTimezone(new DateTimeZone('America/New_York'));
197
		$temp_now_formatted = $temp_now->format('Y-m-d H:i:s');
198
199
		//NOTE: PHP Bug: DateTime:diff doesn't play nice with setTimezone, so we need to create another DT object
200
		$now         = new DateTime($temp_now_formatted);
201
		$future_date = new DateTime($temp_now_formatted);
202
		$now_hour    = (int) $now->format('H');
203
		if($now_hour < 4) {
204
			//Time until 4am
205
			$future_date->setTime(4, 00);
206
		} elseif($now_hour < 8) {
207
			//Time until 8am
208
			$future_date->setTime(8, 00);
209
		} elseif($now_hour < 12) {
210
			//Time until 12pm
211
			$future_date->setTime(12, 00);
212
		} elseif($now_hour < 16) {
213
			//Time until 4pm
214
			$future_date->setTime(16, 00);
215
		} elseif($now_hour < 20) {
216
			//Time until 8pm
217
			$future_date->setTime(20, 00);
218
		} else {
219
			//Time until 12am
220
			$future_date->setTime(00, 00);
221
			$future_date->add(new DateInterval('P1D'));
222
		}
223
224
		$interval = $future_date->diff($now);
225
		return $interval->format("%H:%I:%S");
226
	}
227
}
228