From 74a849a7e4eb7db7729cf03890ca2aec461783c0 Mon Sep 17 00:00:00 2001 From: Tom Schulze Date: Mon, 27 Jun 2022 15:32:49 +0200 Subject: [PATCH] Craft 4 compatibility --- CHANGELOG.md | 7 +++ composer.json | 11 +---- src/Snitch.php | 13 +++--- src/assetbundles/snitch/SnitchAsset.php | 1 - src/assetbundles/snitch/dist/css/snitch.css | 20 ++++++++- src/assetbundles/snitch/dist/js/snitch.js | 4 +- src/config.php | 2 +- src/controllers/CollisionController.php | 26 +++++------ .../m190408_195351_support_multiple_types.php | 5 +-- src/models/Settings.php | 22 ++++------ src/models/SnitchModel.php | 26 +++++------ src/records/SnitchRecord.php | 9 +++- src/services/Collision.php | 44 +++++++++++-------- src/translations/en/snitch.php | 2 +- 14 files changed, 105 insertions(+), 87 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 336606a..40669d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## Unreleased +### Added +- Craft CMS 4 compatibility + +### Changed +- Requires Craft CMS >= 4.0 + ## 3.0.4.1 - 2020.12.24 ### Fixed - Snitch should again work without Two Factor Authentication diff --git a/composer.json b/composer.json index 30786b2..261d371 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "marionnewlevant/snitch", "description": "Report when two people might be editing the same element (eg entry, category, or global) or field", "type": "craft-plugin", - "version": "3.0.4.1", + "version": "4.0.0", "keywords": [ "craft", "cms", @@ -22,7 +22,7 @@ } ], "require": { - "craftcms/cms": "^3.5.0" + "craftcms/cms": "^4.0.0" }, "autoload": { "psr-4": { @@ -32,13 +32,6 @@ "extra": { "name": "Snitch", "handle": "snitch", - "hasCpSettings": false, - "hasCpSection": false, - "documentationUrl": "https://github.com/marionnewlevant/craft-snitch/blob/v2/README.md", - "changelogUrl": "https://raw.githubusercontent.com/marionnewlevant/craft-snitch/v2/CHANGELOG.md", - "components": { - "collision": "marionnewlevant\\snitch\\services\\Collision" - }, "class": "marionnewlevant\\snitch\\Snitch" } } diff --git a/src/Snitch.php b/src/Snitch.php index 1a7b61f..bad9ca2 100644 --- a/src/Snitch.php +++ b/src/Snitch.php @@ -1,6 +1,6 @@ getRequest(); - $response = Craft::$app->getResponse(); if (!$this->isInstalled || $request->getIsConsoleRequest()) { return; @@ -133,9 +132,9 @@ public function init() /** * Creates and returns the model used to store the plugin’s settings. * - * @return \craft\base\Model|null + * @return Settings */ - protected function createSettingsModel() + protected function createSettingsModel(): Settings { return new Settings(); } diff --git a/src/assetbundles/snitch/SnitchAsset.php b/src/assetbundles/snitch/SnitchAsset.php index 106367e..f7607e9 100644 --- a/src/assetbundles/snitch/SnitchAsset.php +++ b/src/assetbundles/snitch/SnitchAsset.php @@ -10,7 +10,6 @@ namespace marionnewlevant\snitch\assetbundles\snitch; -use Craft; use craft\web\AssetBundle; use craft\web\assets\cp\CpAsset; diff --git a/src/assetbundles/snitch/dist/css/snitch.css b/src/assetbundles/snitch/dist/css/snitch.css index 954832e..61ce48d 100644 --- a/src/assetbundles/snitch/dist/css/snitch.css +++ b/src/assetbundles/snitch/dist/css/snitch.css @@ -37,8 +37,11 @@ body.rtl .snitch { background-color: #bf5035; background-image: linear-gradient(#bf5035, #b34b3b); color: white; - /* we are going to close them by animating max-height */ max-height: 3em; +} + +.snitch--main>div { + /* we are going to close them by animating max-height */ transition: max-height .5s; overflow: hidden; } @@ -47,6 +50,11 @@ body.rtl .snitch { max-height: 0; } +.snitch--modal>div.snitch--hidden { + padding: 0; + margin: 0; +} + /* the x for closing */ .snitch span { cursor: pointer; @@ -60,3 +68,13 @@ body.rtl .snitch { color: white; text-decoration: underline; } + +/* the style for the new slideouts */ +.snitch--modal>div { + margin: calc(var(--xl)*-1) var(--neg-padding) var(--xl); + padding: var(--s) var(--xl); +} + +.snitch--modal span { + padding: 0 0 0 .5em; +} \ No newline at end of file diff --git a/src/assetbundles/snitch/dist/js/snitch.js b/src/assetbundles/snitch/dist/js/snitch.js index cee8131..b6a0bb9 100644 --- a/src/assetbundles/snitch/dist/js/snitch.js +++ b/src/assetbundles/snitch/dist/js/snitch.js @@ -84,7 +84,7 @@ $('body').on('click', '.snitch span', function() { var lookForConflicts = function(next) { var myThis = this; var $warnContainer = this.isModal ? this.$form.children('.snitch--modal') : $('.snitch--main'); - if (this.isModal && !this.$form.closest('.hud.has-footer[style*="display: block;"]').length) { + if (this.isModal && !this.$form.closest('.slideout-container:not(.hidden)').length) { // our modal is gone. next(); } else { @@ -118,7 +118,7 @@ var lookForEditFormsByType = function(snitchType, selector) { var $thisIdInput = $(this); var snitchId = $thisIdInput.val(); var $form = $thisIdInput.closest('form'); - var isModal = $form.hasClass('body'); + var isModal = $form.hasClass('slideout'); var snitchData = $form.data('snitch'); if (!snitchData) { diff --git a/src/config.php b/src/config.php index bea00f1..7405ee5 100644 --- a/src/config.php +++ b/src/config.php @@ -1,6 +1,6 @@ requireAcceptsJson(); // require login (gracefully) $userSession = Craft::$app->getUser(); if ($userSession->getIsGuest()) { - $json = $this->asJson([ + return $this->asJson([ 'success' => false, 'error' => 'not logged in', ]); - return $json; } $snitchId = (int)(Craft::$app->getRequest()->getBodyParam('snitchId')); @@ -87,29 +88,28 @@ public function actionAjaxEnter() $collidingUsers = Snitch::$plugin->collision->collidingUsers($collisionModels); $collisionMessages = Snitch::$plugin->collision->collisionMessages($collidingUsers, $messageTemplate); // and return - $json = $this->asJson([ + return $this->asJson([ 'success' => true, 'collisions' => $collisionMessages, ]); - return $json; } /** * Handle a request going to our plugin's actionGetConfig URL, * e.g.: actions/snitch/collision/get-config * - * @return mixed + * @return \yii\web\Response + * @throws \yii\web\BadRequestHttpException */ - public function actionGetConfig() + public function actionGetConfig(): Response { $this->requireAcceptsJson(); $settings = Snitch::$plugin->getSettings(); - $json = $this->asJson([ + return $this->asJson([ 'messageTemplate' => $settings['messageTemplate'], 'serverPollInterval' => $settings['serverPollInterval'], 'elementInputIdSelector' => $settings['elementInputIdSelector'], 'fieldInputIdSelector' => $settings['fieldInputIdSelector'], ]); - return $json; } } diff --git a/src/migrations/m190408_195351_support_multiple_types.php b/src/migrations/m190408_195351_support_multiple_types.php index c8a4b1c..5c86ddf 100644 --- a/src/migrations/m190408_195351_support_multiple_types.php +++ b/src/migrations/m190408_195351_support_multiple_types.php @@ -2,7 +2,6 @@ namespace marionnewlevant\snitch\migrations; -use Craft; use craft\db\Migration; /** @@ -31,8 +30,8 @@ public function safeUp() // foreign keys: our userId must be a user id $this->addForeignKey( - $this->db->getForeignKeyName('{{%snitch_collisions}}', 'userId'), - '{{%snitch_collisions}}', 'userId', '{{%users}}', 'id', 'CASCADE', null); + $this->db->getForeignKeyName(), + '{{%snitch_collisions}}', 'userId', '{{%users}}', 'id', 'CASCADE'); } /** diff --git a/src/models/Settings.php b/src/models/Settings.php index a5420aa..581c67b 100644 --- a/src/models/Settings.php +++ b/src/models/Settings.php @@ -1,6 +1,6 @@ {{user.username}}.'; const ELEMENT_INPUTIDSELECTOR = 'form input[type="hidden"][name="sourceId"]' // entry forms - .', form input[type="hidden"][name="elementId"]' // modals entry forms + .', form input[type="hidden"][name*="elementId"]' // slideout entry forms .', form input[type="hidden"][name="setId"]' // global set .', form input[type="hidden"][name="categoryId"]' // category .', form input[type="hidden"][name="userId"]' // user @@ -51,22 +47,22 @@ class Settings extends Model * * @var int */ - public $serverPollInterval = self::SERVERPOLLINTERVAL; + public int $serverPollInterval = self::SERVERPOLLINTERVAL; /** * @var string */ - public $messageTemplate = self::MESSAGE; + public string $messageTemplate = self::MESSAGE; /** * @var string */ - public $elementInputIdSelector = self::ELEMENT_INPUTIDSELECTOR; + public string $elementInputIdSelector = self::ELEMENT_INPUTIDSELECTOR; /** * @var string */ - public $fieldInputIdSelector = self::FIELD_INPUTIDSELECTOR; + public string $fieldInputIdSelector = self::FIELD_INPUTIDSELECTOR; // Public Methods @@ -82,7 +78,7 @@ class Settings extends Model * * @return array */ - public function rules() + public function rules(): array { $rules = parent::rules(); $myRules = [ @@ -93,8 +89,6 @@ public function rules() ['elementInputIdSelector', 'string'], ['fieldInputIdSelector', 'string'], ]; - $rules = array_merge($rules, $myRules); - - return $rules; + return array_merge($rules, $myRules); } } diff --git a/src/models/SnitchModel.php b/src/models/SnitchModel.php index 41d42c6..da0d618 100644 --- a/src/models/SnitchModel.php +++ b/src/models/SnitchModel.php @@ -1,6 +1,6 @@ true], diff --git a/src/records/SnitchRecord.php b/src/records/SnitchRecord.php index 9a7aeab..3915bcb 100644 --- a/src/records/SnitchRecord.php +++ b/src/records/SnitchRecord.php @@ -11,6 +11,7 @@ namespace marionnewlevant\snitch\records; use craft\db\ActiveRecord; +use DateTime; /** * SnitchRecord Record @@ -27,6 +28,12 @@ * @author Marion Newlevant * @package Snitch * @since 1.0.0 + * + * @property int $id + * @property int $snitchId + * @property string|null $snitchType + * @property int $userId + * @property DateTime $whenEntered */ class SnitchRecord extends ActiveRecord { @@ -45,7 +52,7 @@ class SnitchRecord extends ActiveRecord * * @return string the table name */ - public static function tableName() + public static function tableName(): string { return '{{%snitch_collisions}}'; } diff --git a/src/services/Collision.php b/src/services/Collision.php index 5eb7c05..df4b385 100644 --- a/src/services/Collision.php +++ b/src/services/Collision.php @@ -1,6 +1,6 @@ collision->remove() * - * @return mixed + * @param int $snitchId + * @param string $snitchType + * @param null $userId + * + * @throws \yii\db\Exception + * @throws \yii\db\StaleObjectException */ - public function remove(int $snitchId, string $snitchType, $userId = null) + public function remove(int $snitchId, string $snitchType, $userId = null): void { $userId = $this->_userId($userId); $transaction = Craft::$app->getDb()->beginTransaction(); @@ -55,19 +63,17 @@ public function remove(int $snitchId, string $snitchType, $userId = null) 'userId' => $userId ]); - if ($record) { - $record->delete(); - } + $record?->delete(); $transaction->commit(); - } catch (\Exception $e) { + } catch (Exception $e) { $transaction->rollBack(); throw $e; } } - public function register(int $snitchId, string $snitchType, $userId = null, \DateTime $now = null) + public function register(int $snitchId, string $snitchType, $userId = null, DateTime $now = null) { $now = $this->_now($now); $userId = $this->_userId($userId); @@ -90,13 +96,13 @@ public function register(int $snitchId, string $snitchType, $userId = null, \Dat $record->save(); $transaction->commit(); - } catch (\Exception $e) { + } catch (Exception $e) { $transaction->rollBack(); throw $e; } } - public function getCollisions(int $snitchId, string $snitchType, $userId = null) + public function getCollisions(int $snitchId, string $snitchType, $userId = null): array { $userId = $this->_userId($userId); $result = []; @@ -108,18 +114,18 @@ public function getCollisions(int $snitchId, string $snitchType, $userId = null) { if ($row->userId !== $userId) { - $result[] = new SnitchModel($row); + $result[] = new SnitchModel($row->toArray()); } } return $result; } - public function expire(\DateTime $now = null) + public function expire(DateTime $now = null) { $now = $this->_now($now); $timeOut = $this->_serverPollInterval() * 10; $old = clone $now; - $old->sub(new \DateInterval('PT'.$timeOut.'S')); + $old->sub(new DateInterval('PT'.$timeOut.'S')); $transaction = Craft::$app->getDb()->beginTransaction(); try { $allExpired = SnitchRecord::find() @@ -131,13 +137,13 @@ public function expire(\DateTime $now = null) } $transaction->commit(); - } catch (\Exception $e) { + } catch (Exception $e) { $transaction->rollBack(); throw $e; } } - public function collidingUsers(array $snitchModels) + public function collidingUsers(array $snitchModels): array { $result = []; $userIds = []; @@ -158,7 +164,7 @@ public function collidingUsers(array $snitchModels) return $result; } - public function collisionMessages(array $collidingUsers, string $messageTemplate) + public function collisionMessages(array $collidingUsers, string $messageTemplate): array { $result = []; @@ -180,7 +186,7 @@ public function collisionMessages(array $collidingUsers, string $messageTemplate } // ============== default values ============= - private function _userId($userId) + private function _userId($userId): int { if (!$userId) { $currentUser = Craft::$app->getUser()->getIdentity(); @@ -191,9 +197,9 @@ private function _userId($userId) return (int)($userId); } - private function _now(\DateTime $now = null) + private function _now(DateTime $now = null): DateTime { - return ($now ? $now : new \DateTime()); + return ($now ?: new DateTime()); } private function _serverPollInterval() diff --git a/src/translations/en/snitch.php b/src/translations/en/snitch.php index d9a232c..d470bd9 100644 --- a/src/translations/en/snitch.php +++ b/src/translations/en/snitch.php @@ -1,6 +1,6 @@