فهرست منبع

Working on self update feature

Sergio Brighenti 6 سال پیش
والد
کامیت
af92f3d70a
7فایلهای تغییر یافته به همراه170 افزوده شده و 9 حذف شده
  1. 121 0
      app/Controllers/UpgradeController.php
  2. 2 2
      app/helpers.php
  3. 6 0
      app/routes.php
  4. 3 2
      composer.json
  5. 1 0
      index.php
  6. 22 5
      resources/templates/dashboard/system.twig
  7. 15 0
      src/js/app.js

+ 121 - 0
app/Controllers/UpgradeController.php

@@ -0,0 +1,121 @@
+<?php
+
+namespace App\Controllers;
+
+
+use Slim\Http\Request;
+use Slim\Http\Response;
+use ZipArchive;
+
+class UpgradeController extends Controller
+{
+	const GITHUB_SOURCE_API = 'https://api.github.com/repos/SergiX44/XBackBone/releases';
+
+	/**
+	 * @param Request $request
+	 * @param Response $response
+	 * @return Response
+	 */
+	public function upgrade(Request $request, Response $response): Response
+	{
+		try {
+			$json = $this->getApiJson();
+		} catch (\RuntimeException $e) {
+			$jsonResponse['message'] = $e->getMessage();
+			return $response->withJson($jsonResponse, 503);
+		}
+
+		if (version_compare($json[0]->tag_name, PLATFORM_VERSION, '<=')) {
+			$this->session->alert(lang('already_latest_version'), 'warning');
+			return redirect($response, 'system');
+		}
+
+		$tmpFile = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'xbackbone_update.zip';
+
+		if (file_put_contents($tmpFile, file_get_contents($json[0]->assets[0]->browser_download_url)) === false) {
+			$this->session->alert(lang('cannot_retrieve_file'), 'danger');
+			return redirect($response, 'system');
+		};
+
+		if (filesize($tmpFile) !== $json[0]->assets[0]->size) {
+			$this->session->alert(lang('file_size_no_match'), 'danger');
+			return redirect($response, 'system');
+		}
+
+		$updateZip = new ZipArchive();
+		$updateZip->open($tmpFile);
+
+
+		for ($i = 0; $i < $updateZip->numFiles; $i++) {
+			$nameIndex = $updateZip->getNameIndex($i);
+			if (is_dir(BASE_DIR . $nameIndex)) {
+				continue;
+			}
+			if (file_exists(BASE_DIR . $nameIndex) && md5($updateZip->getFromIndex($i)) !== md5_file(BASE_DIR . $nameIndex)) {
+				$updateZip->extractTo(BASE_DIR, $nameIndex);
+			} elseif (!file_exists(BASE_DIR . $nameIndex)) {
+				$updateZip->extractTo(BASE_DIR, $nameIndex);
+			}
+			print_r($updateZip->getNameIndex($i) . '<br>');
+		}
+
+		$updateZip->close();
+		unlink($tmpFile);
+
+		return redirect($response, '/install');
+	}
+
+	/**
+	 * @param Request $request
+	 * @param Response $response
+	 * @return Response
+	 */
+	public function checkForUpdates(Request $request, Response $response): Response
+	{
+		$jsonResponse = [
+			'status' => null,
+			'message' => null,
+			'upgrade' => false,
+		];
+
+		try {
+			$json = $this->getApiJson();
+
+			$jsonResponse['status'] = 'OK';
+			if (version_compare($json[0]->tag_name, PLATFORM_VERSION, '>')) {
+				$jsonResponse['message'] = lang('new_version_available', $json[0]->tag_name); //"New version {$json[0]->tag_name} available!";
+				$jsonResponse['upgrade'] = true;
+			} else {
+				$jsonResponse['message'] = lang('already_latest_version');//'You have already the latest version.';
+				$jsonResponse['upgrade'] = false;
+			}
+			return $response->withJson($jsonResponse, 200);
+		} catch (\RuntimeException $e) {
+			$jsonResponse['status'] = 'ERROR';
+			$jsonResponse['message'] = $e->getMessage();
+			return $response->withJson($jsonResponse, 503);
+		}
+	}
+
+	protected function getApiJson()
+	{
+		$opts = [
+			'http' => [
+				'method' => 'GET',
+				'header' => [
+					'User-Agent: XBackBone-App',
+					'Accept: application/vnd.github.v3+json',
+				],
+			],
+		];
+
+		$data = file_get_contents(self::GITHUB_SOURCE_API, false, stream_context_create($opts));
+
+		if ($data === false) {
+			throw new \RuntimeException('Cannot contact the Github API. Try again.');
+		}
+
+		return json_decode($data);
+	}
+
+}

+ 2 - 2
app/helpers.php

@@ -233,11 +233,11 @@ if (!function_exists('dd')) {
 	 */
 	function dd()
 	{
-		echo '<pre>';
 		array_map(function ($x) {
+			echo '<pre>';
 			print_r($x);
+			echo '</pre>';
 		}, func_get_args());
-		echo '</pre>';
 		die();
 	}
 }

+ 6 - 0
app/routes.php

@@ -5,9 +5,15 @@ $app->group('', function () {
 
 	$this->group('', function () {
 		$this->get('/home/switchView', \App\Controllers\DashboardController::class . ':switchView')->setName('switchView');
+
 		$this->get('/system/deleteOrphanFiles', \App\Controllers\AdminController::class . ':deleteOrphanFiles')->setName('system.deleteOrphanFiles');
+
 		$this->get('/system/themes', \App\Controllers\ThemeController::class . ':getThemes')->setName('theme');
 		$this->post('/system/theme/apply', \App\Controllers\ThemeController::class . ':applyTheme')->setName('theme.apply');
+
+		$this->post('/system/upgrade', \App\Controllers\UpgradeController::class . ':upgrade')->setName('system.upgrade');
+		$this->get('/system/checkForUpdates', \App\Controllers\UpgradeController::class . ':checkForUpdates')->setName('system.checkForUpdates');
+
 		$this->get('/system', \App\Controllers\AdminController::class . ':system')->setName('system');
 
 		$this->get('/users[/page/{page}]', \App\Controllers\UserController::class . ':index')->setName('user.index');

+ 3 - 2
composer.json

@@ -1,6 +1,6 @@
 {
   "name": "sergix44/xbackbone",
-  "version": "2.4.1",
+  "version": "2.5",
   "description": "A lightweight ShareX PHP backend",
   "type": "project",
   "require": {
@@ -12,7 +12,8 @@
     "intervention/image": "^2.4",
     "ext-json": "*",
     "ext-gd": "*",
-    "ext-pdo": "*"
+    "ext-pdo": "*",
+    "ext-zip": "*"
   },
   "autoload": {
     "files": [

+ 1 - 0
index.php

@@ -1,6 +1,7 @@
 <?php
 require __DIR__ . '/vendor/autoload.php';
 
+define('BASE_DIR', __DIR__ . '/');
 define('PLATFORM_VERSION', json_decode(file_get_contents('composer.json'))->version);
 
 require 'bootstrap/app.php';

+ 22 - 5
resources/templates/dashboard/system.twig

@@ -53,8 +53,8 @@
             </div>
         </div>
         <div class="row">
-            <div class="col-md-8">
-                <div class="card shadow-sm">
+            <div class="col-md-8 mb-3">
+                <div class="card shadow-sm mb-3">
                     <div class="card-header"><i class="fas fa-paint-brush fa-fw"></i> {{ lang('theme') }}</div>
                     <div class="card-body">
                         <form method="post" action="{{ route('theme.apply') }}">
@@ -75,9 +75,26 @@
                         </form>
                     </div>
                 </div>
-            </div>
-            <div class="col-md-4">
                 <div class="card shadow-sm">
+                    <div class="card-header"><i class="fas fa-cloud-download-alt fa-fw"></i> {{ lang('updates') }}</div>
+                    <div class="card-body">
+                        <div class="row">
+                            <div class="col">
+                                <button type="button" id="checkForUpdatesButton" class="btn btn-block btn-outline-info"><i class="fas fa-sync fa-fw"></i> {{ lang('check_for_updates') }}</button>
+                            </div>
+                            <div class="col text-center"><span class="text-muted" id="checkForUpdatesMessage"></span></div>
+
+                            <div class="col">
+                                <form method="post" action="{{ route('system.upgrade') }}">
+                                    <button type="submit" id="doUpgradeButton" class="btn btn-block btn-outline-success"><i class="fas fa-cloud-download-alt fa-fw"></i> {{ lang('update_now') }}</button>
+                                </form>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-md-4 mb-3">
+                <div class="card shadow-sm mb-3">
                     <div class="card-header"><i class="fas fa-cog fa-fw"></i> {{ lang('system_info') }}</div>
                     <div class="card-body">
                         <strong>Max upload size:</strong>
@@ -87,7 +104,7 @@
                         </ul>
                     </div>
                 </div>
-                <div class="card shadow-sm mt-3">
+                <div class="card shadow-sm mb-3">
                     <div class="card-header"><i class="fas fa-tools fa-fw"></i> {{ lang('maintenance') }}</div>
                     <div class="card-body">
                         <a href="{{ route('system.deleteOrphanFiles') }}" class="btn btn-outline-dark btn-block"><i class="fas fa-broom fa-fw"></i> {{ lang('clean_orphaned_uploads') }}</a>

+ 15 - 0
src/js/app.js

@@ -8,6 +8,7 @@ var app = {
         $('.publish-toggle').click(app.publishToggle);
         $('.refresh-token').click(app.refreshToken);
         $('#themes').mousedown(app.loadThemes);
+        $('#checkForUpdatesButton').click(app.checkForUpdates);
 
         $('.alert').fadeTo(4000, 500).slideUp(500, function () {
             $('.alert').slideUp(500);
@@ -89,6 +90,20 @@ var app = {
     },
     telegramShare: function () {
         window.open($('#telegram-share-button').data('url') + $('#telegram-share-text').val(), '_blank');
+    },
+    checkForUpdates: function () {
+        $('#checkForUpdatesMessage').empty().text('...');
+        $('#doUpgradeButton').prop('disabled', true);
+        $.get(window.AppConfig.base_url + '/system/checkForUpdates', function (data) {
+            if (data.status === 'OK') {
+                $('#checkForUpdatesMessage').empty().text(data.message);
+                if (data.upgrade) {
+                    $('#doUpgradeButton').prop('disabled', false);
+                } else {
+                    $('#doUpgradeButton').prop('disabled', true);
+                }
+            }
+        });
     }
 };