Skip to content

Commit 8328cce

Browse files
authored
Settings page (#3)
* fix: changed status codes * fix: changed constructor in settingspage * feat: display version numbers of plugins * test * feat: install plugin button * fix: version number * refactor: remove test code
1 parent 21233de commit 8328cce

File tree

2 files changed

+255
-90
lines changed

2 files changed

+255
-90
lines changed

admin/src/SettingsPage.php

Lines changed: 253 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2,113 +2,278 @@
22

33
namespace Cerberus\AdminPluginsManager;
44

5+
use ZipArchive;
6+
57
class SettingsPage
68
{
7-
private $file_name;
8-
9-
public function __construct( string $file_name )
10-
{
11-
$this->file_name = $file_name;
12-
add_action( 'admin_menu', [ $this, 'admin_menu' ], 1000 );
13-
add_action( 'admin_post_cpm_settings', [ $this, 'admin_post_cpm_settings' ] );
14-
add_action( 'admin_post_nopriv_cpm_settings', [ $this, 'admin_post_cpm_settings' ] );
15-
16-
add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
17-
}
18-
19-
public final function admin_enqueue_scripts(): void
20-
{
21-
wp_enqueue_style( 'cpm-admin', plugin_dir_url( $this->file_name ) . 'admin/assets/css/admin.css' );
22-
}
23-
24-
public final function admin_menu(): void
25-
{
26-
$title = __( 'Cerberus Plugins Manager Settings', 'cerberus-plugins-manager' );
27-
add_submenu_page(
28-
'woocommerce',
29-
$title,
30-
$title,
31-
'administrator',
32-
'cerberus_plugins_manager',
33-
array( $this, 'settingsPage' )
34-
);
35-
}
36-
37-
public final function settingsPage(): void
38-
{
39-
$repoKey = get_option( 'repo-key', '' );
40-
$title = __( 'Cerberus Plugins Manager Settings', 'cerberus-plugins-manager' );
41-
42-
?>
9+
private $file_name;
10+
11+
public function __construct(string $file_name)
12+
{
13+
$this->file_name = $file_name;
14+
add_action('admin_menu', [$this, 'admin_menu'], 1000);
15+
add_action('admin_post_cpm_settings', [$this, 'admin_post_cpm_settings']);
16+
add_action('admin_post_nopriv_cpm_settings', [$this, 'admin_post_cpm_settings']);
17+
18+
add_action('admin_enqueue_scripts', [$this, 'admin_enqueue_scripts']);
19+
20+
add_action('admin_post_download_and_extract_repo', [$this, 'download_and_extract_repo']);
21+
add_action('admin_post_nopriv_download_and_extract_repo', [$this, 'download_and_extract_repo']);
22+
}
23+
24+
public final function admin_enqueue_scripts(): void
25+
{
26+
wp_enqueue_style('cpm-admin', plugin_dir_url($this->file_name) . 'admin/assets/css/admin.css');
27+
}
28+
29+
public final function admin_menu(): void
30+
{
31+
$title = __('Cerberus Plugins Manager Settings', 'cerberus-plugins-manager');
32+
add_submenu_page('woocommerce', $title, $title, 'administrator', 'cerberus_plugins_manager', array(
33+
$this,
34+
'settingsPage'
35+
));
36+
}
37+
38+
public final function settingsPage(): void
39+
{
40+
$repoKey = get_option('repo-key', '');
41+
$title = __('Cerberus Plugins Manager Settings', 'cerberus-plugins-manager');
42+
43+
?>
4344
<div>
4445
<h3><?= $title; ?> </h3>
4546
</div>
4647
<div>
47-
<form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post"
48+
<form action="<?php echo esc_url(admin_url('admin-post.php')); ?>" method="post"
4849
id="cpm_settings">
4950
<input type="hidden" name="action" value="cpm_settings"/>
5051
<label for="repo-key">
5152
<span>Repo Key: </span>
5253
<input type="text" name="repo-key" minlength="1">
5354
</label>
54-
<?php
55-
if ( ! empty( $repoKey ) ) {
56-
echo '<span>Your repo key is set but hidden away.</span>';
57-
} ?>
55+
<?php
56+
if (!empty($repoKey)) {
57+
echo '<span>Your repo key is set but hidden away.</span>';
58+
} ?>
5859
<div>
5960
<button class="button-primary" type="submit">Save</button>
6061
</div>
6162
</form>
6263
</div>
63-
<?php
64+
<?php
65+
66+
$repoKey = get_option('repo-key');
67+
$repos = $this->getRepos('Trizelos', $repoKey);
6468

65-
$responses = apply_filters( 'cerberus-core-repos-settings', [] );
69+
$responses = apply_filters('cerberus-core-repos-settings', $repos);
6670

67-
?>
71+
?>
6872
<br>
69-
<table class="cpm">
70-
<thead>
71-
<tr>
72-
<th>Plugin</th>
73-
<th>Connection Status to Repo</th>
74-
<th>Newest Version</th>
75-
<th>Current Version</th>
76-
</tr>
77-
</thead>
78-
<tbody>
79-
<?php
80-
foreach ( $responses as $name => $data ) {
81-
$response = $data['response'];
82-
$plugin_data = $data['plugin_data'];
83-
84-
$out_of_date = false;
85-
if ( ! empty( $response['tag_name'] ) ) {
86-
$out_of_date = version_compare( $response['tag_name'], $plugin_data['Version'], 'gt' );
87-
}
88-
?>
89-
<tr class="<?= $out_of_date ? 'out-of-date' : ''; ?>">
90-
<td><?= $name; ?></td>
91-
<td><?= ( ! empty( $response ) && is_array( $response ) ? 'connected' : ( ! empty( $response ) ? $response : 'no release found' ) ); ?></td>
92-
<td>
93-
<?= ! empty( $response['tag_name'] ) ? $response['tag_name'] : 'Not version Found'; ?>
94-
</td>
95-
<td>
96-
<?= $plugin_data['Version']; ?>
97-
</td>
73+
<form action="<?php echo esc_url(admin_url('admin-post.php')); ?>" method="post" ,
74+
id="download_and_repo_install">
75+
<input type="hidden" name="action" value="download_and_extract_repo"/>
76+
<input type="hidden" name="repo-to-install" id="repo-to-install" value=""/>
77+
<table class="cpm">
78+
<thead>
79+
<tr>
80+
<th>Plugin</th>
81+
<th>Connection Status to Repo</th>
82+
<th>Newest Version</th>
83+
<th>Current Version</th>
84+
<th>Install</th>
9885
</tr>
99-
<?php } ?>
100-
</tbody>
101-
</table>
102-
<?php
103-
}
104-
105-
public final function admin_post_cpm_settings(): void
106-
{
107-
$data = $_POST;
108-
if ( ! empty( $data['repo-key'] ) ) {
109-
update_option( 'repo-key', $data['repo-key'] );
110-
}
111-
112-
wp_redirect( wp_get_referer() );
113-
}
86+
</thead>
87+
<tbody>
88+
<?php
89+
foreach ($responses as $name => $data) {
90+
if ($name == 'cerberus-plugins-manager/cerberus-plugins-manager.php') {
91+
continue;
92+
}
93+
$response = $data['response'];
94+
$plugin_data = $data['plugin_data'];
95+
$installed = !empty($response);
96+
97+
$out_of_date = false;
98+
if (!empty($response['tag_name'])) {
99+
$out_of_date = version_compare($response['tag_name'], $plugin_data['Version'], 'gt');
100+
}
101+
?>
102+
<tr class="<?= $out_of_date ? 'out-of-date' : ''; ?>">
103+
<td><?= $name; ?></td>
104+
<td><?= (!empty($response) && is_array($response) ? 'connected' : (!empty($response) ? $response : 'no release found')); ?></td>
105+
<td>
106+
<?= !empty($response['tag_name']) ? $response['tag_name'] : 'No version Found'; ?>
107+
</td>
108+
<td>
109+
<?= !empty($plugin_data['Version']) ? $plugin_data['Version'] : 'Base'; ?>
110+
</td>
111+
<td>
112+
<button class="install-button primary button" <?= $installed ? 'disabled' : '' ?>
113+
data-repo="<?= empty($data['name']) ? '' : $data['name']; ?>"
114+
onclick="document.querySelector('#repo-to-install').value =this.dataset.repo;">
115+
Install
116+
</button>
117+
</td>
118+
</tr>
119+
<?php } ?>
120+
</tbody>
121+
</table>
122+
</form>
123+
<?php
124+
}
125+
126+
public function getRepos(string $repository, string $authorizeToken): array
127+
{
128+
$args = array();
129+
$request_uri = sprintf('https://api.github.com/orgs/%s/repos', $repository); // Build URI
130+
131+
if ($authorizeToken) { // Is there an access token?
132+
$args['headers']['Authorization'] = "bearer {$authorizeToken}"; // Set the headers
133+
}
134+
135+
$responses = json_decode(wp_remote_retrieve_body(wp_remote_get($request_uri, $args)), true); // Get JSON and parse it
136+
137+
$repos = [];
138+
foreach ($responses as $response) {
139+
if (!str_contains($response['name'], 'cerberus')) {
140+
continue;
141+
}
142+
$repos[$response['name'] . '/' . $response['name'] . '.php']['name'] = $response['name'];
143+
$repos[$response['name'] . '/' . $response['name'] . '.php']['response'] = "";
144+
$repos[$response['name'] . '/' . $response['name'] . '.php']['plugin_data'] = "";
145+
}
146+
147+
return $repos;
148+
}
149+
150+
public final function download_and_extract_repo(): void
151+
{
152+
if (empty($_POST['repo-to-install'])) {
153+
wp_redirect(wp_get_referer());
154+
return;
155+
}
156+
157+
$repository = $_POST['repo-to-install'];
158+
159+
$response = $this->getRepoResponse($repository);
160+
161+
if (!isset($response["zipball_url"])) {
162+
wp_redirect(wp_get_referer());
163+
return;
164+
}
165+
166+
$zip_url = $response["zipball_url"];
167+
$destination_path = WP_PLUGIN_DIR . '/' . $repository . ".zip";
168+
169+
if (!$this->downloadZipFile($zip_url, $destination_path)) {
170+
wp_redirect(wp_get_referer());
171+
return;
172+
}
173+
174+
175+
$zip = new ZipArchive();
176+
if ($zip->open($destination_path) === true) {
177+
$pluginDestination = WP_PLUGIN_DIR;
178+
179+
$name = $zip->getNameIndex(0);
180+
181+
// extract the plugin
182+
$success = $zip->extractTo($pluginDestination);
183+
$zip->close();
184+
185+
$pluginRepoPath = $pluginDestination . '/' . $repository;
186+
$pluginRepoGeneratedName = $pluginDestination . '/' . $name;
187+
188+
// if old repo data exists delete it
189+
if ($success && is_dir($pluginRepoPath)) {
190+
$deletedOldRepo = $this->delTree($pluginRepoPath);
191+
}
192+
193+
// rename the plugin to the correct name
194+
if (is_dir($pluginRepoGeneratedName)) {
195+
rename($pluginRepoGeneratedName, $pluginRepoPath);
196+
}
197+
198+
// removes the zip file
199+
unlink($destination_path);
200+
201+
// generate autoload files
202+
$this->composer_dump_autoload($pluginRepoPath);
203+
}
204+
wp_redirect(wp_get_referer());
205+
}
206+
207+
private function getRepoResponse(string $repository): mixed
208+
{
209+
$username = 'Trizelos';
210+
$authorize_token = get_option('repo-key');
211+
$args = array();
212+
$request_uri = sprintf('https://api.github.com/repos/%s/%s/releases', $username, $repository); // Build URI
213+
214+
if ($authorize_token) { // Is there an access token?
215+
$args['headers']['Authorization'] = "bearer {$authorize_token}"; // Set the headers
216+
}
217+
218+
$response = json_decode(wp_remote_retrieve_body(wp_remote_get($request_uri, $args)), true); // Get JSON and parse it
219+
220+
if (is_array($response)) { // If it is an array
221+
$response = current($response); // Get the first item
222+
}
223+
224+
return $response;
225+
}
226+
227+
function downloadZipFile($url, $filepath): bool
228+
{
229+
$token = get_option('repo-key');
230+
231+
$ch = curl_init($url);
232+
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
233+
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763');
234+
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Bearer ' . $token));
235+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
236+
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
237+
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
238+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
239+
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
240+
241+
$result = curl_exec($ch);
242+
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); //get status code
243+
curl_close($ch);
244+
245+
file_put_contents($filepath, $result);
246+
247+
return (filesize($filepath) > 0) ? true : false;
248+
}
249+
250+
private function delTree($dir): bool
251+
{
252+
$files = array_diff(scandir($dir), array('.', '..'));
253+
254+
foreach ($files as $file) {
255+
256+
(is_dir("$dir/$file")) ? $this->delTree("$dir/$file") : unlink("$dir/$file");
257+
}
258+
259+
return rmdir($dir);
260+
261+
}
262+
263+
private function composer_dump_autoload(string $filePath): void
264+
{
265+
exec("cd $filePath && composer dump-autoload -o");
266+
267+
prew('updated plugin: ' . $filePath);
268+
}
269+
270+
public final function admin_post_cpm_settings(): void
271+
{
272+
$data = $_POST;
273+
if (!empty($data['repo-key'])) {
274+
update_option('repo-key', $data['repo-key']);
275+
}
276+
277+
wp_redirect(wp_get_referer());
278+
}
114279
}

cerberus-plugins-manager.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/**
44
* Plugin Name: Cerberus Plugins Manager
55
* Description: Manages the cerberus plugins
6-
* Version: 1.0.1
6+
* Version: 1.0.2
77
* Requires at least: 5.7
88
* Author: Casey
99
*/
@@ -12,4 +12,4 @@
1212

1313
require_once "vendor/autoload.php";
1414

15-
$settingsPage = new SettingsPage( __FILE__ );
15+
$settingsPage = new SettingsPage(__FILE__);

0 commit comments

Comments
 (0)