Content locking (anti-concurrent editing) - コンテンツロック(同時編集防止)
編集開始時に自動的にコンテンツをロックし、保存またはページ移動時に解除する悲観的ロックを実装することで、複数のユーザーが同時にコンテンツエンティティを編集することを防止します。
content_lock
インストール
composer require 'drupal/content_lock:8.x-2.4'
composer require 'drupal/content_lock:8.x-2.2'
概要
Content Lock モジュールは、動的コンテンツを持つ繁忙なサイトでの編集競合を防ぐために悲観的ロック戦略を実装します。ユーザーがエンティティの編集を開始すると、それは排他的にロックされ、ロックが解除されるまで他のユーザーは変更を行えません。
ロックはフォーム送信時またはユーザーがページを離れた時に自動的に解除されます。このモジュールはエンティティレベル、翻訳レベル(Conflict モジュール使用時)、およびフォーム操作レベルでのロックをサポートしています。古いロックは cron を通じて設定可能なタイムアウト期間後に自動的に解除できます。
「Break content lock」権限を持つ管理者は、他のユーザーが保持しているロックを強制的に解除できます。このモジュールは、/admin/content/locked-content でアクセス可能な構築済みビューを含む、ロックされたコンテンツの表示と管理のための包括的な Views 統合を提供します。
Features
- ユーザーが編集を開始するとコンテンツを排他的にロックし、同時編集の競合を防止する悲観的ロック
- フォーム送信時、ユーザーログアウト時、またはユーザーセッション終了時の自動ロック解除
- cron を通じた古いロックの自動解除のための設定可能なタイムアウト(デフォルト30分)
- 迅速なセットアップのための「All」オプションを備えたエンティティタイプごとおよびバンドルごとのロック設定
- Conflict モジュールインストール時の翻訳レベルロックサポート。異なる翻訳の同時編集が可能
- 許可リストおよび拒否リストモードによるフォーム操作レベルロック。どのフォーム操作でロックをトリガーするかを細かく制御
- 管理者が他のユーザーが保持しているロックを強制的に解除できるロック解除機能
- /admin/content/locked-content に構築済みの Views ページ。現在ロックされているすべてのノードを一括ロック解除アクションと共に表示
- ロックデータのためのフィールド、フィルター、ソート、リレーションシップを備えた包括的な Views 統合
- ロックされたコンテンツに対してエンティティ一覧に「Break lock」オプションを追加するエンティティ操作統合
- 拡張性のための ContentLockLockedEvent と ContentLockReleaseEvent によるイベント駆動アーキテクチャ
- ゴミ箱に入れられたエンティティの不要なロックを防止する Trash モジュールとの統合
- コンテンツがロックされた時またはロック中にアクセスされた時に情報メッセージを表示する詳細モードオプション
Use Cases
編集ワークフローでの編集競合の防止
複数の編集者がいるニュースサイトで、「記事」ノードタイプのコンテンツロックを有効にします。編集者 A が記事を編集用に開くと、ロックされます。編集者 B が同じ記事を編集しようとすると、編集者 A によってロックされていることを示すメッセージが表示されます。これにより、編集者 A が先に保存したために編集者 B の変更が失われるという困った状況を防ぎます。
同時翻訳作業の管理
複数の翻訳者がいる多言語サイトでは、Conflict モジュールをインストールし、ノードに対して「エンティティ翻訳レベルでのみロック」を有効にします。これにより、ドイツ語翻訳者がドイツ語版で作業している間、フランス語翻訳者が同じコンテンツのフランス語版を同時に編集でき、競合が発生しません。
選択的フォーム操作ロック
フォーム操作ロックを拒否リストモードで設定し、「delete」操作を除外します。これにより、別のユーザーが編集中でもコンテンツを削除できます(古いコンテンツを素早く削除する必要があるコンテンツ管理者に便利)。一方、編集操作は同時アクセスから保護されます。
ロックの監視と管理
/admin/content/locked-content の組み込み「ロックされたコンテンツ」ビューを使用して、現在ロックされているすべてのノードを監視します。「break content lock」権限を持つコンテンツ管理者は、一括操作を使用して複数の古いロックを一度に解除するか、エンティティ操作の「ロックを解除」リンクを使用できます。
タイムアウトによる自動ロッククリーンアップ
設定でロックタイムアウトを 30 分に設定します。ユーザーが編集フォームを閉じ忘れた場合(保存やキャンセルせずにページを離れた場合)、ロックは 30 分後に cron によって自動的に解除され、コンテンツが無期限にロックされたままにならないようにします。
Tips
- 忘れられたロックを自動的に解除するために常にタイムアウト値を設定してください。推奨デフォルトは 30 分(1800 秒)です
- エンティティタイプのロックを最初に有効にする際は「All」(*)バンドルオプションを使用し、必要に応じて特定のバンドルに絞り込んでください
- ロック競合を解決する必要があるサイト管理者とコンテンツ管理者に「break content lock」権限を付与してください
- ロックメッセージをカスタマイズするには、String Overrides モジュール(https://www.drupal.org/project/stringoverrides)の使用を検討してください
- hook_content_lock_entity_lockable() を実装して、カスタムビジネスロジックに基づいて特定のエンティティをロックから除外してください
- ContentLockLockedEvent と ContentLockReleaseEvent をサブスクライブして、通知システムやロギングと統合してください
- content_lock サービスをカスタムコードにインジェクトして、プログラム的にロックのチェック、取得、解除を行えます
Technical Details
Admin Pages 3
/admin/config/content/content_lock
コンテンツロックの動作設定、保護するエンティティタイプとバンドルの選択、およびタイムアウト設定を行うメイン設定ページ。
/admin/content/locked-content
現在ロックされているすべてのノードをロック所有者、タイムスタンプ、言語情報と共に表示する Views ページ。ロック解除の一括操作と個別のエンティティ操作を提供します。
/admin/lock/break/{entity_type}/{entity}/{langcode}/{form_op}
特定のエンティティのコンテンツロックを解除するための確認フォーム。有効な各エンティティタイプに対して動的に生成されます。
権限 2
Hooks 1
hook_content_lock_entity_lockable
エンティティがロック可能かどうかを決定します。isLockable() から呼び出され、モジュールがどのエンティティをロックできるかをプログラム的に制御できます。このフックがエンティティに対して FALSE を返す場合、既存のロックは無視されます。
Troubleshooting 5
Content Lock 設定で適切なタイムアウト値(例: 30 分)を設定してください。この期間後、ロックは cron によって自動的に解除されます。サイトで cron が定期的に実行されていることを確認してください。
「エンティティ翻訳レベルでのみロック」オプションには Conflict モジュールのインストールが必要です。Conflict モジュール(https://www.drupal.org/project/conflict)をインストールして有効にすると、この機能が有効になります。
Content Lock はロックデータを含むビューのキャッシュを自動的に無効にします。それでも問題が発生する場合は、ビューのキャッシュ設定が「なし」に設定されていることを確認し、すべてのキャッシュをクリアしてください。
設計上、「break content lock」権限を持たないユーザーは、他のユーザーによってロックされたコンテンツを削除できません。「break content lock」権限を付与するか、削除操作をロックから除外するようにフォーム操作ロックを設定してください。
フォームが正しく送信されていることを確認してください(単にページを離れるのではなく)。ロック解除はフォーム送信ハンドラーで行われます。フォーム送信を妨げる可能性のある JavaScript エラーがないか確認してください。
Security Notes 3
- 「break content lock」権限は他のユーザーが設定したロックをオーバーライドできるため、慎重に付与する必要があります
- Content Lock は解除権限を持たないユーザーによるロックされたコンテンツの削除を防止し、誤ったデータ損失を防ぎます
- モジュールはデータベースレベルのロック(content_lock テーブル)と Drupal のロックサービスを使用して、ロック取得時の競合状態を防止します