From d6d95b0f4e7fd9aa36971f536543bb7dae976558 Mon Sep 17 00:00:00 2001 From: Brad Bell Date: Thu, 10 Aug 2017 14:04:19 -0700 Subject: [PATCH 01/79] Added the [onLockUser](https://craftcms.com/docs/plugins/events-reference#users-onLockUser) event, which fires when a user account is locked. --- CHANGELOG.md | 3 +++ src/services/UsersService.php | 26 +++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 843d8e1ca4f..82a9311e380 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ Craft CMS Changelog ## Unreleased +### Added +- Added the [onLockUser](https://craftcms.com/docs/plugins/events-reference#users-onLockUser) event, which fires when a user account is locked. + ### Fixed - Fixed a bug where the PHP and DB versions the Craft Support widget passed to GitHub would not escape tildes (`~`), potentially having Markdown confuse them for strikethrough markup delimiters. - Fixed a bug where it was possible for users to be redirected to a 404 in the Control Panel after logging in. ([#1901](https://github.com/craftcms/cms/issues/1901)) diff --git a/src/services/UsersService.php b/src/services/UsersService.php index 3ffa6c3f613..0f696015bae 100644 --- a/src/services/UsersService.php +++ b/src/services/UsersService.php @@ -662,6 +662,7 @@ public function handleInvalidLogin(UserModel $user) { $userRecord = $this->_getUserRecordById($user->id); $currentTime = DateTimeHelper::currentUTCDateTime(); + $locked = false; $userRecord->lastInvalidLoginDate = $user->lastInvalidLoginDate = $currentTime; $userRecord->lastLoginAttemptIPAddress = craft()->request->getUserHostAddress(); @@ -682,6 +683,7 @@ public function handleInvalidLogin(UserModel $user) $userRecord->invalidLoginCount = null; $userRecord->invalidLoginWindowStart = null; $userRecord->lockoutDate = $user->lockoutDate = $currentTime; + $locked = true; } } else @@ -695,7 +697,17 @@ public function handleInvalidLogin(UserModel $user) $user->invalidLoginCount = $userRecord->invalidLoginCount; } - return $userRecord->save(); + $saveSuccess = $userRecord->save(); + + if ($locked) + { + // Fire an 'onLockUser' event + $this->onLockUser(new Event($this, array( + 'user' => $user + ))); + } + + return $saveSuccess; } /** @@ -1378,6 +1390,18 @@ public function onUnlockUser(Event $event) $this->raiseEvent('onUnlockUser', $event); } + /** + * Fires an 'onLockUser' event. + * + * @param Event $event + * + * @return null + */ + public function onLockUser(Event $event) + { + $this->raiseEvent('onLockUser', $event); + } + /** * Fires an 'onBeforeSuspendUser' event. * From b8ccc43ba0ab0b5490a0c48b50994d6bd0d91fcf Mon Sep 17 00:00:00 2001 From: Brad Bell Date: Fri, 11 Aug 2017 12:22:56 -0700 Subject: [PATCH 02/79] Fixed a bug where users would get one extra try to login added to whatever the maxInvalidLogins config setting was set to. --- CHANGELOG.md | 1 + src/services/UsersService.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82a9311e380..41016a0ee52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Craft CMS Changelog ### Fixed - Fixed a bug where the PHP and DB versions the Craft Support widget passed to GitHub would not escape tildes (`~`), potentially having Markdown confuse them for strikethrough markup delimiters. - Fixed a bug where it was possible for users to be redirected to a 404 in the Control Panel after logging in. ([#1901](https://github.com/craftcms/cms/issues/1901)) +- Fixed a bug where users would get one extra try to login added to whatever the [maxInvalidLogins](https://craftcms.com/docs/config-settings#maxInvalidLogins) config setting was set to. ## 2.6.2988 2017-07-28 diff --git a/src/services/UsersService.php b/src/services/UsersService.php index 0f696015bae..3cab29aaebb 100644 --- a/src/services/UsersService.php +++ b/src/services/UsersService.php @@ -676,7 +676,7 @@ public function handleInvalidLogin(UserModel $user) $userRecord->invalidLoginCount++; // Was that one bad password too many? - if ($userRecord->invalidLoginCount > $maxInvalidLogins) + if ($userRecord->invalidLoginCount >= $maxInvalidLogins) { $userRecord->locked = true; $user->locked = true; From e1abdd5dac13d228440271347e2f74160ce336b3 Mon Sep 17 00:00:00 2001 From: Sebastian Weyrauch Date: Mon, 14 Aug 2017 09:15:06 +0200 Subject: [PATCH 03/79] added data-type attributes for matrix blocks (same attribute name as for the buttons) --- src/templates/_components/fieldtypes/Matrix/input.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/_components/fieldtypes/Matrix/input.html b/src/templates/_components/fieldtypes/Matrix/input.html index 42af8b060f5..bf8bbfa41cb 100644 --- a/src/templates/_components/fieldtypes/Matrix/input.html +++ b/src/templates/_components/fieldtypes/Matrix/input.html @@ -10,7 +10,7 @@ {% set blockId = 'new'~totalNewBlocks %} {% endif %} -
+
{% if not static %} From 7fb9213fd4513f33c9a0f00472fe0520bbc6a76a Mon Sep 17 00:00:00 2001 From: Mark Huot Date: Mon, 14 Aug 2017 17:18:54 -0400 Subject: [PATCH 04/79] configuring install through cli --- composer.json | 1 + src/base/ApplicationTrait.php | 2 +- src/console/controllers/MigrateController.php | 86 +++++++++++++++++++ src/db/MigrationManager.php | 4 + 4 files changed, 92 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index cd1b7e944a7..b27793dfe3b 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,7 @@ "league/flysystem": "~1.0.35", "mikehaertl/php-shellcommand": "~1.2.5", "pixelandtonic/imagine": "0.7.1.1", + "seld/cli-prompt": "^1.0", "twig/twig": "~2.3.0", "yiisoft/yii2": "~2.0.12.0", "yiisoft/yii2-debug": "2.0.8", diff --git a/src/base/ApplicationTrait.php b/src/base/ApplicationTrait.php index 01252f1c5e2..cba4ec5c339 100644 --- a/src/base/ApplicationTrait.php +++ b/src/base/ApplicationTrait.php @@ -261,7 +261,7 @@ public function getIsInstalled(): bool return false; } - return $this->_isInstalled = (bool)($this->getRequest()->getIsConsoleRequest() || $this->getDb()->tableExists('{{%info}}', false)); + return $this->_isInstalled = (bool)($this->getDb()->tableExists('{{%info}}', false)); } /** diff --git a/src/console/controllers/MigrateController.php b/src/console/controllers/MigrateController.php index b900715834f..33f691838ed 100644 --- a/src/console/controllers/MigrateController.php +++ b/src/console/controllers/MigrateController.php @@ -58,6 +58,36 @@ class MigrateController extends BaseMigrateController */ public $plugin; + /** + * @var string|null The default email address for the first user to create during install + */ + public $email; + + /** + * @var string|null The default username for the first user to create during install + */ + public $username; + + /** + * @var string|null The default password for the first user to create during install + */ + public $password; + + /** + * @var string|null The default site name for the first site to create during install + */ + public $siteName; + + /** + * @var string|null The default site url for the first site to create during install + */ + public $siteUrl; + + /** + * @var string|null The default langcode for the first site to create during install + */ + public $siteLangcode; + /** * @var MigrationManager|null The migration manager that will be used in this request */ @@ -87,6 +117,15 @@ public function options($actionID) $options[] = 'type'; $options[] = 'plugin'; + if ($actionID == 'install') { + $options[] = 'email'; + $options[] = 'username'; + $options[] = 'password'; + $options[] = 'siteName'; + $options[] = 'siteUrl'; + $options[] = 'siteLangcode'; + } + return $options; } @@ -177,6 +216,53 @@ public function actionCreate($name) } } + public function actionInstall() + { + // Run the install migration + $migrator = Craft::$app->getMigrator(); + + $email = $this->email ?: $this->prompt('Email', ['required' => true]); + $username = $this->username ?: $this->prompt('Username', ['required' => true]); + + if ($this->password) { + $password = $this->password; + } + else { + echo 'Password '; + $password = \Seld\CliPrompt\CliPrompt::hiddenPrompt(); + } + + $siteName = $this->siteName ?: $this->prompt('Site Name', ['required' => true]); + $siteUrl = $this->siteUrl ?: $this->prompt('Site Url', ['required' => true]); + $siteLangcode = $this->siteLangcode ?: $this->prompt('Site Langcode', ['required' => true]); + + $site = new Site([ + 'name' => $siteName, + 'handle' => 'default', + 'hasUrls' => true, + 'baseUrl' => $siteUrl, + 'language' => $siteLangcode, + ]); + + $migration = new Install([ + 'username' => $username, + 'password' => $password, + 'email' => $email, + 'site' => $site, + ]); + + if ($migrator->migrateUp($migration) !== false) { + $this->stdout("{$siteName} was successfully installed.\n", Console::FG_GREEN); + + // Mark all existing migrations as applied + foreach ($migrator->getNewMigrations() as $name) { + $migrator->addMigrationHistory($name); + } + } else { + $this->stderr("There was a problem installing {$siteName}.\n", Console::FG_GREEN); + } + } + // Protected Methods // ========================================================================= diff --git a/src/db/MigrationManager.php b/src/db/MigrationManager.php index 8d756ce1a55..cd7446cd0a4 100644 --- a/src/db/MigrationManager.php +++ b/src/db/MigrationManager.php @@ -336,6 +336,10 @@ public function migrateDown($migration) */ public function getMigrationHistory(int $limit = 0): array { + if (Craft::$app->getIsInstalled() == false) { + return []; + } + $query = $this->_createMigrationQuery(); if ($limit !== 0) { $query->limit($limit); From 3e78f8414a21ee5348d80d6e9d6a47e22caa80f6 Mon Sep 17 00:00:00 2001 From: Mark Huot Date: Mon, 14 Aug 2017 17:32:08 -0400 Subject: [PATCH 05/79] fixing missing use statements --- src/console/controllers/MigrateController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/console/controllers/MigrateController.php b/src/console/controllers/MigrateController.php index 33f691838ed..a6eee3e46d1 100644 --- a/src/console/controllers/MigrateController.php +++ b/src/console/controllers/MigrateController.php @@ -11,6 +11,8 @@ use craft\base\Plugin; use craft\db\MigrationManager; use craft\helpers\FileHelper; +use craft\migrations\Install; +use craft\models\Site; use yii\console\controllers\BaseMigrateController; use yii\console\Exception; use yii\helpers\Console; From e02b9da3bef1ad7c50aba534a9ae6f7e43e5f4e3 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Mon, 14 Aug 2017 17:55:21 -0700 Subject: [PATCH 06/79] Fixed #1911 --- CHANGELOG-v3.md | 1 + src/controllers/UtilitiesController.php | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index a72acecbaf9..ac9e77a6b94 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -68,6 +68,7 @@ Craft CMS 3.0 Working Changelog - Fixed a 404 error for `bootstrap.js` that occurred when the Debug Toolbar was opened. - Fixed some deprecation errors caused by relational and Matrix field inputs. - Fixed a bug where a plugin would get a PHP error if it tried to get the current site in the middle of a Craft update. +- Fixed a bug where the Migrations utility would display an error message even if the migrations were applied successfully. ([#1911](https://github.com/craftcms/cms/issues/1911)) ## 3.0.0-beta.23 - 2017-07-28 diff --git a/src/controllers/UtilitiesController.php b/src/controllers/UtilitiesController.php index b7917825f47..09f62634484 100644 --- a/src/controllers/UtilitiesController.php +++ b/src/controllers/UtilitiesController.php @@ -14,6 +14,7 @@ use craft\base\UtilityInterface; use craft\db\Query; use craft\elements\Asset; +use craft\errors\MigrationException; use craft\helpers\FileHelper; use craft\helpers\Path; use craft\queue\jobs\FindAndReplace; @@ -547,9 +548,10 @@ public function actionApplyNewMigrations() $migrator = Craft::$app->getContentMigrator(); - if ($migrator->up(0)) { + try { + $migrator->up(); Craft::$app->getSession()->setNotice(Craft::t('app', 'Applied new migrations successfully.')); - } else { + } catch (MigrationException $e) { Craft::$app->getSession()->setError(Craft::t('app', 'Couldn’t apply new migrations.')); } From dd0f2499b6ad23ba2e325680aa11d3eab335ef16 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Mon, 14 Aug 2017 18:24:57 -0700 Subject: [PATCH 07/79] Changelog for #1915 --- CHANGELOG-v3.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index ac9e77a6b94..f5796d643d9 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -35,6 +35,7 @@ Craft CMS 3.0 Working Changelog - Renamed `craft\web\twig\nodes\GetAttr` to `GetAttrNode`. - `craft\base\Volume` is now only focussed on things that every volume would need, regardless of whether it will use Flysystem under the hood. - `craft\base\VolumeInterface::createFileByStream()`, `updateFileByStream()`, `deleteFile()`, `renameFile()`, `copyFile()`, `createDir()`, `deleteDir()`, and `renameDir()` no longer require their implementation methods to return a boolean value. +- `div.matrixblock` elements in the Control Panel now have a `data-type` attribute set to the Matrix block type’s handle. ([#1915](https://github.com/craftcms/cms/pull/1915)) ### Deprecated - Looping through element queries directly is now deprecated. Use the `all()` function to fetch the query results before looping over them. ([#1902](https://github.com/craftcms/cms/issues/1902)) From 5922f948399baaf76bb33162234b40fca696e4a8 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Mon, 14 Aug 2017 19:47:09 -0700 Subject: [PATCH 08/79] Bump schema version (fixes #1918) --- src/config/app/main.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/app/main.php b/src/config/app/main.php index 4da218fab74..e872be279e6 100644 --- a/src/config/app/main.php +++ b/src/config/app/main.php @@ -4,7 +4,7 @@ 'id' => 'CraftCMS', 'name' => 'Craft CMS', 'version' => '3.0.0-beta.23', - 'schemaVersion' => '3.0.55', + 'schemaVersion' => '3.0.56', 'minVersionRequired' => '2.6.2788', 'basePath' => dirname(__DIR__, 2), // Defines the @app alias 'runtimePath' => '@storage/runtime', // Defines the @runtime alias From e47129f17ef35d258cef7c1ff0ccf0829066e6ef Mon Sep 17 00:00:00 2001 From: andris-sevcenko Date: Tue, 15 Aug 2017 11:05:47 +0300 Subject: [PATCH 09/79] Removed `craft\controllers\VolumesController::actionLoadVolumeTypeData()` --- CHANGELOG-v3.md | 1 + src/controllers/VolumesController.php | 37 --------------------------- 2 files changed, 1 insertion(+), 37 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index f5796d643d9..c07d8e94b2a 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -45,6 +45,7 @@ Craft CMS 3.0 Working Changelog - Removed `craft\base\TaskInterface`. - Removed `craft\base\TaskTrait`. - Removed `craft\controllers\TasksController`. +- Removed `craft\controllers\VolumesController::actionLoadVolumeTypeData()`. - Removed `craft\db\TaskQuery`. - Removed `craft\events\MailFailureEvent`. - Removed `craft\events\TaskEvent`. diff --git a/src/controllers/VolumesController.php b/src/controllers/VolumesController.php index 1e5aa81684a..74404684e0a 100644 --- a/src/controllers/VolumesController.php +++ b/src/controllers/VolumesController.php @@ -243,41 +243,4 @@ public function actionDeleteVolume(): Response return $this->asJson(['success' => true]); } - - /** - * Load Assets VolumeType data. - * - * This is used to, for example, load Amazon S3 bucket list or Rackspace Cloud Storage Containers. - * - * @return Response - */ - public function actionLoadVolumeTypeData(): Response - { - $this->requirePostRequest(); - $this->requireAcceptsJson(); - - $request = Craft::$app->getRequest(); - $volumeType = $request->getRequiredBodyParam('volumeType'); - $dataType = $request->getRequiredBodyParam('dataType'); - $params = $request->getBodyParam('params'); - - $volumeType = 'craft\volumes\\'.$volumeType; - - if (!class_exists($volumeType)) { - return $this->asErrorJson(Craft::t('app', 'The volume type specified does not exist!')); - } - - try { - $result = call_user_func_array( - [ - $volumeType, - 'load'.ucfirst($dataType) - ], - $params); - - return $this->asJson($result); - } catch (\Throwable $exception) { - return $this->asErrorJson($exception->getMessage()); - } - } } From ee9991309d42724fe1608b97f5c8df332bc885f9 Mon Sep 17 00:00:00 2001 From: Fred Calsen Date: Tue, 15 Aug 2017 11:23:15 +0200 Subject: [PATCH 10/79] Fixed typo --- src/queue/jobs/ResaveElements.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/queue/jobs/ResaveElements.php b/src/queue/jobs/ResaveElements.php index d53476f83d5..aeffdb68ed8 100644 --- a/src/queue/jobs/ResaveElements.php +++ b/src/queue/jobs/ResaveElements.php @@ -44,7 +44,7 @@ class ResaveElements extends BaseJob */ public function execute($queue) { - $class = $this->elementTydddhpe; + $class = $this->elementType; // Let's save ourselves some trouble and just clear all the caches for this element class Craft::$app->getTemplateCaches()->deleteCachesByElementType($class); From 9eb60e4480991d064a8b1101a26694ffa4c77591 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 15 Aug 2017 11:21:48 -0700 Subject: [PATCH 11/79] Moved the installer into its own controller, and added validation --- src/console/controllers/InstallController.php | 222 ++++++++++++++++++ src/console/controllers/MigrateController.php | 88 ------- src/db/MigrationManager.php | 4 - 3 files changed, 222 insertions(+), 92 deletions(-) create mode 100644 src/console/controllers/InstallController.php diff --git a/src/console/controllers/InstallController.php b/src/console/controllers/InstallController.php new file mode 100644 index 00000000000..def36b936e6 --- /dev/null +++ b/src/console/controllers/InstallController.php @@ -0,0 +1,222 @@ + + * @since 3.0 + */ +class InstallController extends Controller +{ + // Properties + // ========================================================================= + + /** + * @var string|null The default email address for the first user to create during install + */ + public $email; + + /** + * @var string|null The default username for the first user to create during install + */ + public $username; + + /** + * @var string|null The default password for the first user to create during install + */ + public $password; + + /** + * @var string|null The default site name for the first site to create during install + */ + public $siteName; + + /** + * @var string|null The default site url for the first site to create during install + */ + public $siteUrl; + + /** + * @var string|null The default langcode for the first site to create during install + */ + public $language; + + // Public Methods + // ========================================================================= + + /** + * @inheritdoc + */ + public function options($actionID) + { + $options = parent::options($actionID); + $options[] = 'email'; + $options[] = 'username'; + $options[] = 'password'; + $options[] = 'siteName'; + $options[] = 'siteUrl'; + $options[] = 'language'; + return $options; + } + + /** + * Runs the install migration + */ + public function actionIndex() + { + if (Craft::$app->getIsInstalled()) { + $this->stdout("Craft is already installed!\n"); + return; + } + + // Validate the arguments + $errors = []; + if ($this->username && !$this->validateUsername($this->username, $error)) { + $errors[] = $error; + } + if ($this->email && !$this->validateEmail($this->email, $error)) { + $errors[] = $error; + } + if ($this->password && !$this->validatePassword($this->password, $error)) { + $errors[] = $error; + } + if ($this->siteName && !$this->validateSiteName($this->siteName, $error)) { + $errors[] = $error; + } + if ($this->siteUrl && !$this->validateSiteUrl($this->siteUrl, $error)) { + $errors[] = $error; + } + if ($this->language && !$this->validateLanguage($this->language, $error)) { + $errors[] = $error; + } + + if (!empty($errors)) { + $this->stderr("Invalid arguments:\n - ".implode("\n - ", $errors)."\n"); + return; + } + + $username = $this->username ?: $this->prompt('Username:', ['validator' => [$this, 'validateUsername'], 'default' => 'admin']); + $email = $this->email ?: $this->prompt('Email:', ['required' => true, 'validator' => [$this, 'validateEmail']]); + $password = $this->password ?: $this->_passwordPrompt(); + $siteName = $this->siteName ?: $this->prompt('Site Name:', ['required' => true, 'validator' => [$this, 'validateSiteName']]); + $siteUrl = $this->siteUrl ?: $this->prompt('Site URL:', ['required' => true, 'validator' => [$this, 'validateSiteUrl']]); + $language = $this->language ?: $this->prompt('Site Language:', ['validator' => [$this, 'validateLanguage'], 'default' => 'en-US']); + + $site = new Site([ + 'name' => $siteName, + 'handle' => 'default', + 'hasUrls' => true, + 'baseUrl' => $siteUrl, + 'language' => $language, + ]); + + $migration = new Install([ + 'username' => $username, + 'password' => $password, + 'email' => $email, + 'site' => $site, + ]); + + // Run the install migration + $migrator = Craft::$app->getMigrator(); + + if ($migrator->migrateUp($migration) !== false) { + $this->stdout("{$siteName} was successfully installed.\n", Console::FG_GREEN); + + // Mark all existing migrations as applied + foreach ($migrator->getNewMigrations() as $name) { + $migrator->addMigrationHistory($name); + } + } else { + $this->stderr("There was a problem installing {$siteName}.\n", Console::FG_RED); + } + } + + public function validateUsername(string $value, string &$error = null): bool + { + return $this->_validateUserAttribute('username', $value, $error); + } + + public function validateEmail(string $value, string &$error = null): bool + { + return $this->_validateUserAttribute('email', $value, $error); + } + + public function validatePassword(string $value, string &$error = null): bool + { + return $this->_validateUserAttribute('newPassword', $value, $error); + } + + public function validateSiteName(string $value, string &$error = null): bool + { + return $this->_validateSiteAttribute('name', $value, $error); + } + + public function validateSiteUrl(string $value, string &$error = null): bool + { + return $this->_validateSiteAttribute('baseUrl', $value, $error); + } + + public function validateLanguage(string $value, string &$error = null): bool + { + return $this->_validateSiteAttribute('language', $value, $error); + } + + // Private Methods + // ========================================================================= + + private function _validateUserAttribute(string $attribute, $value, &$error): bool + { + $user = new User([$attribute => $value]); + if (!$user->validate([$attribute])) { + $error = $user->getFirstError($attribute); + return false; + } + $error = null; + return true; + } + + private function _validateSiteAttribute(string $attribute, $value, &$error): bool + { + $site = new Site([$attribute => $value]); + if (!$site->validate([$attribute])) { + $error = $site->getFirstError($attribute); + return false; + } + $error = null; + return true; + } + + private function _passwordPrompt(): string + { + // todo: would be nice to replace CliPrompt with a native Yii silent prompt + // (https://github.com/yiisoft/yii2/issues/10551) + top: + $this->stdout('Password: '); + if (($password = CliPrompt::hiddenPrompt()) === '') { + $this->stdout("Invalid input.\n"); + goto top; + } + $this->stdout('Confirm: '); + if (!($matched = ($password === CliPrompt::hiddenPrompt()))) { + $this->stdout("Passwords didn't match, try again.\n"); + goto top; + } + return $password; + } +} diff --git a/src/console/controllers/MigrateController.php b/src/console/controllers/MigrateController.php index a6eee3e46d1..b900715834f 100644 --- a/src/console/controllers/MigrateController.php +++ b/src/console/controllers/MigrateController.php @@ -11,8 +11,6 @@ use craft\base\Plugin; use craft\db\MigrationManager; use craft\helpers\FileHelper; -use craft\migrations\Install; -use craft\models\Site; use yii\console\controllers\BaseMigrateController; use yii\console\Exception; use yii\helpers\Console; @@ -60,36 +58,6 @@ class MigrateController extends BaseMigrateController */ public $plugin; - /** - * @var string|null The default email address for the first user to create during install - */ - public $email; - - /** - * @var string|null The default username for the first user to create during install - */ - public $username; - - /** - * @var string|null The default password for the first user to create during install - */ - public $password; - - /** - * @var string|null The default site name for the first site to create during install - */ - public $siteName; - - /** - * @var string|null The default site url for the first site to create during install - */ - public $siteUrl; - - /** - * @var string|null The default langcode for the first site to create during install - */ - public $siteLangcode; - /** * @var MigrationManager|null The migration manager that will be used in this request */ @@ -119,15 +87,6 @@ public function options($actionID) $options[] = 'type'; $options[] = 'plugin'; - if ($actionID == 'install') { - $options[] = 'email'; - $options[] = 'username'; - $options[] = 'password'; - $options[] = 'siteName'; - $options[] = 'siteUrl'; - $options[] = 'siteLangcode'; - } - return $options; } @@ -218,53 +177,6 @@ public function actionCreate($name) } } - public function actionInstall() - { - // Run the install migration - $migrator = Craft::$app->getMigrator(); - - $email = $this->email ?: $this->prompt('Email', ['required' => true]); - $username = $this->username ?: $this->prompt('Username', ['required' => true]); - - if ($this->password) { - $password = $this->password; - } - else { - echo 'Password '; - $password = \Seld\CliPrompt\CliPrompt::hiddenPrompt(); - } - - $siteName = $this->siteName ?: $this->prompt('Site Name', ['required' => true]); - $siteUrl = $this->siteUrl ?: $this->prompt('Site Url', ['required' => true]); - $siteLangcode = $this->siteLangcode ?: $this->prompt('Site Langcode', ['required' => true]); - - $site = new Site([ - 'name' => $siteName, - 'handle' => 'default', - 'hasUrls' => true, - 'baseUrl' => $siteUrl, - 'language' => $siteLangcode, - ]); - - $migration = new Install([ - 'username' => $username, - 'password' => $password, - 'email' => $email, - 'site' => $site, - ]); - - if ($migrator->migrateUp($migration) !== false) { - $this->stdout("{$siteName} was successfully installed.\n", Console::FG_GREEN); - - // Mark all existing migrations as applied - foreach ($migrator->getNewMigrations() as $name) { - $migrator->addMigrationHistory($name); - } - } else { - $this->stderr("There was a problem installing {$siteName}.\n", Console::FG_GREEN); - } - } - // Protected Methods // ========================================================================= diff --git a/src/db/MigrationManager.php b/src/db/MigrationManager.php index cd7446cd0a4..8d756ce1a55 100644 --- a/src/db/MigrationManager.php +++ b/src/db/MigrationManager.php @@ -336,10 +336,6 @@ public function migrateDown($migration) */ public function getMigrationHistory(int $limit = 0): array { - if (Craft::$app->getIsInstalled() == false) { - return []; - } - $query = $this->_createMigrationQuery(); if ($limit !== 0) { $query->limit($limit); From af3439f095270399f180e39efb7fbbea46a053c5 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 15 Aug 2017 11:23:14 -0700 Subject: [PATCH 12/79] Changelog for #1917 --- CHANGELOG-v3.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index c07d8e94b2a..28abfad1e5c 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -6,6 +6,7 @@ Craft CMS 3.0 Working Changelog ### Added - Craft’s tasks implementation has been replaced with a queue, based on the [Yii 2 Queue Extension](https://github.com/yiisoft/yii2-queue). ([#1910](https://github.com/craftcms/cms/issues/1910)) - The “Failed” message in the queue HUD in the Control Panel now shows the full error message as alt text. ([#855](https://github.com/craftcms/cms/issues/855)) +- It’s now possible to install Craft from the command line, using the new `install` command. ([#1917](https://github.com/craftcms/cms/pull/1917)) - Added the `instance of()` Twig test. - Added `craft\base\FlysystemVolume`, which replaces `craft\base\Volume` as the new base class for Flysystem-based volumes. - Added `craft\behaviors\SessionBehavior`, making it possible for `config/app.php` to customize the base `session` component while retaining Craft’s custom session methods. From b02dfbf121e1056437a6528b766894856ef85f9f Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 15 Aug 2017 11:29:27 -0700 Subject: [PATCH 13/79] Resolved #1919 --- CHANGELOG-v3.md | 1 + src/elements/Asset.php | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 28abfad1e5c..bd0c0397ff8 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -72,6 +72,7 @@ Craft CMS 3.0 Working Changelog - Fixed some deprecation errors caused by relational and Matrix field inputs. - Fixed a bug where a plugin would get a PHP error if it tried to get the current site in the middle of a Craft update. - Fixed a bug where the Migrations utility would display an error message even if the migrations were applied successfully. ([#1911](https://github.com/craftcms/cms/issues/1911)) +- Fixed a PHP error that occurred if calling `getMimeType()` on an asset with an extension with an unknown MIME type. ([#1919](https://github.com/craftcms/cms/pull/1919)) ## 3.0.0-beta.23 - 2017-07-28 diff --git a/src/elements/Asset.php b/src/elements/Asset.php index 3117a5f317e..11b8a602119 100644 --- a/src/elements/Asset.php +++ b/src/elements/Asset.php @@ -711,9 +711,11 @@ public function getExtension() } /** - * @return string + * Returns the file’s MIME type, if it can be determined. + * + * @return string|null */ - public function getMimeType(): string + public function getMimeType() { // todo: maybe we should be passing this off to volume types // so Local volumes can call FileHelper::getMimeType() (uses magic file instead of ext) From c59cf7e58e827a69d0161b11bd15f24b0fd6785a Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 15 Aug 2017 11:32:27 -0700 Subject: [PATCH 14/79] Changelog tweak --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41016a0ee52..ed5bf13cf32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ Craft CMS Changelog ### Fixed - Fixed a bug where the PHP and DB versions the Craft Support widget passed to GitHub would not escape tildes (`~`), potentially having Markdown confuse them for strikethrough markup delimiters. - Fixed a bug where it was possible for users to be redirected to a 404 in the Control Panel after logging in. ([#1901](https://github.com/craftcms/cms/issues/1901)) -- Fixed a bug where users would get one extra try to login added to whatever the [maxInvalidLogins](https://craftcms.com/docs/config-settings#maxInvalidLogins) config setting was set to. +- Fixed a bug where users would get one extra login attempt than the [maxInvalidLogins](https://craftcms.com/docs/config-settings#maxInvalidLogins) config setting was set to. ## 2.6.2988 2017-07-28 From a59d8494097f4b8445546117e26b6793f53f5f50 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 15 Aug 2017 11:32:52 -0700 Subject: [PATCH 15/79] Missing '-' --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed5bf13cf32..5c2e3bd67ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ Craft CMS Changelog - Fixed a bug where it was possible for users to be redirected to a 404 in the Control Panel after logging in. ([#1901](https://github.com/craftcms/cms/issues/1901)) - Fixed a bug where users would get one extra login attempt than the [maxInvalidLogins](https://craftcms.com/docs/config-settings#maxInvalidLogins) config setting was set to. -## 2.6.2988 2017-07-28 +## 2.6.2988 - 2017-07-28 ### Changed - Added `.m2t` to the default [allowedFileExtensions](https://craftcms.com/docs/config-settings#allowedFileExtensions) config setting value. From 113b16620588b9f66bb55ae06f4b2a5d44ceda3c Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 15 Aug 2017 11:34:19 -0700 Subject: [PATCH 16/79] Finish 2.6.2989 --- CHANGELOG.md | 2 +- src/Info.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c2e3bd67ed..628018f0915 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ Craft CMS Changelog =================== -## Unreleased +## 2.6.2989 2017-08-15 ### Added - Added the [onLockUser](https://craftcms.com/docs/plugins/events-reference#users-onLockUser) event, which fires when a user account is locked. diff --git a/src/Info.php b/src/Info.php index a6b8b983053..3552aa5d875 100644 --- a/src/Info.php +++ b/src/Info.php @@ -1,6 +1,6 @@ Date: Tue, 15 Aug 2017 12:04:57 -0700 Subject: [PATCH 17/79] Merged redundant user events into UserEvent --- CHANGELOG-v3.md | 6 +++ src/controllers/UsersController.php | 5 +- src/events/UserActivateEvent.php | 27 ----------- .../{UserUnlockEvent.php => UserEvent.php} | 4 +- src/events/UserSuspendEvent.php | 27 ----------- src/events/UserTokenEvent.php | 28 ----------- src/events/UserUnsuspendEvent.php | 27 ----------- src/services/Users.php | 47 +++++++++---------- 8 files changed, 32 insertions(+), 139 deletions(-) delete mode 100644 src/events/UserActivateEvent.php rename src/events/{UserUnlockEvent.php => UserEvent.php} (86%) delete mode 100644 src/events/UserSuspendEvent.php delete mode 100644 src/events/UserTokenEvent.php delete mode 100644 src/events/UserUnsuspendEvent.php diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index bd0c0397ff8..882a4943f7d 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -11,6 +11,7 @@ Craft CMS 3.0 Working Changelog - Added `craft\base\FlysystemVolume`, which replaces `craft\base\Volume` as the new base class for Flysystem-based volumes. - Added `craft\behaviors\SessionBehavior`, making it possible for `config/app.php` to customize the base `session` component while retaining Craft’s custom session methods. - Added `craft\controllers\QueueController`. +- Added `craft\events\UserEvent`. - Added `craft\queue\BaseJob`, a base class for queue jobs that adds support for descriptions and progress. - Added `craft\queue\Command`, which provides `queue/run`, `queue/listen`, and `queue/info` console commands. - Added `craft\queue\InfoAction`. @@ -50,6 +51,11 @@ Craft CMS 3.0 Working Changelog - Removed `craft\db\TaskQuery`. - Removed `craft\events\MailFailureEvent`. - Removed `craft\events\TaskEvent`. +- Removed `craft\events\UserActivateEvent`. Use `craft\events\UserEvent` instead. +- Removed `craft\events\UserSuspendEvent`. Use `craft\events\UserEvent` instead. +- Removed `craft\events\UserTokenEvent`. Use `craft\events\UserEvent` instead. +- Removed `craft\events\UserUnlockEvent`. Use `craft\events\UserEvent` instead. +- Removed `craft\events\UserUnsuspendEvent`. Use `craft\events\UserEvent` instead. - Removed `craft\mail\Mailer::EVENT_SEND_MAIL_FAILURE`. - Removed `craft\records\Task`. - Removed `craft\services\Tasks`. diff --git a/src/controllers/UsersController.php b/src/controllers/UsersController.php index 9ca871aa075..a6814b1b31c 100644 --- a/src/controllers/UsersController.php +++ b/src/controllers/UsersController.php @@ -13,7 +13,6 @@ use craft\errors\UploadFailedException; use craft\events\LoginFailureEvent; use craft\events\RegisterUserActionsEvent; -use craft\events\UserTokenEvent; use craft\helpers\Assets; use craft\helpers\DateTimeHelper; use craft\helpers\FileHelper; @@ -1780,7 +1779,7 @@ private function _processTokenRequest() if ($userToProcess) { // Fire a 'beforeVerifyUser' event Craft::$app->getUsers()->trigger(Users::EVENT_BEFORE_VERIFY_EMAIL, - new UserTokenEvent([ + new UserEvent([ 'user' => $userToProcess ])); @@ -1793,7 +1792,7 @@ private function _processTokenRequest() // Fire an 'afterVerifyUser' event Craft::$app->getUsers()->trigger(Users::EVENT_AFTER_VERIFY_EMAIL, - new UserTokenEvent([ + new UserEvent([ 'user' => $userToProcess ])); diff --git a/src/events/UserActivateEvent.php b/src/events/UserActivateEvent.php deleted file mode 100644 index 0cec4d2e8e0..00000000000 --- a/src/events/UserActivateEvent.php +++ /dev/null @@ -1,27 +0,0 @@ - - * @since 3.0 - */ -class UserActivateEvent extends CancelableEvent -{ - // Properties - // ========================================================================= - - /** - * @var User|null The user model associated with the event. - */ - public $user; -} diff --git a/src/events/UserUnlockEvent.php b/src/events/UserEvent.php similarity index 86% rename from src/events/UserUnlockEvent.php rename to src/events/UserEvent.php index f0a5ce9e796..13bcdf99556 100644 --- a/src/events/UserUnlockEvent.php +++ b/src/events/UserEvent.php @@ -10,12 +10,12 @@ use craft\elements\User; /** - * User unlock event class. + * User event class. * * @author Pixel & Tonic, Inc. * @since 3.0 */ -class UserUnlockEvent extends CancelableEvent +class UserEvent extends CancelableEvent { // Properties // ========================================================================= diff --git a/src/events/UserSuspendEvent.php b/src/events/UserSuspendEvent.php deleted file mode 100644 index d3e0c5f0827..00000000000 --- a/src/events/UserSuspendEvent.php +++ /dev/null @@ -1,27 +0,0 @@ - - * @since 3.0 - */ -class UserSuspendEvent extends CancelableEvent -{ - // Properties - // ========================================================================= - - /** - * @var User|null The user model associated with the event. - */ - public $user; -} diff --git a/src/events/UserTokenEvent.php b/src/events/UserTokenEvent.php deleted file mode 100644 index b7869ddc58f..00000000000 --- a/src/events/UserTokenEvent.php +++ /dev/null @@ -1,28 +0,0 @@ - - * @since 3.0 - */ -class UserTokenEvent extends Event -{ - // Properties - // ========================================================================= - - /** - * @var User|null The user model associated with the event. - */ - public $user; -} diff --git a/src/events/UserUnsuspendEvent.php b/src/events/UserUnsuspendEvent.php deleted file mode 100644 index 49c2a23c144..00000000000 --- a/src/events/UserUnsuspendEvent.php +++ /dev/null @@ -1,27 +0,0 @@ - - * @since 3.0 - */ -class UserUnsuspendEvent extends CancelableEvent -{ - // Properties - // ========================================================================= - - /** - * @var User|null The user model associated with the event. - */ - public $user; -} diff --git a/src/services/Users.php b/src/services/Users.php index 3dd5c0da235..ed6582cb94c 100644 --- a/src/services/Users.php +++ b/src/services/Users.php @@ -15,12 +15,9 @@ use craft\errors\ImageException; use craft\errors\UserNotFoundException; use craft\errors\VolumeException; -use craft\events\UserActivateEvent; +use craft\events\UserEvent; use craft\events\UserAssignGroupEvent; use craft\events\UserGroupsAssignEvent; -use craft\events\UserSuspendEvent; -use craft\events\UserUnlockEvent; -use craft\events\UserUnsuspendEvent; use craft\helpers\Assets as AssetsHelper; use craft\helpers\DateTimeHelper; use craft\helpers\Db; @@ -48,19 +45,19 @@ class Users extends Component // ========================================================================= /** - * @event UserTokenEvent The event that is triggered before a user's email is verified. + * @event UserEvent The event that is triggered before a user's email is verified. */ const EVENT_BEFORE_VERIFY_EMAIL = 'beforeVerifyEmail'; /** - * @event UserTokenEvent The event that is triggered after a user's email is verified. + * @event UserEvent The event that is triggered after a user's email is verified. */ const EVENT_AFTER_VERIFY_EMAIL = 'afterVerifyEmail'; /** - * @event UserActivateEvent The event that is triggered before a user is activated. + * @event UserEvent The event that is triggered before a user is activated. * - * You may set [[UserActivateEvent::isValid]] to `false` to prevent the user from getting activated. + * You may set [[UserEvent::isValid]] to `false` to prevent the user from getting activated. */ const EVENT_BEFORE_ACTIVATE_USER = 'beforeActivateUser'; @@ -70,38 +67,38 @@ class Users extends Component const EVENT_AFTER_ACTIVATE_USER = 'afterActivateUser'; /** - * @event UserUnlockEvent The event that is triggered before a user is unlocked. + * @event UserEvent The event that is triggered before a user is unlocked. * - * You may set [[UserUnlockEvent::isValid]] to `false` to prevent the user from getting unlocked. + * You may set [[UserEvent::isValid]] to `false` to prevent the user from getting unlocked. */ const EVENT_BEFORE_UNLOCK_USER = 'beforeUnlockUser'; /** - * @event UserUnlockEvent The event that is triggered after a user is unlocked. + * @event UserEvent The event that is triggered after a user is unlocked. */ const EVENT_AFTER_UNLOCK_USER = 'afterUnlockUser'; /** - * @event UserSuspendEvent The event that is triggered before a user is suspended. + * @event UserEvent The event that is triggered before a user is suspended. * - * You may set [[UserSuspendEvent::isValid]] to `false` to prevent the user from getting suspended. + * You may set [[UserEvent::isValid]] to `false` to prevent the user from getting suspended. */ const EVENT_BEFORE_SUSPEND_USER = 'beforeSuspendUser'; /** - * @event UserSuspendEvent The event that is triggered after a user is suspended. + * @event UserEvent The event that is triggered after a user is suspended. */ const EVENT_AFTER_SUSPEND_USER = 'afterSuspendUser'; /** - * @event UserUnsuspendEvent The event that is triggered before a user is unsuspended. + * @event UserEvent The event that is triggered before a user is unsuspended. * - * You may set [[UserUnsuspendEvent::isValid]] to `false` to prevent the user from getting unsuspended. + * You may set [[UserEvent::isValid]] to `false` to prevent the user from getting unsuspended. */ const EVENT_BEFORE_UNSUSPEND_USER = 'beforeUnsuspendUser'; /** - * @event UserUnsuspendEvent The event that is triggered after a user is unsuspended. + * @event UserEvent The event that is triggered after a user is unsuspended. */ const EVENT_AFTER_UNSUSPEND_USER = 'afterUnsuspendUser'; @@ -523,7 +520,7 @@ public function handleInvalidLogin(User $user) public function activateUser(User $user): bool { // Fire a 'beforeActivateUser' event - $event = new UserActivateEvent([ + $event = new UserEvent([ 'user' => $user, ]); $this->trigger(self::EVENT_BEFORE_ACTIVATE_USER, $event); @@ -553,7 +550,7 @@ public function activateUser(User $user): bool // Fire an 'afterActivateUser' event if ($this->hasEventHandlers(self::EVENT_AFTER_ACTIVATE_USER)) { - $this->trigger(self::EVENT_AFTER_ACTIVATE_USER, new UserActivateEvent([ + $this->trigger(self::EVENT_AFTER_ACTIVATE_USER, new UserEvent([ 'user' => $user ])); } @@ -609,7 +606,7 @@ public function verifyEmailForUser(User $user): bool public function unlockUser(User $user): bool { // Fire a 'beforeUnlockUser' event - $event = new UserUnlockEvent([ + $event = new UserEvent([ 'user' => $user, ]); $this->trigger(self::EVENT_BEFORE_UNLOCK_USER, $event); @@ -640,7 +637,7 @@ public function unlockUser(User $user): bool // Fire an 'afterUnlockUser' event if ($this->hasEventHandlers(self::EVENT_AFTER_UNLOCK_USER)) { - $this->trigger(self::EVENT_AFTER_UNLOCK_USER, new UserUnlockEvent([ + $this->trigger(self::EVENT_AFTER_UNLOCK_USER, new UserEvent([ 'user' => $user ])); } @@ -659,7 +656,7 @@ public function unlockUser(User $user): bool public function suspendUser(User $user): bool { // Fire a 'beforeSuspendUser' event - $event = new UserSuspendEvent([ + $event = new UserEvent([ 'user' => $user, ]); $this->trigger(self::EVENT_BEFORE_SUSPEND_USER, $event); @@ -683,7 +680,7 @@ public function suspendUser(User $user): bool // Fire an 'afterSuspendUser' event if ($this->hasEventHandlers(self::EVENT_AFTER_SUSPEND_USER)) { - $this->trigger(self::EVENT_AFTER_SUSPEND_USER, new UserSuspendEvent([ + $this->trigger(self::EVENT_AFTER_SUSPEND_USER, new UserEvent([ 'user' => $user ])); } @@ -702,7 +699,7 @@ public function suspendUser(User $user): bool public function unsuspendUser(User $user): bool { // Fire a 'beforeUnsuspendUser' event - $event = new UserUnsuspendEvent([ + $event = new UserEvent([ 'user' => $user, ]); $this->trigger(self::EVENT_BEFORE_UNSUSPEND_USER, $event); @@ -730,7 +727,7 @@ public function unsuspendUser(User $user): bool // Fire an 'afterUnsuspendUser' event if ($this->hasEventHandlers(self::EVENT_AFTER_UNSUSPEND_USER)) { - $this->trigger(self::EVENT_AFTER_UNSUSPEND_USER, new UserUnsuspendEvent([ + $this->trigger(self::EVENT_AFTER_UNSUSPEND_USER, new UserEvent([ 'user' => $user ])); } From 21339ff6542a5dd1cc245cac79d4a83811859c62 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 15 Aug 2017 12:07:27 -0700 Subject: [PATCH 18/79] afterLockUser event --- src/services/Users.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/services/Users.php b/src/services/Users.php index ed6582cb94c..16f44f59e63 100644 --- a/src/services/Users.php +++ b/src/services/Users.php @@ -66,6 +66,11 @@ class Users extends Component */ const EVENT_AFTER_ACTIVATE_USER = 'afterActivateUser'; + /** + * @event UserEvent The event that is triggered after a user is locked. + */ + const EVENT_AFTER_LOCK_USER = 'afterLockUser'; + /** * @event UserEvent The event that is triggered before a user is unlocked. * @@ -507,6 +512,13 @@ public function handleInvalidLogin(User $user) // Update the User model too $user->lastInvalidLoginDate = $now; + + if ($user->locked && $this->hasEventHandlers(self::EVENT_AFTER_LOCK_USER)) { + // Fire an 'afterLockUser' event + $this->trigger(self::EVENT_AFTER_LOCK_USER, new UserEvent([ + 'user' => $user, + ])); + } } /** From 606854fa3cf549331b2d4f0bdb9c6d848e7dcb92 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 15 Aug 2017 12:08:06 -0700 Subject: [PATCH 19/79] Fix maxInvalidLogins bug --- src/services/Users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/Users.php b/src/services/Users.php index 16f44f59e63..3596dc8217e 100644 --- a/src/services/Users.php +++ b/src/services/Users.php @@ -489,7 +489,7 @@ public function handleInvalidLogin(User $user) $userRecord->invalidLoginCount++; // Was that one bad password too many? - if ($userRecord->invalidLoginCount > $maxInvalidLogins) { + if ($userRecord->invalidLoginCount >= $maxInvalidLogins) { $userRecord->locked = true; $userRecord->invalidLoginCount = null; $userRecord->invalidLoginWindowStart = null; From 650ce8085ab824428cba960915701c996a0954f9 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 15 Aug 2017 12:11:39 -0700 Subject: [PATCH 20/79] handleInvalidLogin() probably gets called for locked users too --- src/services/Users.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/Users.php b/src/services/Users.php index 3596dc8217e..7ac5ecaaf00 100644 --- a/src/services/Users.php +++ b/src/services/Users.php @@ -483,6 +483,7 @@ public function handleInvalidLogin(User $user) // Was that one too many? $maxInvalidLogins = Craft::$app->getConfig()->getGeneral()->maxInvalidLogins; + $alreadyLocked = $user->locked; if ($maxInvalidLogins) { if ($this->_isUserInsideInvalidLoginWindow($userRecord)) { @@ -513,7 +514,7 @@ public function handleInvalidLogin(User $user) // Update the User model too $user->lastInvalidLoginDate = $now; - if ($user->locked && $this->hasEventHandlers(self::EVENT_AFTER_LOCK_USER)) { + if (!$alreadyLocked && $user->locked && $this->hasEventHandlers(self::EVENT_AFTER_LOCK_USER)) { // Fire an 'afterLockUser' event $this->trigger(self::EVENT_AFTER_LOCK_USER, new UserEvent([ 'user' => $user, From fd00ce232346b71be09d8daec6f71afadd4a971d Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 15 Aug 2017 12:15:33 -0700 Subject: [PATCH 21/79] Finish 3.0.0-beta.24 --- CHANGELOG-v3.md | 2 +- composer.json | 2 +- src/config/app/main.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 882a4943f7d..55a2fafca09 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -1,7 +1,7 @@ Craft CMS 3.0 Working Changelog =============================== -## Unreleased +## 3.0.0-beta.24 - 2017-08-15 ### Added - Craft’s tasks implementation has been replaced with a queue, based on the [Yii 2 Queue Extension](https://github.com/yiisoft/yii2-queue). ([#1910](https://github.com/craftcms/cms/issues/1910)) diff --git a/composer.json b/composer.json index b27793dfe3b..4cea5a04294 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "craftcms/cms", "description": "Craft CMS", - "version": "3.0.0-beta.23", + "version": "3.0.0-beta.24", "keywords": [ "cms", "craftcms", diff --git a/src/config/app/main.php b/src/config/app/main.php index e872be279e6..b33142ae2da 100644 --- a/src/config/app/main.php +++ b/src/config/app/main.php @@ -3,7 +3,7 @@ return [ 'id' => 'CraftCMS', 'name' => 'Craft CMS', - 'version' => '3.0.0-beta.23', + 'version' => '3.0.0-beta.24', 'schemaVersion' => '3.0.56', 'minVersionRequired' => '2.6.2788', 'basePath' => dirname(__DIR__, 2), // Defines the @app alias From 35e1b275ab08427da2eabc4ab4bbe6d296b9fe58 Mon Sep 17 00:00:00 2001 From: Brad Bell Date: Tue, 15 Aug 2017 12:23:45 -0700 Subject: [PATCH 22/79] Typos. --- CHANGELOG-v3.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 55a2fafca09..0e5abbbd050 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -29,8 +29,8 @@ Craft CMS 3.0 Working Changelog ### Changed - Renamed the `runTasksAutomatically` config setting to `runQueueAutomatically`. - Logs that occur during `queue` requests now get saved in `storage/logs/queue.log`. -- The updater now ensures it can find `composer.json` before putting the system in Maintenance Mode, reducing the liklihood that Craft will mistakingly think that it’s already mid-update later on. ([#1883](https://github.com/craftcms/cms/issues/1883)) -- The updater now ensures that the `COMPOSER_HOME`, `HOME` (\*nix), or `APPDATA` (Windows) environment variable is set before putting the system in Maintenance Mode, reducing the liklihood that Craft will mistakingly think that it’s already mid-update later on. ([#1890](https://github.com/craftcms/cms/issues/1890#issuecomment-319715460)) +- The updater now ensures it can find `composer.json` before putting the system in Maintenance Mode, reducing the likelihood that Craft will mistakingly think that it’s already mid-update later on. ([#1883](https://github.com/craftcms/cms/issues/1883)) +- The updater now ensures that the `COMPOSER_HOME`, `HOME` (\*nix), or `APPDATA` (Windows) environment variable is set before putting the system in Maintenance Mode, reducing the likelihood that Craft will mistakingly think that it’s already mid-update later on. ([#1890](https://github.com/craftcms/cms/issues/1890#issuecomment-319715460)) - `craft\mail\Mailer::send()` now processes Twig code in the email message before parsing it as Markdown, if the message was composed via `craft\mail\Mailer::composeFromKey()`. ([#1895](https://github.com/craftcms/cms/pull/1895)) - `craft\mail\Mailer::send()` no longer catches exceptions thrown by its parent method, or fires a `sendMailFailure` event in the event of a send failure. ([#1896](https://github.com/craftcms/cms/issues/1896)) - Renamed `craft\helpers\Component::applySettings()` to `mergeSettings()`, and it no longer takes the `$config` argument by reference, instead returning a new array. From c576b10394ddca59312e59a5fb5223a181a5bfd5 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Wed, 16 Aug 2017 06:42:41 -0700 Subject: [PATCH 23/79] Fixed #1887 --- CHANGELOG-v3.md | 5 +++ .../ElementQueryBehavior.php.template | 2 +- src/config/app/main.php | 2 +- src/helpers/ChartHelper.php | 42 +++++++++++++++---- ...0816_133741_delete_compiled_behaviors.php} | 6 +-- 5 files changed, 44 insertions(+), 13 deletions(-) rename src/migrations/{m170731_185314_delete_compiled_behaviors.php => m170816_133741_delete_compiled_behaviors.php} (80%) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 0e5abbbd050..341d6c5fcfb 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -1,6 +1,11 @@ Craft CMS 3.0 Working Changelog =============================== +## Unreleased + +### Fixed +- Fixed an error that occurred when chaining a custom field method and a normal query method (e.g. `all()`) together on an element query. ([#1887](https://github.com/craftcms/cms/issues/1887)) + ## 3.0.0-beta.24 - 2017-08-15 ### Added diff --git a/src/behaviors/ElementQueryBehavior.php.template b/src/behaviors/ElementQueryBehavior.php.template index 30100a46110..27d860b4e26 100644 --- a/src/behaviors/ElementQueryBehavior.php.template +++ b/src/behaviors/ElementQueryBehavior.php.template @@ -26,7 +26,7 @@ class ElementQueryBehavior extends ContentBehavior { if (isset(self::$fieldHandles[$name]) && count($params) === 1) { $this->$name = $params[0]; - return $this; + return $this->owner; } return parent::__call($name, $params); } diff --git a/src/config/app/main.php b/src/config/app/main.php index b33142ae2da..386d46cbfaf 100644 --- a/src/config/app/main.php +++ b/src/config/app/main.php @@ -4,7 +4,7 @@ 'id' => 'CraftCMS', 'name' => 'Craft CMS', 'version' => '3.0.0-beta.24', - 'schemaVersion' => '3.0.56', + 'schemaVersion' => '3.0.57', 'minVersionRequired' => '2.6.2788', 'basePath' => dirname(__DIR__, 2), // Defines the @app alias 'runtimePath' => '@storage/runtime', // Defines the @runtime alias diff --git a/src/helpers/ChartHelper.php b/src/helpers/ChartHelper.php index efde6500bd1..b91c8ab5505 100644 --- a/src/helpers/ChartHelper.php +++ b/src/helpers/ChartHelper.php @@ -9,6 +9,7 @@ use Craft; use craft\db\Query; +use craft\elements\db\ElementQueryInterface; use DateTime; use yii\base\Exception; @@ -131,15 +132,40 @@ public static function getRunChartDataFromQuery(Query $query, DateTime $startDat $sqlGroup[] = '[[date]]'; + // Prepare the query + $condition = ['and', "{$dateColumnSql} >= :startDate", "{$dateColumnSql} < :endDate"]; + $params = [ + ':startDate' => Db::prepareDateForDb($startDate), + ':endDate' => Db::prepareDateForDb($endDate), + ]; + $orderBy = ['date' => SORT_ASC]; + + // If this is an element query, modify the prepared query directly + if ($query instanceof ElementQueryInterface) { + $query = $query->prepare(Craft::$app->getDb()->getQueryBuilder()); + /** @var Query $subQuery */ + $subQuery = $query->from['subquery']; + $subQuery + ->addSelect($query->select) + ->addSelect([$select]) + ->andWhere($condition, $params) + ->groupBy($sqlGroup) + ->orderBy($orderBy); + $query + ->select(['subquery.value', 'subquery.date']) + ->orderBy($orderBy); + } else { + $query + ->addSelect([$select]) + ->andWhere($condition, $params) + ->groupBy($sqlGroup) + ->orderBy($orderBy); + } + + die($query->getRawSql()); + // Execute the query - $results = $query - ->addSelect([$select]) - ->andWhere( - ['and', "{$dateColumnSql} >= :startDate", "{$dateColumnSql} < :endDate"], - [':startDate' => Db::prepareDateForDb($startDate), ':endDate' => Db::prepareDateForDb($endDate)]) - ->groupBy($sqlGroup) - ->orderBy(['date' => SORT_ASC]) - ->all(); + $results = $query->all(); // Assemble the data $rows = []; diff --git a/src/migrations/m170731_185314_delete_compiled_behaviors.php b/src/migrations/m170816_133741_delete_compiled_behaviors.php similarity index 80% rename from src/migrations/m170731_185314_delete_compiled_behaviors.php rename to src/migrations/m170816_133741_delete_compiled_behaviors.php index 97f159ee4e4..7bc26a74976 100644 --- a/src/migrations/m170731_185314_delete_compiled_behaviors.php +++ b/src/migrations/m170816_133741_delete_compiled_behaviors.php @@ -7,9 +7,9 @@ use craft\helpers\FileHelper; /** - * m170731_185314_delete_compiled_behaviors migration. + * m170816_133741_delete_compiled_behaviors migration. */ -class m170731_185314_delete_compiled_behaviors extends Migration +class m170816_133741_delete_compiled_behaviors extends Migration { /** * @inheritdoc @@ -34,7 +34,7 @@ public function safeUp() */ public function safeDown() { - echo "m170731_185314_delete_compiled_behaviors cannot be reverted.\n"; + echo "m170816_133741_delete_compiled_behaviors cannot be reverted.\n"; return false; } } From 6de6895e6b6b88b15e7ff1a6ef62b98c1173efbd Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Thu, 17 Aug 2017 09:39:37 -0700 Subject: [PATCH 24/79] Fixed PHP error in UsersController::_processTokenRequest() --- CHANGELOG-v3.md | 1 + src/controllers/UsersController.php | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 341d6c5fcfb..8de77ee7a7c 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -5,6 +5,7 @@ Craft CMS 3.0 Working Changelog ### Fixed - Fixed an error that occurred when chaining a custom field method and a normal query method (e.g. `all()`) together on an element query. ([#1887](https://github.com/craftcms/cms/issues/1887)) +- Fixed a PHP error that occurred when processing a user verification request. ## 3.0.0-beta.24 - 2017-08-15 diff --git a/src/controllers/UsersController.php b/src/controllers/UsersController.php index a6814b1b31c..458c9c1dbe3 100644 --- a/src/controllers/UsersController.php +++ b/src/controllers/UsersController.php @@ -13,6 +13,7 @@ use craft\errors\UploadFailedException; use craft\events\LoginFailureEvent; use craft\events\RegisterUserActionsEvent; +use craft\events\UserEvent; use craft\helpers\Assets; use craft\helpers\DateTimeHelper; use craft\helpers\FileHelper; From 5cf5e8f664d5d7e78c8abf3b78380e2bca8df3fc Mon Sep 17 00:00:00 2001 From: Sebastian Weyrauch Date: Thu, 17 Aug 2017 04:40:50 +0200 Subject: [PATCH 25/79] added the data-type attribute for matrixblocks created with JS --- src/web/assets/matrix/dist/MatrixInput.js | 2 +- src/web/assets/matrix/dist/MatrixInput.min.js | 2 +- src/web/assets/matrix/dist/MatrixInput.min.js.map | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/web/assets/matrix/dist/MatrixInput.js b/src/web/assets/matrix/dist/MatrixInput.js index ecaeaec151a..d8f9cbc48ba 100644 --- a/src/web/assets/matrix/dist/MatrixInput.js +++ b/src/web/assets/matrix/dist/MatrixInput.js @@ -204,7 +204,7 @@ var id = 'new' + this.totalNewBlocks; var html = - '
' + + '
' + '' + '' + '
' + diff --git a/src/web/assets/matrix/dist/MatrixInput.min.js b/src/web/assets/matrix/dist/MatrixInput.min.js index afb3a2e4527..0aec52d8409 100644 --- a/src/web/assets/matrix/dist/MatrixInput.min.js +++ b/src/web/assets/matrix/dist/MatrixInput.min.js @@ -1,2 +1,2 @@ -!function(t){Craft.MatrixInput=Garnish.Base.extend({id:null,blockTypes:null,blockTypesByHandle:null,inputNamePrefix:null,inputIdPrefix:null,maxBlocks:null,showingAddBlockMenu:!1,addBlockBtnGroupWidth:null,addBlockBtnContainerWidth:null,$container:null,$blockContainer:null,$addBlockBtnContainer:null,$addBlockBtnGroup:null,$addBlockBtnGroupBtns:null,blockSort:null,blockSelect:null,totalNewBlocks:0,init:function(i,a,n,s){this.id=i,this.blockTypes=a,this.inputNamePrefix=n,this.inputIdPrefix=Craft.formatInputId(this.inputNamePrefix),this.maxBlocks=s,this.$container=t("#"+this.id),this.$blockContainer=this.$container.children(".blocks"),this.$addBlockBtnContainer=this.$container.children(".buttons"),this.$addBlockBtnGroup=this.$addBlockBtnContainer.children(".btngroup"),this.$addBlockBtnGroupBtns=this.$addBlockBtnGroup.children(".btn"),this.$addBlockMenuBtn=this.$addBlockBtnContainer.children(".menubtn"),this.setNewBlockBtn(),this.blockTypesByHandle={};var l;for(l=0;l .actions > .move",axis:"y",filter:t.proxy(function(){return this.blockSort.$targetItem.hasClass("sel")?this.blockSelect.getSelectedItems():this.blockSort.$targetItem},this),collapseDraggees:!0,magnetStrength:4,helperLagBase:1.5,helperOpacity:.9,onSortChange:t.proxy(function(){this.blockSelect.resetItemOrder()},this)}),this.blockSelect=new Garnish.Select(this.$blockContainer,d,{multi:!0,vertical:!0,handle:"> .checkbox, > .titlebar",checkboxMode:!0}),l=0;lthis.totalNewBlocks&&(this.totalNewBlocks=parseInt(p[1]));var u=new e(this,r);u.id&&-1!==t.inArray(""+u.id,c)&&u.collapse()}this.addListener(this.$addBlockBtnGroupBtns,"click",function(e){var i=t(e.target).data("type");this.addBlock(i)}),new Garnish.MenuBtn(this.$addBlockMenuBtn,{onOptionSelect:t.proxy(function(e){var i=t(e).data("type");this.addBlock(i)},this)}),this.updateAddBlockBtn(),this.addListener(this.$container,"resize","setNewBlockBtn"),Garnish.$doc.ready(t.proxy(this,"setNewBlockBtn"))},setNewBlockBtn:function(){(this.addBlockBtnGroupWidth||(this.addBlockBtnGroupWidth=this.$addBlockBtnGroup.width(),this.addBlockBtnGroupWidth))&&this.addBlockBtnContainerWidth!==(this.addBlockBtnContainerWidth=this.$addBlockBtnContainer.width())&&(this.addBlockBtnGroupWidth>this.addBlockBtnContainerWidth?this.showingAddBlockMenu||(this.$addBlockBtnGroup.addClass("hidden"),this.$addBlockMenuBtn.removeClass("hidden"),this.showingAddBlockMenu=!0):this.showingAddBlockMenu&&(this.$addBlockMenuBtn.addClass("hidden"),this.$addBlockBtnGroup.removeClass("hidden"),this.showingAddBlockMenu=!1,-1!==navigator.userAgent.indexOf("Safari")&&Garnish.requestAnimationFrame(t.proxy(function(){this.$addBlockBtnGroup.css("opacity",.99),Garnish.requestAnimationFrame(t.proxy(function(){this.$addBlockBtnGroup.css("opacity","")},this))},this))))},canAddMoreBlocks:function(){return!this.maxBlocks||this.$blockContainer.children().length
'+this.getBlockTypeByHandle(i).name+'
';var d=t(s);a?d.insertBefore(a):d.appendTo(this.$blockContainer);var c=t('
').appendTo(d),r=this.getParsedBlockHtml(this.blockTypesByHandle[i].bodyHtml,n),h=this.getParsedBlockHtml(this.blockTypesByHandle[i].footHtml,n);t(r).appendTo(c),d.css(this.getHiddenBlockCss(d)).velocity({opacity:1,"margin-bottom":10},"fast",t.proxy(function(){d.css("margin-bottom",""),Garnish.$bod.append(h),Craft.initUiElements(c),new e(this,d),this.blockSort.addItems(d),this.blockSelect.addItems(d),this.updateAddBlockBtn(),Garnish.requestAnimationFrame(function(){Garnish.scrollContainerToElement(d)})},this))}},getBlockTypeByHandle:function(t){for(var e=0;e .actions > .settings"),n=new Garnish.MenuBtn(a);this.$actionMenu=n.menu.$container,n.menu.settings.onOptionSelect=t.proxy(this,"onMenuOptionSelect"),Garnish.hasAttr(this.$container,"data-collapsed")&&this.collapse(),this._handleTitleBarClick=function(t){t.preventDefault(),this.toggle()},this.addListener(this.$titlebar,"doubletap",this._handleTitleBarClick)},toggle:function(){this.collapsed?this.expand():this.collapse(!0)},collapse:function(e){if(!this.collapsed){this.$container.addClass("collapsed");for(var i="",a=this.$fieldsContainer.children(),n=0;n| ":"")+l)}this.$previewContainer.html(i),this.$fieldsContainer.velocity("stop"),this.$container.velocity("stop"),e?(this.$fieldsContainer.velocity("fadeOut",{duration:"fast"}),this.$container.velocity({height:16},"fast")):(this.$previewContainer.show(),this.$fieldsContainer.hide(),this.$container.css({height:16})),setTimeout(t.proxy(function(){this.$actionMenu.find("a[data-action=collapse]:first").parent().addClass("hidden"),this.$actionMenu.find("a[data-action=expand]:first").parent().removeClass("hidden")},this),200),this.isNew?this.$collapsedInput?this.$collapsedInput.val("1"):this.$collapsedInput=t('').appendTo(this.$container):Craft.MatrixInput.rememberCollapsedBlockId(this.id),this.collapsed=!0}},expand:function(){if(this.collapsed){this.$container.removeClass("collapsed"),this.$fieldsContainer.velocity("stop"),this.$container.velocity("stop");var e=this.$container.height();this.$container.height("auto"),this.$fieldsContainer.show();var i=this.$container.height();if(this.$container.height(e),this.$fieldsContainer.hide().velocity("fadeIn",{duration:"fast"}),this.$container.velocity({height:i},"fast",t.proxy(function(){this.$previewContainer.html(""),this.$container.height("auto")},this)),setTimeout(t.proxy(function(){this.$actionMenu.find("a[data-action=collapse]:first").parent().removeClass("hidden"),this.$actionMenu.find("a[data-action=expand]:first").parent().addClass("hidden")},this),200),!this.isNew&&"undefined"!=typeof Storage){var a=Craft.MatrixInput.getCollapsedBlockIds(),n=t.inArray(""+this.id,a);-1!==n&&(a.splice(n,1),Craft.MatrixInput.setCollapsedBlockIds(a))}this.isNew?this.$collapsedInput&&this.$collapsedInput.val(""):Craft.MatrixInput.forgetCollapsedBlockId(this.id),this.collapsed=!1}},disable:function(){this.$container.children('input[name$="[enabled]"]:first').val(""),this.$container.addClass("disabled"),setTimeout(t.proxy(function(){this.$actionMenu.find("a[data-action=disable]:first").parent().addClass("hidden"),this.$actionMenu.find("a[data-action=enable]:first").parent().removeClass("hidden")},this),200),this.collapse(!0)},enable:function(){this.$container.children('input[name$="[enabled]"]:first').val("1"),this.$container.removeClass("disabled"),setTimeout(t.proxy(function(){this.$actionMenu.find("a[data-action=disable]:first").parent().removeClass("hidden"),this.$actionMenu.find("a[data-action=enable]:first").parent().addClass("hidden")},this),200)},onMenuOptionSelect:function(e){var i=this.matrix.blockSelect.totalSelected>1&&this.matrix.blockSelect.isSelected(this.$container),a=t(e);switch(a.data("action")){case"collapse":i?this.matrix.collapseSelectedBlocks():this.collapse(!0);break;case"expand":i?this.matrix.expandSelectedBlocks():this.expand();break;case"disable":i?this.matrix.disableSelectedBlocks():this.disable();break;case"enable":i?this.matrix.enableSelectedBlocks():(this.enable(),this.expand());break;case"add":var n=a.data("type");this.matrix.addBlock(n,this.$container);break;case"delete":i?confirm(Craft.t("app","Are you sure you want to delete the selected blocks?"))&&this.matrix.deleteSelectedBlocks():this.selfDestruct()}},selfDestruct:function(){this.$container.velocity(this.matrix.getHiddenBlockCss(this.$container),"fast",t.proxy(function(){this.$container.remove(),this.matrix.updateAddBlockBtn()},this))}})}(jQuery); +!function(t){Craft.MatrixInput=Garnish.Base.extend({id:null,blockTypes:null,blockTypesByHandle:null,inputNamePrefix:null,inputIdPrefix:null,maxBlocks:null,showingAddBlockMenu:!1,addBlockBtnGroupWidth:null,addBlockBtnContainerWidth:null,$container:null,$blockContainer:null,$addBlockBtnContainer:null,$addBlockBtnGroup:null,$addBlockBtnGroupBtns:null,blockSort:null,blockSelect:null,totalNewBlocks:0,init:function(i,a,n,s){this.id=i,this.blockTypes=a,this.inputNamePrefix=n,this.inputIdPrefix=Craft.formatInputId(this.inputNamePrefix),this.maxBlocks=s,this.$container=t("#"+this.id),this.$blockContainer=this.$container.children(".blocks"),this.$addBlockBtnContainer=this.$container.children(".buttons"),this.$addBlockBtnGroup=this.$addBlockBtnContainer.children(".btngroup"),this.$addBlockBtnGroupBtns=this.$addBlockBtnGroup.children(".btn"),this.$addBlockMenuBtn=this.$addBlockBtnContainer.children(".menubtn"),this.setNewBlockBtn(),this.blockTypesByHandle={};var l;for(l=0;l .actions > .move",axis:"y",filter:t.proxy(function(){return this.blockSort.$targetItem.hasClass("sel")?this.blockSelect.getSelectedItems():this.blockSort.$targetItem},this),collapseDraggees:!0,magnetStrength:4,helperLagBase:1.5,helperOpacity:.9,onSortChange:t.proxy(function(){this.blockSelect.resetItemOrder()},this)}),this.blockSelect=new Garnish.Select(this.$blockContainer,d,{multi:!0,vertical:!0,handle:"> .checkbox, > .titlebar",checkboxMode:!0}),l=0;lthis.totalNewBlocks&&(this.totalNewBlocks=parseInt(p[1]));var u=new e(this,r);u.id&&-1!==t.inArray(""+u.id,c)&&u.collapse()}this.addListener(this.$addBlockBtnGroupBtns,"click",function(e){var i=t(e.target).data("type");this.addBlock(i)}),new Garnish.MenuBtn(this.$addBlockMenuBtn,{onOptionSelect:t.proxy(function(e){var i=t(e).data("type");this.addBlock(i)},this)}),this.updateAddBlockBtn(),this.addListener(this.$container,"resize","setNewBlockBtn"),Garnish.$doc.ready(t.proxy(this,"setNewBlockBtn"))},setNewBlockBtn:function(){(this.addBlockBtnGroupWidth||(this.addBlockBtnGroupWidth=this.$addBlockBtnGroup.width(),this.addBlockBtnGroupWidth))&&this.addBlockBtnContainerWidth!==(this.addBlockBtnContainerWidth=this.$addBlockBtnContainer.width())&&(this.addBlockBtnGroupWidth>this.addBlockBtnContainerWidth?this.showingAddBlockMenu||(this.$addBlockBtnGroup.addClass("hidden"),this.$addBlockMenuBtn.removeClass("hidden"),this.showingAddBlockMenu=!0):this.showingAddBlockMenu&&(this.$addBlockMenuBtn.addClass("hidden"),this.$addBlockBtnGroup.removeClass("hidden"),this.showingAddBlockMenu=!1,-1!==navigator.userAgent.indexOf("Safari")&&Garnish.requestAnimationFrame(t.proxy(function(){this.$addBlockBtnGroup.css("opacity",.99),Garnish.requestAnimationFrame(t.proxy(function(){this.$addBlockBtnGroup.css("opacity","")},this))},this))))},canAddMoreBlocks:function(){return!this.maxBlocks||this.$blockContainer.children().length
'+this.getBlockTypeByHandle(i).name+'
';var d=t(s);a?d.insertBefore(a):d.appendTo(this.$blockContainer);var c=t('
').appendTo(d),r=this.getParsedBlockHtml(this.blockTypesByHandle[i].bodyHtml,n),h=this.getParsedBlockHtml(this.blockTypesByHandle[i].footHtml,n);t(r).appendTo(c),d.css(this.getHiddenBlockCss(d)).velocity({opacity:1,"margin-bottom":10},"fast",t.proxy(function(){d.css("margin-bottom",""),Garnish.$bod.append(h),Craft.initUiElements(c),new e(this,d),this.blockSort.addItems(d),this.blockSelect.addItems(d),this.updateAddBlockBtn(),Garnish.requestAnimationFrame(function(){Garnish.scrollContainerToElement(d)})},this))}},getBlockTypeByHandle:function(t){for(var e=0;e .actions > .settings"),n=new Garnish.MenuBtn(a);this.$actionMenu=n.menu.$container,n.menu.settings.onOptionSelect=t.proxy(this,"onMenuOptionSelect"),Garnish.hasAttr(this.$container,"data-collapsed")&&this.collapse(),this._handleTitleBarClick=function(t){t.preventDefault(),this.toggle()},this.addListener(this.$titlebar,"doubletap",this._handleTitleBarClick)},toggle:function(){this.collapsed?this.expand():this.collapse(!0)},collapse:function(e){if(!this.collapsed){this.$container.addClass("collapsed");for(var i="",a=this.$fieldsContainer.children(),n=0;n| ":"")+l)}this.$previewContainer.html(i),this.$fieldsContainer.velocity("stop"),this.$container.velocity("stop"),e?(this.$fieldsContainer.velocity("fadeOut",{duration:"fast"}),this.$container.velocity({height:16},"fast")):(this.$previewContainer.show(),this.$fieldsContainer.hide(),this.$container.css({height:16})),setTimeout(t.proxy(function(){this.$actionMenu.find("a[data-action=collapse]:first").parent().addClass("hidden"),this.$actionMenu.find("a[data-action=expand]:first").parent().removeClass("hidden")},this),200),this.isNew?this.$collapsedInput?this.$collapsedInput.val("1"):this.$collapsedInput=t('').appendTo(this.$container):Craft.MatrixInput.rememberCollapsedBlockId(this.id),this.collapsed=!0}},expand:function(){if(this.collapsed){this.$container.removeClass("collapsed"),this.$fieldsContainer.velocity("stop"),this.$container.velocity("stop");var e=this.$container.height();this.$container.height("auto"),this.$fieldsContainer.show();var i=this.$container.height();if(this.$container.height(e),this.$fieldsContainer.hide().velocity("fadeIn",{duration:"fast"}),this.$container.velocity({height:i},"fast",t.proxy(function(){this.$previewContainer.html(""),this.$container.height("auto")},this)),setTimeout(t.proxy(function(){this.$actionMenu.find("a[data-action=collapse]:first").parent().removeClass("hidden"),this.$actionMenu.find("a[data-action=expand]:first").parent().addClass("hidden")},this),200),!this.isNew&&"undefined"!=typeof Storage){var a=Craft.MatrixInput.getCollapsedBlockIds(),n=t.inArray(""+this.id,a);-1!==n&&(a.splice(n,1),Craft.MatrixInput.setCollapsedBlockIds(a))}this.isNew?this.$collapsedInput&&this.$collapsedInput.val(""):Craft.MatrixInput.forgetCollapsedBlockId(this.id),this.collapsed=!1}},disable:function(){this.$container.children('input[name$="[enabled]"]:first').val(""),this.$container.addClass("disabled"),setTimeout(t.proxy(function(){this.$actionMenu.find("a[data-action=disable]:first").parent().addClass("hidden"),this.$actionMenu.find("a[data-action=enable]:first").parent().removeClass("hidden")},this),200),this.collapse(!0)},enable:function(){this.$container.children('input[name$="[enabled]"]:first').val("1"),this.$container.removeClass("disabled"),setTimeout(t.proxy(function(){this.$actionMenu.find("a[data-action=disable]:first").parent().removeClass("hidden"),this.$actionMenu.find("a[data-action=enable]:first").parent().addClass("hidden")},this),200)},onMenuOptionSelect:function(e){var i=this.matrix.blockSelect.totalSelected>1&&this.matrix.blockSelect.isSelected(this.$container),a=t(e);switch(a.data("action")){case"collapse":i?this.matrix.collapseSelectedBlocks():this.collapse(!0);break;case"expand":i?this.matrix.expandSelectedBlocks():this.expand();break;case"disable":i?this.matrix.disableSelectedBlocks():this.disable();break;case"enable":i?this.matrix.enableSelectedBlocks():(this.enable(),this.expand());break;case"add":var n=a.data("type");this.matrix.addBlock(n,this.$container);break;case"delete":i?confirm(Craft.t("app","Are you sure you want to delete the selected blocks?"))&&this.matrix.deleteSelectedBlocks():this.selfDestruct()}},selfDestruct:function(){this.$container.velocity(this.matrix.getHiddenBlockCss(this.$container),"fast",t.proxy(function(){this.$container.remove(),this.matrix.updateAddBlockBtn()},this))}})}(jQuery); //# sourceMappingURL=MatrixInput.min.js.map \ No newline at end of file diff --git a/src/web/assets/matrix/dist/MatrixInput.min.js.map b/src/web/assets/matrix/dist/MatrixInput.min.js.map index 8e496a8cd08..61f3e2aa326 100644 --- a/src/web/assets/matrix/dist/MatrixInput.min.js.map +++ b/src/web/assets/matrix/dist/MatrixInput.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["MatrixInput.js"],"names":["$","Craft","MatrixInput","Garnish","Base","extend","id","blockTypes","blockTypesByHandle","inputNamePrefix","inputIdPrefix","maxBlocks","showingAddBlockMenu","addBlockBtnGroupWidth","addBlockBtnContainerWidth","$container","$blockContainer","$addBlockBtnContainer","$addBlockBtnGroup","$addBlockBtnGroupBtns","blockSort","blockSelect","totalNewBlocks","init","this","formatInputId","children","$addBlockMenuBtn","setNewBlockBtn","i","length","blockType","handle","$blocks","collapsedBlocks","getCollapsedBlockIds","DragSort","axis","filter","proxy","$targetItem","hasClass","getSelectedItems","collapseDraggees","magnetStrength","helperLagBase","helperOpacity","onSortChange","resetItemOrder","Select","multi","vertical","checkboxMode","$block","blockId","data","newMatch","match","parseInt","block","MatrixBlock","inArray","collapse","addListener","ev","type","target","addBlock","MenuBtn","onOptionSelect","option","updateAddBlockBtn","$doc","ready","width","addClass","removeClass","navigator","userAgent","indexOf","requestAnimationFrame","css","canAddMoreBlocks","$items","eq","$actionMenu","find","parent","$insertBefore","html","getBlockTypeByHandle","name","t","insertBefore","appendTo","$fieldsContainer","bodyHtml","getParsedBlockHtml","footHtml","getHiddenBlockCss","velocity","opacity","margin-bottom","$bod","append","initUiElements","addItems","scrollContainerToElement","collapseSelectedBlocks","callOnSelectedBlocks","expandSelectedBlocks","disableSelectedBlocks","enableSelectedBlocks","deleteSelectedBlocks","fn","$selectedItems","marginBottom","outerHeight","replace","collapsedBlockStorageKey","systemUid","localStorage","filterArray","split","setCollapsedBlockIds","ids","join","rememberCollapsedBlockId","Storage","push","forgetCollapsedBlockId","collapsedBlocksIndex","splice","matrix","$titlebar","$previewContainer","$collapsedInput","isNew","collapsed","substr","$menuBtn","menuBtn","menu","settings","hasAttr","_handleTitleBarClick","preventDefault","toggle","expand","animate","previewHtml","$fields","$inputs","inputPreviewText","j","value","$input","$maybeLightswitchContainer","text","getText","getInputPostVal","Array","trim","duration","height","show","hide","setTimeout","val","collapsedContainerHeight","expandedContainerHeight","disable","enable","onMenuOptionSelect","batchAction","totalSelected","isSelected","$option","confirm","selfDestruct","remove","jQuery"],"mappings":"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","file":"MatrixInput.min.js"} \ No newline at end of file +{"version":3,"sources":["MatrixInput.js"],"names":["$","Craft","MatrixInput","Garnish","Base","extend","id","blockTypes","blockTypesByHandle","inputNamePrefix","inputIdPrefix","maxBlocks","showingAddBlockMenu","addBlockBtnGroupWidth","addBlockBtnContainerWidth","$container","$blockContainer","$addBlockBtnContainer","$addBlockBtnGroup","$addBlockBtnGroupBtns","blockSort","blockSelect","totalNewBlocks","init","this","formatInputId","children","$addBlockMenuBtn","setNewBlockBtn","i","length","blockType","handle","$blocks","collapsedBlocks","getCollapsedBlockIds","DragSort","axis","filter","proxy","$targetItem","hasClass","getSelectedItems","collapseDraggees","magnetStrength","helperLagBase","helperOpacity","onSortChange","resetItemOrder","Select","multi","vertical","checkboxMode","$block","blockId","data","newMatch","match","parseInt","block","MatrixBlock","inArray","collapse","addListener","ev","type","target","addBlock","MenuBtn","onOptionSelect","option","updateAddBlockBtn","$doc","ready","width","addClass","removeClass","navigator","userAgent","indexOf","requestAnimationFrame","css","canAddMoreBlocks","$items","eq","$actionMenu","find","parent","$insertBefore","html","getBlockTypeByHandle","name","t","insertBefore","appendTo","$fieldsContainer","bodyHtml","getParsedBlockHtml","footHtml","getHiddenBlockCss","velocity","opacity","margin-bottom","$bod","append","initUiElements","addItems","scrollContainerToElement","collapseSelectedBlocks","callOnSelectedBlocks","expandSelectedBlocks","disableSelectedBlocks","enableSelectedBlocks","deleteSelectedBlocks","fn","$selectedItems","marginBottom","outerHeight","replace","collapsedBlockStorageKey","systemUid","localStorage","filterArray","split","setCollapsedBlockIds","ids","join","rememberCollapsedBlockId","Storage","push","forgetCollapsedBlockId","collapsedBlocksIndex","splice","matrix","$titlebar","$previewContainer","$collapsedInput","isNew","collapsed","substr","$menuBtn","menuBtn","menu","settings","hasAttr","_handleTitleBarClick","preventDefault","toggle","expand","animate","previewHtml","$fields","$inputs","inputPreviewText","j","value","$input","$maybeLightswitchContainer","text","getText","getInputPostVal","Array","trim","duration","height","show","hide","setTimeout","val","collapsedContainerHeight","expandedContainerHeight","disable","enable","onMenuOptionSelect","batchAction","totalSelected","isSelected","$option","confirm","selfDestruct","remove","jQuery"],"mappings":"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","file":"MatrixInput.min.js"} \ No newline at end of file From 8a7b603472fbecdf73817dd8017f6a18e3b3175d Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Thu, 17 Aug 2017 09:46:38 -0700 Subject: [PATCH 26/79] Changelog for #1925 --- CHANGELOG-v3.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 8de77ee7a7c..8f86498a35b 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -6,6 +6,7 @@ Craft CMS 3.0 Working Changelog ### Fixed - Fixed an error that occurred when chaining a custom field method and a normal query method (e.g. `all()`) together on an element query. ([#1887](https://github.com/craftcms/cms/issues/1887)) - Fixed a PHP error that occurred when processing a user verification request. +- Fixed a bug where newly-created `div.matrixblock` elements weren’t getting a `data-type` attribute like existing blocks had. ([#1925](https://github.com/craftcms/cms/pull/1925)) ## 3.0.0-beta.24 - 2017-08-15 From 992a8b80a6493454c60858a762464d6d2a0a2955 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Thu, 17 Aug 2017 10:27:58 -0700 Subject: [PATCH 27/79] Allow $siteId to be null in getVersionsByEntryId() --- src/services/EntryRevisions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/EntryRevisions.php b/src/services/EntryRevisions.php index 9e94a3b9d0f..fb7e5b4124c 100644 --- a/src/services/EntryRevisions.php +++ b/src/services/EntryRevisions.php @@ -338,14 +338,14 @@ public function getVersionById(int $versionId) * Returns versions by an entry ID. * * @param int $entryId The entry ID to search for. - * @param int $siteId The site ID to search for. + * @param int|null $siteId The site ID to search for. * @param int|null $limit The limit on the number of versions to retrieve. * @param bool $includeCurrent Whether to include the current "top" version of the entry. * @param bool $withContent Whether the field content should be included on the versions * * @return EntryVersion[] */ - public function getVersionsByEntryId(int $entryId, int $siteId, int $limit = null, bool $includeCurrent = false, bool $withContent = false): array + public function getVersionsByEntryId(int $entryId, int $siteId = null, int $limit = null, bool $includeCurrent = false, bool $withContent = false): array { if (!$siteId) { $siteId = Craft::$app->getSites()->getPrimarySite()->id; From 0bfb15222d84564166d51e6ecfb51f9d9cb58168 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Thu, 17 Aug 2017 10:49:56 -0700 Subject: [PATCH 28/79] Resolved #1926 --- CHANGELOG-v3.md | 7 +++++++ src/controllers/EntriesController.php | 11 ++++++++++- src/elements/Entry.php | 5 +++++ src/services/EntryRevisions.php | 21 ++++++++++++++++++++- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 8f86498a35b..cfa931ac2d0 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -3,6 +3,13 @@ Craft CMS 3.0 Working Changelog ## Unreleased +### Added +- Added `craft\elements\Entry::$revisionCreatorId`. +- Added `craft\services\EntryRevisions::doesEntryHaveVersions()`. + +### Changed +- Craft now retroactively creates entry versions when saving entries, for entries that didn’t have any version history yet. ([#1926](https://github.com/craftcms/cms/issues/1926)) + ### Fixed - Fixed an error that occurred when chaining a custom field method and a normal query method (e.g. `all()`) together on an element query. ([#1887](https://github.com/craftcms/cms/issues/1887)) - Fixed a PHP error that occurred when processing a user verification request. diff --git a/src/controllers/EntriesController.php b/src/controllers/EntriesController.php index 1c963bd6d7c..c97326371a4 100644 --- a/src/controllers/EntriesController.php +++ b/src/controllers/EntriesController.php @@ -477,6 +477,15 @@ public function actionSaveEntry() } } + // Make sure the entry has at least one version if the section has versioning enabled + $revisionsService = Craft::$app->getEntryRevisions(); + if ($entry->getSection()->enableVersioning && !$revisionsService->doesEntryHaveVersions($entry->id, $entry->siteId)) { + $currentEntry = Craft::$app->getEntries()->getEntryById($entry->id, $entry->siteId); + $currentEntry->revisionCreatorId = $entry->authorId; + $currentEntry->revisionNotes = 'Revision from '.Craft::$app->getFormatter()->asDatetime($entry->dateUpdated); + $revisionsService->saveVersion($currentEntry); + } + // Save the entry (finally!) if (!Craft::$app->getElements()->saveElement($entry)) { if ($request->getAcceptsJson()) { @@ -497,7 +506,7 @@ public function actionSaveEntry() // Should we save a new version? if ($entry->getSection()->enableVersioning) { - Craft::$app->getEntryRevisions()->saveVersion($entry); + $revisionsService->saveVersion($entry); } if ($request->getAcceptsJson()) { diff --git a/src/elements/Entry.php b/src/elements/Entry.php index cf66fc2cca7..6e3beca9057 100644 --- a/src/elements/Entry.php +++ b/src/elements/Entry.php @@ -476,6 +476,11 @@ protected static function prepElementQueryForTableAttribute(ElementQueryInterfac */ public $newParentId; + /** + * @var int|null Revision creator ID + */ + public $revisionCreatorId; + /** * @var string|null Revision notes */ diff --git a/src/services/EntryRevisions.php b/src/services/EntryRevisions.php index fb7e5b4124c..f4c44385e94 100644 --- a/src/services/EntryRevisions.php +++ b/src/services/EntryRevisions.php @@ -334,6 +334,25 @@ public function getVersionById(int $versionId) return $version; } + /** + * Returns whether an entry has any versions stored. + * + * @param int $entryId The entry ID to search for + * @param int|null $siteId The site ID to search for + * + * @return bool + */ + public function doesEntryHaveVersions(int $entryId, int $siteId = null): bool + { + if (!$siteId) { + $siteId = Craft::$app->getSites()->getPrimarySite()->id; + } + + return $this->_getRevisionsQuery() + ->where(['entryId' => $entryId, 'siteId' => $siteId]) + ->exists(); + } + /** * Returns versions by an entry ID. * @@ -397,7 +416,7 @@ public function saveVersion(Entry $entry): bool $versionRecord = new EntryVersionRecord(); $versionRecord->entryId = $entry->id; $versionRecord->sectionId = $entry->sectionId; - $versionRecord->creatorId = Craft::$app->getUser()->getIdentity()->id ?? $entry->authorId; + $versionRecord->creatorId = $entry->revisionCreatorId ?? Craft::$app->getUser()->getIdentity()->id ?? $entry->authorId; $versionRecord->siteId = $entry->siteId; $versionRecord->num = $totalVersions + 1; $versionRecord->data = $this->_getRevisionData($entry); From 80d977845210988b9d375cdddd5227eb9a2a0715 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Thu, 17 Aug 2017 11:02:41 -0700 Subject: [PATCH 29/79] Finish 3.0.0-beta.25 --- CHANGELOG-v3.md | 2 +- composer.json | 2 +- src/config/app/main.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index cfa931ac2d0..875beb26600 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -1,7 +1,7 @@ Craft CMS 3.0 Working Changelog =============================== -## Unreleased +## 3.0.0-beta.25 - 2017-08-17 ### Added - Added `craft\elements\Entry::$revisionCreatorId`. diff --git a/composer.json b/composer.json index 4cea5a04294..496a4aab17c 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "craftcms/cms", "description": "Craft CMS", - "version": "3.0.0-beta.24", + "version": "3.0.0-beta.25", "keywords": [ "cms", "craftcms", diff --git a/src/config/app/main.php b/src/config/app/main.php index 386d46cbfaf..c9b7b3d1a07 100644 --- a/src/config/app/main.php +++ b/src/config/app/main.php @@ -3,7 +3,7 @@ return [ 'id' => 'CraftCMS', 'name' => 'Craft CMS', - 'version' => '3.0.0-beta.24', + 'version' => '3.0.0-beta.25', 'schemaVersion' => '3.0.57', 'minVersionRequired' => '2.6.2788', 'basePath' => dirname(__DIR__, 2), // Defines the @app alias From af453b0c7ac4d69279a4ed8a60d3ecd40f2d015f Mon Sep 17 00:00:00 2001 From: Brad Bell Date: Fri, 18 Aug 2017 12:42:13 -0700 Subject: [PATCH 30/79] Fixed a bug where you could get a PHP error uploading some JPG files on PHP 7.1. --- CHANGELOG.md | 5 +++++ composer.json | 2 +- composer.lock | 50 +++++++++++++++++++++++++------------------------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 628018f0915..accb370da69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Craft CMS Changelog =================== +## Unreleased + +### Fixed +- Fixed a bug where you could get a PHP error uploading some JPG files on PHP 7.1. + ## 2.6.2989 2017-08-15 ### Added diff --git a/composer.json b/composer.json index 33b5bbe2ed5..2c078a519e3 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "simplepie/simplepie": "1.3.3", "phpmailer/phpmailer": "v5.2.21", "pixelandtonic/imagine": "v0.7.1.1", - "lsolesen/pel": "0.9.4.2", + "lsolesen/pel": "0.9.4.3", "pclzip/pclzip": "2.8.2", "yiisoft/yii": "1.1.19.3", "enshrined/svg-sanitize": "0.6.0" diff --git a/composer.lock b/composer.lock index bc612f09df4..6e588c9ad25 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "b206495be965bedff0d8fc5832383380", + "content-hash": "b985ea63f3943e0bdddc875042136584", "packages": [ { "name": "enshrined/svg-sanitize", @@ -147,16 +147,16 @@ }, { "name": "lsolesen/pel", - "version": "0.9.4.2", + "version": "0.9.4.3", "source": { "type": "git", "url": "https://github.com/pixelandtonic/pel.git", - "reference": "997acac523a62753da50450d2d2944ccef12b083" + "reference": "ba75801103d43272feae21453ff4bda1cdf4198e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pixelandtonic/pel/zipball/997acac523a62753da50450d2d2944ccef12b083", - "reference": "997acac523a62753da50450d2d2944ccef12b083", + "url": "https://api.github.com/repos/pixelandtonic/pel/zipball/ba75801103d43272feae21453ff4bda1cdf4198e", + "reference": "ba75801103d43272feae21453ff4bda1cdf4198e", "shasum": "" }, "require": { @@ -196,9 +196,9 @@ "image" ], "support": { - "source": "https://github.com/pixelandtonic/pel/tree/0.9.4.2" + "source": "https://github.com/pixelandtonic/pel/tree/0.9.4.3" }, - "time": "2016-12-30T22:03:09+00:00" + "time": "2017-08-18T19:14:40+00:00" }, { "name": "pclzip/pclzip", @@ -413,7 +413,7 @@ }, { "name": "symfony/event-dispatcher", - "version": "v2.8.24", + "version": "v2.8.26", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -853,22 +853,22 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.1.1", + "version": "3.2.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" + "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/4aada1f93c72c35e22fb1383b47fee43b8f1d157", + "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157", "shasum": "" }, "require": { "php": ">=5.5", "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.2.0", + "phpdocumentor/type-resolver": "^0.3.0", "webmozart/assert": "^1.0" }, "require-dev": { @@ -894,24 +894,24 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-09-30T07:12:33+00:00" + "time": "2017-08-08T06:39:58+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.2.1", + "version": "0.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" + "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fb3933512008d8162b3cdf9e18dba9309b7c3773", + "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773", "shasum": "" }, "require": { - "php": ">=5.5", + "php": "^5.5 || ^7.0", "phpdocumentor/reflection-common": "^1.0" }, "require-dev": { @@ -941,7 +941,7 @@ "email": "me@mikevanriel.com" } ], - "time": "2016-11-25T06:54:22+00:00" + "time": "2017-06-03T08:32:36+00:00" }, { "name": "phpspec/prophecy", @@ -1756,16 +1756,16 @@ }, { "name": "symfony/yaml", - "version": "v3.3.4", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "1f93a8d19b8241617f5074a123e282575b821df8" + "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/1f93a8d19b8241617f5074a123e282575b821df8", - "reference": "1f93a8d19b8241617f5074a123e282575b821df8", + "url": "https://api.github.com/repos/symfony/yaml/zipball/ddc23324e6cfe066f3dd34a37ff494fa80b617ed", + "reference": "ddc23324e6cfe066f3dd34a37ff494fa80b617ed", "shasum": "" }, "require": { @@ -1807,7 +1807,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-06-15T12:58:50+00:00" + "time": "2017-07-23T12:43:26+00:00" }, { "name": "webmozart/assert", From b00dab4bdcb0e63a27bbcdb7c3b6827ef07404b5 Mon Sep 17 00:00:00 2001 From: Brad Bell Date: Sun, 20 Aug 2017 13:33:34 -0700 Subject: [PATCH 31/79] Fixed a bug where you would get a SQL error if you tried to push a job to the queue using PostgreSQL. --- CHANGELOG-v3.md | 1 + src/queue/Queue.php | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index cfa931ac2d0..5b3f3501907 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -14,6 +14,7 @@ Craft CMS 3.0 Working Changelog - Fixed an error that occurred when chaining a custom field method and a normal query method (e.g. `all()`) together on an element query. ([#1887](https://github.com/craftcms/cms/issues/1887)) - Fixed a PHP error that occurred when processing a user verification request. - Fixed a bug where newly-created `div.matrixblock` elements weren’t getting a `data-type` attribute like existing blocks had. ([#1925](https://github.com/craftcms/cms/pull/1925)) +- Fixed a bug where you would get a SQL error if you tried to push a job to the queue using PostgreSQL. ## 3.0.0-beta.24 - 2017-08-15 diff --git a/src/queue/Queue.php b/src/queue/Queue.php index 7680e4bdf88..ccea430d650 100644 --- a/src/queue/Queue.php +++ b/src/queue/Queue.php @@ -418,8 +418,7 @@ protected function pushMessage($message, $ttr, $delay, $priority) false) ->execute(); - $tableSchema = $db->getTableSchema('{{%queue}}'); - return $db->getLastInsertID($tableSchema->sequenceName); + return $db->getLastInsertID('{{%queue}}'); } /** From a8e3c9816baee1d611011316714c9225e03803a5 Mon Sep 17 00:00:00 2001 From: Brad Bell Date: Sun, 20 Aug 2017 13:46:49 -0700 Subject: [PATCH 32/79] Better fix for #1926 that doesn't break saving new entries. --- src/controllers/EntriesController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/EntriesController.php b/src/controllers/EntriesController.php index c97326371a4..2d2d5c7ba2f 100644 --- a/src/controllers/EntriesController.php +++ b/src/controllers/EntriesController.php @@ -479,7 +479,7 @@ public function actionSaveEntry() // Make sure the entry has at least one version if the section has versioning enabled $revisionsService = Craft::$app->getEntryRevisions(); - if ($entry->getSection()->enableVersioning && !$revisionsService->doesEntryHaveVersions($entry->id, $entry->siteId)) { + if ($entry->getSection()->enableVersioning && $entry->id && !$revisionsService->doesEntryHaveVersions($entry->id, $entry->siteId)) { $currentEntry = Craft::$app->getEntries()->getEntryById($entry->id, $entry->siteId); $currentEntry->revisionCreatorId = $entry->authorId; $currentEntry->revisionNotes = 'Revision from '.Craft::$app->getFormatter()->asDatetime($entry->dateUpdated); From 38d003da72f482728242f53d94edcccc01127c11 Mon Sep 17 00:00:00 2001 From: Brad Bell Date: Sun, 20 Aug 2017 13:51:38 -0700 Subject: [PATCH 33/79] =?UTF-8?q?Fixed=20a=20bug=20that=20would=20trigger?= =?UTF-8?q?=20the=20browser=E2=80=99s=20JavaScript=20debugger=20if=20you?= =?UTF-8?q?=20saved=20a=20Matrix=20field=20that=20had=20collapsed=20blocks?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG-v3.md | 1 + src/services/Matrix.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 5b3f3501907..f0b0f1ba325 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -15,6 +15,7 @@ Craft CMS 3.0 Working Changelog - Fixed a PHP error that occurred when processing a user verification request. - Fixed a bug where newly-created `div.matrixblock` elements weren’t getting a `data-type` attribute like existing blocks had. ([#1925](https://github.com/craftcms/cms/pull/1925)) - Fixed a bug where you would get a SQL error if you tried to push a job to the queue using PostgreSQL. +- Fixed a bug that would trigger the browser’s JavaScript debugger if you saved a Matrix field that had collapsed blocks. ## 3.0.0-beta.24 - 2017-08-15 diff --git a/src/services/Matrix.php b/src/services/Matrix.php index 4f8b2caab7b..7063eae9092 100644 --- a/src/services/Matrix.php +++ b/src/services/Matrix.php @@ -730,7 +730,7 @@ public function saveField(MatrixField $field, ElementInterface $owner): bool Craft::$app->getSession()->addAssetBundleFlash(MatrixAsset::class); foreach ($collapsedBlockIds as $blockId) { - Craft::$app->getSession()->addJsFlash('debugger;'."\n".'Craft.MatrixInput.rememberCollapsedBlockId('.$blockId.');'); + Craft::$app->getSession()->addJsFlash('Craft.MatrixInput.rememberCollapsedBlockId('.$blockId.');'); } } From 48c300ecd21b4772e8730acf6e7f2b997047f0fd Mon Sep 17 00:00:00 2001 From: Benjamin David Date: Mon, 21 Aug 2017 12:36:05 +0200 Subject: [PATCH 34/79] Fixed a bug where \craft\helpers\ChartHelper::getRunChartDataFromQuery() an SQL query instead of the actual results --- CHANGELOG-v3.md | 1 + src/helpers/ChartHelper.php | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index f0b0f1ba325..277fcc56eb1 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -16,6 +16,7 @@ Craft CMS 3.0 Working Changelog - Fixed a bug where newly-created `div.matrixblock` elements weren’t getting a `data-type` attribute like existing blocks had. ([#1925](https://github.com/craftcms/cms/pull/1925)) - Fixed a bug where you would get a SQL error if you tried to push a job to the queue using PostgreSQL. - Fixed a bug that would trigger the browser’s JavaScript debugger if you saved a Matrix field that had collapsed blocks. +- Fixed a bug where \craft\helpers\ChartHelper::getRunChartDataFromQuery() an SQL query instead of the actual results. ## 3.0.0-beta.24 - 2017-08-15 diff --git a/src/helpers/ChartHelper.php b/src/helpers/ChartHelper.php index b91c8ab5505..e79d2d54d73 100644 --- a/src/helpers/ChartHelper.php +++ b/src/helpers/ChartHelper.php @@ -162,8 +162,6 @@ public static function getRunChartDataFromQuery(Query $query, DateTime $startDat ->orderBy($orderBy); } - die($query->getRawSql()); - // Execute the query $results = $query->all(); @@ -313,4 +311,4 @@ public static function dateRanges(): array return $dateRanges; } -} +} \ No newline at end of file From 20e8e4fe08237642189aaaa1e6f5dc265ee1bc54 Mon Sep 17 00:00:00 2001 From: Benjamin David Date: Mon, 21 Aug 2017 12:39:06 +0200 Subject: [PATCH 35/79] Fixed a bug where `\craft\controllers\BaseElementsController::context()` was expecting a`string ` return, while return could also be `null` --- CHANGELOG-v3.md | 3 ++- src/controllers/BaseElementsController.php | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 277fcc56eb1..95653ffd0e1 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -16,7 +16,8 @@ Craft CMS 3.0 Working Changelog - Fixed a bug where newly-created `div.matrixblock` elements weren’t getting a `data-type` attribute like existing blocks had. ([#1925](https://github.com/craftcms/cms/pull/1925)) - Fixed a bug where you would get a SQL error if you tried to push a job to the queue using PostgreSQL. - Fixed a bug that would trigger the browser’s JavaScript debugger if you saved a Matrix field that had collapsed blocks. -- Fixed a bug where \craft\helpers\ChartHelper::getRunChartDataFromQuery() an SQL query instead of the actual results. +- Fixed a bug where `craft\helpers\ChartHelper::getRunChartDataFromQuery()` an SQL query instead of the actual results. +- Fixed a bug where `craft\controllers\BaseElementsController::context()` was expecting a`string ` return, while return could also be `null`. ## 3.0.0-beta.24 - 2017-08-15 diff --git a/src/controllers/BaseElementsController.php b/src/controllers/BaseElementsController.php index 6d68672b2f3..2c464a25413 100644 --- a/src/controllers/BaseElementsController.php +++ b/src/controllers/BaseElementsController.php @@ -72,9 +72,9 @@ protected function elementType(): string /** * Returns the context that this controller is being called in. * - * @return string + * @return string|null */ - protected function context(): string + protected function context() { return Craft::$app->getRequest()->getParam('context'); } From 676623b0f528d7212a289e6b9e3fbe16b3f53af3 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Mon, 21 Aug 2017 11:15:56 -0700 Subject: [PATCH 36/79] Fixed #1927 --- CHANGELOG-v3.md | 5 ++++ src/config/app/main.php | 2 +- src/migrations/Install.php | 2 +- ...70821_180624_deprecation_line_nullable.php | 29 +++++++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 src/migrations/m170821_180624_deprecation_line_nullable.php diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 290bc3587d8..739d3dad728 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -1,6 +1,11 @@ Craft CMS 3.0 Working Changelog =============================== +## Unreleased + +### Fixed +- Fixed a SQL error that could occur when logging deprecation errors if the line number is unknown. ([#1927](https://github.com/craftcms/cms/issues/1927)) + ## 3.0.0-beta.25 - 2017-08-17 ### Added diff --git a/src/config/app/main.php b/src/config/app/main.php index c9b7b3d1a07..41c878c31ff 100644 --- a/src/config/app/main.php +++ b/src/config/app/main.php @@ -4,7 +4,7 @@ 'id' => 'CraftCMS', 'name' => 'Craft CMS', 'version' => '3.0.0-beta.25', - 'schemaVersion' => '3.0.57', + 'schemaVersion' => '3.0.58', 'minVersionRequired' => '2.6.2788', 'basePath' => dirname(__DIR__, 2), // Defines the @app alias 'runtimePath' => '@storage/runtime', // Defines the @runtime alias diff --git a/src/migrations/Install.php b/src/migrations/Install.php index 7c857c6d994..db60e944ea2 100644 --- a/src/migrations/Install.php +++ b/src/migrations/Install.php @@ -220,7 +220,7 @@ protected function createTables() 'fingerprint' => $this->string()->notNull(), 'lastOccurrence' => $this->dateTime()->notNull(), 'file' => $this->string()->notNull(), - 'line' => $this->smallInteger()->notNull()->unsigned(), + 'line' => $this->smallInteger()->unsigned(), 'message' => $this->string(), 'traces' => $this->text(), 'dateCreated' => $this->dateTime()->notNull(), diff --git a/src/migrations/m170821_180624_deprecation_line_nullable.php b/src/migrations/m170821_180624_deprecation_line_nullable.php new file mode 100644 index 00000000000..a0281040aeb --- /dev/null +++ b/src/migrations/m170821_180624_deprecation_line_nullable.php @@ -0,0 +1,29 @@ +alterColumn('{{%deprecationerrors}}', 'line', $this->smallInteger()->unsigned()); + } + + /** + * @inheritdoc + */ + public function safeDown() + { + echo "m170821_180624_deprecation_line_nullable cannot be reverted.\n"; + return false; + } +} From a76c74c9447384e84848ccb17ad180883c75b789 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Mon, 21 Aug 2017 15:28:49 -0700 Subject: [PATCH 37/79] Could be null --- src/fields/BaseRelationField.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fields/BaseRelationField.php b/src/fields/BaseRelationField.php index 17df7c00078..9d99c8ce335 100644 --- a/src/fields/BaseRelationField.php +++ b/src/fields/BaseRelationField.php @@ -334,7 +334,7 @@ public function getIsTranslatable(ElementInterface $element = null): bool */ public function getInputHtml($value, ElementInterface $element = null): string { - /** @var Element $element */ + /** @var Element|null $element */ if ($element !== null && $element->hasEagerLoadedElements($this->handle)) { $value = $element->getEagerLoadedElements($this->handle); } From 060ddfabca6ba26754115b73e688a90791a799d4 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Mon, 21 Aug 2017 15:30:13 -0700 Subject: [PATCH 38/79] Fixed #1932 --- CHANGELOG-v3.md | 1 + src/fields/Tags.php | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 739d3dad728..728d9e51e0f 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -5,6 +5,7 @@ Craft CMS 3.0 Working Changelog ### Fixed - Fixed a SQL error that could occur when logging deprecation errors if the line number is unknown. ([#1927](https://github.com/craftcms/cms/issues/1927)) +- Fixed a deprecation error that occurred when using a Tags field. ([#1932](https://github.com/craftcms/cms/issues/1932)) ## 3.0.0-beta.25 - 2017-08-17 diff --git a/src/fields/Tags.php b/src/fields/Tags.php index 5302b910fc3..1500cd76c8b 100644 --- a/src/fields/Tags.php +++ b/src/fields/Tags.php @@ -10,6 +10,7 @@ use Craft; use craft\base\Element; use craft\base\ElementInterface; +use craft\elements\db\ElementQuery; use craft\elements\db\ElementQueryInterface; use craft\elements\Tag; use craft\models\TagGroup; @@ -76,11 +77,17 @@ public function init() public function getInputHtml($value, ElementInterface $element = null): string { /** @var Element|null $element */ - if (!($value instanceof ElementQueryInterface)) { - /** @var Element $class */ - $class = static::elementType(); - $value = $class::find() - ->id(false); + if ($element !== null && $element->hasEagerLoadedElements($this->handle)) { + $value = $element->getEagerLoadedElements($this->handle); + } + + if ($value instanceof ElementQueryInterface) { + $value = $value + ->status(null) + ->enabledForSite(false) + ->all(); + } else if (!is_array($value)) { + $value = []; } $tagGroup = $this->_getTagGroup(); From 48268541c23b277109d92e9bc79ee8e90776c558 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 22 Aug 2017 08:26:04 -0700 Subject: [PATCH 39/79] null => false --- src/base/VolumeInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/VolumeInterface.php b/src/base/VolumeInterface.php index 4f0ba2b611e..77ad7b07f4f 100644 --- a/src/base/VolumeInterface.php +++ b/src/base/VolumeInterface.php @@ -28,7 +28,7 @@ interface VolumeInterface extends SavableComponentInterface /** * Returns the URL to the source, if it’s accessible via HTTP traffic. * - * @return string|null The root URL, or `false` if there isn’t one + * @return string|false The root URL, or `false` if there isn’t one */ public function getRootUrl(); From 9f2712e52dc6218c4a142e8ff786d73a929baeb7 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 22 Aug 2017 08:27:48 -0700 Subject: [PATCH 40/79] Fixed #1934 --- CHANGELOG-v3.md | 1 + src/volumes/MissingVolume.php | 114 ++++++++++++++++++++++++++++++++-- 2 files changed, 111 insertions(+), 4 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 728d9e51e0f..73c7797ca0a 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -6,6 +6,7 @@ Craft CMS 3.0 Working Changelog ### Fixed - Fixed a SQL error that could occur when logging deprecation errors if the line number is unknown. ([#1927](https://github.com/craftcms/cms/issues/1927)) - Fixed a deprecation error that occurred when using a Tags field. ([#1932](https://github.com/craftcms/cms/issues/1932)) +- Fixed a PHP error that occurred if a volume type class was missing. ([#1934](https://github.com/craftcms/cms/issues/1934)) ## 3.0.0-beta.25 - 2017-08-17 diff --git a/src/volumes/MissingVolume.php b/src/volumes/MissingVolume.php index dcec9217a5a..968bfe12007 100644 --- a/src/volumes/MissingVolume.php +++ b/src/volumes/MissingVolume.php @@ -10,6 +10,7 @@ use craft\base\MissingComponentInterface; use craft\base\MissingComponentTrait; use craft\base\Volume; +use yii\base\NotSupportedException; /** * MissingVolume represents a volume with an invalid class. @@ -30,16 +31,121 @@ class MissingVolume extends Volume implements MissingComponentInterface /** * @inheritdoc */ - protected function createAdapter() + public function getRootUrl() { - return null; + return false; } /** * @inheritdoc */ - public function getRootUrl() + public function getFileList(string $directory, bool $recursive): array + { + throw new NotSupportedException('getFileList() is not implemented.'); + } + + /** + * @inheritdoc + */ + public function getFileMetadata(string $uri): array + { + throw new NotSupportedException('getFileMetadata() is not implemented.'); + } + + /** + * @inheritdoc + */ + public function createFileByStream(string $path, $stream, array $config) + { + throw new NotSupportedException('createFileByStream() is not implemented.'); + } + + /** + * @inheritdoc + */ + public function updateFileByStream(string $path, $stream, array $config) + { + throw new NotSupportedException('updateFileByStream() is not implemented.'); + } + + /** + * @inheritdoc + */ + public function fileExists(string $path): bool + { + throw new NotSupportedException('fileExists() is not implemented.'); + } + + /** + * @inheritdoc + */ + public function deleteFile(string $path) + { + throw new NotSupportedException('deleteFile() is not implemented.'); + } + + /** + * @inheritdoc + */ + public function renameFile(string $path, string $newPath) + { + throw new NotSupportedException('renameFile() is not implemented.'); + } + + /** + * @inheritdoc + */ + public function copyFile(string $path, string $newPath) + { + throw new NotSupportedException('copyFile() is not implemented.'); + } + + /** + * @inheritdoc + */ + public function saveFileLocally(string $uriPath, string $targetPath): int + { + throw new NotSupportedException('saveFileLocally() is not implemented.'); + } + + /** + * @inheritdoc + */ + public function getFileStream(string $uriPath) + { + throw new NotSupportedException('getFileStream() is not implemented.'); + } + + /** + * @inheritdoc + */ + public function folderExists(string $path): bool + { + throw new NotSupportedException('folderExists() is not implemented.'); + } + + /** + * + * @inheritdoc + */ + public function createDir(string $path) + { + throw new NotSupportedException('createDir() is not implemented.'); + } + + /** + * @inheritdoc + */ + public function deleteDir(string $path) + { + throw new NotSupportedException('deleteDir() is not implemented.'); + } + + /** + * @inheritdoc + */ + public function renameDir(string $path, string $newName) { - return null; + throw new NotSupportedException('renameDir() is not implemented.'); } } From 006c9f65037f36f397d57df377d4cb7599a1c153 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 22 Aug 2017 08:38:27 -0700 Subject: [PATCH 41/79] a8e3c9816baee1d611011316714c9225e03803a5 fixed #1935 --- CHANGELOG-v3.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 73c7797ca0a..f730ca4dcca 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -7,6 +7,7 @@ Craft CMS 3.0 Working Changelog - Fixed a SQL error that could occur when logging deprecation errors if the line number is unknown. ([#1927](https://github.com/craftcms/cms/issues/1927)) - Fixed a deprecation error that occurred when using a Tags field. ([#1932](https://github.com/craftcms/cms/issues/1932)) - Fixed a PHP error that occurred if a volume type class was missing. ([#1934](https://github.com/craftcms/cms/issues/1934)) +- Fixed a PHP error that occurred when saving a new entry in a section with versioning enabled. ([#1935](https://github.com/craftcms/cms/issues/1935)) ## 3.0.0-beta.25 - 2017-08-17 From baf85c916b0ffe854435f3e4c0d176bbca2f16f7 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 22 Aug 2017 12:43:51 -0700 Subject: [PATCH 42/79] Finish 3.0.0-beta.26 --- CHANGELOG-v3.md | 2 +- composer.json | 2 +- src/config/app/main.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index f730ca4dcca..287e447ac58 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -1,7 +1,7 @@ Craft CMS 3.0 Working Changelog =============================== -## Unreleased +## 3.0.0-beta.26 - 2017-08-22 ### Fixed - Fixed a SQL error that could occur when logging deprecation errors if the line number is unknown. ([#1927](https://github.com/craftcms/cms/issues/1927)) diff --git a/composer.json b/composer.json index 496a4aab17c..6f34d63d96c 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "craftcms/cms", "description": "Craft CMS", - "version": "3.0.0-beta.25", + "version": "3.0.0-beta.26", "keywords": [ "cms", "craftcms", diff --git a/src/config/app/main.php b/src/config/app/main.php index 41c878c31ff..0946ff81d52 100644 --- a/src/config/app/main.php +++ b/src/config/app/main.php @@ -3,7 +3,7 @@ return [ 'id' => 'CraftCMS', 'name' => 'Craft CMS', - 'version' => '3.0.0-beta.25', + 'version' => '3.0.0-beta.26', 'schemaVersion' => '3.0.58', 'minVersionRequired' => '2.6.2788', 'basePath' => dirname(__DIR__, 2), // Defines the @app alias From 3f66c8d8382b6932ac08d3838decf4a64a0d9341 Mon Sep 17 00:00:00 2001 From: Brad Bell Date: Tue, 22 Aug 2017 14:17:30 -0700 Subject: [PATCH 43/79] Fixed a potential XSS vuln where you could access TemplatesController methods directly (specifically actionRender()) if you used a capital T in the action request. --- CHANGELOG.md | 3 +++ src/controllers/TemplatesController.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index accb370da69..130d6371950 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ Craft CMS Changelog ### Fixed - Fixed a bug where you could get a PHP error uploading some JPG files on PHP 7.1. +### Security +- Fixed an XSS vulnerability. + ## 2.6.2989 2017-08-15 ### Added diff --git a/src/controllers/TemplatesController.php b/src/controllers/TemplatesController.php index 046bfb2f29e..7496e4802c9 100644 --- a/src/controllers/TemplatesController.php +++ b/src/controllers/TemplatesController.php @@ -44,7 +44,7 @@ class TemplatesController extends BaseController public function beforeAction($action) { $actionSegments = craft()->request->getActionSegments(); - if (isset($actionSegments[0]) && $actionSegments[0] === 'templates') { + if (isset($actionSegments[0]) && StringHelper::toLowerCase($actionSegments[0]) === 'templates') { throw new HttpException(403); } From d514fb7aaa4190c76e7cfc96c58c4bc602e7c606 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Wed, 23 Aug 2017 09:30:57 -0700 Subject: [PATCH 44/79] StringHelper::split() --- CHANGELOG-v3.md | 5 +++++ src/db/Connection.php | 6 +++--- src/helpers/StringHelper.php | 13 +++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 287e447ac58..e7213f3e8e6 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -1,6 +1,11 @@ Craft CMS 3.0 Working Changelog =============================== +## Unreleased + +### Added +- Added `craft\helpers\StringHelper::split()`. + ## 3.0.0-beta.26 - 2017-08-22 ### Fixed diff --git a/src/db/Connection.php b/src/db/Connection.php index c5909f49b4e..0029bc7b34a 100644 --- a/src/db/Connection.php +++ b/src/db/Connection.php @@ -309,7 +309,7 @@ public function getPrimaryKeyName(string $table, $columns): string { $table = $this->_getTableNameWithoutPrefix($table); if (is_string($columns)) { - $columns = preg_split('/\s*,\s*/', $columns, -1, PREG_SPLIT_NO_EMPTY); + $columns = StringHelper::split($columns); } $name = $this->tablePrefix.$table.'_'.implode('_', $columns).'_pk'; @@ -328,7 +328,7 @@ public function getForeignKeyName(string $table, $columns): string { $table = $this->_getTableNameWithoutPrefix($table); if (is_string($columns)) { - $columns = preg_split('/\s*,\s*/', $columns, -1, PREG_SPLIT_NO_EMPTY); + $columns = StringHelper::split($columns); } $name = $this->tablePrefix.$table.'_'.implode('_', $columns).'_fk'; @@ -350,7 +350,7 @@ public function getIndexName(string $table, $columns, bool $unique = false, bool { $table = $this->_getTableNameWithoutPrefix($table); if (is_string($columns)) { - $columns = preg_split('/\s*,\s*/', $columns, -1, PREG_SPLIT_NO_EMPTY); + $columns = StringHelper::split($columns); } $name = $this->tablePrefix.$table.'_'.implode('_', $columns).($unique ? '_unq' : '').($foreignKey ? '_fk' : '_idx'); diff --git a/src/helpers/StringHelper.php b/src/helpers/StringHelper.php index 8f281011447..71e7d0f73ee 100644 --- a/src/helpers/StringHelper.php +++ b/src/helpers/StringHelper.php @@ -511,6 +511,19 @@ public static function toSnakeCase(string $string): string return implode('_', $words); } + /** + * Splits a string into chunks on a given delimiter. + * + * @param string $string The string + * @param string $delimiter The delimiter to split the string on (defaults to a comma) + * + * @return string[] The segments of the string + */ + public static function split(string $string, string $delimiter = ','): array + { + return preg_split('/\s*'.preg_quote($delimiter, '/').'\s*/', $string, -1, PREG_SPLIT_NO_EMPTY); + } + /** * Splits a string into an array of the words in the string. * From e70fc98994af597cb66878ae225c8263897ae760 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Wed, 23 Aug 2017 13:00:25 -0700 Subject: [PATCH 45/79] withTransforms can be set to a string --- src/elements/db/AssetQuery.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/elements/db/AssetQuery.php b/src/elements/db/AssetQuery.php index db1329d5c6c..f4ab55782f0 100644 --- a/src/elements/db/AssetQuery.php +++ b/src/elements/db/AssetQuery.php @@ -81,7 +81,7 @@ class AssetQuery extends ElementQuery public $includeSubfolders = false; /** - * @var array|null The asset transform indexes that should be eager-loaded, if they exist + * @var string|array|null The asset transform indexes that should be eager-loaded, if they exist */ public $withTransforms; @@ -283,7 +283,7 @@ public function includeSubfolders(bool $value = true) /** * Sets the [[withTransforms]] property. * - * @param array|null $value The transforms to include. + * @param string|array|null $value The transforms to include. * * @return self The query object itself */ From c4b054284d08789864d3e9c52e59a6386b298ae9 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Wed, 23 Aug 2017 13:03:46 -0700 Subject: [PATCH 46/79] Default status values should be arrays --- src/elements/db/ElementQuery.php | 2 +- src/elements/db/EntryQuery.php | 2 +- src/elements/db/UserQuery.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/elements/db/ElementQuery.php b/src/elements/db/ElementQuery.php index 97a7601c265..b4ab799142e 100644 --- a/src/elements/db/ElementQuery.php +++ b/src/elements/db/ElementQuery.php @@ -125,7 +125,7 @@ class ElementQuery extends Query implements ElementQueryInterface /** * @var string|string[]|null The status(es) that the resulting elements must have. */ - public $status = 'enabled'; + public $status = ['enabled']; /** * @var bool Whether to return only archived elements. diff --git a/src/elements/db/EntryQuery.php b/src/elements/db/EntryQuery.php index 9190ed953a3..32d16258e08 100644 --- a/src/elements/db/EntryQuery.php +++ b/src/elements/db/EntryQuery.php @@ -88,7 +88,7 @@ public function __construct($elementType, array $config = []) { // Default status if (!isset($config['status'])) { - $config['status'] = 'live'; + $config['status'] = ['live']; } parent::__construct($elementType, $config); diff --git a/src/elements/db/UserQuery.php b/src/elements/db/UserQuery.php index e5d2f387334..14cf1c09f64 100644 --- a/src/elements/db/UserQuery.php +++ b/src/elements/db/UserQuery.php @@ -95,7 +95,7 @@ public function __construct($elementType, array $config = []) // Default status if (!isset($config['status'])) { - $config['status'] = User::STATUS_ACTIVE; + $config['status'] = [User::STATUS_ACTIVE]; } parent::__construct($elementType, $config); From d72d134465ee2d892b2dbc425bf90f521140f42f Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Wed, 23 Aug 2017 13:40:47 -0700 Subject: [PATCH 47/79] Fixed #1939 --- CHANGELOG-v3.md | 6 +++ src/config/GeneralConfig.php | 6 +-- src/elements/db/AssetQuery.php | 11 +++-- src/elements/db/CategoryQuery.php | 8 +++- src/elements/db/ElementQuery.php | 11 ++++- .../db/ElementRelationParamParser.php | 17 +++++--- src/elements/db/EntryQuery.php | 27 +++++++++--- src/helpers/ArrayHelper.php | 4 ++ src/helpers/Component.php | 2 - src/helpers/Db.php | 41 ++++++++++++++++++- src/helpers/MigrationHelper.php | 8 +++- src/services/Elements.php | 5 ++- src/validators/UniqueValidator.php | 8 +++- tests/unit/helpers/ArrayHelperTest.php | 1 - 14 files changed, 123 insertions(+), 32 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index e7213f3e8e6..4e446390324 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -6,6 +6,12 @@ Craft CMS 3.0 Working Changelog ### Added - Added `craft\helpers\StringHelper::split()`. +### Deprecated +- Splitting a string on commas via `craft\helpers\ArrayHelper::toArray()` is now deprecated. Use `craft\helpers\StringHelper::split()` instead. + +### Fixed +- Fixed a SQL error that could occur when using the `relatedTo` element query param. ([#1939](https://github.com/craftcms/cms/issues/1939)) + ## 3.0.0-beta.26 - 2017-08-22 ### Fixed diff --git a/src/config/GeneralConfig.php b/src/config/GeneralConfig.php index 647d919ecf2..b27ef668e56 100644 --- a/src/config/GeneralConfig.php +++ b/src/config/GeneralConfig.php @@ -7,8 +7,8 @@ namespace craft\config; -use craft\helpers\ArrayHelper; use craft\helpers\ConfigHelper; +use craft\helpers\StringHelper; use yii\base\InvalidConfigException; use yii\base\Object; use yii\base\UnknownPropertyException; @@ -768,10 +768,10 @@ public function init() // Merge extraAllowedFileExtensions into allowedFileExtensions if (is_string($this->allowedFileExtensions)) { - $this->allowedFileExtensions = ArrayHelper::toArray($this->allowedFileExtensions); + $this->allowedFileExtensions = StringHelper::split($this->allowedFileExtensions); } if (is_string($this->extraAllowedFileExtensions)) { - $this->extraAllowedFileExtensions = ArrayHelper::toArray($this->extraAllowedFileExtensions); + $this->extraAllowedFileExtensions = StringHelper::split($this->extraAllowedFileExtensions); } if (is_array($this->extraAllowedFileExtensions)) { $this->allowedFileExtensions = array_merge($this->allowedFileExtensions, $this->extraAllowedFileExtensions); diff --git a/src/elements/db/AssetQuery.php b/src/elements/db/AssetQuery.php index f4ab55782f0..17b8fb3fec5 100644 --- a/src/elements/db/AssetQuery.php +++ b/src/elements/db/AssetQuery.php @@ -11,8 +11,8 @@ use craft\base\Volume; use craft\db\Query; use craft\elements\Asset; -use craft\helpers\ArrayHelper; use craft\helpers\Db; +use craft\helpers\StringHelper; use yii\db\Connection; /** @@ -302,10 +302,13 @@ public function populate($rows) $elements = parent::populate($rows); // Eager-load transforms? - if ($this->asArray === false && !empty($this->withTransforms)) { - $transforms = ArrayHelper::toArray($this->withTransforms); + if ($this->asArray === false && $this->withTransforms) { + $transforms = $this->withTransforms; + if (!is_array($transforms)) { + $transforms = is_string($transforms) ? StringHelper::split($transforms) : [$transforms]; + } - Craft::$app->getAssetTransforms()->eagerLoadTransforms($elements, $transforms); + Craft::$app->getAssetTransforms()->eagerLoadTransforms($elements, $this->withTransforms); } return $elements; diff --git a/src/elements/db/CategoryQuery.php b/src/elements/db/CategoryQuery.php index c715ca2ccde..86f11fffd5c 100644 --- a/src/elements/db/CategoryQuery.php +++ b/src/elements/db/CategoryQuery.php @@ -11,8 +11,8 @@ use craft\db\Query; use craft\db\QueryAbortedException; use craft\elements\Category; -use craft\helpers\ArrayHelper; use craft\helpers\Db; +use craft\helpers\StringHelper; use craft\models\CategoryGroup; use yii\db\Connection; @@ -201,7 +201,11 @@ private function _applyRefParam() return; } - $refs = ArrayHelper::toArray($this->ref); + $refs = $this->ref; + if (!is_array($refs)) { + $refs = is_string($refs) ? StringHelper::split($refs) : [$refs]; + } + $condition = ['or']; $joinCategoryGroups = false; diff --git a/src/elements/db/ElementQuery.php b/src/elements/db/ElementQuery.php index b4ab799142e..1263de3e1f6 100644 --- a/src/elements/db/ElementQuery.php +++ b/src/elements/db/ElementQuery.php @@ -1474,7 +1474,11 @@ private function _applyStatusParam(string $class) return; } - $statuses = ArrayHelper::toArray($this->status); + $statuses = $this->status; + if (!is_array($statuses)) { + $statuses = is_string($statuses) ? StringHelper::split($statuses) : [$statuses]; + } + $condition = ['or']; foreach ($statuses as $status) { @@ -1775,7 +1779,10 @@ private function _applyOrderByParams(Connection $db) // Any other empty value means we should set it if (empty($this->orderBy)) { if ($this->fixedOrder) { - $ids = ArrayHelper::toArray($this->id); + $ids = $this->id; + if (!is_array($ids)) { + $ids = is_string($ids) ? StringHelper::split($ids) : [$ids]; + } if (empty($ids)) { throw new QueryAbortedException; diff --git a/src/elements/db/ElementRelationParamParser.php b/src/elements/db/ElementRelationParamParser.php index 4f8d893fac2..c47a49609d0 100644 --- a/src/elements/db/ElementRelationParamParser.php +++ b/src/elements/db/ElementRelationParamParser.php @@ -15,6 +15,7 @@ use craft\fields\BaseRelationField; use craft\fields\Matrix; use craft\helpers\ArrayHelper; +use craft\helpers\StringHelper; use craft\models\Site; /** @@ -68,10 +69,8 @@ class ElementRelationParamParser public function parse($relatedToParam) { // Ensure the criteria is an array - if (is_string($relatedToParam)) { - $relatedToParam = ArrayHelper::toArray($relatedToParam); - } else if (!is_array($relatedToParam)) { - $relatedToParam = [$relatedToParam]; + if (!is_array($relatedToParam)) { + $relatedToParam = is_string($relatedToParam) ? StringHelper::split($relatedToParam) : [$relatedToParam]; } if (isset($relatedToParam['element']) || isset($relatedToParam['sourceElement']) || isset($relatedToParam['targetElement'])) { @@ -179,7 +178,10 @@ private function _subparse($relCriteria) foreach ($elementParams as $elementParam) { if (isset($relCriteria[$elementParam])) { - $elements = ArrayHelper::toArray($relCriteria[$elementParam], [], false); + $elements = $relCriteria[$elementParam]; + if (!is_array($elements)) { + $elements = is_string($elements) ? StringHelper::split($elements) : [$elements]; + } if (isset($elements[0]) && ($elements[0] === 'and' || $elements[0] === 'or')) { $glue = array_shift($elements); @@ -247,7 +249,10 @@ private function _subparse($relCriteria) if ($relCriteria['field']) { // Loop through all of the fields in this rel criteria, create the Matrix-specific conditions right away // and save the normal field IDs for later - $fields = ArrayHelper::toArray($relCriteria['field']); + $fields = $relCriteria['field']; + if (!is_array($fields)) { + $fields = is_string($fields) ? StringHelper::split($fields) : [$fields]; + } foreach ($fields as $field) { if (($fieldModel = $this->_getField($field, $fieldHandleParts)) === null) { diff --git a/src/elements/db/EntryQuery.php b/src/elements/db/EntryQuery.php index 32d16258e08..63acb0bedb7 100644 --- a/src/elements/db/EntryQuery.php +++ b/src/elements/db/EntryQuery.php @@ -13,6 +13,7 @@ use craft\elements\Entry; use craft\helpers\ArrayHelper; use craft\helpers\Db; +use craft\helpers\StringHelper; use craft\models\EntryType; use craft\models\Section; use craft\models\UserGroup; @@ -302,8 +303,14 @@ public function before($value) $value = $value->format(DateTime::W3C); } - $this->postDate = ArrayHelper::toArray($this->postDate); - $this->postDate[] = '<'.$value; + if (!$this->postDate) { + $this->postDate = '<'.$value; + } else { + if (!is_array($this->postDate)) { + $this->postDate = [$this->postDate]; + } + $this->postDate[] = '<'.$value;; + } return $this; } @@ -321,8 +328,14 @@ public function after($value) $value = $value->format(DateTime::W3C); } - $this->postDate = ArrayHelper::toArray($this->postDate); - $this->postDate[] = '>='.$value; + if (!$this->postDate) { + $this->postDate = '>='.$value; + } else { + if (!is_array($this->postDate)) { + $this->postDate = [$this->postDate]; + } + $this->postDate[] = '>='.$value;; + } return $this; } @@ -514,7 +527,11 @@ private function _applyRefParam() return; } - $refs = ArrayHelper::toArray($this->ref); + $refs = $this->ref; + if (!is_array($refs)) { + $refs = is_string($refs) ? StringHelper::split($refs) : [$refs]; + } + $joinSections = false; $condition = ['or']; diff --git a/src/helpers/ArrayHelper.php b/src/helpers/ArrayHelper.php index f6d19959d62..351bfdd8ac4 100644 --- a/src/helpers/ArrayHelper.php +++ b/src/helpers/ArrayHelper.php @@ -7,6 +7,8 @@ namespace craft\helpers; +use Craft; + /** * Class ArrayHelper * @@ -28,6 +30,8 @@ public static function toArray($object, $properties = [], $recursive = true): ar } if (is_string($object)) { + Craft::$app->getDeprecator()->log('ArrayHelper::toArray(string)', 'Passing a string to ArrayHelper::toArray() has been deprectaed. Use StringHelper::split() instead.'); + // Split it on the non-escaped commas $object = preg_split('/(? $val) { + // Remove leading/trailing whitespace + $val = trim($val); + + // Remove any backslashes used to escape commas + $val = str_replace('\,', ',', $val); + + $value[$key] = $val; + } + + // Remove any empty elements and reset the keys + $value = array_merge(array_filter($value)); + + return $value; + } + + return ArrayHelper::toArray($value); + } + /** * Normalizes “empty” values. * diff --git a/src/helpers/MigrationHelper.php b/src/helpers/MigrationHelper.php index b253a2143f4..d268ba15342 100644 --- a/src/helpers/MigrationHelper.php +++ b/src/helpers/MigrationHelper.php @@ -35,7 +35,9 @@ public static function doesForeignKeyExist(string $tableName, $columns): bool $schema = $db->getSchema(); $tableName = $schema->getRawTableName($tableName); $schema->refreshTableSchema($tableName); - $columns = ArrayHelper::toArray($columns); + if (is_string($columns)) { + $columns = StringHelper::split($columns); + } $table = $db->getTableSchema($tableName); foreach ($table->foreignKeys as $num => $fk) { @@ -87,7 +89,9 @@ public static function doesIndexExist(string $tableName, $columns, bool $unique { $db = Craft::$app->getDb(); $schema = $db->getSchema(); - $columns = ArrayHelper::toArray($columns); + if (!is_string($columns)) { + $columns = StringHelper::split($columns); + } $allIndexes = $schema->findIndexes($tableName); $needleIndex = $db->getIndexName($tableName, $columns, $unique, $foreignKey); diff --git a/src/services/Elements.php b/src/services/Elements.php index b34fea1bd13..d29cbb52bfb 100644 --- a/src/services/Elements.php +++ b/src/services/Elements.php @@ -1190,7 +1190,10 @@ public function eagerLoadElements(string $elementType, array $elements, $with) } // Normalize the paths and find any custom path criterias - $with = ArrayHelper::toArray($with); + if (is_string($with)) { + $with = StringHelper::split($with); + } + $paths = []; $pathCriterias = []; diff --git a/src/validators/UniqueValidator.php b/src/validators/UniqueValidator.php index 643ae02dad3..69e5f76f5fb 100644 --- a/src/validators/UniqueValidator.php +++ b/src/validators/UniqueValidator.php @@ -7,7 +7,7 @@ namespace craft\validators; -use craft\helpers\ArrayHelper; +use craft\helpers\StringHelper; use yii\base\Model; use yii\db\ActiveRecord; use yii\validators\UniqueValidator as YiiUniqueValidator; @@ -51,7 +51,11 @@ public function validateAttribute($model, $attribute) // Set the primary key values on the record, if they're set $pks = $record::primaryKey(); - $pkMap = $this->pk !== null ? ArrayHelper::toArray($this->pk) : $pks; + if ($this->pk !== null) { + $pkMap = is_string($this->pk) ? StringHelper::split($this->pk) : $this->pk; + } else { + $pkMap = $pks; + } $isNewRecord = true; foreach ($pkMap as $k => $v) { diff --git a/tests/unit/helpers/ArrayHelperTest.php b/tests/unit/helpers/ArrayHelperTest.php index b5d8e2df141..63c8be6128c 100644 --- a/tests/unit/helpers/ArrayHelperTest.php +++ b/tests/unit/helpers/ArrayHelperTest.php @@ -21,7 +21,6 @@ protected function _after() public function testToArray() { $this->assertEquals([], ArrayHelper::toArray(null)); - $this->assertEquals([1, 1, 1, 2, 2, 2, 3, 3, 3], ArrayHelper::toArray('1,1,1,2,2,2,3,3,3')); $this->assertEquals([1, 2, 3], ArrayHelper::toArray([1, 2, 3])); } From 65dd9b5b49af30f0816f78e4b8233d923dbd2ac2 Mon Sep 17 00:00:00 2001 From: Sebastian Weyrauch Date: Wed, 23 Aug 2017 07:17:06 +0200 Subject: [PATCH 48/79] added integer casts for all maxLevel comparisons --- src/controllers/CategoriesController.php | 2 +- src/controllers/EntriesController.php | 2 +- src/services/Categories.php | 2 +- src/services/Sections.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/controllers/CategoriesController.php b/src/controllers/CategoriesController.php index 63b8b14099a..d7b30ef3482 100644 --- a/src/controllers/CategoriesController.php +++ b/src/controllers/CategoriesController.php @@ -270,7 +270,7 @@ public function actionEditCategory(string $groupHandle, int $categoryId = null, // Parent Category selector variables // --------------------------------------------------------------------- - if ($variables['group']->maxLevels != 1) { + if ((int)$variables['group']->maxLevels !== 1) { $variables['elementType'] = Category::class; // Define the parent options criteria diff --git a/src/controllers/EntriesController.php b/src/controllers/EntriesController.php index 2d2d5c7ba2f..7f941dfc084 100644 --- a/src/controllers/EntriesController.php +++ b/src/controllers/EntriesController.php @@ -129,7 +129,7 @@ public function actionEditEntry(string $sectionHandle, int $entryId = null, int if ( $section->type === Section::TYPE_STRUCTURE && - $section->maxLevels !== 1 + (int)$section->maxLevels !== 1 ) { $variables['elementType'] = Entry::class; diff --git a/src/services/Categories.php b/src/services/Categories.php index 725b4aca0a4..0fc3c55e677 100644 --- a/src/services/Categories.php +++ b/src/services/Categories.php @@ -314,7 +314,7 @@ public function saveGroup(CategoryGroup $group, bool $runValidation = true): boo } // If they've set maxLevels to 0 (don't ask why), then pretend like there are none. - if ($group->maxLevels === 0) { + if ((int)$group->maxLevels === 0) { $group->maxLevels = null; } diff --git a/src/services/Sections.php b/src/services/Sections.php index 3da2cee86d0..01553e555c5 100644 --- a/src/services/Sections.php +++ b/src/services/Sections.php @@ -410,7 +410,7 @@ public function saveSection(Section $section, bool $runValidation = true): bool } // If they've set maxLevels to 0 (don't ask why), then pretend like there are none. - if ($section->maxLevels === 0 || $section->maxLevels === '0') { + if ((int)$section->maxLevels === 0) { $section->maxLevels = null; } From 70fb8b5899a789b8c5e27eb7976f861ce660a650 Mon Sep 17 00:00:00 2001 From: Brad Bell Date: Thu, 24 Aug 2017 09:55:54 -0700 Subject: [PATCH 49/79] Fixed a bug where user photos and site logos/icons were not taking into account the sanitizeSvgUploads config setting. --- CHANGELOG.md | 1 + src/controllers/RebrandController.php | 16 ++++++++++------ src/controllers/UsersController.php | 17 +++++++++-------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 130d6371950..9461b8effd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Craft CMS Changelog ### Fixed - Fixed a bug where you could get a PHP error uploading some JPG files on PHP 7.1. +- Fixed a bug where user photos and site logos/icons were not taking into account the [sanitizeSvgUploads](https://craftcms.com/docs/config-settings#sanitizeSvgUploads) config setting. ### Security - Fixed an XSS vulnerability. diff --git a/src/controllers/RebrandController.php b/src/controllers/RebrandController.php index 43105a118ea..1f44f5d3d0a 100644 --- a/src/controllers/RebrandController.php +++ b/src/controllers/RebrandController.php @@ -60,24 +60,28 @@ public function actionUploadSiteImage() } $folderPath = craft()->path->getTempUploadsPath(); + $fullPath = $folderPath.$fileName; + IOHelper::ensureFolderExists($folderPath); IOHelper::clearFolder($folderPath, true); - move_uploaded_file($file->getTempName(), $folderPath.$fileName); + move_uploaded_file($file->getTempName(), $fullPath); // Test if we will be able to perform image actions on this image - if (!craft()->images->checkMemoryForImage($folderPath.$fileName)) + if (!craft()->images->checkMemoryForImage($fullPath)) { - IOHelper::deleteFile($folderPath.$fileName); + IOHelper::deleteFile($fullPath); $this->returnErrorJson(Craft::t('The uploaded image is too large')); } + craft()->images->cleanImage($fullPath); + craft()->images-> - loadImage($folderPath.$fileName)-> + loadImage($fullPath)-> scaleToFit(500, 500, false)-> - saveAs($folderPath.$fileName); + saveAs($fullPath); - list ($width, $height) = ImageHelper::getImageSize($folderPath.$fileName); + list ($width, $height) = ImageHelper::getImageSize($fullPath); // If the file is in the format badscript.php.gif perhaps. if ($width && $height) diff --git a/src/controllers/UsersController.php b/src/controllers/UsersController.php index 69a49d54dff..f2810f23bd2 100644 --- a/src/controllers/UsersController.php +++ b/src/controllers/UsersController.php @@ -1157,28 +1157,29 @@ public function actionUploadUserPhoto() $user = craft()->users->getUserById($userId); $userName = AssetsHelper::cleanAssetName($user->username, false, true); - $folderPath = craft()->path->getTempUploadsPath().'userphotos/'.$userName.'/'; + $fullPath = $folderPath.$fileName; IOHelper::clearFolder($folderPath); - IOHelper::ensureFolderExists($folderPath); - move_uploaded_file($file->getTempName(), $folderPath.$fileName); + move_uploaded_file($file->getTempName(), $fullPath); // Test if we will be able to perform image actions on this image - if (!craft()->images->checkMemoryForImage($folderPath.$fileName)) + if (!craft()->images->checkMemoryForImage($fullPath)) { - IOHelper::deleteFile($folderPath.$fileName); + IOHelper::deleteFile($fullPath); $this->returnErrorJson(Craft::t('The uploaded image is too large')); } + craft()->images->cleanImage($fullPath); + craft()->images-> - loadImage($folderPath.$fileName)-> + loadImage($fullPath)-> scaleToFit(500, 500, false)-> - saveAs($folderPath.$fileName); + saveAs($fullPath); - list ($width, $height) = ImageHelper::getImageSize($folderPath.$fileName); + list ($width, $height) = ImageHelper::getImageSize($fullPath); // If the file is in the format badscript.php.gif perhaps. if ($width && $height) From d5a052d923e61875889fd805341deaa5a2a2c2c0 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Thu, 24 Aug 2017 10:35:22 -0700 Subject: [PATCH 50/79] Changelog for #1940 --- CHANGELOG-v3.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 4e446390324..0f84cb0da29 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -11,6 +11,7 @@ Craft CMS 3.0 Working Changelog ### Fixed - Fixed a SQL error that could occur when using the `relatedTo` element query param. ([#1939](https://github.com/craftcms/cms/issues/1939)) +- Fixed a bug where the “Parent” field was showing up on Edit Entry pages in Structure sections that were limited to a single level. ([#1940](https://github.com/craftcms/cms/pull/1940)) ## 3.0.0-beta.26 - 2017-08-22 From 5b28d552d303829cacce6f08e8fd6928bcbfd37a Mon Sep 17 00:00:00 2001 From: Brad Bell Date: Wed, 30 Aug 2017 14:31:49 -0700 Subject: [PATCH 51/79] =?UTF-8?q?Fixed=20a=20bug=20where=20the=20=E2=80=9C?= =?UTF-8?q?Delete=20Stale=20Template=20Cache=E2=80=9D=20task=20would=20fai?= =?UTF-8?q?l=20when=20saving=20an=20existing=20Single=20section.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG-v3.md | 1 + src/services/TemplateCaches.php | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 0f84cb0da29..54f10c935c4 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -12,6 +12,7 @@ Craft CMS 3.0 Working Changelog ### Fixed - Fixed a SQL error that could occur when using the `relatedTo` element query param. ([#1939](https://github.com/craftcms/cms/issues/1939)) - Fixed a bug where the “Parent” field was showing up on Edit Entry pages in Structure sections that were limited to a single level. ([#1940](https://github.com/craftcms/cms/pull/1940)) +- Fixed a bug where the “Delete Stale Template Cache” task would fail when saving an existing Single section. ## 3.0.0-beta.26 - 2017-08-22 diff --git a/src/services/TemplateCaches.php b/src/services/TemplateCaches.php index fe5126d432a..362ce76b77b 100644 --- a/src/services/TemplateCaches.php +++ b/src/services/TemplateCaches.php @@ -518,10 +518,14 @@ public function deleteCachesByElementId($elementId, bool $deleteQueryCaches = tr */ public function handleResponse() { - Craft::$app->getQueue()->push(new DeleteStaleTemplateCaches([ - 'elementId' => array_keys($this->_deleteCachesIndex), - ])); - $this->_deleteCachesIndex = null; + // It's possible this is already null + if ($this->_deleteCachesIndex !== null) { + Craft::$app->getQueue()->push(new DeleteStaleTemplateCaches([ + 'elementId' => array_keys($this->_deleteCachesIndex), + ])); + + $this->_deleteCachesIndex = null; + } } /** From a3ac39ae4c49f28a129102478949cd027b2c3395 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Thu, 31 Aug 2017 11:12:27 -0400 Subject: [PATCH 52/79] forceTranslations for plugin translation sources --- CHANGELOG-v3.md | 3 +++ src/base/Plugin.php | 1 + 2 files changed, 4 insertions(+) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 54f10c935c4..6d331797db3 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -6,6 +6,9 @@ Craft CMS 3.0 Working Changelog ### Added - Added `craft\helpers\StringHelper::split()`. +### Changed +- Plugin translation sources are now configured with `forceTranslations` enabled. + ### Deprecated - Splitting a string on commas via `craft\helpers\ArrayHelper::toArray()` is now deprecated. Use `craft\helpers\StringHelper::split()` instead. diff --git a/src/base/Plugin.php b/src/base/Plugin.php index 57ef1c0521f..d6dcb3c3123 100644 --- a/src/base/Plugin.php +++ b/src/base/Plugin.php @@ -70,6 +70,7 @@ public function __construct($id, $parent = null, array $config = []) 'class' => PhpMessageSource::class, 'sourceLanguage' => $this->sourceLanguage, 'basePath' => $this->getBasePath().DIRECTORY_SEPARATOR.'translations', + 'forceTranslation' => true, 'allowOverrides' => true, ]; } From 76702cb69efb71b8a92c7863fc29d9c620ac7333 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Thu, 31 Aug 2017 19:42:40 -0400 Subject: [PATCH 53/79] Fixed PHP error --- src/helpers/MigrationHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/MigrationHelper.php b/src/helpers/MigrationHelper.php index d268ba15342..e749c8f71e5 100644 --- a/src/helpers/MigrationHelper.php +++ b/src/helpers/MigrationHelper.php @@ -89,7 +89,7 @@ public static function doesIndexExist(string $tableName, $columns, bool $unique { $db = Craft::$app->getDb(); $schema = $db->getSchema(); - if (!is_string($columns)) { + if (is_string($columns)) { $columns = StringHelper::split($columns); } From 80139637e939f5553ef5dfa93f41d3d3746aafb1 Mon Sep 17 00:00:00 2001 From: andris-sevcenko Date: Fri, 1 Sep 2017 11:44:09 +0300 Subject: [PATCH 54/79] Fixed a bug where it was not possible to use `:notempty:` with PostgreSQL. --- CHANGELOG-v3.md | 1 + src/helpers/Db.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 6d331797db3..e48c4e3a508 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -16,6 +16,7 @@ Craft CMS 3.0 Working Changelog - Fixed a SQL error that could occur when using the `relatedTo` element query param. ([#1939](https://github.com/craftcms/cms/issues/1939)) - Fixed a bug where the “Parent” field was showing up on Edit Entry pages in Structure sections that were limited to a single level. ([#1940](https://github.com/craftcms/cms/pull/1940)) - Fixed a bug where the “Delete Stale Template Cache” task would fail when saving an existing Single section. +- Fixed a bug where it was not possible to use `:notempty:` with PostgreSQL. ## 3.0.0-beta.26 - 2017-08-22 diff --git a/src/helpers/Db.php b/src/helpers/Db.php index babb39eab01..84d8c6b47b9 100644 --- a/src/helpers/Db.php +++ b/src/helpers/Db.php @@ -506,7 +506,7 @@ public static function parseParam(string $column, $value) $condition[] = [ 'not', [ - [$column => null], + $column => null, ] ]; } From 8bbb2f8906fd2a78a0d6153d519fbacc27451db4 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Sun, 3 Sep 2017 12:32:53 -0700 Subject: [PATCH 55/79] Fixed #1948 --- CHANGELOG-v3.md | 1 + src/config/app/main.php | 2 +- src/db/mysql/QueryBuilder.php | 11 +++++++ ...m170903_192801_longblob_for_queue_jobs.php | 32 +++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/migrations/m170903_192801_longblob_for_queue_jobs.php diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 6d331797db3..7df475ea1d1 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -16,6 +16,7 @@ Craft CMS 3.0 Working Changelog - Fixed a SQL error that could occur when using the `relatedTo` element query param. ([#1939](https://github.com/craftcms/cms/issues/1939)) - Fixed a bug where the “Parent” field was showing up on Edit Entry pages in Structure sections that were limited to a single level. ([#1940](https://github.com/craftcms/cms/pull/1940)) - Fixed a bug where the “Delete Stale Template Cache” task would fail when saving an existing Single section. +- Fixed a bug where the `job` column in the `queue` table wasn’t large enough to store some job data. ([#1948](https://github.com/craftcms/cms/issues/1948)) ## 3.0.0-beta.26 - 2017-08-22 diff --git a/src/config/app/main.php b/src/config/app/main.php index 0946ff81d52..3995c61dd23 100644 --- a/src/config/app/main.php +++ b/src/config/app/main.php @@ -4,7 +4,7 @@ 'id' => 'CraftCMS', 'name' => 'Craft CMS', 'version' => '3.0.0-beta.26', - 'schemaVersion' => '3.0.58', + 'schemaVersion' => '3.0.59', 'minVersionRequired' => '2.6.2788', 'basePath' => dirname(__DIR__, 2), // Defines the @app alias 'runtimePath' => '@storage/runtime', // Defines the @runtime alias diff --git a/src/db/mysql/QueryBuilder.php b/src/db/mysql/QueryBuilder.php index c0e5f285caa..f28056bafd7 100644 --- a/src/db/mysql/QueryBuilder.php +++ b/src/db/mysql/QueryBuilder.php @@ -22,6 +22,17 @@ */ class QueryBuilder extends \yii\db\mysql\QueryBuilder { + /** + * @inheritdoc + */ + public function init() + { + parent::init(); + + // Use LONGBLOB for "binary" columns rather than BLOB + $this->typeMap[Schema::TYPE_BINARY] = 'longblob'; + } + /** * @inheritdoc * diff --git a/src/migrations/m170903_192801_longblob_for_queue_jobs.php b/src/migrations/m170903_192801_longblob_for_queue_jobs.php new file mode 100644 index 00000000000..c5f4712ac0f --- /dev/null +++ b/src/migrations/m170903_192801_longblob_for_queue_jobs.php @@ -0,0 +1,32 @@ +db->getIsMysql()) { + // "binary" resolves to LONGBLOB now rather than BLOB + $this->alterColumn('{{%queue}}', 'job', $this->binary()->notNull()); + } + } + + /** + * @inheritdoc + */ + public function safeDown() + { + echo "m170903_192801_longblob_for_queue_jobs cannot be reverted.\n"; + return false; + } +} From a24fc426bf4cf5f32f177347cc5bff52e9211914 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Tue, 5 Sep 2017 11:31:24 -0700 Subject: [PATCH 56/79] Fixed ##1950 --- CHANGELOG-v3.md | 1 + src/web/assets/cp/dist/js/Craft.js | 4 ++-- src/web/assets/cp/dist/js/Craft.min.js | 2 +- src/web/assets/cp/dist/js/Craft.min.js.map | 2 +- src/web/assets/cp/src/js/CP.js | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 3bff5ede400..c02f2140ca5 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -18,6 +18,7 @@ Craft CMS 3.0 Working Changelog - Fixed a bug where the “Delete Stale Template Cache” task would fail when saving an existing Single section. - Fixed a bug where it was not possible to use `:notempty:` with PostgreSQL. - Fixed a bug where the `job` column in the `queue` table wasn’t large enough to store some job data. ([#1948](https://github.com/craftcms/cms/issues/1948)) +- Fixed a JS error that occurred on CP templates that extended `_layouts/cp` but overrode the `body` block to remove the sidebar, if there were any running/waiting jobs in the queue. ([#1950](https://github.com/craftcms/cms/issues/1950)) ## 3.0.0-beta.26 - 2017-08-22 diff --git a/src/web/assets/cp/dist/js/Craft.js b/src/web/assets/cp/dist/js/Craft.js index e9eb3c1323a..9b3194c229a 100644 --- a/src/web/assets/cp/dist/js/Craft.js +++ b/src/web/assets/cp/dist/js/Craft.js @@ -1,4 +1,4 @@ -/*! - 2017-08-14 */ +/*! - 2017-09-05 */ (function($){ /** global: Craft */ @@ -8895,7 +8895,7 @@ Craft.CP = Garnish.Base.extend( }, updateJobIcon: function(animate) { - if (!this.enableQueue) { + if (!this.enableQueue || !this.$nav.length) { return; } diff --git a/src/web/assets/cp/dist/js/Craft.min.js b/src/web/assets/cp/dist/js/Craft.min.js index 678c4237172..0c436d5b843 100644 --- a/src/web/assets/cp/dist/js/Craft.min.js +++ b/src/web/assets/cp/dist/js/Craft.min.js @@ -1,2 +1,2 @@ -!function(t){t.extend(Craft,{navHeight:48,asciiCharMap:{a:["à","á","ả","ã","ạ","ă","ắ","ằ","ẳ","ẵ","ặ","â","ấ","ầ","ẩ","ẫ","ậ","ä","ā","ą","å","α","ά","ἀ","ἁ","ἂ","ἃ","ἄ","ἅ","ἆ","ἇ","ᾀ","ᾁ","ᾂ","ᾃ","ᾄ","ᾅ","ᾆ","ᾇ","ὰ","ά","ᾰ","ᾱ","ᾲ","ᾳ","ᾴ","ᾶ","ᾷ","а","أ"],b:["б","β","Ъ","Ь","ب"],c:["ç","ć","č","ĉ","ċ"],d:["ď","ð","đ","ƌ","ȡ","ɖ","ɗ","ᵭ","ᶁ","ᶑ","д","δ","د","ض"],e:["é","è","ẻ","ẽ","ẹ","ê","ế","ề","ể","ễ","ệ","ë","ē","ę","ě","ĕ","ė","ε","έ","ἐ","ἑ","ἒ","ἓ","ἔ","ἕ","ὲ","έ","е","ё","э","є","ə"],f:["ф","φ","ف"],g:["ĝ","ğ","ġ","ģ","г","ґ","γ","ج"],h:["ĥ","ħ","η","ή","ح","ه"],i:["í","ì","ỉ","ĩ","ị","î","ï","ī","ĭ","į","ı","ι","ί","ϊ","ΐ","ἰ","ἱ","ἲ","ἳ","ἴ","ἵ","ἶ","ἷ","ὶ","ί","ῐ","ῑ","ῒ","ΐ","ῖ","ῗ","і","ї","и"],j:["ĵ","ј","Ј"],k:["ķ","ĸ","к","κ","Ķ","ق","ك"],l:["ł","ľ","ĺ","ļ","ŀ","л","λ","ل"],m:["м","μ","م"],n:["ñ","ń","ň","ņ","ʼn","ŋ","ν","н","ن"],o:["ó","ò","ỏ","õ","ọ","ô","ố","ồ","ổ","ỗ","ộ","ơ","ớ","ờ","ở","ỡ","ợ","ø","ō","ő","ŏ","ο","ὀ","ὁ","ὂ","ὃ","ὄ","ὅ","ὸ","ό","ö","о","و","θ"],p:["п","π"],r:["ŕ","ř","ŗ","р","ρ","ر"],s:["ś","š","ş","с","σ","ș","ς","س","ص"],t:["ť","ţ","т","τ","ț","ت","ط"],u:["ú","ù","ủ","ũ","ụ","ư","ứ","ừ","ử","ữ","ự","ü","û","ū","ů","ű","ŭ","ų","µ","у"],v:["в"],w:["ŵ","ω","ώ"],x:["χ"],y:["ý","ỳ","ỷ","ỹ","ỵ","ÿ","ŷ","й","ы","υ","ϋ","ύ","ΰ","ي"],z:["ź","ž","ż","з","ζ","ز"],aa:["ع"],ae:["æ"],ch:["ч"],dj:["ђ","đ"],dz:["џ"],gh:["غ"],kh:["х","خ"],lj:["љ"],nj:["њ"],oe:["œ"],ps:["ψ"],sh:["ш"],shch:["щ"],ss:["ß"],th:["þ","ث","ذ","ظ"],ts:["ц"],ya:["я"],yu:["ю"],zh:["ж"],"(c)":["©"],A:["Á","À","Ả","Ã","Ạ","Ă","Ắ","Ằ","Ẳ","Ẵ","Ặ","Â","Ấ","Ầ","Ẩ","Ẫ","Ậ","Ä","Å","Ā","Ą","Α","Ά","Ἀ","Ἁ","Ἂ","Ἃ","Ἄ","Ἅ","Ἆ","Ἇ","ᾈ","ᾉ","ᾊ","ᾋ","ᾌ","ᾍ","ᾎ","ᾏ","Ᾰ","Ᾱ","Ὰ","Ά","ᾼ","А"],B:["Б","Β"],C:["Ć","Č","Ĉ","Ċ"],D:["Ď","Ð","Đ","Ɖ","Ɗ","Ƌ","ᴅ","ᴆ","Д","Δ"],E:["É","È","Ẻ","Ẽ","Ẹ","Ê","Ế","Ề","Ể","Ễ","Ệ","Ë","Ē","Ę","Ě","Ĕ","Ė","Ε","Έ","Ἐ","Ἑ","Ἒ","Ἓ","Ἔ","Ἕ","Έ","Ὲ","Е","Ё","Э","Є","Ə"],F:["Ф","Φ"],G:["Ğ","Ġ","Ģ","Г","Ґ","Γ"],H:["Η","Ή"],I:["Í","Ì","Ỉ","Ĩ","Ị","Î","Ï","Ī","Ĭ","Į","İ","Ι","Ί","Ϊ","Ἰ","Ἱ","Ἳ","Ἴ","Ἵ","Ἶ","Ἷ","Ῐ","Ῑ","Ὶ","Ί","И","І","Ї"],K:["К","Κ"],L:["Ĺ","Ł","Л","Λ","Ļ"],M:["М","Μ"],N:["Ń","Ñ","Ň","Ņ","Ŋ","Н","Ν"],O:["Ó","Ò","Ỏ","Õ","Ọ","Ô","Ố","Ồ","Ổ","Ỗ","Ộ","Ơ","Ớ","Ờ","Ở","Ỡ","Ợ","Ö","Ø","Ō","Ő","Ŏ","Ο","Ό","Ὀ","Ὁ","Ὂ","Ὃ","Ὄ","Ὅ","Ὸ","Ό","О","Θ","Ө"],P:["П","Π"],R:["Ř","Ŕ","Р","Ρ"],S:["Ş","Ŝ","Ș","Š","Ś","С","Σ"],T:["Ť","Ţ","Ŧ","Ț","Т","Τ"],U:["Ú","Ù","Ủ","Ũ","Ụ","Ư","Ứ","Ừ","Ử","Ữ","Ự","Û","Ü","Ū","Ů","Ű","Ŭ","Ų","У"],V:["В"],W:["Ω","Ώ"],X:["Χ"],Y:["Ý","Ỳ","Ỷ","Ỹ","Ỵ","Ÿ","Ῠ","Ῡ","Ὺ","Ύ","Ы","Й","Υ","Ϋ"],Z:["Ź","Ž","Ż","З","Ζ"],AE:["Æ"],CH:["Ч"],DJ:["Ђ"],DZ:["Џ"],KH:["Х"],LJ:["Љ"],NJ:["Њ"],PS:["Ψ"],SH:["Ш"],SHCH:["Щ"],SS:["ẞ"],TH:["Þ"],TS:["Ц"],YA:["Я"],YU:["Ю"],ZH:["Ж"]," ":[" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "]},t:function(t,e,s){if(void 0!==Craft.translations[t]&&void 0!==Craft.translations[t][e]&&(e=Craft.translations[t][e]),s)for(var i in s)s.hasOwnProperty(i)&&(e=e.replace("{"+i+"}",s[i]));return e},formatDate:function(e){return"object"!=typeof e&&(e=new Date(e)),t.datepicker.formatDate(Craft.datepickerOptions.dateFormat,e)},escapeHtml:function(e){return t("
").text(e).html()},getText:function(e){return t("
").html(e).text()},encodeUriComponent:function(t){t=encodeURIComponent(t);var e={"!":"%21","*":"%2A","'":"%27","(":"%28",")":"%29"};for(var s in e){var i=new RegExp("\\"+s,"g");t=t.replace(i,e[s])}return t},selectFullValue:function(e){var s=t(e),i=s.val();if(void 0!==s[0].setSelectionRange){var n=2*i.length;s[0].setSelectionRange(0,n)}else s.val(i)},formatInputId:function(t){return this.rtrim(t.replace(/[\[\]\\]+/g,"-"),"-")},getUrl:function(e,s,i){if("string"!=typeof e&&(e=""),-1!==e.search("://")||"//"===e.substr(0,2))return e;e=Craft.trim(e,"/");var n="";if(t.isPlainObject(s)){var a=[];for(var r in s)if(s.hasOwnProperty(r)){var o=s[r];"#"===r?n=o:null!==o&&""!==o&&a.push(r+"="+o)}s=a}s=Garnish.isArray(s)?s.join("&"):Craft.trim(s,"&?");var l=e.indexOf("?");-1!==l&&(s=e.substr(l+1)+(s?"&"+s:""),e=e.substr(0,l));var h;if(i){if(h=i,e){var d=h.match(/[&\?]p=[^&]+/);d&&(h=h.replace(d[0],d[0]+"/"+e),e="")}}else h=Craft.baseUrl;if(-1!==(l=h.indexOf("?"))&&(s=h.substr(l+1)+(s?"&"+s:""),h=h.substr(0,l)),!Craft.omitScriptNameInUrls&&e)if(Craft.usePathInfo)-1===h.search(Craft.scriptName)&&(h=Craft.rtrim(h,"/")+"/"+Craft.scriptName);else{if(s&&"p="===s.substr(0,2)){var c,u=s.indexOf("&");-1!==u?(c=s.substring(2,u),s=s.substr(u+1)):(c=s.substr(2),s=null),e=(c=Craft.rtrim(c))+(e?"/"+e:"")}s="p="+e+(s?"&"+s:""),e=null}return e&&(h=Craft.rtrim(h,"/")+"/"+e),s&&(h+="?"+s),n&&(h+="#"+n),h},getCpUrl:function(t,e){return this.getUrl(t,e,Craft.baseCpUrl)},getSiteUrl:function(t,e){return this.getUrl(t,e,Craft.baseSiteUrl)},getResourceUrl:function(t,e){return Craft.getUrl(t,e,Craft.resourceUrl)},getActionUrl:function(t,e){return Craft.getUrl(t,e,Craft.actionUrl)},redirectTo:function(t){document.location.href=this.getUrl(t)},getCsrfInput:function(){return Craft.csrfTokenName?'':""},postActionRequest:function(e,s,i,n){"function"==typeof s&&(n=i,i=s,s={});var a={};Craft.csrfTokenValue&&Craft.csrfTokenName&&(a["X-CSRF-Token"]=Craft.csrfTokenValue);var r=t.ajax(t.extend({url:Craft.getActionUrl(e),type:"POST",dataType:"json",headers:a,data:s,success:i,error:function(t,e){i&&i(null,e,t)},complete:function(t,e){"success"!==e&&(void 0!==Craft.cp?Craft.cp.displayError():alert(Craft.t("app","An unknown error occurred.")))}},n));return n&&"function"==typeof n.send&&n.send(r),r},_waitingOnAjax:!1,_ajaxQueue:[],queueActionRequest:function(t,e,s,i){"function"==typeof e&&(i=s,s=e,e=void 0),Craft._ajaxQueue.push([t,e,s,i]),Craft._waitingOnAjax||Craft._postNextActionRequestInQueue()},_postNextActionRequestInQueue:function(){Craft._waitingOnAjax=!0;var t=Craft._ajaxQueue.shift();Craft.postActionRequest(t[0],t[1],function(e,s,i){t[2]&&"function"==typeof t[2]&&t[2](e,s,i),Craft._ajaxQueue.length?Craft._postNextActionRequestInQueue():Craft._waitingOnAjax=!1},t[3])},stringToArray:function(e){if("string"!=typeof e)return e;for(var s=e.split(","),i=0;i=32&&i<128)e+=n;else for(var a in Craft.asciiCharMap)if(Craft.asciiCharMap.hasOwnProperty(a))for(var r=0;r]*href="(?:'+i.join("|")+')".*?><\/script>',"g");e=e.replace(r,"")}t("head").append(e)}},appendFootHtml:function(e){if(e){var s=t("script[src]");if(s.length){for(var i=[],n=0;n]*src="(?:'+i.join("|")+')".*?><\/script>',"g");e=e.replace(r,"")}Garnish.$bod.append(e)}},initUiElements:function(e){t(".grid",e).grid(),t(".pane",e).pane(),t(".info",e).infoicon(),t(".checkbox-select",e).checkboxselect(),t(".fieldtoggle",e).fieldtoggle(),t(".lightswitch",e).lightswitch(),t(".nicetext",e).nicetext(),t(".pill",e).pill(),t(".formsubmit",e).formsubmit(),t(".menubtn",e).menubtn()},_elementIndexClasses:{},_elementSelectorModalClasses:{},_elementEditorClasses:{},registerElementIndexClass:function(t,e){if(void 0!==this._elementIndexClasses[t])throw"An element index class has already been registered for the element type “"+t+"”.";this._elementIndexClasses[t]=e},registerElementSelectorModalClass:function(t,e){if(void 0!==this._elementSelectorModalClasses[t])throw"An element selector modal class has already been registered for the element type “"+t+"”.";this._elementSelectorModalClasses[t]=e},registerElementEditorClass:function(t,e){if(void 0!==this._elementEditorClasses[t])throw"An element editor class has already been registered for the element type “"+t+"”.";this._elementEditorClasses[t]=e},createElementIndex:function(t,e,s){return new(void 0!==this._elementIndexClasses[t]?this._elementIndexClasses[t]:Craft.BaseElementIndex)(t,e,s)},createElementSelectorModal:function(t,e){return new(void 0!==this._elementSelectorModalClasses[t]?this._elementSelectorModalClasses[t]:Craft.BaseElementSelectorModal)(t,e)},createElementEditor:function(t,e,s){return new(void 0!==this._elementEditorClasses[t]?this._elementEditorClasses[t]:Craft.BaseElementEditor)(e,s)},getLocalStorage:function(t,e){return t="Craft-"+Craft.systemUid+"."+t,"undefined"!=typeof localStorage&&void 0!==localStorage[t]?JSON.parse(localStorage[t]):e},setLocalStorage:function(t,e){if("undefined"!=typeof localStorage){t="Craft-"+Craft.systemUid+"."+t;try{localStorage[t]=JSON.stringify(e)}catch(t){}}},getElementInfo:function(e){var s=t(e);return s.hasClass("element")||(s=s.find(".element:first")),{id:s.data("id"),siteId:s.data("site-id"),label:s.data("label"),status:s.data("status"),url:s.data("url"),hasThumb:s.hasClass("hasthumb"),$element:s}},setElementSize:function(e,s){var i=t(e);if("small"!==s&&"large"!==s&&(s="small"),!i.hasClass(s)){var n="small"===s?"large":"small";if(i.addClass(s).removeClass(n),i.hasClass("hasthumb")){var a=i.find("> .elementthumb > img"),r=t("",{sizes:("small"===s?"30":"100")+"px",srcset:a.attr("srcset")||a.attr("data-pfsrcset")});a.replaceWith(r),picturefill({elements:[r[0]]})}}}}),t.extend(t.fn,{animateLeft:function(t,e,s,i){return"ltr"===Craft.orientation?this.velocity({left:t},e,s,i):this.velocity({right:t},e,s,i)},animateRight:function(t,e,s,i){return"ltr"===Craft.orientation?this.velocity({right:t},e,s,i):this.velocity({left:t},e,s,i)},disable:function(){return this.each(function(){var e=t(this);e.addClass("disabled"),e.data("activatable")&&e.removeAttr("tabindex")})},enable:function(){return this.each(function(){var e=t(this);e.removeClass("disabled"),e.data("activatable")&&e.attr("tabindex","0")})},grid:function(){return this.each(function(){var e=t(this),s={};e.data("item-selector")&&(s.itemSelector=e.data("item-selector")),e.data("cols")&&(s.cols=parseInt(e.data("cols"))),e.data("max-cols")&&(s.maxCols=parseInt(e.data("max-cols"))),e.data("min-col-width")&&(s.minColWidth=parseInt(e.data("min-col-width"))),e.data("mode")&&(s.mode=e.data("mode")),e.data("fill-mode")&&(s.fillMode=e.data("fill-mode")),e.data("col-class")&&(s.colClass=e.data("col-class")),e.data("snap-to-grid")&&(s.snapToGrid=!!e.data("snap-to-grid")),new Craft.Grid(this,s)})},infoicon:function(){return this.each(function(){new Craft.InfoIcon(this)})},pane:function(){return this.each(function(){t.data(this,"pane")||new Craft.Pane(this)})},checkboxselect:function(){return this.each(function(){t.data(this,"checkboxselect")||new Garnish.CheckboxSelect(this)})},fieldtoggle:function(){return this.each(function(){t.data(this,"fieldtoggle")||new Craft.FieldToggle(this)})},lightswitch:function(e,s,i){return"settings"===e?("string"==typeof s?(e={})[s]=i:e=s,this.each(function(){var s=t.data(this,"lightswitch");s&&s.setSettings(e)})):(t.isPlainObject(e)||(e={}),this.each(function(){var s=t.extend({},e);Garnish.hasAttr(this,"data-value")&&(s.value=t(this).attr("data-value")),t.data(this,"lightswitch")||new Craft.LightSwitch(this,s)}))},nicetext:function(){return this.each(function(){t.data(this,"nicetext")||new Garnish.NiceText(this)})},pill:function(){return this.each(function(){t.data(this,"pill")||new Garnish.Pill(this)})},formsubmit:function(){this.on("click",function(e){var s=t(e.currentTarget);if(!s.attr("data-confirm")||confirm(s.attr("data-confirm"))){var i;i=s.data("menu")?s.data("menu").$anchor.closest("form"):s.closest("form"),s.attr("data-action")&&t('').val(s.attr("data-action")).appendTo(i),s.attr("data-redirect")&&t('').val(s.attr("data-redirect")).appendTo(i),s.attr("data-param")&&t('').attr({name:s.attr("data-param"),value:s.attr("data-value")}).appendTo(i),i.submit()}})},menubtn:function(){return this.each(function(){var e=t(this);if(!e.data("menubtn")&&e.next().hasClass("menu")){var s={};e.data("menu-anchor")&&(s.menuAnchor=e.data("menu-anchor")),new Garnish.MenuBtn(e,s)}})}}),Garnish.$doc.ready(function(){Craft.initUiElements()}),Craft.BaseElementEditor=Garnish.Base.extend({$element:null,elementId:null,siteId:null,$form:null,$fieldsContainer:null,$cancelBtn:null,$saveBtn:null,$spinner:null,$languageSelect:null,$siteSpinner:null,hud:null,init:function(e,s){void 0===s&&t.isPlainObject(e)&&(s=e,e=null),this.$element=t(e),this.setSettings(s,Craft.BaseElementEditor.defaults),this.loadHud()},setElementAttribute:function(t,e){this.settings.attributes||(this.settings.attributes={}),null===e?delete this.settings.attributes[t]:this.settings.attributes[t]=e},getBaseData:function(){var e=t.extend({},this.settings.params);return this.settings.siteId?e.siteId=this.settings.siteId:this.$element&&this.$element.data("site-id")&&(e.siteId=this.$element.data("site-id")),this.settings.elementId?e.elementId=this.settings.elementId:this.$element&&this.$element.data("id")&&(e.elementId=this.$element.data("id")),this.settings.elementType&&(e.elementType=this.settings.elementType),this.settings.attributes&&(e.attributes=this.settings.attributes),e},loadHud:function(){this.onBeginLoading();var e=this.getBaseData();e.includeSites=this.settings.showSiteSwitcher,Craft.postActionRequest("elements/get-editor-html",e,t.proxy(this,"showHud"))},showHud:function(e,s){if(this.onEndLoading(),"success"===s){var i=t();if(e.sites){var n=t('
'),a=t('
').appendTo(n);this.$siteSelect=t("').appendTo(h),this.$spinner=t('