From bfcbe29c7ccf9112d9991e76849d59aeda88e5cf Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Wed, 18 Apr 2018 14:30:36 -0700 Subject: [PATCH] Better way to keep track of whether a user has a dashboard fixes #2769 --- CHANGELOG-v3.md | 6 +++ src/config/app.php | 2 +- src/elements/User.php | 5 +++ src/elements/db/UserQuery.php | 1 + src/migrations/Install.php | 1 + .../m180418_205713_widget_cleanup.php | 45 +++++++++++++++++++ src/records/User.php | 1 + src/records/Widget.php | 1 - src/services/Dashboard.php | 31 +++++++------ 9 files changed, 77 insertions(+), 16 deletions(-) create mode 100644 src/migrations/m180418_205713_widget_cleanup.php diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index dc43fb682a3..532a4ef8e92 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -2,9 +2,15 @@ ## Unreleased +### Added +- Added `craft\elements\User::hasDashboard`. + ### Changed - Sections and category groups now ignore posted Template settings for sites that don’t have URI Formats. +### Fixed +- Fixed a bug where users would regain all default Dashboard widgets if all widgets were removed. ([#2769](https://github.com/craftcms/cms/issues/2769)) + ## 3.0.3.1 - 2018-04-18 ### Fixed diff --git a/src/config/app.php b/src/config/app.php index 566195194a9..a08e4ec9475 100644 --- a/src/config/app.php +++ b/src/config/app.php @@ -4,7 +4,7 @@ 'id' => 'CraftCMS', 'name' => 'Craft CMS', 'version' => '3.0.3.1', - 'schemaVersion' => '3.0.90', + 'schemaVersion' => '3.0.91', 'minVersionRequired' => '2.6.2788', 'basePath' => dirname(__DIR__), // Defines the @app alias 'runtimePath' => '@storage/runtime', // Defines the @runtime alias diff --git a/src/elements/User.php b/src/elements/User.php index 5a3752e8855..8dfecb43c3a 100644 --- a/src/elements/User.php +++ b/src/elements/User.php @@ -456,6 +456,11 @@ public static function authData(string $authKey) */ public $lockoutDate; + /** + * @var bool Whether the user has a dashboard + */ + public $hasDashboard = false; + /** * @var bool Password reset required */ diff --git a/src/elements/db/UserQuery.php b/src/elements/db/UserQuery.php index e0087ca164a..afd5a920270 100644 --- a/src/elements/db/UserQuery.php +++ b/src/elements/db/UserQuery.php @@ -253,6 +253,7 @@ protected function beforePrepare(): bool 'users.suspended', 'users.lastLoginDate', 'users.lockoutDate', + 'users.hasDashboard', ]); // TODO: remove after next breakpoint diff --git a/src/migrations/Install.php b/src/migrations/Install.php index d4d947a6b56..6c39ac01e62 100644 --- a/src/migrations/Install.php +++ b/src/migrations/Install.php @@ -681,6 +681,7 @@ public function createTables() 'invalidLoginCount' => $this->tinyInteger()->unsigned(), 'lastInvalidLoginDate' => $this->dateTime(), 'lockoutDate' => $this->dateTime(), + 'hasDashboard' => $this->boolean()->notNull()->defaultValue(false), 'verificationCode' => $this->string(), 'verificationCodeIssuedDate' => $this->dateTime(), 'unverifiedEmail' => $this->string(), diff --git a/src/migrations/m180418_205713_widget_cleanup.php b/src/migrations/m180418_205713_widget_cleanup.php new file mode 100644 index 00000000000..3534503e65d --- /dev/null +++ b/src/migrations/m180418_205713_widget_cleanup.php @@ -0,0 +1,45 @@ +addColumn('{{%users}}', 'hasDashboard', $this->boolean()->notNull()->defaultValue(false)->after('lockoutDate')); + + $usersWithWidgets = (new Query()) + ->select(['userId']) + ->distinct() + ->from(['{{%widgets}}']) + ->column(); + + $this->update('{{%users}}', [ + 'hasDashboard' => true, + ], [ + 'id' => $usersWithWidgets, + ], [], false); + + $this->delete('{{%widgets}}', ['enabled' => false]); + $this->dropColumn('{{%widgets}}', 'enabled'); + } + + /** + * @inheritdoc + */ + public function safeDown() + { + echo "m180418_205713_widget_cleanup cannot be reverted.\n"; + return false; + } +} diff --git a/src/records/User.php b/src/records/User.php index da7367e464e..ffd53d7c04e 100644 --- a/src/records/User.php +++ b/src/records/User.php @@ -30,6 +30,7 @@ * @property int $invalidLoginCount Invalid login count * @property \DateTime $lastInvalidLoginDate Last invalid login date * @property \DateTime $lockoutDate Lockout date + * @property bool $hasDashboard Whether the user has a dashboard * @property string $verificationCode Verification code * @property \DateTime $verificationCodeIssuedDate Verification code issued date * @property string $unverifiedEmail Unverified email diff --git a/src/records/Widget.php b/src/records/Widget.php index 34bf6a67630..322d4a5d794 100644 --- a/src/records/Widget.php +++ b/src/records/Widget.php @@ -19,7 +19,6 @@ * @property int $sortOrder Sort order * @property int $colspan Colspan * @property array $settings Settings - * @property bool $enabled Enabled * @property User $user User * @author Pixel & Tonic, Inc. * @since 3.0 diff --git a/src/services/Dashboard.php b/src/services/Dashboard.php index 9647b84bb08..491820cf045 100644 --- a/src/services/Dashboard.php +++ b/src/services/Dashboard.php @@ -127,7 +127,7 @@ public function getAllWidgets(): array $widgets = $this->_getUserWidgets(); // If there are no widgets, this is the first time they've hit the dashboard. - if (empty($widgets)) { + if ($widgets === false) { // Add the defaults and try again $this->_addDefaultUserWidgets(); $widgets = $this->_getUserWidgets(); @@ -148,7 +148,6 @@ public function doesUserHaveWidget(string $type): bool ->where([ 'userId' => Craft::$app->getUser()->getIdentity()->id, 'type' => $type, - 'enabled' => true ]) ->exists(); } @@ -206,9 +205,6 @@ public function saveWidget(WidgetInterface $widget, bool $runValidation = true): $widgetRecord->settings = $widget->getSettings(); if ($isNewWidget) { - // Enabled by default. - $widgetRecord->enabled = true; - // Set the sortOrder $maxSortOrder = (new Query()) ->from(['{{%widgets}}']) @@ -284,11 +280,8 @@ public function deleteWidget(WidgetInterface $widget): bool $transaction = Craft::$app->getDb()->beginTransaction(); try { $widgetRecord = $this->_getUserWidgetRecordById($widget->id); - $widgetRecord->enabled = false; - $widgetRecord->save(); - + $widgetRecord->delete(); $widget->afterDelete(); - $transaction->commit(); } catch (\Throwable $e) { $transaction->rollBack(); @@ -379,6 +372,12 @@ private function _addDefaultUserWidgets() 'url' => 'https://craftcms.com/news.rss', 'title' => 'Craft News' ])); + + // Update the user record + $user->hasDashboard = true; + Craft::$app->getDb()->createCommand() + ->update('{{%users}}', ['hasDashboard' => true], ['id' => $user->id]) + ->execute(); } /** @@ -422,19 +421,23 @@ private function _noWidgetExists(int $widgetId) /** * Returns the widget records for the current user. * - * @return WidgetInterface[] + * @return WidgetInterface[]|false * @throws Exception if no user is logged-in */ - private function _getUserWidgets(): array + private function _getUserWidgets() { - $userId = Craft::$app->getUser()->getId(); + $user = Craft::$app->getUser()->getIdentity(); - if (!$userId) { + if (!$user) { throw new Exception('No logged-in user'); } + if (!$user->hasDashboard) { + return false; + } + $results = $this->_createWidgetsQuery() - ->where(['userId' => $userId, 'enabled' => true]) + ->where(['userId' => $user->id]) ->orderBy(['sortOrder' => SORT_ASC]) ->all();