mini-projet
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM;
|
||||
|
||||
use Grav\Common\Iterator;
|
||||
|
||||
/**
|
||||
* Class AbstractCollection
|
||||
* @package Grav\Common\GPM
|
||||
*/
|
||||
abstract class AbstractCollection extends Iterator
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function toJson()
|
||||
{
|
||||
return json_encode($this->toArray(), JSON_THROW_ON_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$items = [];
|
||||
|
||||
foreach ($this->items as $name => $package) {
|
||||
$items[$name] = $package->toArray();
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Common;
|
||||
|
||||
use Grav\Common\Iterator;
|
||||
|
||||
/**
|
||||
* Class AbstractPackageCollection
|
||||
* @package Grav\Common\GPM\Common
|
||||
*/
|
||||
abstract class AbstractPackageCollection extends Iterator
|
||||
{
|
||||
/** @var string */
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function toJson()
|
||||
{
|
||||
$items = [];
|
||||
|
||||
foreach ($this->items as $name => $package) {
|
||||
$items[$name] = $package->toArray();
|
||||
}
|
||||
|
||||
return json_encode($items, JSON_THROW_ON_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$items = [];
|
||||
|
||||
foreach ($this->items as $name => $package) {
|
||||
$items[$name] = $package->toArray();
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Common;
|
||||
|
||||
use Grav\Common\Iterator;
|
||||
|
||||
/**
|
||||
* Class CachedCollection
|
||||
* @package Grav\Common\GPM\Common
|
||||
*/
|
||||
class CachedCollection extends Iterator
|
||||
{
|
||||
/** @var array */
|
||||
protected static $cache = [];
|
||||
|
||||
/**
|
||||
* CachedCollection constructor.
|
||||
*
|
||||
* @param array $items
|
||||
*/
|
||||
public function __construct($items)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$method = static::class . __METHOD__;
|
||||
|
||||
// local cache to speed things up
|
||||
if (!isset(self::$cache[$method])) {
|
||||
self::$cache[$method] = $items;
|
||||
}
|
||||
|
||||
foreach (self::$cache[$method] as $name => $item) {
|
||||
$this->append([$name => $item]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Common;
|
||||
|
||||
use Grav\Common\Data\Data;
|
||||
|
||||
/**
|
||||
* @property string $name
|
||||
*/
|
||||
class Package
|
||||
{
|
||||
/** @var Data */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* Package constructor.
|
||||
* @param Data $package
|
||||
* @param string|null $type
|
||||
*/
|
||||
public function __construct(Data $package, $type = null)
|
||||
{
|
||||
$this->data = $package;
|
||||
|
||||
if ($type) {
|
||||
$this->data->set('package_type', $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Data
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->data->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function __set($key, $value)
|
||||
{
|
||||
$this->data->set($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function __isset($key)
|
||||
{
|
||||
return isset($this->data->{$key});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function __toString()
|
||||
{
|
||||
return $this->toJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function toJson()
|
||||
{
|
||||
return $this->data->toJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->data->toArray();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,544 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM;
|
||||
|
||||
use DirectoryIterator;
|
||||
use Grav\Common\Filesystem\Folder;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Utils;
|
||||
use RuntimeException;
|
||||
use ZipArchive;
|
||||
use function count;
|
||||
use function in_array;
|
||||
use function is_string;
|
||||
|
||||
/**
|
||||
* Class Installer
|
||||
* @package Grav\Common\GPM
|
||||
*/
|
||||
class Installer
|
||||
{
|
||||
/** @const No error */
|
||||
public const OK = 0;
|
||||
/** @const Target already exists */
|
||||
public const EXISTS = 1;
|
||||
/** @const Target is a symbolic link */
|
||||
public const IS_LINK = 2;
|
||||
/** @const Target doesn't exist */
|
||||
public const NOT_FOUND = 4;
|
||||
/** @const Target is not a directory */
|
||||
public const NOT_DIRECTORY = 8;
|
||||
/** @const Target is not a Grav instance */
|
||||
public const NOT_GRAV_ROOT = 16;
|
||||
/** @const Error while trying to open the ZIP package */
|
||||
public const ZIP_OPEN_ERROR = 32;
|
||||
/** @const Error while trying to extract the ZIP package */
|
||||
public const ZIP_EXTRACT_ERROR = 64;
|
||||
/** @const Invalid source file */
|
||||
public const INVALID_SOURCE = 128;
|
||||
|
||||
/** @var string Destination folder on which validation checks are applied */
|
||||
protected static $target;
|
||||
|
||||
/** @var int|string Error code or string */
|
||||
protected static $error = 0;
|
||||
|
||||
/** @var int Zip Error Code */
|
||||
protected static $error_zip = 0;
|
||||
|
||||
/** @var string Post install message */
|
||||
protected static $message = '';
|
||||
|
||||
/** @var array Default options for the install */
|
||||
protected static $options = [
|
||||
'overwrite' => true,
|
||||
'ignore_symlinks' => true,
|
||||
'sophisticated' => false,
|
||||
'theme' => false,
|
||||
'install_path' => '',
|
||||
'ignores' => [],
|
||||
'exclude_checks' => [self::EXISTS, self::NOT_FOUND, self::IS_LINK]
|
||||
];
|
||||
|
||||
/**
|
||||
* Installs a given package to a given destination.
|
||||
*
|
||||
* @param string $zip the local path to ZIP package
|
||||
* @param string $destination The local path to the Grav Instance
|
||||
* @param array $options Options to use for installing. ie, ['install_path' => 'user/themes/antimatter']
|
||||
* @param string|null $extracted The local path to the extacted ZIP package
|
||||
* @param bool $keepExtracted True if you want to keep the original files
|
||||
* @return bool True if everything went fine, False otherwise.
|
||||
*/
|
||||
public static function install($zip, $destination, $options = [], $extracted = null, $keepExtracted = false)
|
||||
{
|
||||
$destination = rtrim($destination, DS);
|
||||
$options = array_merge(self::$options, $options);
|
||||
$install_path = rtrim($destination . DS . ltrim($options['install_path'], DS), DS);
|
||||
|
||||
if (!self::isGravInstance($destination) || !self::isValidDestination(
|
||||
$install_path,
|
||||
$options['exclude_checks']
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((self::lastErrorCode() === self::IS_LINK && $options['ignore_symlinks']) ||
|
||||
(self::lastErrorCode() === self::EXISTS && !$options['overwrite'])
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a tmp location
|
||||
$tmp_dir = Grav::instance()['locator']->findResource('tmp://', true, true);
|
||||
$tmp = $tmp_dir . '/Grav-' . uniqid('', false);
|
||||
|
||||
if (!$extracted) {
|
||||
$extracted = self::unZip($zip, $tmp);
|
||||
if (!$extracted) {
|
||||
Folder::delete($tmp);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!file_exists($extracted)) {
|
||||
self::$error = self::INVALID_SOURCE;
|
||||
return false;
|
||||
}
|
||||
|
||||
$is_install = true;
|
||||
$installer = self::loadInstaller($extracted, $is_install);
|
||||
|
||||
if (isset($options['is_update']) && $options['is_update'] === true) {
|
||||
$method = 'preUpdate';
|
||||
} else {
|
||||
$method = 'preInstall';
|
||||
}
|
||||
|
||||
if ($installer && method_exists($installer, $method)) {
|
||||
$method_result = $installer::$method();
|
||||
if ($method_result !== true) {
|
||||
self::$error = 'An error occurred';
|
||||
if (is_string($method_result)) {
|
||||
self::$error = $method_result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$options['sophisticated']) {
|
||||
$isTheme = $options['theme'] ?? false;
|
||||
// Make sure that themes are always being copied, even if option was not set!
|
||||
$isTheme = $isTheme || preg_match('|/themes/[^/]+|ui', $install_path);
|
||||
if ($isTheme) {
|
||||
self::copyInstall($extracted, $install_path);
|
||||
} else {
|
||||
self::moveInstall($extracted, $install_path);
|
||||
}
|
||||
} else {
|
||||
self::sophisticatedInstall($extracted, $install_path, $options['ignores'], $keepExtracted);
|
||||
}
|
||||
|
||||
Folder::delete($tmp);
|
||||
|
||||
if (isset($options['is_update']) && $options['is_update'] === true) {
|
||||
$method = 'postUpdate';
|
||||
} else {
|
||||
$method = 'postInstall';
|
||||
}
|
||||
|
||||
self::$message = '';
|
||||
if ($installer && method_exists($installer, $method)) {
|
||||
self::$message = $installer::$method();
|
||||
}
|
||||
|
||||
self::$error = self::OK;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unzip a file to somewhere
|
||||
*
|
||||
* @param string $zip_file
|
||||
* @param string $destination
|
||||
* @return string|false
|
||||
*/
|
||||
public static function unZip($zip_file, $destination)
|
||||
{
|
||||
$zip = new ZipArchive();
|
||||
$archive = $zip->open($zip_file);
|
||||
|
||||
if ($archive === true) {
|
||||
Folder::create($destination);
|
||||
|
||||
$unzip = $zip->extractTo($destination);
|
||||
|
||||
|
||||
if (!$unzip) {
|
||||
self::$error = self::ZIP_EXTRACT_ERROR;
|
||||
Folder::delete($destination);
|
||||
$zip->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
$package_folder_name = $zip->getNameIndex(0);
|
||||
if ($package_folder_name === false) {
|
||||
throw new \RuntimeException('Bad package file: ' . Utils::basename($zip_file));
|
||||
}
|
||||
$package_folder_name = preg_replace('#\./$#', '', $package_folder_name);
|
||||
$zip->close();
|
||||
|
||||
return $destination . '/' . $package_folder_name;
|
||||
}
|
||||
|
||||
self::$error = self::ZIP_EXTRACT_ERROR;
|
||||
self::$error_zip = $archive;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates and returns the package installer class
|
||||
*
|
||||
* @param string $installer_file_folder The folder path that contains install.php
|
||||
* @param bool $is_install True if install, false if removal
|
||||
* @return string|null
|
||||
*/
|
||||
private static function loadInstaller($installer_file_folder, $is_install)
|
||||
{
|
||||
$installer_file_folder = rtrim($installer_file_folder, DS);
|
||||
|
||||
$install_file = $installer_file_folder . DS . 'install.php';
|
||||
|
||||
if (!file_exists($install_file)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
require_once $install_file;
|
||||
|
||||
if ($is_install) {
|
||||
$slug = '';
|
||||
if (($pos = strpos($installer_file_folder, 'grav-plugin-')) !== false) {
|
||||
$slug = substr($installer_file_folder, $pos + strlen('grav-plugin-'));
|
||||
} elseif (($pos = strpos($installer_file_folder, 'grav-theme-')) !== false) {
|
||||
$slug = substr($installer_file_folder, $pos + strlen('grav-theme-'));
|
||||
}
|
||||
} else {
|
||||
$path_elements = explode('/', $installer_file_folder);
|
||||
$slug = end($path_elements);
|
||||
}
|
||||
|
||||
if (!$slug) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$class_name = ucfirst($slug) . 'Install';
|
||||
|
||||
if (class_exists($class_name)) {
|
||||
return $class_name;
|
||||
}
|
||||
|
||||
$class_name_alphanumeric = preg_replace('/[^a-zA-Z0-9]+/', '', $class_name) ?? $class_name;
|
||||
|
||||
if (class_exists($class_name_alphanumeric)) {
|
||||
return $class_name_alphanumeric;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $source_path
|
||||
* @param string $install_path
|
||||
* @return bool
|
||||
*/
|
||||
public static function moveInstall($source_path, $install_path)
|
||||
{
|
||||
if (file_exists($install_path)) {
|
||||
Folder::delete($install_path);
|
||||
}
|
||||
|
||||
Folder::move($source_path, $install_path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $source_path
|
||||
* @param string $install_path
|
||||
* @return bool
|
||||
*/
|
||||
public static function copyInstall($source_path, $install_path)
|
||||
{
|
||||
if (empty($source_path)) {
|
||||
throw new RuntimeException("Directory $source_path is missing");
|
||||
}
|
||||
|
||||
Folder::rcopy($source_path, $install_path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $source_path
|
||||
* @param string $install_path
|
||||
* @param array $ignores
|
||||
* @param bool $keep_source
|
||||
* @return bool
|
||||
*/
|
||||
public static function sophisticatedInstall($source_path, $install_path, $ignores = [], $keep_source = false)
|
||||
{
|
||||
foreach (new DirectoryIterator($source_path) as $file) {
|
||||
if ($file->isLink() || $file->isDot() || in_array($file->getFilename(), $ignores, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = $install_path . DS . $file->getFilename();
|
||||
|
||||
if ($file->isDir()) {
|
||||
Folder::delete($path);
|
||||
if ($keep_source) {
|
||||
Folder::copy($file->getPathname(), $path);
|
||||
} else {
|
||||
Folder::move($file->getPathname(), $path);
|
||||
}
|
||||
|
||||
if ($file->getFilename() === 'bin') {
|
||||
$glob = glob($path . DS . '*') ?: [];
|
||||
foreach ($glob as $bin_file) {
|
||||
@chmod($bin_file, 0755);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@unlink($path);
|
||||
@copy($file->getPathname(), $path);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstalls one or more given package
|
||||
*
|
||||
* @param string $path The slug of the package(s)
|
||||
* @param array $options Options to use for uninstalling
|
||||
* @return bool True if everything went fine, False otherwise.
|
||||
*/
|
||||
public static function uninstall($path, $options = [])
|
||||
{
|
||||
$options = array_merge(self::$options, $options);
|
||||
if (!self::isValidDestination($path, $options['exclude_checks'])
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$installer_file_folder = $path;
|
||||
$is_install = false;
|
||||
$installer = self::loadInstaller($installer_file_folder, $is_install);
|
||||
|
||||
if ($installer && method_exists($installer, 'preUninstall')) {
|
||||
$method_result = $installer::preUninstall();
|
||||
if ($method_result !== true) {
|
||||
self::$error = 'An error occurred';
|
||||
if (is_string($method_result)) {
|
||||
self::$error = $method_result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$result = Folder::delete($path);
|
||||
|
||||
self::$message = '';
|
||||
if ($result && $installer && method_exists($installer, 'postUninstall')) {
|
||||
self::$message = $installer::postUninstall();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a set of checks on the destination and sets the Error if any
|
||||
*
|
||||
* @param string $destination The directory to run validations at
|
||||
* @param array $exclude An array of constants to exclude from the validation
|
||||
* @return bool True if validation passed. False otherwise
|
||||
*/
|
||||
public static function isValidDestination($destination, $exclude = [])
|
||||
{
|
||||
self::$error = 0;
|
||||
self::$target = $destination;
|
||||
|
||||
if (is_link($destination)) {
|
||||
self::$error = self::IS_LINK;
|
||||
} elseif (file_exists($destination)) {
|
||||
self::$error = self::EXISTS;
|
||||
} elseif (!file_exists($destination)) {
|
||||
self::$error = self::NOT_FOUND;
|
||||
} elseif (!is_dir($destination)) {
|
||||
self::$error = self::NOT_DIRECTORY;
|
||||
}
|
||||
|
||||
if (count($exclude) && in_array(self::$error, $exclude, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !self::$error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if the given path is a Grav Instance
|
||||
*
|
||||
* @param string $target The local path to the Grav Instance
|
||||
* @return bool True if is a Grav Instance. False otherwise
|
||||
*/
|
||||
public static function isGravInstance($target)
|
||||
{
|
||||
self::$error = 0;
|
||||
self::$target = $target;
|
||||
|
||||
if (!file_exists($target . DS . 'index.php') ||
|
||||
!file_exists($target . DS . 'bin') ||
|
||||
!file_exists($target . DS . 'user') ||
|
||||
!file_exists($target . DS . 'system' . DS . 'config' . DS . 'system.yaml')
|
||||
) {
|
||||
self::$error = self::NOT_GRAV_ROOT;
|
||||
}
|
||||
|
||||
return !self::$error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last message added by the installer
|
||||
*
|
||||
* @return string The message
|
||||
*/
|
||||
public static function getMessage()
|
||||
{
|
||||
return self::$message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last error occurred in a string message format
|
||||
*
|
||||
* @return string The message of the last error
|
||||
*/
|
||||
public static function lastErrorMsg()
|
||||
{
|
||||
if (is_string(self::$error)) {
|
||||
return self::$error;
|
||||
}
|
||||
|
||||
switch (self::$error) {
|
||||
case 0:
|
||||
$msg = 'No Error';
|
||||
break;
|
||||
|
||||
case self::EXISTS:
|
||||
$msg = 'The target path "' . self::$target . '" already exists';
|
||||
break;
|
||||
|
||||
case self::IS_LINK:
|
||||
$msg = 'The target path "' . self::$target . '" is a symbolic link';
|
||||
break;
|
||||
|
||||
case self::NOT_FOUND:
|
||||
$msg = 'The target path "' . self::$target . '" does not appear to exist';
|
||||
break;
|
||||
|
||||
case self::NOT_DIRECTORY:
|
||||
$msg = 'The target path "' . self::$target . '" does not appear to be a folder';
|
||||
break;
|
||||
|
||||
case self::NOT_GRAV_ROOT:
|
||||
$msg = 'The target path "' . self::$target . '" does not appear to be a Grav instance';
|
||||
break;
|
||||
|
||||
case self::ZIP_OPEN_ERROR:
|
||||
$msg = 'Unable to open the package file';
|
||||
break;
|
||||
|
||||
case self::ZIP_EXTRACT_ERROR:
|
||||
$msg = 'Unable to extract the package. ';
|
||||
if (self::$error_zip) {
|
||||
switch (self::$error_zip) {
|
||||
case ZipArchive::ER_EXISTS:
|
||||
$msg .= 'File already exists.';
|
||||
break;
|
||||
|
||||
case ZipArchive::ER_INCONS:
|
||||
$msg .= 'Zip archive inconsistent.';
|
||||
break;
|
||||
|
||||
case ZipArchive::ER_MEMORY:
|
||||
$msg .= 'Memory allocation failure.';
|
||||
break;
|
||||
|
||||
case ZipArchive::ER_NOENT:
|
||||
$msg .= 'No such file.';
|
||||
break;
|
||||
|
||||
case ZipArchive::ER_NOZIP:
|
||||
$msg .= 'Not a zip archive.';
|
||||
break;
|
||||
|
||||
case ZipArchive::ER_OPEN:
|
||||
$msg .= "Can't open file.";
|
||||
break;
|
||||
|
||||
case ZipArchive::ER_READ:
|
||||
$msg .= 'Read error.';
|
||||
break;
|
||||
|
||||
case ZipArchive::ER_SEEK:
|
||||
$msg .= 'Seek error.';
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case self::INVALID_SOURCE:
|
||||
$msg = 'Invalid source file';
|
||||
break;
|
||||
|
||||
default:
|
||||
$msg = 'Unknown Error';
|
||||
break;
|
||||
}
|
||||
|
||||
return $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last error code of the occurred error
|
||||
*
|
||||
* @return int|string The code of the last error
|
||||
*/
|
||||
public static function lastErrorCode()
|
||||
{
|
||||
return self::$error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to manually set an error
|
||||
*
|
||||
* @param int|string $error the Error code
|
||||
* @return void
|
||||
*/
|
||||
public static function setError($error)
|
||||
{
|
||||
self::$error = $error;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM;
|
||||
|
||||
use Grav\Common\File\CompiledYamlFile;
|
||||
use Grav\Common\Grav;
|
||||
use RocketTheme\Toolbox\File\FileInterface;
|
||||
use function is_string;
|
||||
|
||||
/**
|
||||
* Class Licenses
|
||||
*
|
||||
* @package Grav\Common\GPM
|
||||
*/
|
||||
class Licenses
|
||||
{
|
||||
/** @var string Regex to validate the format of a License */
|
||||
protected static $regex = '^(?:[A-F0-9]{8}-){3}(?:[A-F0-9]{8}){1}$';
|
||||
/** @var FileInterface */
|
||||
protected static $file;
|
||||
|
||||
/**
|
||||
* Returns the license for a Premium package
|
||||
*
|
||||
* @param string $slug
|
||||
* @param string $license
|
||||
* @return bool
|
||||
*/
|
||||
public static function set($slug, $license)
|
||||
{
|
||||
$licenses = self::getLicenseFile();
|
||||
$data = (array)$licenses->content();
|
||||
$slug = strtolower($slug);
|
||||
|
||||
if ($license && !self::validate($license)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_string($license)) {
|
||||
if (isset($data['licenses'][$slug])) {
|
||||
unset($data['licenses'][$slug]);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$data['licenses'][$slug] = $license;
|
||||
}
|
||||
|
||||
$licenses->save($data);
|
||||
$licenses->free();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the license for a Premium package
|
||||
*
|
||||
* @param string|null $slug
|
||||
* @return string[]|string
|
||||
*/
|
||||
public static function get($slug = null)
|
||||
{
|
||||
$licenses = self::getLicenseFile();
|
||||
$data = (array)$licenses->content();
|
||||
$licenses->free();
|
||||
|
||||
if (null === $slug) {
|
||||
return $data['licenses'] ?? [];
|
||||
}
|
||||
|
||||
$slug = strtolower($slug);
|
||||
|
||||
return $data['licenses'][$slug] ?? '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates the License format
|
||||
*
|
||||
* @param string|null $license
|
||||
* @return bool
|
||||
*/
|
||||
public static function validate($license = null)
|
||||
{
|
||||
if (!is_string($license)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool)preg_match('#' . self::$regex. '#', $license);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the License File object
|
||||
*
|
||||
* @return FileInterface
|
||||
*/
|
||||
public static function getLicenseFile()
|
||||
{
|
||||
if (!isset(self::$file)) {
|
||||
$path = Grav::instance()['locator']->findResource('user-data://') . '/licenses.yaml';
|
||||
if (!file_exists($path)) {
|
||||
touch($path);
|
||||
}
|
||||
self::$file = CompiledYamlFile::instance($path);
|
||||
}
|
||||
|
||||
return self::$file;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Local;
|
||||
|
||||
use Grav\Common\GPM\Common\AbstractPackageCollection as BaseCollection;
|
||||
|
||||
/**
|
||||
* Class AbstractPackageCollection
|
||||
* @package Grav\Common\GPM\Local
|
||||
*/
|
||||
abstract class AbstractPackageCollection extends BaseCollection
|
||||
{
|
||||
/**
|
||||
* AbstractPackageCollection constructor.
|
||||
*
|
||||
* @param array $items
|
||||
*/
|
||||
public function __construct($items)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
foreach ($items as $name => $data) {
|
||||
$data->set('slug', $name);
|
||||
$this->items[$name] = new Package($data, $this->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Local;
|
||||
|
||||
use Grav\Common\Data\Data;
|
||||
use Grav\Common\GPM\Common\Package as BasePackage;
|
||||
use Parsedown;
|
||||
|
||||
/**
|
||||
* Class Package
|
||||
* @package Grav\Common\GPM\Local
|
||||
*/
|
||||
class Package extends BasePackage
|
||||
{
|
||||
/** @var array */
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* Package constructor.
|
||||
* @param Data $package
|
||||
* @param string|null $package_type
|
||||
*/
|
||||
public function __construct(Data $package, $package_type = null)
|
||||
{
|
||||
$data = new Data($package->blueprints()->toArray());
|
||||
parent::__construct($data, $package_type);
|
||||
|
||||
$this->settings = $package->toArray();
|
||||
|
||||
$html_description = Parsedown::instance()->line($this->__get('description'));
|
||||
$this->data->set('slug', $package->__get('slug'));
|
||||
$this->data->set('description_html', $html_description);
|
||||
$this->data->set('description_plain', strip_tags($html_description));
|
||||
$this->data->set('symlink', is_link(USER_DIR . $package_type . DS . $this->__get('slug')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isEnabled()
|
||||
{
|
||||
return (bool)$this->settings['enabled'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Local;
|
||||
|
||||
use Grav\Common\GPM\Common\CachedCollection;
|
||||
|
||||
/**
|
||||
* Class Packages
|
||||
* @package Grav\Common\GPM\Local
|
||||
*/
|
||||
class Packages extends CachedCollection
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$items = [
|
||||
'plugins' => new Plugins(),
|
||||
'themes' => new Themes()
|
||||
];
|
||||
|
||||
parent::__construct($items);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Local;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
|
||||
/**
|
||||
* Class Plugins
|
||||
* @package Grav\Common\GPM\Local
|
||||
*/
|
||||
class Plugins extends AbstractPackageCollection
|
||||
{
|
||||
/** @var string */
|
||||
protected $type = 'plugins';
|
||||
|
||||
/**
|
||||
* Local Plugins Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
/** @var \Grav\Common\Plugins $plugins */
|
||||
$plugins = Grav::instance()['plugins'];
|
||||
|
||||
parent::__construct($plugins->all());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Local;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
|
||||
/**
|
||||
* Class Themes
|
||||
* @package Grav\Common\GPM\Local
|
||||
*/
|
||||
class Themes extends AbstractPackageCollection
|
||||
{
|
||||
/** @var string */
|
||||
protected $type = 'themes';
|
||||
|
||||
/**
|
||||
* Local Themes Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
/** @var \Grav\Common\Themes $themes */
|
||||
$themes = Grav::instance()['themes'];
|
||||
|
||||
parent::__construct($themes->all());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Remote;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\HTTP\Response;
|
||||
use Grav\Common\GPM\Common\AbstractPackageCollection as BaseCollection;
|
||||
use \Doctrine\Common\Cache\FilesystemCache;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Class AbstractPackageCollection
|
||||
* @package Grav\Common\GPM\Remote
|
||||
*/
|
||||
class AbstractPackageCollection extends BaseCollection
|
||||
{
|
||||
/** @var string The cached data previously fetched */
|
||||
protected $raw;
|
||||
/** @var string */
|
||||
protected $repository;
|
||||
/** @var FilesystemCache */
|
||||
protected $cache;
|
||||
|
||||
/** @var int The lifetime to store the entry in seconds */
|
||||
private $lifetime = 86400;
|
||||
|
||||
/**
|
||||
* AbstractPackageCollection constructor.
|
||||
*
|
||||
* @param string|null $repository
|
||||
* @param bool $refresh
|
||||
* @param callable|null $callback
|
||||
*/
|
||||
public function __construct($repository = null, $refresh = false, $callback = null)
|
||||
{
|
||||
parent::__construct();
|
||||
if ($repository === null) {
|
||||
throw new RuntimeException('A repository is required to indicate the origin of the remote collection');
|
||||
}
|
||||
|
||||
$channel = Grav::instance()['config']->get('system.gpm.releases', 'stable');
|
||||
$cache_dir = Grav::instance()['locator']->findResource('cache://gpm', true, true);
|
||||
$this->cache = new FilesystemCache($cache_dir);
|
||||
|
||||
$this->repository = $repository . '?v=' . GRAV_VERSION . '&' . $channel . '=1';
|
||||
$this->raw = $this->cache->fetch(md5($this->repository));
|
||||
|
||||
$this->fetch($refresh, $callback);
|
||||
foreach (json_decode($this->raw, true) as $slug => $data) {
|
||||
// Temporarily fix for using multi-sites
|
||||
if (isset($data['install_path'])) {
|
||||
$path = preg_replace('~^user/~i', 'user://', $data['install_path']);
|
||||
$data['install_path'] = Grav::instance()['locator']->findResource($path, false, true);
|
||||
}
|
||||
$this->items[$slug] = new Package($data, $this->type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $refresh
|
||||
* @param callable|null $callback
|
||||
* @return string
|
||||
*/
|
||||
public function fetch($refresh = false, $callback = null)
|
||||
{
|
||||
if (!$this->raw || $refresh) {
|
||||
$response = Response::get($this->repository, [], $callback);
|
||||
$this->raw = $response;
|
||||
$this->cache->save(md5($this->repository), $this->raw, $this->lifetime);
|
||||
}
|
||||
|
||||
return $this->raw;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Remote;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use \Doctrine\Common\Cache\FilesystemCache;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Class GravCore
|
||||
* @package Grav\Common\GPM\Remote
|
||||
*/
|
||||
class GravCore extends AbstractPackageCollection
|
||||
{
|
||||
/** @var string */
|
||||
protected $repository = 'https://getgrav.org/downloads/grav.json';
|
||||
|
||||
/** @var array */
|
||||
private $data;
|
||||
/** @var string */
|
||||
private $version;
|
||||
/** @var string */
|
||||
private $date;
|
||||
/** @var string|null */
|
||||
private $min_php;
|
||||
|
||||
/**
|
||||
* @param bool $refresh
|
||||
* @param callable|null $callback
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct($refresh = false, $callback = null)
|
||||
{
|
||||
$channel = Grav::instance()['config']->get('system.gpm.releases', 'stable');
|
||||
$cache_dir = Grav::instance()['locator']->findResource('cache://gpm', true, true);
|
||||
$this->cache = new FilesystemCache($cache_dir);
|
||||
$this->repository .= '?v=' . GRAV_VERSION . '&' . $channel . '=1';
|
||||
$this->raw = $this->cache->fetch(md5($this->repository));
|
||||
|
||||
$this->fetch($refresh, $callback);
|
||||
|
||||
$this->data = json_decode($this->raw, true);
|
||||
$this->version = $this->data['version'] ?? '-';
|
||||
$this->date = $this->data['date'] ?? '-';
|
||||
$this->min_php = $this->data['min_php'] ?? null;
|
||||
|
||||
if (isset($this->data['assets'])) {
|
||||
foreach ((array)$this->data['assets'] as $slug => $data) {
|
||||
$this->items[$slug] = new Package($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of assets associated to the latest version of Grav
|
||||
*
|
||||
* @return array list of assets
|
||||
*/
|
||||
public function getAssets()
|
||||
{
|
||||
return $this->data['assets'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the changelog list for each version of Grav
|
||||
*
|
||||
* @param string|null $diff the version number to start the diff from
|
||||
* @return array changelog list for each version
|
||||
*/
|
||||
public function getChangelog($diff = null)
|
||||
{
|
||||
if (!$diff) {
|
||||
return $this->data['changelog'];
|
||||
}
|
||||
|
||||
$diffLog = [];
|
||||
foreach ((array)$this->data['changelog'] as $version => $changelog) {
|
||||
preg_match("/[\w\-\.]+/", $version, $cleanVersion);
|
||||
|
||||
if (!$cleanVersion || version_compare($diff, $cleanVersion[0], '>=')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$diffLog[$version] = $changelog;
|
||||
}
|
||||
|
||||
return $diffLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the release date of the latest Grav
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDate()
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this version of Grav is eligible to be updated
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function isUpdatable()
|
||||
{
|
||||
return version_compare(GRAV_VERSION, $this->getVersion(), '<');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the latest version of Grav available remotely
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum PHP version
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMinPHPVersion()
|
||||
{
|
||||
// If non min set, assume current PHP version
|
||||
if (null === $this->min_php) {
|
||||
$this->min_php = PHP_VERSION;
|
||||
}
|
||||
|
||||
return $this->min_php;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this installation symlinked?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSymlink()
|
||||
{
|
||||
return is_link(GRAV_ROOT . DS . 'index.php');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Remote;
|
||||
|
||||
use Grav\Common\Data\Data;
|
||||
use Grav\Common\GPM\Common\Package as BasePackage;
|
||||
|
||||
/**
|
||||
* Class Package
|
||||
* @package Grav\Common\GPM\Remote
|
||||
*/
|
||||
class Package extends BasePackage implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* Package constructor.
|
||||
* @param array $package
|
||||
* @param string|null $package_type
|
||||
*/
|
||||
public function __construct($package, $package_type = null)
|
||||
{
|
||||
$data = new Data($package);
|
||||
parent::__construct($data, $package_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->data->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the changelog list for each version of a package
|
||||
*
|
||||
* @param string|null $diff the version number to start the diff from
|
||||
* @return array changelog list for each version
|
||||
*/
|
||||
public function getChangelog($diff = null)
|
||||
{
|
||||
if (!$diff) {
|
||||
return $this->data['changelog'];
|
||||
}
|
||||
|
||||
$diffLog = [];
|
||||
foreach ((array)$this->data['changelog'] as $version => $changelog) {
|
||||
preg_match("/[\w\-.]+/", $version, $cleanVersion);
|
||||
|
||||
if (!$cleanVersion || version_compare($diff, $cleanVersion[0], '>=')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$diffLog[$version] = $changelog;
|
||||
}
|
||||
|
||||
return $diffLog;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Remote;
|
||||
|
||||
use Grav\Common\GPM\Common\CachedCollection;
|
||||
|
||||
/**
|
||||
* Class Packages
|
||||
* @package Grav\Common\GPM\Remote
|
||||
*/
|
||||
class Packages extends CachedCollection
|
||||
{
|
||||
/**
|
||||
* Packages constructor.
|
||||
* @param bool $refresh
|
||||
* @param callable|null $callback
|
||||
*/
|
||||
public function __construct($refresh = false, $callback = null)
|
||||
{
|
||||
$items = [
|
||||
'plugins' => new Plugins($refresh, $callback),
|
||||
'themes' => new Themes($refresh, $callback)
|
||||
];
|
||||
|
||||
parent::__construct($items);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Remote;
|
||||
|
||||
/**
|
||||
* Class Plugins
|
||||
* @package Grav\Common\GPM\Remote
|
||||
*/
|
||||
class Plugins extends AbstractPackageCollection
|
||||
{
|
||||
/** @var string */
|
||||
protected $type = 'plugins';
|
||||
/** @var string */
|
||||
protected $repository = 'https://getgrav.org/downloads/plugins.json';
|
||||
|
||||
/**
|
||||
* Local Plugins Constructor
|
||||
* @param bool $refresh
|
||||
* @param callable|null $callback Either a function or callback in array notation
|
||||
*/
|
||||
public function __construct($refresh = false, $callback = null)
|
||||
{
|
||||
parent::__construct($this->repository, $refresh, $callback);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM\Remote;
|
||||
|
||||
/**
|
||||
* Class Themes
|
||||
* @package Grav\Common\GPM\Remote
|
||||
*/
|
||||
class Themes extends AbstractPackageCollection
|
||||
{
|
||||
/** @var string */
|
||||
protected $type = 'themes';
|
||||
/** @var string */
|
||||
protected $repository = 'https://getgrav.org/downloads/themes.json';
|
||||
|
||||
/**
|
||||
* Local Themes Constructor
|
||||
* @param bool $refresh
|
||||
* @param callable|null $callback Either a function or callback in array notation
|
||||
*/
|
||||
public function __construct($refresh = false, $callback = null)
|
||||
{
|
||||
parent::__construct($this->repository, $refresh, $callback);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
// Create alias for the deprecated class.
|
||||
class_alias(\Grav\Common\HTTP\Response::class, \Grav\Common\GPM\Response::class);
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\GPM
|
||||
*
|
||||
* @copyright Copyright (c) 2015 - 2025 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\GPM;
|
||||
|
||||
use Grav\Common\GPM\Remote\GravCore;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Class Upgrader
|
||||
*
|
||||
* @package Grav\Common\GPM
|
||||
*/
|
||||
class Upgrader
|
||||
{
|
||||
/** @var GravCore Remote details about latest Grav version */
|
||||
private $remote;
|
||||
|
||||
/** @var string|null */
|
||||
private $min_php;
|
||||
|
||||
/**
|
||||
* Creates a new GPM instance with Local and Remote packages available
|
||||
*
|
||||
* @param boolean $refresh Applies to Remote Packages only and forces a refetch of data
|
||||
* @param callable|null $callback Either a function or callback in array notation
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct($refresh = false, $callback = null)
|
||||
{
|
||||
$this->remote = new Remote\GravCore($refresh, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the release date of the latest version of Grav
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getReleaseDate()
|
||||
{
|
||||
return $this->remote->getDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the installed Grav
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalVersion()
|
||||
{
|
||||
return GRAV_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the remotely available Grav
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRemoteVersion()
|
||||
{
|
||||
return $this->remote->getVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of assets available to download remotely
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAssets()
|
||||
{
|
||||
return $this->remote->getAssets();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the changelog list for each version of Grav
|
||||
*
|
||||
* @param string|null $diff the version number to start the diff from
|
||||
* @return array return the changelog list for each version
|
||||
*/
|
||||
public function getChangelog($diff = null)
|
||||
{
|
||||
return $this->remote->getChangelog($diff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure this meets minimum PHP requirements
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function meetsRequirements()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, $this->minPHPVersion(), '<')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get minimum PHP version from remote
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function minPHPVersion()
|
||||
{
|
||||
if (null === $this->min_php) {
|
||||
$this->min_php = $this->remote->getMinPHPVersion();
|
||||
}
|
||||
|
||||
return $this->min_php;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the currently installed Grav is upgradable to a newer version
|
||||
*
|
||||
* @return bool True if it's upgradable, False otherwise.
|
||||
*/
|
||||
public function isUpgradable()
|
||||
{
|
||||
return version_compare($this->getLocalVersion(), $this->getRemoteVersion(), '<');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if Grav is currently symbolically linked
|
||||
*
|
||||
* @return bool True if Grav is symlinked, False otherwise.
|
||||
*/
|
||||
public function isSymlink()
|
||||
{
|
||||
return $this->remote->isSymlink();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user