WordPress: 記事に出席確認ボタンを埋め込む

各ページごとのユーザーからのフィードバックを集める例として出席確認ボタンをつくってみた。ショートコード ([rollbook title=”集計するタイトル”]) をページに埋め込むと出席確認のボタンが表示される。クリックすると、Ajax 通信を通じてデータベースに保存される。今回は練習なので、ごく少数のデータなので、Options API を使った。管理画面の「Simple Rollbook」から集計結果が表示される。

<?php

/*
Plugin Name: Simple RollBook
Plugin URI: http://blog.sarabande.jp/post/92999522293
Version: 0.1
Author: Masaki Kagaya

Description: 各ページに出席確認のボタン ([rollbook title="タイトル"]) を取りつけることができます。管理画面の「Simple Rollbook」のページから集計結果を見ることができます。
License: GPLv2 or later
*/

add_action( 'admin_menu', function() {
    $slug = 'rollbook';
    add_plugins_page( 'Simple Rollbook', 'Simple Rollbook', 'manage_options', $slug, 'rollbook_page' );
} );

add_action( 'plugins_loaded', function() {
    $settings = myplugin_get_settings();
    $ajax_callback = $settings['ajax_callback'];
    $option_name = $settings['option_name'];

    add_action( 'wp_ajax_rollbook_check', $ajax_callback );
    add_shortcode( 'rollbook', 'rollbook_shortcode' );

    register_deactivation_hook( __FILE__, function() use ($option_name) {
        delete_option( $option_name );
    } );
} );


function myplugin_get_settings() {
    return array(
        'slug' => 'rollbook',
        'option_name' => 'rollbook',
        'ajax_callback' => 'rollbook_check',
        'nonce' => 'rollbook_nonce'
    );
}

function rollbook_check() {
    $settings = myplugin_get_settings();
    $nonce = $settings['nonce'];

    check_ajax_referer( $nonce, 'security' );
    $title = $_POST['title'];
    $user_name = $_POST['user_name'];

    $settings = myplugin_get_settings();
    $option_name = $settings['option_name'];
    $data = get_option( $option_name );

    if ( !in_array( $title, $data[$user_name] ) ) {
      $data[$user_name][] = $title;
      update_option($option_name, $data);
    }

    header( 'Content-Type: application/json' );
    wp_send_json( array( 'msg' => 'ok', 'data' => $data ) );
}

function rollbook_page() {
    $settings = myplugin_get_settings();
    $option_name = $settings['option_name'];
    $data = get_option( $option_name );

    echo '<h2>出欠確認</h2>';

    if ( false !== $data ) {

        foreach ($data as $user => $values) {

            echo '<h3>'.esc_html( $user ).' さん</h3>';
            echo '<p>';
            echo '<ul>';
        
            foreach ($values as $value) {
                echo '<li>'.esc_html( $value ).'</li>';
            }
        
            echo '</ul>';
            echo '</p>';
        }
    }
}

function rollbook_shortcode($atts) {
    $url = admin_url( 'admin-ajax.php' );
    $settings = myplugin_get_settings();
    $option_name = $settings['option_name'];
    $ajax_callback = $settings['ajax_callback'];
    $nonce = wp_create_nonce( $settings['nonce'] );
    $user_name = is_user_logged_in() ? wp_get_current_user()->user_login : '';
    $a = shortcode_atts( array('title' => ''), $atts );
    $title = $a['title'];

    $data = get_option($option_name);

    if ( isset($data[$user_name]) && in_array($title, $data[$user_name]) ) {
        $lavel = '出席は確認されています。';
    } else if ( '' === $user_name ) {
        $lavel = 'ログインしてください。';
    } else if ( mb_strlen( $title, 'UTF-8' ) <= 0 ) {
        $lavel = 'title に文字を指定してください。';
    } else {
        $lavel = '出席を確認する';
    }

    $json_options = JSON_HEX_QUOT|JSON_HEX_AMP|JSON_HEX_APOS|JSON_HEX_TAG;
    $url = json_encode($url, $json_options);
    $json = json_encode(array(
        'security' => $nonce,
        'action' => $ajax_callback,
        'user_name' => $user_name,
        'title' => $title 
      ), $json_options);
?>
  <p>
  <input id="rollbook_button" type="button" value="<?= $lavel ?>">
  </p>
  <p id="rollbook_msg" style="color:red"></p>
  <script type="text/javascript">
    (function($) {

      var url = <?= $url ?>;
      var data = <?= $json ?>;

        $button = $( '#rollbook_button' );
        $button.on( 'click', function() {

        $.post( url, data, function(res) {

            $msg = $( '#rollbook_msg' );

            if ( 'ok' === res['msg'] ) {
              $msg.html( '出席を確認しました。' );
            } else {
              $msg.html( '出席確認が失敗しました。通信環境を見直した上で再度お試しください。' );
            }

        }, 'json' );

        } );

    })(jQuery);
  </script>
<?php
}

WordPress: データベースのテーブルをつくる

$wpdb オブジェクトはプラグイン独自のテーブルを操作するためにも使える。テーブルの作成には dbDelta が使える。

global $wpdb;
$table_name = 'test_table';

$sql = "CREATE TABLE IF NOT EXISTS $table_name (
  id int NOT NULL AUTO_INCREMENT,
  text text NOT NULL,
  UNIQUE KEY id (id)
);";

require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql );

$wpdb->insert( $table_name, ['text' => 'テスト']);

$ret = $wpdb->get_results( "SELECT text FROM $table_name", 'ARRAY_A' );
var_dump( $ret );

WordPress: ログイン名を取得する

WP_User オブジェクトを返す wp_get_current_user() を使う。ログインしているかの判定は is_user_logged_in を使う。

$name = is_user_logged_in() ? wp_get_current_user()->user_login : 'ゲスト';
echo $name, 'さん、こんにちは';

HackLang: Vector、Map、Set で filter、map を使う

Vector、Map にはキーを引数にとることのできる filterWithKey、mapWithKey も用意されている。reduce は用意されていない。

$v = Vector {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
$ret = $v->filter($value ==> $value % 2 === 0)
  ->map($value ==> $value * $value);

$ret2 = $v->filterWithKey(($key, $value) ==> $key % 2 === 0)
  ->mapWithKey(($key, $value) ==> $value * $value);

var_dump(
    [4, 16, 36, 64, 100] === $ret->toArray(),
    [1, 9, 25, 49, 81] === $ret2->toArray()
);
$map = Map {'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 };
$ret3 = $map->filter($value ==> $value % 2 === 0)
  ->map($value ==> $value * $value);

$ret4 = $map->filterWithKey(($key, $value) ==> $key === 'c' ||  $key === 'e')
  ->mapWithKey(($key, $value) ==> $value * $value);

var_dump(
    ['b' => 4, 'd' => 16] === $ret3->ToArray(),
    ['c' => 9, 'e' => 25] === $ret4->ToArray()
);

Set の場合、filterWithKey、mapWithKey は用意されていない。

$set = Set {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
$ret5 = $set->filter($value ==> $value % 2 === 0)
  ->map($value ==> $value * $value);

var_dump([4, 16, 36, 64, 100] === $ret5->toValuesArray());

Objective-C: NSArray の一部の要素を取り出す

objectsAtIndexes メソッドを使う。範囲は NSIndexSet を使ってあらわす。

@import Foundation;

int main(void) {

    NSArray *myArray = [NSArray arrayWithObjects:
        [NSNumber numberWithInt:100],
        [NSNumber numberWithInt:200],
        [NSNumber numberWithInt:300],
        [NSNumber numberWithInt:400],
        [NSNumber numberWithInt:500],
        nil
    ];

    NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 3)];
    NSArray *ret = [myArray objectsAtIndexes:indexes];
    NSLog(@"%@", ret);

    return 0;
}
アーカイブ ランダム ホーム 次のページ ページ 1 / 365