イベントカレンダーを表示するプラグインを作ってみた

配布しているイベントプラグインでもいいのだけれど、高機能すぎて使いづらいし、イベントが多い日はカレンダーにタイトルがずら~と並んでも・・・
と言うことで、プラグインを作ってみた。

こんな条件
・「イベント(スラッグがevent)」カテゴリーに投稿されたものが対象。
・「○○日~☓☓日まで」のような連日にも対応。
・表示はカレンダー形式でイベントがある日に印がつく。
・印をクリックするとイベントの一覧が表示される。

最低限の機能、いいかげんなCSSなので、実使用するにはカスタマイズが必要。

参考サイト
http://www.webopixel.net/wordpress/343.html
http://shanabrian.com/web/php_calendar.php
http://memo.ark-under.net/memo/718


■カレンダーの表示

スクリーンショット_2013_06_18_13_40

カレンダーはショートコードで

[mec_calendar]

と入れると表示されるので、固定ページやウイジェットでもOK。

一覧表示はテンプレートを作ってもいいんだけれど、面倒だったので固定ページに「event-date」スラッグでページを作ってショートコードで表示しています。

[mec_event_date]

スクリーンショット_2013_06_18_13_50
一覧の表示がいいかげんなので、カスタマイズが必要。


■投稿画面

スクリーンショット_2013_06_18_13_38

スクリーンショット_2013_06_18_13_43

jQueryのdatepickerで開始日、終了日を入力


プラグインの構成

my-event-calendar
├ my-event-calendar.php
├ css
│ ├ my-event-calendar.css
│ └ smoothness
│  ├ jquery-ui.min.css
│  ├ jquery.ui.datepicker.min.css
│  └ images
└ js
  ├ jquery.ui.datepicker-ja.min.js
  └ jquery.ui.datepicker.min.js

smoothnessは「jQuery UI – ThemeRoller」からダウンロードして必要なものをコピーしてください。
私はsmoothnessを使用していますが、他のテーマの場合は、テーマ名に合わせて変更して下さい。以下のソースも。


■プラグインのソース(my-event-calendar.php)

<?php
/*
Plugin Name: My Event Calendar
Plugin URI: https://webpaprika.com
Description: My Event Calendar
Version: 1.0
Author: webpaprika
Author URI: https://webpaprika.com
*/

/**
 * query_var に追加
 */
function add_aws_query_var($vars) {
  $vars[] = 'eventdate';
  return $vars;
}
add_filter('query_vars', 'add_aws_query_var');

/**
 * Widgetでショートコード
 */
add_filter('widget_text', 'do_shortcode');

/**
 * CSS追加
 */
function mec_load_stylesheet() {
  echo '<link rel="stylesheet"  href="'.plugins_url('css/my-event-calendar.css', __FILE__).'" type="text/css" media="all" />';
}
add_action('wp_head', 'mec_load_stylesheet');

/**
 * CSS追加(Admin)
 */
function mec_admin_load_stylesheet() {
  echo '<link rel="stylesheet"  href="'.plugins_url('css/smoothness/jquery-ui.min.css', __FILE__).'" type="text/css" media="all" />';
  echo '<link rel="stylesheet"  href="'.plugins_url('css/smoothness/jquery.ui.datepicker.min.css', __FILE__).'" type="text/css" media="all" />';
}
add_action('admin_print_styles-post.php', 'mec_admin_load_stylesheet');
add_action('admin_print_styles-post-new.php', 'mec_admin_load_stylesheet');

/**
 * JS追加(Admin)
 */
function mec_admin_load_scripts() {
  wp_enqueue_script('jquery');
  wp_enqueue_script('jquery.ui.datepicker', plugins_url('js/jquery.ui.datepicker.min.js', __FILE__));
  wp_enqueue_script('jquery.ui.datepicker-ja', plugins_url('js/jquery.ui.datepicker-ja.min.js', __FILE__));
}
add_action('admin_print_scripts-post.php', 'mec_admin_load_scripts');
add_action('admin_print_scripts-post-new.php', 'mec_admin_load_scripts');
function mec_admin_load_scripts2() {
  echo '<script type="text/javascript">
jQuery(document).ready(function(){
  jQuery("#datepicker").datepicker();
  jQuery("#datepicker2").datepicker();
});
</script>';
}
add_action('admin_footer-post.php', 'mec_admin_load_scripts2');
add_action('admin_footer-post-new.php', 'mec_admin_load_scripts2');

/**
 * 投稿カスタムフィールド
 */
add_action( 'admin_init', 'event_create' );
function event_create() {
  add_meta_box('events_meta', 'イベント期間', 'events_meta_html', 'post');
}
function events_meta_html () {
  global $post;
  $custom = get_post_custom($post->ID);
  if(!empty($custom)) {
    $mec_startdate = $custom['mec_startdate'][0];
    $mec_enddate = $custom['mec_enddate'][0];
  }
  echo '<input type="hidden" name="events-nonce" id="events-nonce" value="' . wp_create_nonce( 'events-nonce' ) . '" />';
  ?>
<div id="event-meta">
<table>
<tr>
<td>開始日:<input size="10" name="mec_startdate" id="datepicker" value="<?php if (isset($mec_startdate)) echo $mec_startdate; ?>" /> ~ 終了日:<input size="10" name="mec_enddate" id="datepicker2" value="<?php if (isset($mec_enddate)) echo $mec_enddate; ?>" /><br />
例)2013-01-01 ※1日だけのイベントは開始日と終了日に同じ日付を入力</td>
</tr>
</table>
</div>
<?php
}
add_action ('save_post', 'save_events');
function save_events($post_id){
  global $post;
  if ( !wp_verify_nonce( $_POST['events-nonce'], 'events-nonce' )) {
    return $post_id;
  }
  if ( !current_user_can( 'edit_post', $post->ID )) {
    return $post_id;
  }
  $mec_startdate = $_POST['mec_startdate'];
  $mec_enddate = $_POST['mec_enddate'];
  if (!$mec_enddate) { $mec_enddate = $mec_startdate;}
  update_post_meta($post->ID, 'mec_startdate', $mec_startdate);
  update_post_meta($post->ID, 'mec_enddate', $mec_enddate);
}

/**
 * カレンダー
 */
function my_event_calendar($year=null, $month=null, $eventArray=array()) {
  if(empty($year) && empty($month)) {
    $year = date("Y");
    $month = date("n");
  }
  // 月末の取得
  $l_day = date("j", mktime(0, 0, 0, $month + 1, 0, $year));
  // 初期出力
  $out = <<<EOM
<h2>{$year}年{$month}月<h2>
<table class="mycalendar">
<tr>
<th class="sun">日</th>
<th>月</th>
<th>火</th>
<th>水</th>
<th>木</th>
<th>金</th>
<th class="sat">土</th>
</tr>
EOM;
  $lc = 0;
  // 月末分繰り返す
  for ($i = 1; $i < $l_day + 1;$i++) {
    // 曜日の取得
    $week = date("w", mktime(0, 0, 0, $month, $i, $year));
    // 曜日が日曜日の場合
    if ($week == 0) {
      $out .= '<tr>';
      $lc++;
    }
    // 1日の場合
    if ($i == 1) {
      if($week != 0) {
        $out .= '<tr>';
        $lc++;
      }
      $out .= repeat($week);
    }
    if ($i == date("j") && $year == date("Y") && $month == date("n")) {
      // 現在の日付の場合
      $out .= '<td class="today"><span class="num">'.$i;
    } else {
      // 現在の日付ではない場合
      $out .= '<td><span class="num">'.$i;
    }
    // イベント日
    foreach($eventArray as $key => $val) {
      $eventdate = date("Y-m").'-'.sprintf("%02d",$i);
      if (($key == $i) && $val) { $out .= '<div class="event"><a href="'.get_bloginfo('url').'/event-date/?eventdate='.$eventdate.'">○</a></div>'; }
    }  
    $out .= '</span></td>';
    // 月末の場合
    if ($i == $l_day) {
      $out .= repeat(6 - $week);
    }
    // 土曜日の場合
    if($week == 6) {
      $out .= '</tr>';
    }
  }
  if($lc < 6) {
    $out .= '<tr>';
    $out .= repeat(7);
    $out .= '</tr>';
  }
  if($lc == 4) {
    $out .= '<tr>';
    $out .= repeat(7);
    $out .= '</tr>';
  }
  $out .= '</table>';

  return $out;
}
function repeat($n) {
  return str_repeat('<td>&nbsp;</td>', $n);
}

/**
 * カレンダーショートコード
 */
function mec_calendar_shortcode() {
  $min = date('Y-m-01');
  $max = date('Y-m-31');

  $wp_query = new WP_Query(
    array(
      'posts_per_page' => -1,
      'post_status' => 'publish',
      'category_name' => 'event',
      'meta_query' => array(
        'relation' => 'OR',
          array(
            'key' => 'mec_startdate',
            'value' => array($min, $max),
            'compare' => 'BETWEEN',
          ),
          array(
            'key' => 'mec_enddate',
            'value' => array($min, $max),
            'compare' => 'BETWEEN',
          )
      ),
      'meta_key'  => 'mec_startdate',
      'orderby'  => 'meta_value',
      'order'=>'ASC'
    )
  );

  $eventArray = array();
  while ($wp_query->have_posts()) : $wp_query->the_post();
    global $post;

    $startdate = get_post_meta($post->ID,'mec_startdate');
    $enddate = get_post_meta($post->ID,'mec_enddate');
    if ($startdate[0] && $enddate[0]) {
      if (date("m", strtotime($startdate[0])) == date("m")) {
        $sdate = date("j", strtotime($startdate[0]));
      } elseif (date("m", strtotime($startdate[0])) <= date("m")) {
        $sdate = 1;
      } else {
        break;
      }
      if (date("m", strtotime($enddate[0])) == date("m")) {
        $edate = date("j", strtotime($enddate[0]));
      } elseif (date("m", strtotime($enddate[0])) > date("m")) {
        $edate = date("j", mktime(0, 0, 0, date("m")+1, 0, date("Y")));
      } else {
        break;
      }
      for ($i=$sdate;$i<=$edate;$i++) {
          $eventArray[$i] = 1;
      }
    } elseif ($startdate[0]) {
      $edate = date("j", strtotime($startdate[0]));
      $eventArray[$edate] = 1;
    }
  endwhile;
  wp_reset_postdata();

  return my_event_calendar(date("Y"), date("m"), $eventArray);
}
add_shortcode('mec_calendar', 'mec_calendar_shortcode');

/**
 * 日付でイベント表示ショートコード
 */
function mec_event_date_shortcode() {
  global $wp_query;

  $out = '';  
  $eventdate = $wp_query->query_vars['eventdate'];
  $out .= '<h1>'.date("Y/n/j", strtotime($eventdate)).'のイベント</h1>';

  if ($eventdate) {
    $event_query = new WP_Query(
      array(
        'posts_per_page' => -1,
        'post_status' => 'publish',
        'category_name' => 'event',
        'meta_query' => array(
          'relation' => 'AND',
            array(
              'key' => 'mec_startdate',
              'value' => $eventdate,
              'compare' => '<=',
            ),
            array(
              'key' => 'mec_enddate',
              'value' => $eventdate,
              'compare' => '>=',
            )
        ),
        'meta_key'  => 'mec_startdate',
        'orderby'  => 'meta_value',
        'order'=>'ASC'
      )
    );
    while ($event_query->have_posts()) : $event_query->the_post();
      global $post;

      $startdate = get_post_meta($post->ID,'mec_startdate');
      $enddate = get_post_meta($post->ID,'mec_enddate');

      $out .= '<h2><a href="'.get_permalink($post->ID).'">'.get_the_title().'</a></h2>';
      $out .= 'イベント開催期間:'.date("Y/n/j", strtotime($startdate[0])).'~'.date("Y/n/j", strtotime($enddate[0]));
      $out .= '<p>'.get_the_content().'</p>';

    endwhile;

    wp_reset_postdata();
  }
  return $out;
}
add_shortcode('mec_event_date', 'mec_event_date_shortcode');

?>

■CSSのソース(my-event-calendar.css)

/* my event calendar styles  */
table.mycalendar {
  border-left-color: #999999;
  border-top-color: #999999;
  border-left-style: solid;
  border-top-style: solid;
  border-left-width: 1px;
  border-top-width: 1px;
  padding: 0px;
  margin: 0px;
  width: 95%;
}

table.mycalendar th {
  border-right-color: #999999;
  border-bottom-color: #999999;
  border-right-style: solid;
  border-bottom-style: solid;
  border-right-width: 1px;
  border-bottom-width: 1px;
  padding-left: 5px;
  padding-bottom: 0px;
  padding-right: 5px;
  padding-top: 0px;
  text-align: center;
  font-weight: bold;
  font-size: 1em;
  margin: 0px;
  background-color: #eeeeee;
}

table.mycalendar th.sun {
  background-color: #ffcccc;
}

table.mycalendar th.sat {
  background-color: #99ffff;
}

table.mycalendar td {
  border-right-color: #999999;
  border-bottom-color: #999999;
  border-right-style: solid;
  border-bottom-style: solid;
  border-right-width: 1px;
  border-bottom-width: 1px;
  height: 3.5em;
  text-align: left;
  padding: 5px;
  margin: 0px;
  vertical-align: top;
}

table.mycalendar td.today {
  background-color: #ffff99;
}

table.mycalendar td span.num {
  font-size: 0.8em;
}

table.mycalendar td div.event {
  font-family: "MS Pゴシック", Osaka, "ヒラギノ角ゴ Pro W3";
  color: red;
  font-size: 1.5em;
  text-align: center;
  padding: 0px;
  margin: 0px;
}

/* end of css file */

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)