1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is part of Peachy MediaWiki Bot API |
5
|
|
|
* |
6
|
|
|
* Peachy is free software: you can redistribute it and/or modify |
7
|
|
|
* it under the terms of the GNU General Public License as published by |
8
|
|
|
* the Free Software Foundation, either version 3 of the License, or |
9
|
|
|
* (at your option) any later version. |
10
|
|
|
* |
11
|
|
|
* This program is distributed in the hope that it will be useful, |
12
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14
|
|
|
* GNU General Public License for more details. |
15
|
|
|
* |
16
|
|
|
* You should have received a copy of the GNU General Public License |
17
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
18
|
|
|
*/ |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Checks for a new version of Peachy and installs it if there is one. |
22
|
|
|
*/ |
23
|
|
|
Class AutoUpdate { |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @var Http |
27
|
|
|
*/ |
28
|
|
|
protected $http; |
29
|
|
|
protected $repository; |
30
|
|
|
protected $logfile; |
31
|
|
|
protected $lastused; |
32
|
|
|
protected $commits; |
33
|
|
|
|
34
|
|
|
function __construct( $http ) { |
|
|
|
|
35
|
|
|
global $pgIP, $pgExperimentalupdates; |
36
|
|
|
$this->http = $http; |
37
|
|
|
$this->repository = ( $pgExperimentalupdates ? 'master' : 'stable' ); |
38
|
|
|
$this->logfile = ( $pgExperimentalupdates ? 'Update.log' : 'StableUpdate.log' ); |
39
|
|
|
$this->lastused = ( file_exists( $pgIP . 'Includes/updateversion' ) ? unserialize( file_get_contents( $pgIP . 'Includes/updateversion' ) ) : 'Unknown' ); |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Scans the GitHub repository for any updates and returns false if there are. |
44
|
|
|
* |
45
|
|
|
* @access public |
46
|
|
|
* @return bool |
47
|
|
|
*/ |
48
|
|
|
public function Checkforupdate() { |
49
|
|
|
global $pgIP, $pgExperimentalupdates; |
50
|
|
|
pecho( "Checking for updates...\n\n", PECHO_NORMAL ); |
51
|
|
|
if( $pgExperimentalupdates ) pecho( "Warning: You have experimental updates switched on.\nExperimental updates are not fully tested and can cause problems,\nsuch as, bot misbehaviors up to complete crashes.\nUse at your own risk.\nPeachy will not revert back to a stable release until switched off.\n\n", PECHO_NOTICE ); |
52
|
|
|
$data = json_decode( $this->http->get( 'https://api.github.com/repos/MW-Peachy/Peachy/branches/' . $this->repository, null, array(), false ), true ); |
53
|
|
|
$this->commits = $data; |
54
|
|
|
/*if( strstr( $this->http->getLastHeader(), 'Status: 304 Not Modified') ) { |
55
|
|
|
pecho( "Peachy is up to date.\n\n", PECHO_NORMAL ); |
56
|
|
|
return true; |
57
|
|
|
}*/ |
58
|
|
|
if( is_array( $data ) && array_key_exists( 'message', $data ) && strpos( $data['message'], 'API rate limit exceeded' ) === 0 ) { |
59
|
|
|
pecho( "Cant check for updates right now, next window in " . $this->getTimeToNextLimitWindow() . "\n\n", PECHO_NOTICE ); |
60
|
|
|
return true; |
61
|
|
|
} |
62
|
|
|
$this->cacheLastGithubETag(); |
63
|
|
|
if( $this->lastused !== $this->repository ) { |
64
|
|
|
pecho( "Changing Peachy version to run using " . ( $pgExperimentalupdates ? "experimental" : "stable" ) . " updates.\n\n", PECHO_NOTICE ); |
65
|
|
|
return false; |
66
|
|
|
} |
67
|
|
|
if( file_exists( $pgIP . 'Includes' . DIRECTORY_SEPARATOR . $this->logfile ) ) { |
68
|
|
|
$log = unserialize( file_get_contents( $pgIP . 'Includes' . DIRECTORY_SEPARATOR . $this->logfile ) ); |
69
|
|
|
if( isset( $data['commit']['sha'] ) && $log['commit']['sha'] != $data['commit']['sha'] ) { |
70
|
|
|
pecho( "Update available!\n\n", PECHO_NOTICE ); |
71
|
|
|
return false; |
72
|
|
|
} else { |
73
|
|
|
pecho( "Peachy is up to date.\n\n", PECHO_NORMAL ); |
74
|
|
|
return true; |
75
|
|
|
} |
76
|
|
|
} else { |
77
|
|
|
pecho( "No update log found.\n\n", PECHO_WARN ); |
78
|
|
|
return false; |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Caches the last Etag from github in a tmp file |
84
|
|
|
*/ |
85
|
|
|
private function cacheLastGithubETag() { |
86
|
|
|
global $pgIP; |
87
|
|
|
if( preg_match( '/ETag\: \"([^\"]*)\"/', $this->http->getLastHeader(), $matches ) ) { |
88
|
|
|
file_put_contents( $pgIP . 'tmp' . DIRECTORY_SEPARATOR . 'github-ETag.tmp', $matches[1] ); |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @return string representing time to next github api request window |
94
|
|
|
*/ |
95
|
|
|
private function getTimeToNextLimitWindow() { |
96
|
|
|
if( preg_match( '/X-RateLimit-Reset: (\d*)/', $this->http->getLastHeader(), $matches ) ) { |
97
|
|
|
return gmdate( "i \m\i\\n\u\\t\\e\s s \s\\e\c\o\\n\d\s", $matches[1] - time() ); |
98
|
|
|
} |
99
|
|
|
return 'Unknown'; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
private function getLocalPath( $fullUpdatePath ) { |
103
|
|
|
global $pgIP; |
104
|
|
|
$xplodesAt = DIRECTORY_SEPARATOR . 'gitUpdate' . DIRECTORY_SEPARATOR . 'Peachy-' . $this->repository . DIRECTORY_SEPARATOR; |
105
|
|
|
$parts = explode( $xplodesAt, $fullUpdatePath, 2 ); |
106
|
|
|
return $pgIP . $parts[1]; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Updates the Peachy framework |
111
|
|
|
* |
112
|
|
|
* @access public |
113
|
|
|
* @return boolean|null |
114
|
|
|
*/ |
115
|
|
|
public function updatePeachy() { |
116
|
|
|
global $pgIP, $pgExperimentalupdates; |
117
|
|
|
$gitZip = $pgIP . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'gitUpdate.zip'; |
118
|
|
|
if( file_exists( $gitZip ) ) { |
119
|
|
|
unlink( $gitZip ); |
120
|
|
|
} |
121
|
|
|
file_put_contents( $gitZip, file_get_contents( 'http://github.com/MW-Peachy/Peachy/archive/' . $this->repository . '.zip' ) ); |
122
|
|
|
$zip = new ZipArchive(); |
123
|
|
|
$res = $zip->open( $gitZip ); |
124
|
|
|
if( $res === true ) { |
125
|
|
|
$gitFolder = $pgIP . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'gitUpdate'; |
126
|
|
|
if( file_exists( $gitFolder ) ) { |
127
|
|
|
$this->rrmdir( $gitFolder ); |
128
|
|
|
} |
129
|
|
|
mkdir( $gitFolder, 02775 ); |
130
|
|
|
$zip->extractTo( $gitFolder ); |
131
|
|
|
$zip->close(); |
132
|
|
|
|
133
|
|
|
$this->copyOverGitFiles( $gitFolder . DIRECTORY_SEPARATOR . 'Peachy-' . $this->repository ); |
134
|
|
|
|
135
|
|
|
file_put_contents( $pgIP . 'Includes' . DIRECTORY_SEPARATOR . 'updateversion', serialize( ( $pgExperimentalupdates ? 'master' : 'stable' ) ) ); |
136
|
|
|
|
137
|
|
|
pecho( "Peachy Updated! Changes will go into effect on the next run.\n\n", PECHO_NOTICE ); |
138
|
|
|
|
139
|
|
|
file_put_contents( $pgIP . 'Includes' . DIRECTORY_SEPARATOR . $this->logfile, serialize( $this->commits ) ); |
140
|
|
|
} else { |
141
|
|
|
pecho( "Update failed! Peachy could not retrieve all contents from GitHub.\n\n", PECHO_WARN ); |
142
|
|
|
} |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* @param string $gitFolder |
147
|
|
|
*/ |
148
|
|
|
private function copyOverGitFiles( $gitFolder ) { |
149
|
|
|
/** @var $fileInfo DirectoryIterator */ |
150
|
|
|
foreach( new DirectoryIterator( $gitFolder ) as $fileInfo ){ |
151
|
|
|
if( $fileInfo->isDot() ) continue; |
152
|
|
|
$gitPath = $fileInfo->getRealPath(); |
153
|
|
|
$lclPatch = $this->getLocalPath( $gitPath ); |
154
|
|
|
|
155
|
|
|
if( $fileInfo->isDir() ) { |
156
|
|
|
if( !file_exists( $lclPatch ) ) { |
157
|
|
|
mkdir( $lclPatch ); |
158
|
|
|
} |
159
|
|
|
$this->copyOverGitFiles( $gitPath ); |
160
|
|
|
} elseif( $fileInfo->isFile() ) { |
161
|
|
|
file_put_contents( $lclPatch, file_get_contents( $gitPath ) ); |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* recursively remove a directory |
168
|
|
|
* @param string $dir |
169
|
|
|
*/ |
170
|
|
|
private function rrmdir( $dir ) { |
171
|
|
|
if( is_dir( $dir ) ) { |
172
|
|
|
$objects = scandir( $dir ); |
173
|
|
|
foreach( $objects as $object ){ |
174
|
|
|
if( $object != "." && $object != ".." ) { |
175
|
|
|
if( filetype( $dir . "/" . $object ) == "dir" ) $this->rrmdir( $dir . "/" . $object ); else unlink( $dir . "/" . $object ); |
176
|
|
|
} |
177
|
|
|
} |
178
|
|
|
reset( $objects ); |
179
|
|
|
rmdir( $dir ); |
180
|
|
|
} |
181
|
|
|
} |
182
|
|
|
} |
183
|
|
|
|
Adding explicit visibility (
private
,protected
, orpublic
) is generally recommend to communicate to other developers how, and from where this method is intended to be used.