スキーマチュートリアル
スキーマチュートリアルレッスン16:新しい投稿があった際に通知を送信する

レッスン16:新しい投稿があった際に通知を送信する

Gato GraphQL は、新しい投稿があった際に管理者へ通知メールを送信するなど、アプリケーションのタスクを自動化するのに役立ちます。

このチュートリアルレッスンでは、これを実現する2つの方法を探ります。

管理者に通知メールを送信するGraphQLクエリ

このGraphQLクエリは管理者ユーザーにメールを送信し、サイトに新しい投稿が作成されたことを通知します。

query GetEmailData(
  $postTitle: String!,
  $postContent: String!
  $postURL: URL!
) {
  adminEmail: optionValue(name: "admin_email")
    @export(as: "adminEmail")
 
  emailMessageTemplate: _strConvertMarkdownToHTML(
    text: """
 
There is a [new post on the site]({$postURL}):
 
**{$postTitle}**:
 
{$postContent}
 
    """
  )
  emailMessage: _strReplaceMultiple(
    search: ["{$postTitle}", "{$postContent}", "{$postURL}"],
    replaceWith: [$postTitle, $postContent, $postURL],
    in: $__emailMessageTemplate
  )
    @export(as: "emailMessage")
 
  emailSubject: _sprintf(
    string: "New post: \"%s\"",
    values: [$postTitle]
  )
    @export(as: "emailSubject")
}
 
mutation SendEmail @depends(on: "GetEmailData") {
  _sendEmail(
    input: {
      to: $adminEmail
      subject: $emailSubject
      messageAs: {
        html: $emailMessage
      }
    }
  ) {
    status
  }
}

メールをプレーンテキストで送信するには:

  • _sendEmail ミューテーションで入力 messageAs: { text: ... } を使用する
  • PHP Functions via Schema 拡張機能が提供するグローバルフィールド _htmlStripTags を使って、投稿コンテンツからHTMLタグを除去する

次に、GraphQLクエリの実行をトリガーする方法を見ていきましょう。

オプション1:WordPressのフックに反応して常にトリガーする

WordPress coreのアクション new_to_publish にフックし、新しく作成された投稿からデータを取得し、Internal GraphQL Server 拡張機能が提供する内部GraphQLサーバーに対して上記のGraphQLクエリを実行します。

use GatoGraphQL\InternalGraphQLServer\GraphQLServer;
use WP_Post;
 
// The GraphQL query, under var `$query`, is the one defined above
// $query = '...';
add_action(
  'new_to_publish',
  function (WP_Post $post) use ($query) {
    $variables = [
      'postTitle' => $post->post_title,
      'postContent' => $post->post_content,
      'postURL' => get_permalink($post->ID),
    ]
    GraphQLServer::executeQuery($query, $variables, 'SendEmail');
  }
);

クラス GatoGraphQL\InternalGraphQLServer\GraphQLServer は外部APIとしてアクセスできません。代わりに、PHPコードを通じてアプリケーションが使用し、GraphQLクエリによって管理タスクを実行・自動化するためのものです。

このクラスはクエリを実行するための3つのスタティックメソッドを提供します。

  • executeQuery:GraphQLクエリを実行する
  • executeQueryInFile:(.gql)ファイルに含まれるGraphQLクエリを実行する
  • executePersistedQuery:パーシステッドGraphQLクエリを実行する(IDをintとして、またはスラッグをstringとして指定)

このGraphQLクエリは、新しい投稿が作成されるたびに実行されます。より正確には、WordPressの関数 wp_insert_post が呼び出されるたびに実行されます(この関数がフック new_to_publish をトリガーするため):

$postID = wp_insert_post([
  'post_title' => 'Hello world!'
]);

これは、createPost ミューテーションを実行する別のGraphQLクエリを実行する場合にも同様です(そのリゾルバーがPHPコードで関数 wp_insert_post を呼び出すため):

mutation CreatePost {
  createPost(input: {
    title: "Hello world!"
  }) {
    status
    postID
  }
}

GraphQLサーバー(HTTPを通じてAPIとしてアクセスする「外部」サーバー)とInternal GraphQLサーバーは、それぞれ独自のSchema Configurationを適用してクエリを実行します。これは両者の実行が絡み合っている場合でも同様です。

例えば、シングルエンドポイントに対してGraphQLクエリを実行しており、それが createPost ミューテーションを実行して投稿を作成するとします。このとき、次の一連のステップが発生します。

(外部) GraphQL ServerInternal GraphQL Server
シングルエンドポイントに対してGraphQLクエリを実行し、独自のSchema Configurationを使用(非アクティブ)
投稿を作成し、new_to_publish をトリガー(非アクティブ)
(待機中...)new_to_publish フックに反応:Internal GraphQLサーバーを起動し、独自のSchema Configurationを使用
(待機中...)メール送信クエリを実行
(待機中...)メールを送信し、そのクエリを終了
(待機中...)サーバーをシャットダウン
クエリの実行を継続し、そのクエリを終了(非アクティブ)
サーバーをシャットダウン(非アクティブ)

オプション2:GraphQLクエリをチェーンすることでトリガーする

Automation 拡張機能により、GraphQLサーバーはGraphQLクエリの実行完了後にフックをトリガーします。これにより、GraphQLクエリをチェーンすることができます。

このPHPコードは、GraphQLサーバーが CreatePost オペレーションを持つ何らかのクエリ(上記のGraphQLクエリ)を実行した後に、SendEmail オペレーション(上記で定義したGraphQLクエリ)を実行します。

// The GraphQL query, under var `$query`, is the one defined above
// $query = '...';
add_action(
  "gatographql__executed_query:CreatePost",
  function (Response $response) use ($query) {
    // @var string
    $responseContent = $response->getContent();
    // @var array<string,mixed>
    $responseJSON = json_decode($responseContent, true);
    $postID = $responseJSON['data']['createPost']['postID'] ?? null;
    if ($postID === null) {
      // Do nothing
      return;
    }
 
    $post = get_post($postID);
    $variables = [
      'postTitle' => $post->post_title,
      'postContent' => $post->post_content,
      'postURL' => get_permalink($post->ID),
    ]
    GraphQLServer::executeQuery($query, $variables, 'SendEmail');
  }
);

GraphQLクエリをチェーンすることで、多くのリソースがミューテーションされた場合でも、実行するクエリを1つだけにすることができます。

例えば、このGraphQLクエリは多くの投稿を更新します。

mutation ReplaceDomains {
  posts {
    id
    rawContent
    adaptedRawContent: _strReplace(
      search: "https://my-old-domain.com"
      replaceWith: "https://my-new-domain.com"
      in: $__rawContent
    )
    update(input: {
      contentAs: { html: $__adaptedRawContent }
    }) {
      status
      postID
    }
  }
}

戦略に応じて、1つまたは複数の追加GraphQLクエリの実行をトリガーできます。

フックする対象...トリガーされるGraphQLクエリの数...
post_updated(WordPress coreによる)更新された投稿ごとに1つ
gatographql__executed_query:ReplaceDomainsAutomation 拡張機能による)合計1つ(更新されたすべての投稿のデータを受け取る)