アカウント削除ボタンのカスタマイズ

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
redboxhosting's picture

Drupal7でアカウント削除ボタンを任意の場所に設置しようと考えていますが
フォーム関連の実装がよく分からずアドバイス頂けると助かります。

Drupal7 デフォルトでは、ユーザーアカウント編集ページの中のアカウントキャンセルボタンをクリックすると、アカウント削除確認画面に飛ばされます。
その後、再度アカウントキャンセルボタンを押すことにより、削除確認のメールアドレスが送信されると思います。

これを、/user/%uid/edit 画面のテンプレート内にMODAL画面を設置し、
直接アカウント削除メールを送信出来るようにしたいと考えています。

既に、/user/%uid/edit ページは以下の様にテンプレート化し、
各種フォームの編集・保存は出来ているのですが、テンプレート内にModal用のHTMLを記載し、どのように記載したらアカウント削除申請が行えるのか分からない状況です。

お手数ですが、アドバイス頂けると助かります。

template.php

function テーマ名_theme(&$existing, $type, $theme, $path) {

  $hooks['user_profile_form'] = array(
   'render element' => 'form',
   'template' => 'templates/user-profile-form',
   'preprocess functions' => array(
    'テーマ名_preprocess_user_profile_form'
    ),
  );

  return $hooks;
}

user-profile-form.tpl.php

<?php print render($form['form_id']);?>
<?php print render($form['form_build_id']);?>
<?php print drupal_render($form['form_token']); ?>

<?php print drupal_render($form['actions']['submit']);?>
<?php print drupal_render($form['actions']['cancel']);?>

<a class="btn grey-cascade" data-target="#deleteform" data-toggle="modal">アカウント削除<span class="glyphicon glyphicon-cog"></span></a>


        <!--Modal Window -->
        <div id="deleteform" class="modal fade" tabindex="-1" data-backdrop="static" data-keyboard="false">
                <div class="modal-body">
                        <div class="note note-danger">
                                <h4 class="block">アカウント削除の確認</h4>
                        </div>
                </div>
                <div class="modal-footer">
                        <button id="delete" data-dismiss="modal" class="btn red" type="submit" name="deletedomain">削除</button>
                </div>
        </div>

Comments

hgoto's picture

必要なタスクを切り分けると次のような形でしょうか。

  1. フォームを作る
  2. フォームをモーダルボックスに表示する仕組みを作る

端的にはなりますが、以下課題になっていそうな箇所別に参考情報をお出ししてみますね。

  • A. メール送信を含むアカウントキャンセル処理の実装方法がわからない → コアのオリジナルの処理を参考に実装されるとよいかと思います。該当する関数は user モジュール内の user_cancel_confirm_form()
    user_cancel_confirm() 等です。
  • B. (フォームそのものを Ajax で取得して生成したい場合)フォームをモーダルボックスに表示する方法がわからない → D7 でよく使われるモーダルボックスの実装方法は ctools モジュールのモーダル API でしょうか。 ctools のモーダル API の詳細はこちらでは説明しきれないので ctools の README や d.o. の developer guide をご覧になってみてください。
  • C. (フォームを最初からページの中に入れておいて Ajax なしでモーダルボックスとして表示したい場合)フォームをモーダルボックスに表示する方法がわからない → フォームをブロックに入れる形で実装されるのがよいのではないかと思います。その場合は、まず 1) ブロックにフォームを表示する方法を調べて、 2) ブロックを JS で(「アカウント削除」ボタンクリック時に)モーダルボックスに表示する方法を調べて、と進めていかれるとよろしいかと思います。この場合は A の ctools を使うアプローチではなく、単純に JS でモーダルボックスを作ればいいはずです。

B と C については択一のオプションです。 B の方が完成形はきれいですが、工数が多くなるかと思います。ですので、「 B と C のどちらでもいい」という場合は C を選ばれるとよいでしょう。

セキュリティその他のことを考慮すると、テンプレート内に HTML で直接フォームを書くのではなく Drupal の Form API を使ってフォームを生成する形がよいかと思います。そのために Drupal の Form API を利用する B / C のオプションをあげています。

ご参考になればと思います。

(投稿後にわかりづらいところを編集しました)

redboxhosting's picture

とても詳しい説明を有り難うございます。

A. メール送信を含むアカウントキャンセル処理の実装方法がわからない → コアのオリジナルの処理を参考に実装されるとよいかと思います。該当する関数は user モジュール内の user_cancel_confirm_form() や
user_cancel_confirm() 等です

こちらは、template.php内に記載しテンプレートファイル内で読み出すのだと思いますが、
おそらくこのあたりの実装がよく分かっていません。

たとえば、template.php内に以下の様にコードを記載すると、DrupalCoreの機能に追加もしくは上書きされるようなイメージで利用していました。
※以下の例はアカウント削除ボタンのテキストを上書きした際に利用しています。

function テーマ名_form_alter(&$form, &$form_state, $form_id) {

if ($form_id = 'edit-cancel') {

$form['actions']['cancel'] = array(
'#type' => 'submit',
'#value' => t('退会'),
'#limit_validation_errors' => array(),
);
}

}

理解不足で申し訳ないのですが、このように既存のCoreの要素を上書きまたはUNSET、追記する用でTemplate.phpに記載しておりました。

今回の場合、user_cancel_confirm() の内容をtemplate.phpに記載し、必要事項を上書き。その後、任意のテンプレートにて、キャンセルボタンを読み出すように記載するということでよろしいでしょうか。

例:キャンセルボタンのみ個別に読み出し

<?php
print drupal_render($form['actions']['cancel']);
?>

また質問の仕方がよくなかったのですが、実装したいことは以下の通りでした。

1:ボタンを実行することにより、確認ページに飛ばずアカウントキャンセルを実行できるようにする。

2:1だけでは怖いので、テンプレートファイル内のJSでModalを実装し、独自の簡易確認ページやアラートを出す。

MODALに関してはDrupalではCtoolで利用する例が多く記載されておりましたが、よく分からなかったため、今回はシンプルに C で実装する予定です。

宜しくお願い致します。

hgoto's picture

ご返信いただきありがとうございます。

理解不足で申し訳ないのですが、このように既存のCoreの要素を上書きまたはUNSET、追記する用でTemplate.phpに記載しておりました。

「コアやコントリビュートモジュールが提供するフォームを少しだけ変えたいときには template.php 内に テーマ名_form_alter() を書けばよい」という点についてはご認識のとおりかと思います。

一方のキャンセルボタンの件についてはおそらく前提の認識が近くなると話が進めやすいはずなので、先にそこをご説明させてください。私は前提として次のように考えていました。

  • P. CSRF を考慮する必要がある。よって、ボタンだけ設置するようなアプローチはなしで。 CSRF 対策用のトークンを含むフォームを丸ごと生成して埋め込む必要あり。
  • Q. HTML の <form> は入れ子にはできないので、 P とあわせて考えると、ユーザ編集フォーム内にキャンセルボタンを入れることはそもそもできない(やろうと思えばできると思いますがおそらく不必要に複雑になると思います)。

この前提の認識のもと、私は今回の実装は「 A. アカウント編集ページにボタンを追加する」「 B. そのボタンがクリックされたらアカウント削除用フォームがモーダルボックスに表示されるようにする」「 C. そのフォームが送信されたときにアカウント削除処理を行う」という形になるはずだと考えていました。

最初にご説明されていた内容から私は A についてはテンプレートを書き換える形で実装が済んでいるものだと理解していて、あとは B/C ができればいいのだと思い ctools やブロックのお話を前のコメントでさせていただいていました。


今回の場合、user_cancel_confirm() の内容をtemplate.phpに記載し、必要事項を上書き。その後、任意のテンプレートにて、キャンセルボタンを読み出すように記載するということでよろしいでしょうか。

メール送信処理などはテーマの template.php ではなくモジュールの .module ファイルの中で実装されるのがよろしいかと思います。

フォームの作成方法についての詳細の説明は多くのページでなされているので検索してみてください。以下のページや Examples プロジェクトの form_example モジュールなどを参考にされるとよいでしょう。

How to Make a Simple Module with a Form and Menu Link
https://www.drupal.org/docs/7/howtos/how-to-make-a-simple-module-with-a-...

Examples for Developers
https://www.drupal.org/project/examples

ブロックの作成方法についても同じ Examples プロジェクトの block_example などが参考になります。

その前にモジュールの作成方法がどうもよくわからないぞという場合には、日本語でも「 Drupal モジュール 作成方法」などと検索されると参考になるページがひっかかってくるかと思いますのでそれらを参考にされるとよろしいかと思います。

ご質問へのお答えになっているでしょうか。

今回の機能の実装に必要なことをこちらですべてご説明するの大変なのでリファレンスだけのご提供にしていますが、ご参考になれば幸いです :)

redboxhosting's picture

ご連絡が遅くなりましたが、詳しいアドバイスありがとうございました。

以下については、認識の通りです。

この前提の認識のもと、私は今回の実装は「 A. アカウント編集ページにボタンを追加する」「 B. そのボタンがクリックされたらアカウント削除用フォームがモーダルボックスに表示されるようにする」「 C. そのフォームが送信されたときにアカウント削除処理を行う」という形になるはずだと考えていました。

モーダルを読み出すボタンを設置し、MODAL内にフォーム一式を生成するように調整していたのですが、生成したフォーム内の内容を色々と変更しなければいけない状況のため、シンプルに以下のような実装をしました。

・Flagモジュールを導入
・FlagモジュールでFlaggedになったらアカウントブロックするようRulesに記載。
・テーマのテンプレート内にMODAL呼び出しボタンを設置し、MODAL内でFlagボタンを読み出すようPHPにて記載。

これにより、ユーザーはMODALにて確認後、アカウントのキャンセルをするのか否かが選べるようになりました。

その他、モジュールを作成して動作を分けることについては今回見送りましたが、今後何か作成する際に必ず必要となってくるとおもうので、いただいたリンクを参考にしてまずは簡単な動作から試してみようと思います。

ありがとうございました!

hgoto's picture

ご返信いただきありがとうございます。

別のところでもお話しさせていただきましたが、そうなんですね! Flag モジュール + Rules モジュールという使う方法は思いつきませんでした。

とても丁寧にご状況をご説明いただいたにもかかわらず私はあまりお役に立てなかった気がしますが・・・ともあれ目的を達成されたようでよかったです!