diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d34a009c..2a130268f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ 1. [](#new) * Added `CsvFormatter` and `CsvFile` classes * Register theme prefixes as namespaces in Twig [#2210](https://github.com/getgrav/grav/pull/2210) + * Added `$grav->setup()` to simplify CLI and custom access points 1. [](#improved) * Support negotiated content types set via the Request `Accept:` header * Support negotiated language types set via the Request `Accept-Language:` header @@ -14,6 +15,7 @@ * Fixed `Uri::hasStandardPort()` to support reverse proxy configurations [#1786](https://github.com/getgrav/grav/issues/1786) * Use `append_url_extension` from page header to set template format if set [#2604](https://github.com/getgrav/grav/pull/2064) * Remove hardcoded `302` when redirecting trailing slash [#2155](https://github.com/getgrav/grav/pull/2155) + * Fixed some bugs in environment selection # v1.6.0-beta.5 ## 11/05/2018 diff --git a/bin/gpm b/bin/gpm index e8eff5a00..d17d73428 100755 --- a/bin/gpm +++ b/bin/gpm @@ -1,26 +1,23 @@ #!/usr/bin/env php arguments->add([ ] ]); $climate->arguments->parse(); -$environment = $climate->arguments->get('environment'); // Set up environment based on params. -Setup::$environment = $environment; +$environment = $climate->arguments->get('environment'); $grav = Grav::instance(array('loader' => $autoload)); -$grav['uri']->init(); +$grav->setup($environment); + $grav['config']->init(); -$grav['streams']; +$grav['uri']->init(); $app = new Application('Grav Package Manager', GRAV_VERSION); $app->addCommands(array( diff --git a/bin/grav b/bin/grav index d68be7c04..4fef12faf 100755 --- a/bin/grav +++ b/bin/grav @@ -1,18 +1,17 @@ #!/usr/bin/env php $autoload)); if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) { exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req)); } +Grav::instance(array('loader' => $autoload)); + if (!ini_get('date.timezone')) { date_default_timezone_set('UTC'); } -if (!file_exists(ROOT_DIR . 'index.php')) { +if (!file_exists(GRAV_ROOT . '/index.php')) { exit('FATAL: Must be run from ROOT directory of Grav!'); } diff --git a/bin/plugin b/bin/plugin index 9cb75666f..f1fb775c7 100755 --- a/bin/plugin +++ b/bin/plugin @@ -1,30 +1,27 @@ #!/usr/bin/env php arguments->add([ ] ]); $climate->arguments->parse(); + $environment = $climate->arguments->get('environment'); -// Set up environment based on params. -Setup::$environment = $environment; - $grav = Grav::instance(array('loader' => $autoload)); -$grav['uri']->init(); +$grav->setup($environment); + $grav['config']->init(); -$grav['streams']; +$grav['uri']->init(); $grav['plugins']->init(); $grav['themes']->init(); @@ -101,14 +97,14 @@ if (!$name) { $entry = array_shift($split); $index = str_pad($index++ + 1, 2, '0', STR_PAD_LEFT); $total = str_pad($total++ + 1, 2, '0', STR_PAD_LEFT); - if (in_array($entry, $available)) { - $total -= 1; + if (\in_array($entry, $available, true)) { + $total--; continue; } $available[] = $entry; $commands_count = $index - $total + 1; - $output->writeln(' ' . $total . '. ' . str_pad($entry, 15) . " ${bla} ${bin} ${entry} list"); + $output->writeln(' ' . $total . '. ' . str_pad($entry, 15) . " {$bin} {$entry} list"); } } diff --git a/system/src/Grav/Common/Config/Setup.php b/system/src/Grav/Common/Config/Setup.php index 5b3b4226c..d67541716 100644 --- a/system/src/Grav/Common/Config/Setup.php +++ b/system/src/Grav/Common/Config/Setup.php @@ -11,12 +11,24 @@ namespace Grav\Common\Config; use Grav\Common\File\CompiledYamlFile; use Grav\Common\Data\Data; use Grav\Common\Utils; +use Grav\Framework\Psr7\ServerRequest; use Pimple\Container; -use RocketTheme\Toolbox\File\YamlFile; use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; class Setup extends Data { + /** + * @var array Environment aliases normalized to lower case. + */ + public static $environments = [ + '' => 'unknown', + '127.0.0.1' => 'localhost', + '::1' => 'localhost' + ]; + + /** + * @var string Current environment normalized to lower case. + */ public static $environment; protected $streams = [ @@ -133,11 +145,25 @@ class Setup extends Data */ public function __construct($container) { - $environment = static::$environment ?? $container['uri']->environment() ?: 'localhost'; + // If no environment is set, make sure we get one (CLI or hostname). + if (!static::$environment) { + if (\defined('GRAV_CLI')) { + static::$environment = 'cli'; + } else { + /** @var ServerRequest $request */ + $request = $container['request']; + $host = $request->getUri()->getHost(); + + static::$environment = $host; + } + } + + // Resolve server aliases to the proper environment. + $environment = $this->environments[static::$environment] ?? static::$environment; // Pre-load setup.php which contains our initial configuration. // Configuration may contain dynamic parts, which is why we need to always load it. - // If "GRAVE_SETUP_PATH" has been defined, use it, otherwise use defaults. + // If "GRAV_SETUP_PATH" has been defined, use it, otherwise use defaults. $file = \defined('GRAV_SETUP_PATH') ? GRAV_SETUP_PATH : GRAV_ROOT . '/setup.php'; $setup = is_file($file) ? (array) include $file : []; @@ -151,8 +177,8 @@ class Setup extends Data parent::__construct($setup); // Set up environment. - $this->def('environment', $environment ?: 'cli'); - $this->def('streams.schemes.environment.prefixes', ['' => $environment ? ["user://{$environment}"] : []]); + $this->def('environment', $environment); + $this->def('streams.schemes.environment.prefixes', ['' => ["user://{$this->get('environment')}"]]); } /** @@ -272,7 +298,7 @@ class Setup extends Data // Create security.yaml if it doesn't exist. $filename = $locator->findResource('config://security.yaml', true, true); $security_file = CompiledYamlFile::instance($filename); - $security_content = $security_file->content(); + $security_content = (array)$security_file->content(); if (!isset($security_content['salt'])) { $security_content = array_merge($security_content, ['salt' => Utils::generateRandomString(14)]); diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index fafe29a67..a67e4e43b 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -9,6 +9,7 @@ namespace Grav\Common; use Grav\Common\Config\Config; +use Grav\Common\Config\Setup; use Grav\Common\Page\Medium\ImageMedium; use Grav\Common\Page\Medium\Medium; use Grav\Common\Page\Page; @@ -25,7 +26,6 @@ use Grav\Common\Processors\PluginsProcessor; use Grav\Common\Processors\RenderProcessor; use Grav\Common\Processors\RequestProcessor; use Grav\Common\Processors\SchedulerProcessor; -use Grav\Common\Processors\SiteSetupProcessor; use Grav\Common\Processors\TasksProcessor; use Grav\Common\Processors\ThemesProcessor; use Grav\Common\Processors\TwigProcessor; @@ -64,6 +64,7 @@ class Grav extends Container 'Grav\Common\Service\PageServiceProvider', 'Grav\Common\Service\RequestServiceProvider', 'Grav\Common\Service\SessionServiceProvider', + 'Grav\Common\Service\SetupServiceProvider', 'Grav\Common\Service\StreamsServiceProvider', 'Grav\Common\Service\TaskServiceProvider', 'browser' => 'Grav\Common\Browser', @@ -85,7 +86,6 @@ class Grav extends Container * @var array All middleware processors that are processed in $this->process() */ protected $middleware = [ - 'siteSetupProcessor', 'configurationProcessor', 'loggerProcessor', 'errorsProcessor', @@ -104,6 +104,8 @@ class Grav extends Container 'renderProcessor', ]; + protected $initialized = []; + /** * Reset the Grav instance. */ @@ -135,16 +137,51 @@ class Grav extends Container return self::$instance; } + /** + * Setup Grav instance using specific environment. + * + * Initializes Grav streams by + * + * @param string|null $environment + * @return $this + */ + public function setup(string $environment = null) + { + if (isset($this->initialized['setup'])) { + return $this; + } + + $this->initialized['setup'] = true; + + $this->measureTime('_setup', 'Site Setup', function () use ($environment) { + // Force environment if passed to the method. + if ($environment) { + Setup::$environment = $environment; + } + + $this['setup']; + $this['streams']; + }); + + return $this; + } + /** * Process a request */ public function process() { + if (isset($this->initialized['process'])) { + return; + } + + // Initialize Grav if needed. + $this->setup(); + + $this->initialized['process'] = true; + $container = new Container( [ - 'siteSetupProcessor' => function () { - return new SiteSetupProcessor($this); - }, 'configurationProcessor' => function () { return new ConfigurationProcessor($this); }, @@ -382,7 +419,9 @@ class Grav extends Container /** * Magic Catch All Function - * Used to call closures like measureTime on the instance. + * + * Used to call closures. + * * Source: http://stackoverflow.com/questions/419804/closures-as-class-members */ public function __call($method, $args) @@ -391,6 +430,24 @@ class Grav extends Container \call_user_func_array($closure, $args); } + /** + * Measure how long it takes to do an action. + * + * @param string $timerId + * @param string $timerTitle + * @param callable $callback + * @return mixed Returns value returned by the callable. + */ + public function measureTime(string $timerId, string $timerTitle, callable $callback) + { + $debugger = $this['debugger']; + $debugger->startTimer($timerId, $timerTitle); + $result = $callback(); + $debugger->stopTimer($timerId); + + return $result; + } + /** * Initialize and return a Grav instance * @@ -402,18 +459,11 @@ class Grav extends Container { $container = new static($values); - $container['grav'] = $container; - $container['debugger'] = new Debugger(); - $debugger = $container['debugger']; + $container['grav'] = function (Container $container) { + user_error('Calling $grav[\'grav\'] or {{ grav.grav }} is deprecated since Grav 1.6, just use $grav or {{ grav }}', E_USER_DEPRECATED); - // closure that measures time by wrapping a function into startTimer and stopTimer - // The debugger can be passed to the closure. Should be more performant - // then to get it from the container all time. - $container->measureTime = function ($timerId, $timerTitle, $callback) use ($debugger) { - $debugger->startTimer($timerId, $timerTitle); - $callback(); - $debugger->stopTimer($timerId); + return $container; }; $container->measureTime('_services', 'Services', function () use ($container) { diff --git a/system/src/Grav/Common/Processors/InitializeProcessor.php b/system/src/Grav/Common/Processors/InitializeProcessor.php index 64863d71d..9cf7321f1 100644 --- a/system/src/Grav/Common/Processors/InitializeProcessor.php +++ b/system/src/Grav/Common/Processors/InitializeProcessor.php @@ -37,8 +37,9 @@ class InitializeProcessor extends ProcessorBase } // Initialize the timezone. - if ($config->get('system.timezone')) { - date_default_timezone_set($this->container['config']->get('system.timezone')); + $timezone = $config->get('system.timezone'); + if ($timezone) { + date_default_timezone_set($timezone); } // FIXME: Initialize session should happen later after plugins have been loaded. This is a workaround to fix session issues in AWS. diff --git a/system/src/Grav/Common/Processors/SiteSetupProcessor.php b/system/src/Grav/Common/Processors/SiteSetupProcessor.php deleted file mode 100644 index 4e32a5632..000000000 --- a/system/src/Grav/Common/Processors/SiteSetupProcessor.php +++ /dev/null @@ -1,31 +0,0 @@ -startTimer(); - $this->container['request']; - $this->container['setup']->init(); - $this->container['streams']; - $this->stopTimer(); - - return $handler->handle($request); - } -} diff --git a/system/src/Grav/Common/Service/ConfigServiceProvider.php b/system/src/Grav/Common/Service/ConfigServiceProvider.php index 379c042e7..54e31f4f2 100644 --- a/system/src/Grav/Common/Service/ConfigServiceProvider.php +++ b/system/src/Grav/Common/Service/ConfigServiceProvider.php @@ -93,12 +93,15 @@ class ConfigServiceProvider implements ServiceProviderInterface $paths = $locator->findResources('plugins://'); $files += (new ConfigFileFinder)->setBase('plugins')->locateInFolders($paths); - $config = new CompiledConfig($cache, $files, GRAV_ROOT); - $config->setBlueprints(function() use ($container) { + $compiled = new CompiledConfig($cache, $files, GRAV_ROOT); + $compiled->setBlueprints(function() use ($container) { return $container['blueprints']; }); - return $config->name("master-{$setup->environment}")->load(); + $config = $compiled->name("master-{$setup->environment}")->load(); + $config->environment = $setup->environment; + + return $config; } public static function languages(Container $container) diff --git a/system/src/Grav/Common/Service/SetupServiceProvider.php b/system/src/Grav/Common/Service/SetupServiceProvider.php new file mode 100644 index 000000000..37180f783 --- /dev/null +++ b/system/src/Grav/Common/Service/SetupServiceProvider.php @@ -0,0 +1,26 @@ +init(); + + return $setup; + }; + } +} diff --git a/system/src/Grav/Common/Service/StreamsServiceProvider.php b/system/src/Grav/Common/Service/StreamsServiceProvider.php index a2ebcc671..bfd826919 100644 --- a/system/src/Grav/Common/Service/StreamsServiceProvider.php +++ b/system/src/Grav/Common/Service/StreamsServiceProvider.php @@ -20,22 +20,22 @@ class StreamsServiceProvider implements ServiceProviderInterface { public function register(Container $container) { - $container['locator'] = function($c) { + $container['locator'] = function(Container $container) { $locator = new UniformResourceLocator(GRAV_ROOT); /** @var Setup $setup */ - $setup = $c['setup']; + $setup = $container['setup']; $setup->initializeLocator($locator); return $locator; }; - $container['streams'] = function($c) { + $container['streams'] = function(Container $container) { /** @var Setup $setup */ - $setup = $c['setup']; + $setup = $container['setup']; /** @var UniformResourceLocator $locator */ - $locator = $c['locator']; + $locator = $container['locator']; // Set locator to both streams. Stream::setLocator($locator); diff --git a/system/src/Grav/Console/Cli/SchedulerCommand.php b/system/src/Grav/Console/Cli/SchedulerCommand.php index b75fb1bf5..e115eb04a 100644 --- a/system/src/Grav/Console/Cli/SchedulerCommand.php +++ b/system/src/Grav/Console/Cli/SchedulerCommand.php @@ -53,10 +53,10 @@ class SchedulerCommand extends ConsoleCommand { // error_reporting(1); $grav = Grav::instance(); + $grav->setup(); $grav['uri']->init(); $grav['config']->init(); - $grav['streams']; $grav['plugins']->init(); $grav['themes']->init(); $grav['backups']->init(); diff --git a/system/src/Grav/Console/Cli/SecurityCommand.php b/system/src/Grav/Console/Cli/SecurityCommand.php index 8e8cf6313..81e3020a7 100644 --- a/system/src/Grav/Console/Cli/SecurityCommand.php +++ b/system/src/Grav/Console/Cli/SecurityCommand.php @@ -38,19 +38,16 @@ class SecurityCommand extends ConsoleCommand */ protected function serve() { - - /** @var Grav $grav */ $grav = Grav::instance(); + $grav->setup(); $grav['uri']->init(); $grav['config']->init(); $grav['debugger']->enabled(false); - $grav['streams']; $grav['plugins']->init(); $grav['themes']->init(); - $grav['twig']->init(); $grav['pages']->init();