From 39980d8346d1e5a231ff81ca66e4d0c219706e3c Mon Sep 17 00:00:00 2001 From: Flynsarmy Date: Sun, 22 Mar 2020 16:32:27 +1000 Subject: [PATCH 1/7] Add formGetRedirectUrl method. (#4954) Fixes #4946. Documented in https://github.com/octobercms/docs/pull/432 --- modules/backend/behaviors/FormController.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/backend/behaviors/FormController.php b/modules/backend/behaviors/FormController.php index 175571f54..b918a89c3 100644 --- a/modules/backend/behaviors/FormController.php +++ b/modules/backend/behaviors/FormController.php @@ -474,7 +474,7 @@ class FormController extends ControllerBehavior } if (post('redirect', true)) { - $redirectUrl = $this->getRedirectUrl($context); + $redirectUrl = $this->controller->formGetRedirectUrl($context, $model); } if ($model && $redirectUrl) { @@ -493,13 +493,15 @@ class FormController extends ControllerBehavior } /** - * Internal method that returns a redirect URL from the config based on - * supplied context. Otherwise the default redirect is used. + * Returns a redirect URL from the config based on supplied context. + * Otherwise the default redirect is used. Relative URLs are treated as + * backend URLs. * * @param string $context Redirect context, eg: create, update, delete. + * @param Model $model The active model. * @return string */ - protected function getRedirectUrl($context = null) + public function formGetRedirectUrl($context = null, $model = null) { $redirectContext = explode('-', $context, 2)[0]; $redirectSource = ends_with($context, '-close') ? 'redirectClose' : 'redirect'; From 3450921c260b4827e4234e6edb55ac5004db7d74 Mon Sep 17 00:00:00 2001 From: jacobdekeizer Date: Mon, 23 Mar 2020 10:12:49 +0100 Subject: [PATCH 2/7] Fix docbocks ListController behaviour. (#4989) * Fix docbocks ListController behaviour. --- modules/backend/behaviors/ListController.php | 50 +++++++++++--------- modules/backend/traits/WidgetMaker.php | 2 +- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/modules/backend/behaviors/ListController.php b/modules/backend/behaviors/ListController.php index 06709017d..0a14fff18 100644 --- a/modules/backend/behaviors/ListController.php +++ b/modules/backend/behaviors/ListController.php @@ -42,17 +42,17 @@ class ListController extends ControllerBehavior protected $listConfig = []; /** - * @var \Backend\Classes\WidgetBase Reference to the list widget object. + * @var \Backend\Classes\WidgetBase[] Reference to the list widget object. */ protected $listWidgets = []; /** - * @var \Backend\Classes\WidgetBase Reference to the toolbar widget objects. + * @var \Backend\Classes\WidgetBase[] Reference to the toolbar widget objects. */ protected $toolbarWidgets = []; /** - * @var \Backend\Classes\WidgetBase Reference to the filter widget objects. + * @var \Backend\Classes\WidgetBase[] Reference to the filter widget objects. */ protected $filterWidgets = []; @@ -114,7 +114,7 @@ class ListController extends ControllerBehavior /** * Prepare the widgets used by this action - * @return void + * @return \Backend\Widgets\Lists */ public function makeList($definition = null) { @@ -165,7 +165,7 @@ class ListController extends ControllerBehavior /* * List Widget with extensibility */ - $widget = $this->makeWidget('Backend\Widgets\Lists', $columnConfig); + $widget = $this->makeWidget(\Backend\Widgets\Lists::class, $columnConfig); $widget->bindEvent('list.extendColumns', function () use ($widget) { $this->controller->listExtendColumns($widget); @@ -203,7 +203,7 @@ class ListController extends ControllerBehavior if (isset($listConfig->toolbar)) { $toolbarConfig = $this->makeConfig($listConfig->toolbar); $toolbarConfig->alias = $widget->alias . 'Toolbar'; - $toolbarWidget = $this->makeWidget('Backend\Widgets\Toolbar', $toolbarConfig); + $toolbarWidget = $this->makeWidget(\Backend\Widgets\Toolbar::class, $toolbarConfig); $toolbarWidget->bindToController(); $toolbarWidget->cssClasses[] = 'list-header'; @@ -236,7 +236,7 @@ class ListController extends ControllerBehavior $filterConfig = $this->makeConfig($listConfig->filter); $filterConfig->alias = $widget->alias . 'Filter'; - $filterWidget = $this->makeWidget('Backend\Widgets\Filter', $filterConfig); + $filterWidget = $this->makeWidget(\Backend\Widgets\Filter::class, $filterConfig); $filterWidget->bindToController(); /* @@ -286,6 +286,7 @@ class ListController extends ControllerBehavior /** * Bulk delete records. * @return void + * @throws \October\Rain\Exception\ApplicationException when the parent definition is missing. */ public function index_onDelete() { @@ -353,6 +354,7 @@ class ListController extends ControllerBehavior * Renders the widget collection. * @param string $definition Optional list definition. * @return string Rendered HTML for the list. + * @throws \October\Rain\Exception\ApplicationException when there are no list widgets set. */ public function listRender($definition = null) { @@ -455,7 +457,7 @@ class ListController extends ControllerBehavior /** * Called after the list columns are defined. - * @param \Backend\Widgets\List $host The hosting list widget + * @param \Backend\Widgets\Lists $host The hosting list widget * @return void */ public function listExtendColumns($host) @@ -473,8 +475,9 @@ class ListController extends ControllerBehavior /** * Controller override: Extend supplied model - * @param Model $model - * @return Model + * @param \October\Rain\Database\Model $model + * @param string|null $definition + * @return \October\Rain\Database\Model */ public function listExtendModel($model, $definition = null) { @@ -485,6 +488,7 @@ class ListController extends ControllerBehavior * Controller override: Extend the query used for populating the list * before the default query is processed. * @param \October\Rain\Database\Builder $query + * @param string|null $definition */ public function listExtendQueryBefore($query, $definition = null) { @@ -494,6 +498,7 @@ class ListController extends ControllerBehavior * Controller override: Extend the query used for populating the list * after the default query is processed. * @param \October\Rain\Database\Builder $query + * @param string|null $definition */ public function listExtendQuery($query, $definition = null) { @@ -502,7 +507,8 @@ class ListController extends ControllerBehavior /** * Controller override: Extend the records used for populating the list * after the query is processed. - * @param Illuminate\Contracts\Pagination\LengthAwarePaginator|Illuminate\Database\Eloquent\Collection $records + * @param \Illuminate\Contracts\Pagination\LengthAwarePaginator|\Illuminate\Database\Eloquent\Collection $records + * @param string|null $definition */ public function listExtendRecords($records, $definition = null) { @@ -520,9 +526,9 @@ class ListController extends ControllerBehavior /** * Returns a CSS class name for a list row (). - * @param Model $record The populated model used for the column - * @param string $definition List definition (optional) - * @return string CSS class name + * @param \October\Rain\Database\Model $record The populated model used for the column + * @param string|null $definition List definition (optional) + * @return string|void CSS class name */ public function listInjectRowClass($record, $definition = null) { @@ -530,10 +536,10 @@ class ListController extends ControllerBehavior /** * Replace a table column value (...) - * @param Model $record The populated model used for the column + * @param \October\Rain\Database\Model $record The populated model used for the column * @param string $columnName The column name to override - * @param string $definition List definition (optional) - * @return string HTML view + * @param string|null $definition List definition (optional) + * @return string|void HTML view */ public function listOverrideColumnValue($record, $columnName, $definition = null) { @@ -542,8 +548,8 @@ class ListController extends ControllerBehavior /** * Replace the entire table header contents (...) with custom HTML * @param string $columnName The column name to override - * @param string $definition List definition (optional) - * @return string HTML view + * @param string|null $definition List definition (optional) + * @return string|void HTML view */ public function listOverrideHeaderValue($columnName, $definition = null) { @@ -557,7 +563,7 @@ class ListController extends ControllerBehavior public static function extendListColumns($callback) { $calledClass = self::getCalledExtensionClass(); - Event::listen('backend.list.extendColumns', function ($widget) use ($calledClass, $callback) { + Event::listen('backend.list.extendColumns', function (\Backend\Widgets\Lists $widget) use ($calledClass, $callback) { if (!is_a($widget->getController(), $calledClass)) { return; } @@ -565,7 +571,7 @@ class ListController extends ControllerBehavior }); } - /** + /** * Static helper for extending filter scopes. * @param callable $callback * @return void @@ -573,7 +579,7 @@ class ListController extends ControllerBehavior public static function extendListFilterScopes($callback) { $calledClass = self::getCalledExtensionClass(); - Event::listen('backend.filter.extendScopes', function ($widget) use ($calledClass, $callback) { + Event::listen('backend.filter.extendScopes', function (\Backend\Widgets\Filter $widget) use ($calledClass, $callback) { if (!is_a($widget->getController(), $calledClass)) { return; } diff --git a/modules/backend/traits/WidgetMaker.php b/modules/backend/traits/WidgetMaker.php index 0ed7049b0..a26a8ab29 100644 --- a/modules/backend/traits/WidgetMaker.php +++ b/modules/backend/traits/WidgetMaker.php @@ -19,7 +19,7 @@ trait WidgetMaker * Makes a widget object with the supplied configuration file. * @param string $class Widget class name * @param array $widgetConfig An array of config. - * @return \Backend\Classes\WidgetBase The widget object + * @return mixed|\Backend\Classes\WidgetBase The widget object */ public function makeWidget($class, $widgetConfig = []) { From c79bea7449b48b2d4963e78b83573c54516786be Mon Sep 17 00:00:00 2001 From: Klaas Poortinga Date: Wed, 25 Mar 2020 21:47:39 +0100 Subject: [PATCH 3/7] Modify codeditor widget to implement html attributes set through form field definition (#5001) --- .../backend/formwidgets/codeeditor/partials/_codeeditor.htm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/backend/formwidgets/codeeditor/partials/_codeeditor.htm b/modules/backend/formwidgets/codeeditor/partials/_codeeditor.htm index d8609f688..33d1c9721 100644 --- a/modules/backend/formwidgets/codeeditor/partials/_codeeditor.htm +++ b/modules/backend/formwidgets/codeeditor/partials/_codeeditor.htm @@ -24,7 +24,8 @@ data-read-only="" data-language="" data-margin="" - data-vendor-path=""> + data-vendor-path="" + formField->getAttributes() ?>>
  • From 6dbfdd7e6530aa9987dcbe4bb39a6fec824d4321 Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Thu, 26 Mar 2020 23:40:01 +0800 Subject: [PATCH 4/7] Allow quotes to be correctly handled by october:env (#4986) This fix will apply quotes around string environment variables which contain either a single, or double, quote as well as any variables with a hash symbol - escaping any double-quotes encountered. When artisan october:env is run, this should correctly transfer all configuration values from the config files to the .env file. Fixes #4979. --- modules/system/console/OctoberEnv.php | 17 +-- tests/fixtures/config/app.php | 9 ++ tests/fixtures/config/cache.php | 6 + tests/fixtures/config/cms.php | 10 ++ tests/fixtures/config/database.php | 16 +++ tests/fixtures/config/mail.php | 11 ++ tests/fixtures/config/queue.php | 6 + tests/fixtures/config/session.php | 6 + tests/unit/system/console/OctoberEnvTest.php | 130 +++++++++++++++++++ 9 files changed, 200 insertions(+), 11 deletions(-) create mode 100644 tests/fixtures/config/app.php create mode 100644 tests/fixtures/config/cache.php create mode 100644 tests/fixtures/config/cms.php create mode 100644 tests/fixtures/config/database.php create mode 100644 tests/fixtures/config/mail.php create mode 100644 tests/fixtures/config/queue.php create mode 100644 tests/fixtures/config/session.php create mode 100644 tests/unit/system/console/OctoberEnvTest.php diff --git a/modules/system/console/OctoberEnv.php b/modules/system/console/OctoberEnv.php index 62000a7aa..99bfbf66d 100644 --- a/modules/system/console/OctoberEnv.php +++ b/modules/system/console/OctoberEnv.php @@ -203,7 +203,7 @@ class OctoberEnv extends Command private function saveEnvSettings($key, $value) { if (! $this->envKeyExists($key)) { - $line = sprintf("%s=%s\n", $key, $this->stripQuotes($value)); + $line = sprintf("%s=%s\n", $key, $value); if ($this->config == 'database' && $key != 'DB_CONNECTION') { $this->writeDbEnvSettings($line); @@ -266,7 +266,11 @@ class OctoberEnv extends Command private function normalize($value) { if (is_string($value)) { - return "'$value'"; + if (preg_match('/["\'#]/', $value)) { + return '"' . str_replace('"', '\\"', $value) . '"'; + } else { + return $value; + } } elseif (is_bool($value)) { return $value ? 'true' : 'false'; } elseif ($value === null) { @@ -276,15 +280,6 @@ class OctoberEnv extends Command return $value; } - /** - * @param $string - * @return string - */ - private function stripQuotes($string) - { - return strtr($string, ['"' => '', "'" => '']); - } - /** * @param $matches * @return bool diff --git a/tests/fixtures/config/app.php b/tests/fixtures/config/app.php new file mode 100644 index 000000000..35a840794 --- /dev/null +++ b/tests/fixtures/config/app.php @@ -0,0 +1,9 @@ + true, + 'url' => 'https://localhost', + 'key' => 'CHANGE_ME!!!!!!!!!!!!!!!!!!!!!!!', + 'timezone' => 'UTC', +]; diff --git a/tests/fixtures/config/cache.php b/tests/fixtures/config/cache.php new file mode 100644 index 000000000..c3638a2c6 --- /dev/null +++ b/tests/fixtures/config/cache.php @@ -0,0 +1,6 @@ + 'file', +]; diff --git a/tests/fixtures/config/cms.php b/tests/fixtures/config/cms.php new file mode 100644 index 000000000..806a6e642 --- /dev/null +++ b/tests/fixtures/config/cms.php @@ -0,0 +1,10 @@ + false, + 'enableAssetCache' => false, + 'databaseTemplates' => false, + 'linkPolicy' => 'detect', + 'enableCsrfProtection' => true, +]; diff --git a/tests/fixtures/config/database.php b/tests/fixtures/config/database.php new file mode 100644 index 000000000..d17612d79 --- /dev/null +++ b/tests/fixtures/config/database.php @@ -0,0 +1,16 @@ + 'mysql', + 'connections' => [ + 'mysql' => [ + 'host' => 'localhost', + 'port' => 3306, + 'database' => 'data#base', + 'username' => 'teal\'c', + 'password' => 'test"quotes\'test', + ], + ], + 'useConfigForTesting' => false, +]; diff --git a/tests/fixtures/config/mail.php b/tests/fixtures/config/mail.php new file mode 100644 index 000000000..e7a354d57 --- /dev/null +++ b/tests/fixtures/config/mail.php @@ -0,0 +1,11 @@ + 'smtp', + 'host' => 'smtp.mailgun.org', + 'port' => 587, + 'encryption' => 'tls', + 'username' => null, + 'password' => null, +]; diff --git a/tests/fixtures/config/queue.php b/tests/fixtures/config/queue.php new file mode 100644 index 000000000..570cdd6e9 --- /dev/null +++ b/tests/fixtures/config/queue.php @@ -0,0 +1,6 @@ + 'sync', +]; diff --git a/tests/fixtures/config/session.php b/tests/fixtures/config/session.php new file mode 100644 index 000000000..6c00ef5e7 --- /dev/null +++ b/tests/fixtures/config/session.php @@ -0,0 +1,6 @@ + 'file', +]; diff --git a/tests/unit/system/console/OctoberEnvTest.php b/tests/unit/system/console/OctoberEnvTest.php new file mode 100644 index 000000000..d05f43794 --- /dev/null +++ b/tests/unit/system/console/OctoberEnvTest.php @@ -0,0 +1,130 @@ +setUpConfigFixtures(); + $this->stubOutEnvFile(); + } + + public function testCommand() + { + $command = new OctoberEnv(); + $command->setLaravel($this->app); + $command->run(new ArrayInput([]), new NullOutput); + + // Check environment file + $envFile = file_get_contents(base_path('.env')); + + // Forward compatible assertions + // @TODO: Use only `assertStringContainsString` after L6 upgrade + + if (method_exists($this, 'assertStringContainsString')) { + $this->assertStringContainsString('APP_DEBUG=true', $envFile); + $this->assertStringContainsString('APP_URL=https://localhost', $envFile); + $this->assertStringContainsString('DB_CONNECTION=mysql', $envFile); + $this->assertStringContainsString('DB_DATABASE="data#base"', $envFile); + $this->assertStringContainsString('DB_USERNAME="teal\'c"', $envFile); + $this->assertStringContainsString('DB_PASSWORD="test\\"quotes\'test"', $envFile); + $this->assertStringContainsString('DB_PORT=3306', $envFile); + } else { + $this->assertContains('APP_DEBUG=true', $envFile); + $this->assertContains('APP_URL=https://localhost', $envFile); + $this->assertContains('DB_CONNECTION=mysql', $envFile); + $this->assertContains('DB_DATABASE="data#base"', $envFile); + $this->assertContains('DB_USERNAME="teal\'c"', $envFile); + $this->assertContains('DB_PASSWORD="test\\"quotes\'test"', $envFile); + $this->assertContains('DB_PORT=3306', $envFile); + } + } + + protected function tearDown() + { + $this->tearDownConfigFixtures(); + $this->restoreEnvFile(); + + parent::tearDown(); + } + + protected function setUpConfigFixtures() + { + // Mock config path and copy fixtures + if (!is_dir(storage_path('temp/tests/config'))) { + mkdir(storage_path('temp/tests/config'), 0777, true); + } + + foreach (glob(base_path('tests/fixtures/config/*.php')) as $file) { + $path = pathinfo($file); + copy($file, storage_path('temp/tests/config/' . $path['basename'])); + } + + static::$fixturesCopied = true; + + // Store original config path + static::$origConfigPath = $this->app->make('path.config'); + + $this->app->instance('path.config', storage_path('temp/tests/config')); + + // Re-load configuration + $configBootstrap = new LoadConfiguration; + $configBootstrap->bootstrap($this->app); + } + + protected function tearDownConfigFixtures() + { + // Remove copied config fixtures + if (static::$fixturesCopied) { + foreach (glob(storage_path('temp/tests/config/*.php')) as $file) { + unlink($file); + } + rmdir(storage_path('temp/tests/config')); + rmdir(storage_path('temp/tests')); + + static::$fixturesCopied = false; + } + + // Restore config path + if (self::$origConfigPath) { + $this->app->instance('path.config', static::$origConfigPath); + + static::$origConfigPath = null; + } + + // Re-load configuration + $configBootstrap = new LoadConfiguration; + $configBootstrap->bootstrap($this->app); + } + + protected function stubOutEnvFile() + { + if (file_exists(base_path('.env.stub'))) { + unlink(base_path('.env.stub')); + } + if (file_exists(base_path('.env'))) { + rename(base_path('.env'), base_path('.env.stub')); + } + } + + protected function restoreEnvFile() + { + unlink(base_path('.env')); + + if (file_exists(base_path('.env.stub'))) { + rename(base_path('.env.stub'), base_path('.env')); + } + } +} From bd2a774a58aa5c3b210a56b04d758f9d76a2b129 Mon Sep 17 00:00:00 2001 From: Fl0Cri Date: Thu, 26 Mar 2020 20:17:51 +0100 Subject: [PATCH 5/7] Add UTF-8 BOM when exporting with useList option (#4873) Same as #1958 but when using the list controller without an ExportModel (with `useList` in the export options) --- modules/backend/behaviors/ImportExportController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/backend/behaviors/ImportExportController.php b/modules/backend/behaviors/ImportExportController.php index 88e063ce7..950234362 100644 --- a/modules/backend/behaviors/ImportExportController.php +++ b/modules/backend/behaviors/ImportExportController.php @@ -619,6 +619,7 @@ class ImportExportController extends ControllerBehavior * Prepare CSV */ $csv = CsvWriter::createFromFileObject(new SplTempFileObject); + $csv->setOutputBOM(CsvWriter::BOM_UTF8); $csv->setDelimiter($options['delimiter']); $csv->setEnclosure($options['enclosure']); $csv->setEscape($options['escape']); From cbfa309c39f9d633aa85e72c9196fd4ab83ed253 Mon Sep 17 00:00:00 2001 From: Klaas Poortinga Date: Thu, 26 Mar 2020 20:38:40 +0100 Subject: [PATCH 6/7] Modify password field to support placeholder attribute (#5003) --- modules/backend/widgets/form/partials/_field_password.htm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/backend/widgets/form/partials/_field_password.htm b/modules/backend/widgets/form/partials/_field_password.htm index 578f660d2..86f361d5c 100644 --- a/modules/backend/widgets/form/partials/_field_password.htm +++ b/modules/backend/widgets/form/partials/_field_password.htm @@ -7,9 +7,10 @@ name="getName() ?>" id="getId() ?>" value="" + placeholder="placeholder)) ?>" class="form-control" autocomplete="off" hasAttribute('maxlength') ? '' : 'maxlength="255"' ?> getAttributes() ?> /> - \ No newline at end of file + From 61cadeb6231a91eae2571e32a9bdcd144ed6cc1b Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Fri, 27 Mar 2020 14:48:45 +0800 Subject: [PATCH 7/7] Switch PHP Parallel Lint provider. jakub-onderka/php-parallel-lint has been abandoned, and the original author has recommended swithcing to php-parallel-lint/php-parallel-lint. Fixes #5007. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a4a140a12..1ce60636f 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,7 @@ "phpunit/phpunit-selenium": "~1.2", "meyfa/phpunit-assert-gd": "1.1.0", "squizlabs/php_codesniffer": "3.*", - "jakub-onderka/php-parallel-lint": "^1.0" + "php-parallel-lint/php-parallel-lint": "^1.0" }, "autoload-dev": { "classmap": [