[PHP] Google Calendar API から日本の祝日データを取得

Google Calendarから日本の祝日データを取得する方法についての調査メモ。

ポイント

  • GDataを使う場合はデベロッパーKEYが必要だが、GDataを使わなくても日本の祝日カレンダーは取得できる。
  • 祝日名と日付を取得したい場合、Projection valueは”full-noattendees”で。(fullより少しだけデータが小さくなる。)
  • 利用規約はGoogleカレンダー利用規約。

via. floatingdays: Google Calendar API で日本の祝日データを取得

PHP でやるなら…

$holidays_url = sprintf(
        'http://www.google.com/calendar/feeds/%s/public/full-noattendees?start-min=%s&start-max=%s&max-results=%d&alt=json' ,
        'outid3el0qkcrsuf89fltf7a4qbacgt9@import.calendar.google.com' , // 'japanese@holiday.calendar.google.com' ,
        '2012-01-01' ,  // 取得開始日
        '2012-12-31' ,  // 取得終了日
        50              // 最大取得数
        );
if ( $results = file_get_contents($holidays_url) ) {
        $results = json_decode($results, true);
        $holidays = array();
        foreach ($results['feed']['entry'] as $val ) {
                $date  = $val['gd$when'][0]['startTime'];
                $title = $val['title']['$t'];
                $holidays[$date] = $title;
        }
        ksort($holidays);
}

[2014-8-26 追記] Google Calendar API v3 に対応させる記事を書きました
[PHP] Google Calendar API v3 で日本の祝日を取得する

CentOS 64bit版への APC のインストール

CentOS 64bit 版で PHP 5.4.0 RC4 を使おうとすると pecl からインストールした APC が動作しないので開発版をインストールする。
PHP 5.4 を、以下の方法でビルド & インストールした場合の APC 開発版のインストール方法
PHP 5.4.0 RC4 のビルド&インストール « メモとか

$ svn co http://svn.php.net/repository/pecl/apc/trunk/ apc-trunk
$ cd apc-trunk
$ /usr/local/php/bin/phpize
$ ./configure --enable-apc --enable-apc-mmap --with-apxs \
 --with-php-config=/usr/local/php/bin/php-config
$ make; make test
$ sudo make install

あとは、/usr/local/php/lib/php.ini に extension="apc.so" を追加する。

via. Installing APC from beta/alpha development onto centOS 5.4 64 bit dual core | Drupal SEO and Website Solutions By Peter Christopher of Hilo, Hawaii

PHP 5.4.0 RC4 のビルド&インストール

$ sudo yum install libxml2-devel  libicu-devel libmcrypt-devel
$ wget http://downloads.php.net/stas/php-5.4.0RC4.tar.gz
$ tar xvzf php-5.4.0RC4.tar.gz
$ cd php-5.4.0RC4
$ ./configure --prefix=/usr/local/php \
 --enable-mbstring \
 --with-mysql --with-pdo-mysql --with-mysqli \
 --enable-pcntl \
 --enable-fpm --with-fpm-user=nginx --with-fpm-group=nginx \
 --with-openssl \
 --with-pcre-regex \
 --with-zlib \
 --with-mhash \
 --with-xsl \
 --with-mcrypt \
 --with-pear \
 --enable-exif \
 --enable-ftp \
 --with-gd --enable-gd-native-ttf --enable-gd-jis-conv \
 --without-unixODBC \
 --disable-posix --disable-sysvmsg --disable-sysvshm --disable-sysvsem --disable-debug \
 --enable-intl
$ make; make test
$ sudo make install

make & make test は結構時間かかるので、気長に待ちましょう。
make install で /usr/local/php/ に PHP 5.4 がインストールされる。
php, php-cgi, php-config, phpize とか pear とかは /usr/local/php/bin/ にコピーされます。
php-fpm は /usr/local/php/sbin/

バージョン確認は、こんな感じ。

$ /usr/local/php/bin/php -v
PHP 5.4.0RC4 (cli) (built: Jan  5 2012 13:50:20)
Copyright (c) 1997-2011 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2011 Zend Technologies

アンインストールしたいときは /usr/local/php/ をフォルダごと削除しちゃってください。

設定ファイル

上記でビルド & インストールした場合の設定ファイルの置き場所。

  • php.ini は /usr/local/php/lib/php.ini
  • php-fpm.conf は /usr/local/php/etc/php-fpm.conf

php.ini は、存在しないので適当に作成する。
php-fpm.conf は、同じディレクトリに php-fpm.conf.default ってのが作成されてるので、そいつをコピーして修正。

[PHP] csv ファイルを連想配列に読み込む

function parse_csv( $csv_file, $title_row = -1, $start_row = 0, $key_cal = -1, $length = 0, $delimiter = ',', $enclosure = '"' ) {
    $results = FALSE;

    if ( file_exists($csv_file) && ($fp = fopen($csv_file, 'r')) ) {
        $row = 0;
        $results  = array();
        $col_name = array();
        while ( $field_array = fgetcsv($fp, $length, $delimiter, $enclosure) ) {
            if ( $row === $title_row ) {
                $col = 0;
                foreach ($field_array as $value) {
                    $col_name[$col] = !empty($value) ? $value : $col;
                    $col++;
                }
            }
            if ( $row >= $start_row ) {
                $result = array();
                $col = 0;
                foreach ($field_array as $value) {
                    $key = isset($col_name[$col]) ? $col_name[$col] : $col;
                    $result[$key] = $value;
                    $col++;
                }

                $key = $row;
                if ( is_numeric($key_cal) ) {
                    $key =
                        ( $key_cal >= 0 && isset($col_name[$key_cal]) )
                        ? $result[$col_name[$key_cal]]
                        : $row;
                } else {
                    foreach ($col_name as $value) {
                        if ( $key_cal === $value ) {
                            $key = $result[$value];
                            break;
                        }
                    }
                }
                $results[$key] = $result;
            }
            $row++;
        }
        fclose($fp);
    }

    return $results;
}

[PHP] サブディレクトリ内のファイル名をすべて取得

function get_files($dir, $pre = '', $excluded = '') {
    $result = array();
    $excluded = empty($excluded)
        ? array('.'.DIRECTORY_SEPARATOR, '..'.DIRECTORY_SEPARATOR)
        : (array)$excluded;
    if ( is_dir($dir) ) {
        if ( $dh = opendir($dir) ) {
            while ( ($file = readdir($dh)) !== FALSE ) {
                if ( is_dir($dir.$file) ) {
                    $file .= DIRECTORY_SEPARATOR;
                    if ( !(in_array($file, $excluded) || in_array($pre.$file, $excluded)) ) {
                        $result = array_merge($result, get_files($dir.$file, $pre.$file, $excluded));
                    }
                } else if ( !(in_array($file, $excluded) || in_array($pre.$file, $excluded)) ) {
                    $result[] = $pre.$file;
                }
            }
            closedir($dh);
        }
    }
    return $result;
}
$files = get_files('/path/to/');

Re: これ、どう考えてももっと短くなる気がしてならない

http://twitter.com/#!/shinichiN/status/113883259829628928

if ( $_POST['cawaii_desuka'] == 'yes' ) {
    if ( isset($_POST['bg_css']) ) {
        $bg_css = $_POST['bg_css'];
    }
    if ( $bg_css == 'bg_brown' || $bg_css == 'bg_check' || $bg_css == 'bg_none' ) {
        update_option('bg_css', $bg_css);
    }
}

短くするならこうかな?(未検証)

if (isset($_POST['cawaii_desuka']) && $_POST['cawaii_desuka'] === 'yes') {
    $bg_css = isset($_POST['bg_css']) ? $_POST['bg_css'] : '';
    preg_match('/^bg_(brown|check|none)$/', $bg_css) && update_option('bg_css', $bg_css);
}

わかりやすいのならこう

if (isset($_POST['cawaii_desuka']) && $_POST['cawaii_desuka'] === 'yes') {
    $bg_css = isset($_POST['bg_css']) ? $_POST['bg_css'] : '';
    switch ($bg_css) {
        case 'bg_brown':
        case 'bg_check':
        case 'bg_none':
            update_option('bg_css', $bg_css);
    }
}

[WordPress] プラグインがアクティブかどうか調べる

アクティブなプラグインは get_option(‘active_plugins’) で取得できる。

function is_plugin_active($file) {
	$is_active = false;
	foreach ((array) get_option('active_plugins') as $val) {
		if (preg_match('/'.preg_quote($file, '/').'/i', $val)) {
			$is_active = true;
			break;
		}
	}
	return $is_active;
}

is_plugin_active('hello.php'); とか is_plugin_active('akismet/akismet.php'); とかすれば良いよ。

PHP5.3.2環境で WordPress 管理画面がこける

ソースからのコンパイルインストールではなく現状維持での解決方法です(yum管理)
Wordpress 3.2からtimezone_identifiers_listの利用は必須になったようなので、
どうしようか悩んでいましたが解決できてよかったです。

状況
Redhat Linuxでyum管理していると、timezone関連の関数が使えない問題に起因しています。PHP5.3以降で問題が発生しており、timezone_identifiers_list()を呼び出すと、Segmentation faultsがでます。

対策

  1. timezonedbの更新
    $ pecl upgrade timezonedb
  2. timezonedbをphpのextensionとして読み込む
    /etc/php.d/timezone.ini を作成し
    extension=timezonedb.so
  3. 確認
    $ php -r 'timezone_identifiers_list();'
    というコマンドラインでエラーが発生しないことを確認した上で、
    Apacheを再起動すれば、timezonedbがTimezoneで使われ、本問題が回避できるようです

via WordPress > フォーラム » PHP5.3.2環境で管理者画面の一部(options-general.php)で処理がコケる

[WordPress] ショートコードが存在したときだけ Javascript をロードする

ショートコードを使って、投稿の内容にJavascriptによる効果を付加するプラグインを作って使っていますが、現状では

add_action('init', 'load_jqtools_ini');
add_action('wp_head', 'start_jqtools');

を使って常時ロードしている構成です。
これをショートコードが存在したときにだけ、スクリプトの類をロードさせるようにするにはどのような仕掛けを施したらよいのでしょうか。

via WordPress › フォーラム » ショートコードが存在したときにだけJavascriptをロードさせたい

こんな感じで、$wp_query->posts に目的のショートコードが含まれているか正規表現でチェックし、無ければ wp_enqueue_script() を呼び出さないようにしてます。

add_action('wp_print_scripts', 'add_my_scripts');

function add_my_scripts() {
	if (!has_shortcode('shortcode'))
		return;
	wp_enqueue_script('hogehoge', 'http://example.com/fugafuga.js');
}

function has_shortcode($shortcode) {
	global $wp_query;

	$posts   = $wp_query->posts;
	$pattern = '/\[' . preg_quote($shortcode) . '[^\]]*\]/im';
	$found   = false;
	$hasTeaser = !( is_single() || is_page() );

	foreach($posts as $post) {
		if (isset($post->post_content)) {
			$post_content = $post->post_content;
			if ( $hasTeaser && preg_match('/<!--more(.*?)?-->/', $post_content, $matches) ) {
				$content = explode($matches[0], $post_content, 2);
				$post_content = $content[0];
			}

			if ( !empty($post_content) && preg_match($pattern, $post_content) ) {
				$found = true;
			}
		}
		if ( $found )
			break;
	}
	unset($posts);
	return $found;
}