リストから選択して一括で「既読」にするには

Events happening in the community are now at Drupal community events on www.drupal.org.
wataru.kato's picture

Views Bulk Operationsモジュールでいろいろ試しましたが、
残念ながら「選択したコンテンツを『既読(新規・更新ではない状態)』にする」という命令が見つかりませんでした。

同じことを実現された方はいらっしゃいませんでしょうか。

Drupal7です。

Comments

blauerberg's picture

ざっと探した感じではmoduleで機能は提供されていないみたいです。

仕掛け的にはhistory テーブルにnode id, user id, 最終アクセス時のタイムスタンプが保存されており、
その値と比較して状態を判断しています。

実現方法としては、[1] が参考になります。
モジュールとして用意するのが難しければ、Views Bulk Operationsで任意のPHPスクリプトを実行するように設定し、historyテーブルに現在の時刻を保存してあげても実現できます。

VBO+PHPスクリプトの方向性

wataru.kato's picture

blauerberg様

アドバイス有難う御座います。
[1] の情報のうち、

/**
* Implementation of the actual function mark_as_read_noderead_action()
*/
            
function mark_as_read_noderead_action(&$node) {
    global $user;
            
    if ($user->uid) {
    $sql = 'delete from {history} ' .
           "where nid='" . $node->nid . "' ".   
           "and uid='" . $user->uid . "'";

        db_query($sql);
        
    $sql = 'insert into {history} (nid,uid,timestamp) ' .
           "values ('" . $node->nid . "', '" . $user->uid . "', unix_timestamp()) ";

        db_query($sql);
    }    
}
?>

この部分をコンバートすれば良いということですかね。
updateではなくてdeleteとinsertで更新する処理になってますね。

historyテーブルも uid,nid,timestamp の3項目しかないのも確認できました。

あとはVBOから呼び出すPHPスクリプトの書き出し方が判ればできる気がしてきました。
PHPはほぼ素人なので、これから調べながらやってみます。

散発でごめんなさい。 Drupal

blauerberg's picture

散発でごめんなさい。
Drupal 7であればnode_tag_new[1]のコードがほぼそのまま使えます。
実際にページにアクセスした時にhistoryテーブルを更新している処理がこの関数になります。

たびたびありがとうございます。

wataru.kato's picture

なるほど、今私もソースを読んで、node_tag_new を nodeモジュール内のコードに見つけました。
この関数をVBOで呼び出すようにすれば良いんでしょうか。
試してみます。

テスト実行は成功

wataru.kato's picture

成功しました。

Views Bulk Operations で 「任意のPHPスクリプトを実行」 を実行可能にして、
そのスクリプトの記述に

node_tag_new($entity);

を記述して実行したところ、選択したノードのタイムスタンプ更新に成功して既読となりました。

あとはこれを、ボタン一発にできるとうれしいんですが・・・

VBOの選択画面に「スクリプトAの実行」ボタンかメニュー作れる(PHPスクリプトを定義済みのボタンを作る)とか、いい手がないものでしょうか。

https://drupal.org/node/20520

wataru.kato's picture

https://drupal.org/node/2052067
Views Bulk Operations development guide (Drupal 7)

これを見つけて読み始めました。
モジュールとして追加するのがこの場合は正しいのだろうなと思ってます。

結構進んだつもりなのですが

wataru.kato's picture

あと一歩まで来たと思うのですが、詰まっています。

(参考URL)
https://drupal.org/node/2052067
http://www.zyxware.com/articles/3633/drupal-7-how-to-add-your-own-custom...
http://drupal.stackexchange.com/questions/16865/new-action-for-views-bul...

(方針)
・Views+VBOでノード一覧を作り、チェックを入れたノードに対して「既読にする」を実行する
・「Mark as read」という自作モジュールを作り、アクション登録>VBOの処理に紐付け

(実装手順)
1)事前に「レポート>最近のログメッセージ」を確認し、「孤立したアクション」があれば削除しておく
 #モジュール開発中に開発中アクションが良くゴミとして残ったので毎回この方法で削除していた
2)以下構成でモジュールファイルを作成


「ファイル構成」

mark_as_read フォルダ
    mark_as_read.info
    mark_as_read.module

「mark_as_read.info」

name = Mark As Read
description = Mark As Read.
core = 7.x
dependencies[] = 'views_bulk_operations'

「mark_as_read.module」

<?php
function mark_as_read_action_info() {
  return array(
   
'mark_as_read_mark_action' => array(
     
'type' => 'node',
     
'label' => t('Mark as read'),
     
'behavior' => array('changes_property'),
     
'configurable' => FALSE,
     
'vbo_configurable' => TRUE,
     
'triggers' => array('any'),
    ),
  );
}

function
mark_as_read_mark_action(&$entity, $context = array()) {
 
node_tag_new($entity);
}
?>

3)sites/all/modules 以下にモジュールを配置
4)モジュール画面から「Mark As Read」を有効化
5)環境設定>システム>アクションから、アクションのタイプ=node、ラベル=Mark as read が出ていることを確認
6)VBO用に作ったビューを開く(Display=Page)
7)フィールドに「一括処理:コンテンツ」を追加
8)Configure field: 一括処理: コンテンツが開く
9)「BULK OPERATIONS SETTINGS」を以下に設定
 ・各アクションごとに別々のボタン=ON
 ・Enable "Select all items on all pages"=ON
10)「SELECTED BULK OPARATIONS」を以下に設定
 ・Mark as read=ON
 ・任意のPHPスクリプトを実行=ON
11)ビューを保存

⇒この結果としてVBOのビューにアクセスすると、「任意のPHPスクリプトを実行」はボタンとして出るが、「Mark as read」はボタンに出てこない ×これが解決しない

ちなみに、

12)どれか1件の記事にチェックを入れて、任意のPHPスクリプトを実行
13)PHPスクリプトの入力画面が開くので、「node_tag_new($entity);」を入力して実行
14)確認画面として「You selected the following item:」 先ほどの1件が表示されるので「確認」
15)Performing 任意のPHPスクリプトを実行中・・・ 画面が出る
16)ビューに戻り、「Performed 任意のPHPスクリプトを実行 on 1 項目」 のメッセージが出る

という動きになり、PHPプログラムとして node_tag_new は問題なく動きそうです。

以上のような状況なんですが、何か怪しい箇所がありませんでしょうか。

もしくはこの状態をトレースして追えるようなデバッグ方法がありませんでしょうか。

P.S.
ちなみに上記のVBO処理の実行方法で、
・確認のステップをスキップ=ON
・Enqueue the operation instead of executing it directly=ON
にすると、確認画面も経由せず、Perform・・・画面も出なくなり、私が最初にイメージしていた「ノードを選択してボタンを押すと既読にできる」という動きにできそうなのは判りました。

解決しました

wataru.kato's picture

解決できました。

変更点1)
mark as readアクションに対してユーザー権限を与えていませんでした。
ユーザー>権限 の画面にて、「Actions permissions (VBO)>Execute Mark as read=ON」にしました。これで権限のあるユーザーであればボタンが出るようになりました。

変更点2)
「mark_as_read.module」 の間違いを修正しました。

<?php
function mark_as_read_action_info() {
  return array(
   
'mark_as_read_mark_action' => array(
     
'type' => 'entity',                // ×node だった
     
'label' => t('Mark as read'),
     
// ×不要 'behavior' => array('changes_property'), これがあると元記事の日付が更新されてしまった;;;
     
'configurable' => FALSE,
     
'vbo_configurable' => FALSE,       // ×TRUE、configurable、vbo_configurableともにTRUEだとオプション条件を入力するフォームの定義を求められてしまう(必要なアクションなら使えばいいが)
     
'triggers' => array('any'),
    ),
  );
}

function
mark_as_read_mark_action(&$entity, $context = array()) {
 
node_tag_new($entity);
}
?>

これで無事に「既読にする」ボタンが使えるようになりました。さらに、

変更点3)
・確認のステップをスキップ=ON 〇
・Enqueue the operation instead of executing it directly=ON ×OFF ※ONだと既読にするための処理が即時実行されず、直後だと既読になっていない記事が一覧に出てしまってユーザーが誤解する動きになったため。しかもちゃんとバックグラウンド実行で適用されるのか確認できなかった。なので紛らわしいので即時実行にした。残念ながらここでプログレスバーが出てしまうが仕方ない。

という適用もしました。

この件を深く検討したので、だいぶVBOでできそうな処理の流れが判りました。
デバッグが大変なことも判りました;;;
モジュールを修正するたびにモジュールを無効>孤立アクション削除>モジュール有効、を繰り返して確認しました。そこまでしなくても良かったんだろうか・・・

wataru.kato's picture

この権限の件は、今回より以前に私が専用のモジュールを導入していたから起きた内容でした。

改めてまとめると、私は今回の実装の為に以下の2モジュールを使っていました。

Views Bulk Operations
Actions permissions (VBO)

blauerberg's picture

いいですね。
同じような事をしようとする場合に非常に参考になりそうです。

wataru.kato's picture

いま現在原因が不明なのですが・・・

VBOの列を追加したViewを表示するたびに、出てくる記事の更新日付が勝手に(たとえば数分前に)一括で更新されてしまう現象が出ています;;;
困った。

なのでまだテストされる方はご注意を。

wataru.kato's picture

この「Mark as read」モジュール開発の最初のころに、

・Enqueue the operation instead of executing it directly

の条件を有効にして実行していました。
その時に「ある特定の10件の記事を既読にする」という処理をEnqueueした回があったのですが、
これはcronに登録され、3時間指定のcronの実行時にまるで幽霊のように毎回呼び出されているようです。
消えていません。
毎回エラーっぽいログも残しています。
そして該当の10件の記事が、cronと同じ時刻に毎回記事更新がなされています。

これはこうなると、cron登録内容を初期化したい感じです。
#匿名ユーザーによる「cronが重複して実行されました。」というログもいっぱい出るんです。
#今回以外の原因でもゴミがある状態なのかも

cronの棚卸というのは何からやればいいんでしょうか。
Apache再起動ではダメでした。
ということはcron登録内容はDBに入ってるのかと推測しています。
テーブル名でいうと
batch
queue
あたりが怪しいです。
レコードがたまっています。
でもテーブル内のレコードを全部削除とか、ちょっと怖くてまだできません。

ちなみにWindowsサーバーで動かしています。

多分解決?しました

wataru.kato's picture

cron で実行されるアクションは queue テーブルに登録されているようでした。

テスト1) queue テーブルの expire 列に非0のタイムスタンプ値が入っているレコードがあったのでこれを0にしてcron実行
⇒×、解決しなかった

テスト2) queue テーブルの上記レコードを含む、name列=”views_bulk_operations*" のレコードが全て今までのVBO実行でゴミになっていたレコードに見えたので、このレコード自体を全てDB上から削除
⇒〇 cronを実行しても10件の更新が起きなかった、解決

という訳で、自分としては荒っぽい対処になりましたがこれでおそらく解決です。
DB直接ではないcronの整理方法が知りたいです。。。

日本 コミュニティ: Drupal Japan User Group

Group organizers

Group categories

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: