Merge branch 'release/1.7.2'

This commit is contained in:
Andy Miller 2021-01-21 11:57:16 -07:00
commit 7cfc8dc00e
No known key found for this signature in database
GPG Key ID: 2B07A47E470BCFDE
11 changed files with 218 additions and 33 deletions

View File

@ -1,3 +1,17 @@
# v1.7.2
## 01/21/2021
1. [](#improved)
* IMPORTANT - Please [checkout the process](https://getgrav.org/blog/grav-170-cli-self-upgrade-bug) to `self-upgrade` from CLI if you are on **Grav 1.7.0 or 1.7.1**
* Added support for symlinking individual plugins and themes by using `bin/grav install -p myplugin` or `-t mytheme`
* Added support for symlinking plugins and themes with `hebe.json` file to support custom folder structures
* Added support for running post-install scripts in `bin/gpm selfupgrade` if Grav was updated manually
1. [](#bugfix)
* Fixed default GPM Channel back to 'stable' - this was inadvertently left as 'testing' [#3163](https://github.com/getgrav/grav/issues/3163)
* Fixed broken stream initialization if `environment://` paths aren't streams
* Fixed Clockwork debugger in sub-folder multi-site setups
* Fixed `Unsupported option "curl" passed to "Symfony\Component\HttpClient\CurlHttpClient"` in `bin/gpm selfupgrade` [#3165](https://github.com/getgrav/grav/issues/3165)
# v1.7.1
## 01/20/2021

View File

@ -173,7 +173,7 @@ session:
path:
gpm:
releases: testing # Set to either 'stable' or 'testing'
releases: stable # Set to either 'stable' or 'testing'
proxy_url: # Configure a manual proxy URL for GPM (eg 127.0.0.1:3128)
method: 'auto' # Either 'curl', 'fopen' or 'auto'. 'auto' will try fopen first and if not available cURL
verify_peer: true # Sometimes on some systems (Windows most commonly) GPM is unable to connect because the SSL certificate cannot be verified. Disabling this setting might help.

View File

@ -8,8 +8,8 @@
// Some standard defines
define('GRAV', true);
define('GRAV_VERSION', '1.7.1');
define('GRAV_SCHEMA', '1.7.0_2020-11-20_1');
define('GRAV_VERSION', '1.7.2');
define('GRAV_SCHEMA', '1.7.2_2021-01-21_1');
define('GRAV_TESTING', false);
// PHP minimum requirement

View File

@ -362,19 +362,27 @@ class Setup extends Data
try {
// If environment is found, remove all missing override locations (B/C compatibility).
if ($locator->findResource('environment://', true)) {
$prefixes = $this->get('streams.schemes.environment.prefixes.');
$update = false;
foreach ($prefixes as $i => $prefix) {
if ($locator->findResource($prefix, true)) {
break;
$force = $this->get('streams.schemes.environment.force', false);
if (!$force) {
$prefixes = $this->get('streams.schemes.environment.prefixes.');
$update = false;
foreach ($prefixes as $i => $prefix) {
if ($locator->isStream($prefix)) {
if ($locator->findResource($prefix, true)) {
break;
}
} elseif (file_exists($prefix)) {
break;
}
unset($prefixes[$i]);
$update = true;
}
unset($prefixes[$i]);
$update = true;
}
if ($update) {
$this->set('streams.schemes.environment.prefixes', ['' => array_values($prefixes)]);
$this->initializeLocator($locator);
if ($update) {
$this->set('streams.schemes.environment.prefixes', ['' => array_values($prefixes)]);
$this->initializeLocator($locator);
}
}
}

View File

@ -279,7 +279,8 @@ class Debugger
->withHeader('X-Clockwork-Id', $clockworkRequest->id)
->withHeader('X-Clockwork-Version', $clockwork::VERSION);
$basePath = Grav::instance()['uri']->rootUrl();
$grav = Grav::instance();
$basePath = $this->grav['base_url_relative'] . $grav['pages']->base();
if ($basePath) {
$response = $response->withHeader('X-Clockwork-Path', $basePath . '/__clockwork/');
}

View File

@ -10,9 +10,12 @@
namespace Grav\Console\Cli;
use Grav\Console\GravCommand;
use Grav\Framework\File\Formatter\JsonFormatter;
use Grav\Framework\File\JsonFile;
use RocketTheme\Toolbox\File\YamlFile;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use function is_array;
/**
* Class InstallCommand
@ -40,6 +43,18 @@ class InstallCommand extends GravCommand
InputOption::VALUE_NONE,
'Symlink the required bits'
)
->addOption(
'plugin',
'p',
InputOption::VALUE_REQUIRED,
'Install plugin (symlink)'
)
->addOption(
'theme',
't',
InputOption::VALUE_REQUIRED,
'Install theme (symlink)'
)
->addArgument(
'destination',
InputArgument::OPTIONAL,
@ -58,7 +73,7 @@ class InstallCommand extends GravCommand
$io = $this->getIO();
$dependencies_file = '.dependencies';
$this->destination = $input->getArgument('destination') ?: ROOT_DIR;
$this->destination = $input->getArgument('destination') ?: GRAV_ROOT;
// fix trailing slash
$this->destination = rtrim($this->destination, DS) . DS;
@ -93,14 +108,21 @@ class InstallCommand extends GravCommand
return 1;
}
if (!$input->getOption('symlink')) {
$plugin = $input->getOption('plugin');
$theme = $input->getOption('theme');
$name = $plugin ?? $theme;
$symlink = $name || $input->getOption('symlink');
if (!$symlink) {
// Updates composer first
$io->writeln("\nInstalling vendor dependencies");
$io->writeln($this->composerUpdate(GRAV_ROOT, 'install'));
$error = $this->gitclone();
} else {
$error = $this->symlink();
$type = $name ? ($plugin ? 'plugin' : 'theme') : null;
$error = $this->symlink($name, $type);
}
return $error;
@ -147,9 +169,11 @@ class InstallCommand extends GravCommand
/**
* Symlinks
*
* @param string|null $name
* @param string|null $type
* @return int
*/
private function symlink(): int
private function symlink(string $name = null, string $type = null): int
{
$io = $this->getIO();
@ -167,7 +191,21 @@ class InstallCommand extends GravCommand
$error = 0;
$this->destination = rtrim($this->destination, DS);
foreach ($this->config['links'] as $name => $data) {
if ($name) {
$src = "grav-{$type}-{$name}";
$links = [
$name => [
'scm' => 'github', // TODO: make configurable
'src' => $src,
'path' => "user/{$type}s/{$name}"
]
];
} else {
$links = $this->config['links'];
}
foreach ($links as $name => $data) {
$scm = $data['scm'] ?? null;
$src = $data['src'] ?? null;
$path = $data['path'] ?? null;
@ -191,7 +229,7 @@ class InstallCommand extends GravCommand
}
}
if (is_link($to) && !is_file("{$to}/{$name}.yaml")) {
if (is_link($to) && !realpath($to)) {
$io->writeln('<yellow>Removed broken symlink '. $path .'</yellow>');
unlink($to);
}
@ -200,8 +238,7 @@ class InstallCommand extends GravCommand
$io->newLine();
$error = 1;
} elseif (!file_exists($to)) {
symlink($from, $to);
$io->writeln('<green>SUCCESS</green> symlinked <magenta>' . $src . '</magenta> -> <cyan>' . $path . '</cyan>');
$error = $this->addSymlinks($from, $to, ['name' => $name, 'src' => $src, 'path' => $path]);
$io->newLine();
} else {
$io->writeln('<yellow>destination: ' . $path . ' already exists, skipping...</yellow>');
@ -211,4 +248,55 @@ class InstallCommand extends GravCommand
return $error;
}
private function addSymlinks(string $from, string $to, array $options): int
{
$io = $this->getIO();
$hebe = $this->readHebe($from);
if (null === $hebe) {
symlink($from, $to);
$io->writeln('<green>SUCCESS</green> symlinked <magenta>' . $options['src'] . '</magenta> -> <cyan>' . $options['path'] . '</cyan>');
} else {
$to = GRAV_ROOT;
$name = $options['name'];
$io->writeln("Processing <magenta>{$name}</magenta>");
foreach ($hebe as $section => $symlinks) {
foreach ($symlinks as $symlink) {
$src = trim($symlink['source'], '/');
$dst = trim($symlink['destination'], '/');
$s = "{$from}/{$src}";
$d = "{$to}/{$dst}";
if (is_link($d) && !realpath($d)) {
unlink($d);
$io->writeln(' <yellow>Removed broken symlink '. $dst .'</yellow>');
}
if (!file_exists($d)) {
symlink($s, $d);
$io->writeln(' symlinked <magenta>' . $src . '</magenta> -> <cyan>' . $dst . '</cyan>');
}
}
}
$io->writeln('<green>SUCCESS</green>');
}
return 0;
}
private function readHebe(string $folder): ?array
{
$filename = "{$folder}/hebe.json";
if (!is_file($filename)) {
return null;
}
$formatter = new JsonFormatter();
$file = new JsonFile($filename, $formatter);
$hebe = $file->load();
$paths = $hebe['platforms']['grav']['nodes'] ?? null;
return is_array($paths) ? $paths : null;
}
}

View File

@ -16,6 +16,7 @@ use Grav\Common\GPM\Response;
use Grav\Common\GPM\Upgrader;
use Grav\Common\Grav;
use Grav\Console\GpmCommand;
use Grav\Installer\Install;
use RuntimeException;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputOption;
@ -126,7 +127,32 @@ class SelfupgradeCommand extends GpmCommand
}
if (!$this->overwrite && !$this->upgrader->isUpgradable()) {
$io->writeln("You are already running the latest version of Grav (v{$local}) released on {$release}");
$io->writeln("You are already running the latest version of <green>Grav v{$local}</green>");
$io->writeln("which was released on {$release}");
$config = Grav::instance()['config'];
if ($config->get('versions.core.grav.schema') !== GRAV_SCHEMA) {
$io->newLine();
$io->writeln('However post-install scripts have not been run.');
if (!$this->all_yes) {
$question = new ConfirmationQuestion(
'Would you like to run the scripts? [Y|n] ',
true
);
$answer = $io->askQuestion($question);
} else {
$answer = true;
}
if ($answer) {
// Finalize installation.
Install::instance()->finalize();
$io->write(' |- Running post-install scripts... ');
$io->writeln(" '- <green>Success!</green> ");
$io->newLine();
}
}
return 0;
}
@ -220,12 +246,7 @@ class SelfupgradeCommand extends GpmCommand
$tmp_dir = Grav::instance()['locator']->findResource('tmp://', true, true);
$this->tmp = $tmp_dir . '/grav-update-' . uniqid('', false);
$options = [
'curl' => [
CURLOPT_TIMEOUT => $this->timeout,
],
'fopen' => [
'timeout' => $this->timeout,
],
'timeout' => $this->timeout,
];
$output = Response::get($package['download'], $options, [$this, 'progress']);

View File

@ -283,6 +283,13 @@ ERR;
*/
public function finalize(): void
{
// Finalize can be run without installing Grav first.
if (!$this->updater) {
$versions = Versions::instance(GRAV_ROOT . '/user/config/versions.yaml');
$this->updater = new VersionUpdater('core/grav', __DIR__ . '/updates', GRAV_VERSION, $versions);
$this->updater->install();
}
$this->updater->postflight();
Cache::clearCache('all');

View File

@ -148,6 +148,26 @@ final class YamlUpdater
array_splice($this->lines, abs($currentLine)+1, 0, $value);
}
public function undefine(string $variable): void
{
// If variable does not have value, we're good.
if ($this->get($variable) === null) {
return;
}
// If one of the parents isn't array, we're good, too.
if (!$this->canDefine($variable)) {
return;
}
$this->undef($variable);
if (!$this->isHandWritten()) {
return;
}
// TODO: support also removing property from handwritten configuration file.
}
private function __construct(string $filename)
{
$content = is_file($filename) ? (string)file_get_contents($filename) : '';

View File

@ -5,7 +5,8 @@ use Grav\Installer\VersionUpdate;
use Grav\Installer\YamlUpdater;
return [
'preflight' =>
'preflight' => null,
'postflight' =>
function () {
/** @var VersionUpdate $this */
try {
@ -19,6 +20,5 @@ return [
} catch (\Exception $e) {
throw new InstallException('Could not update system configuration to maintain backwards compatibility', $e);
}
},
'postflight' => null
}
];

View File

@ -0,0 +1,26 @@
<?php
use Grav\Installer\InstallException;
use Grav\Installer\VersionUpdate;
use Grav\Installer\YamlUpdater;
return [
'preflight' => null,
'postflight' =>
function () {
// Only reset GPM releases value if upgrading from Grav 1.7 RC.
if (version_compare(GRAV_VERSION, '1.7', '<')) {
return;
}
/** @var VersionUpdate $this */
try {
// Keep old defaults for backwards compatibility.
$yaml = YamlUpdater::instance(GRAV_ROOT . '/user/config/system.yaml');
$yaml->undefine('gpm.releases');
$yaml->save();
} catch (\Exception $e) {
throw new InstallException('Could not update system configuration to maintain backwards compatibility', $e);
}
}
];