見出し画像

サイボウズOFFICE10のスケジュールを iCalendar形式にしてみた。

目的は、一方通行でいいからサイボウズのスケジュールをGoogleカレンダーでみたいです。残念ながら、OFFICE10のクラウド版では、その機能があるようなのですが、パッケージ版には、無いようなのです。そこで、ネットで調べてみると紹介されているサイトがあるにはあるのですが、なかなか難しいようです。先人の方々を参考にさせていただきながら、PHPの勉強のつもりで作成してみました。

GoogleカレンダーのURL指定でも読込ができましたが、いつ更新されるかわからないので、GoogleカレンダーAPIを使って登録する方法にチャレンジしようと思っています。

サイボウズOFFICE10 バージョン10.8.5パッケージ版。phpは、バージョン7.4です。プログラムは、素人です。

<?php
//サイボウズOFFICE10の設定
//ログイン名、パスワード
define('LOGIN_ID','ログイン名');
define('LOGIN_PASS','パスワード');

//サイボウズOFFICE10のURL
define('CYBOZU_URL', 'https://(なんちゃらかんちゃら)/scripts/cbag/ag.cgi');
define("CYBOZU_CGI", 'ag.cgi');       //サイボウズの実行ファイル名
define("CHAR_CODE", 'UTF-8');         //サイボウズ10は、UTF-8
define("SCHEDULE_TITLE", 'Cybozu');   //スケジュールタイトル
define("SCHEDULE_MEMO",   FALSE);     //メモまで取得する場合は'TRUE'にする。でも時間がかかる。
define("SCHEDULE_BANNER", TRUE);      //スケジュールバナーまで取得する場合は'TRUE'
define('PRODID', 'Cybozu2iCal');

//主な検索タグ
//日付タグ検索用文字列と文字数
$wdate_str = '<span class="date">';
$wdate_str_len = strlen($wdate_str);

//スケジュールID検索用文字列と文字数
$schedule_id_str = '<div class="eventLink scheduleMarkTitle0 highlight-event';
$schedule_id_str_len = strlen($schedule_id_str);

//スケジュールのメモ検索用文字列と文字数
$wlink_str = '<a class="event" href="';
$wlink_str_len = strlen($wlink_str);

//バナータグ検索用文字列と文字数
$bdate_str = '<a class="bannerevent" href="';
$bdate_str_len = strlen($bdate_str);

//配列と制御関連の変数
$loop_flg = TRUE;           //日付データ読込のループ
$bseid_moji = " ";          //バナーデータの二重取得を防止
$dschedule_list = [];       //日付スケジュール配列
$bschedule_list = [];       //バナースケジュール配列

//ログインのためのPOSTデータ組立
$data = array(
	"_System" => "login",
	"_Login" => "1",
	"LoginMethod" => "2",
	"_Account" => LOGIN_ID,
	"Password" => LOGIN_PASS
);
$data = http_build_query($data, "", "&");

//headerにセット
$header = array(
	"Content-Type: application/x-www-form-urlencoded",
	"Content-Length: ".strlen($data)
);
$context = array(
	"http" => array(
	"method"  => "POST",
	"header"  => implode("\r\n", $header),
	"content" => $data
	)
);

//サイボウズからHTMLデータ取得
$durl = CYBOZU_URL.'?page=ScheduleUserMonth';
$dhtml = file_get_contents($durl, false, stream_context_create($context));

//文字コードをUTF-8へ変換
$dhtml = mb_convert_encoding($dhtml, "UTF-8", CHAR_CODE);

while ( $loop_flg == TRUE ) {
	//日付タグ
	$wdate = substr(strchr($dhtml,$wdate_str), $wdate_str_len);
	$wdate = substr($wdate, 0, strpos($wdate, '</span>'));
	if ($wdate == "") {
		break;
	}

	//日付タグ、カット
	$dhtml = substr(strchr($dhtml,$wdate_str), $wdate_str_len);

	$loop_flg2 = TRUE;
	$han_id = 0;
	while ( $loop_flg2 == TRUE ) {
		if ( strpos($dhtml, $wlink_str) > strpos($dhtml, $wdate_str) ) {
			break;
		} else {
			//スケジュールID
			$schedule_id = substr(strchr($dhtml,$schedule_id_str), $schedule_id_str_len);
			$schedule_id = substr($schedule_id, 0, strpos($schedule_id, '" '));
			if ( $schedule_id == "" ) {
				break;
			}
			//日付をAタグから取得、メモ取得する場合の準備
			$wlink = substr(strchr($dhtml,$wlink_str), $wlink_str_len);
			$wlink = substr(strchr($wlink,CYBOZU_CGI), 6);
			$wlink = substr($wlink, 0, strpos($wlink, '" title="'));
			//日付
			$tmpdate = substr(strchr($wlink,'Date=da.'), 8);
			$tmpdate = substr($tmpdate, 0, strpos($tmpdate, '&amp;BDate'));
			//メモ取得の場合のURL
			$wlink = str_replace("&amp;","&",$wlink);
			$wlink = CYBOZU_URL.$wlink;
			//日付のフォーマットを変更
			$date_sp = explode('.', $tmpdate);
			$schedule_date =  sprintf("%04d",$date_sp[0]) . sprintf("%02d",$date_sp[1]) . sprintf("%02d",$date_sp[2]);
			//次の日も取得
			$schedule_date_tommorow = Date('Ymd', mktime(0, 0, 0, (int)$date_sp[1], (int)((int)$date_sp[2] + 1), (int)$date_sp[0] ) );

			//メモ(動作未検証)
			if ( SCHEDULE_MEMO ) {
				//サイボウズからHTMLデータ取得
				$dhtml2 = file_get_contents($wlink, false, stream_context_create($context));
				//文字コードをUTF-8へ変換
				$dhtml2 = mb_convert_encoding($dhtml2, "UTF-8", CHAR_CODE);
				$schedule_description = substr(strchr($dhtml2,'<div id="scheduleMemo">'), 23);
				$schedule_description = substr($schedule_description, 0, strpos($schedule_description, '</tt>'));
				//HTMLタグをとる
				$schedule_description = strip_tags($schedule_description);
				//記号をとる
				$schedule_description = str_replace("&nbsp;"," ", $schedule_description);
				$schedule_description = str_replace("&amp;","&", $schedule_description);
				$schedule_description = str_replace("&gt;",">", $schedule_description);
				$schedule_description = str_replace("&lt;","<", $schedule_description);
				//改行コードとかをとる
				$schedule_description = str_replace("\n\r","", $schedule_description);
				$schedule_description = str_replace("\n","", $schedule_description);
				$schedule_description = str_replace("\r","", $schedule_description);
			} else {
				$schedule_description = "";
			}
			//タイトル
			$schedule_title = substr(strchr($dhtml,'=sm" title="'), 12);
			$schedule_title = substr($schedule_title, 0, strpos($schedule_title, '">'));
			//時刻
			if (strpos($dhtml, '<span class="eventDateTime">') < strpos($dhtml, '=sm" title="')) {
				$schedule_time = substr(strchr($dhtml, '<span class="eventDateTime">'), 28);
				$schedule_time = substr($schedule_time, 0, strpos($schedule_time, '&nbsp;'));
			} else {
				$schedule_time = '';
			}
			//重複予定あり、カット
			if (strpos($schedule_time, '/image/warn16.png') > 0 ){
				//時刻の抽出
				$count_jyu = strlen('<img src="/cb1080/image/warn16.png" align=absmiddle alt="重複予定あり" title="重複予定あり">');
				$count_zen = strlen( $schedule_time );
				$temp_time = substr( $schedule_time, $count_jyu);
				$schedule_time = $temp_time;
			}
			//タイトル、カット
			$dhtml = substr(strchr($dhtml,'=sm" title="'), 12);

			if ( !empty($schedule_time) ) {
				//日時
				$time_sp = "";
				$time_sp = explode('-', $schedule_time);
				//翌日まで続く予定
				if(strpos(@$time_sp[1],'/') > 0 ){
					//終わりが日付表示である場合。23:59とする。
					$time_sp[1] = "23:59";
				}
				if(strpos(@$time_sp[0],'/') > 0 ){
					//始まりが日付表示である場合。0:00とする。
					$time_sp[0] = "0:00";
				}

				$from_sp = explode(':', @$time_sp[0]);
				if ( count($time_sp) > 1 ) {
					$to_sp   = explode(':', @$time_sp[1]);
				} else {
					$to_sp = $from_sp;
				}
				//時
				$from_sp[0] = sprintf('%02d', @$from_sp[0]); 
				$to_sp[0] = sprintf('%02d', @$to_sp[0]); 

				//24:00は、Googleでダメ?
				if ( strcmp(@$from_sp[0], "24") == 0 ) {
					$from_sp[0] = "23";
					$from_sp[1] = "59";
				}
				if ( strcmp(@$to_sp[0], "24") == 0 ) {
					$to_sp[0] = "23";
					$to_sp[1] = "59";
				}

				//動作わからん:23:59 は、翌日の0:00とする。
				if (  ((strcmp(@$from_sp[0],"23")) ==0)  and ((strcmp(@$from_sp[1],"59")) ==0) ) {
					$schedule_from = ':' . $schedule_date_tommorow . 'T000000';
				}else{
					$schedule_from = ':' . $schedule_date . 'T' . @$from_sp[0] . @$from_sp[1]. '00';
				}
				if (  ((strcmp(@$to_sp[0],"23")) ==0)  and ((strcmp(@$to_sp[1],"59")) ==0) ) {
					$schedule_to = ':' . $schedule_date_tommorow .'T000000';
				}else{
					$schedule_to = ':' . $schedule_date . 'T' . @$to_sp[0] . @$to_sp[1]. '00';
				}
				$schedule_summary     = $schedule_title;
				$schedule_description = $schedule_title . " " . $schedule_description;
				$schedule_dtstamp     = $schedule_date . 'T' . @$from_sp[0] . @$from_sp[1]. '00';

			} else {
				//時刻、日付がない場合
				$schedule_summary     = $schedule_title;
				$schedule_from        = ';VALUE=DATE:' . $schedule_date;
				$schedule_to          = ';VALUE=DATE:' . $schedule_date_tommorow;
				$schedule_description = $schedule_title . " " . $schedule_description;
				$schedule_dtstamp     = $schedule_date . 'T080000';
			}

			//乱数でUIDを違うようにする
			$schedule_temp = uniqid();
			$dschedule_list[] = array('id'    => $schedule_id.$schedule_temp.$schedule_date,
								'description' => $schedule_description,
								'dtstart'     => $schedule_from,
								'dtend'       => $schedule_to,
								'summary'     => $schedule_summary,
								'dtstamp'     => $schedule_dtstamp);
		}

		//バナー
		if ( SCHEDULE_BANNER ) {
			//バナー文字列検索
			$bdate = substr(strchr($dhtml,$bdate_str), $bdate_str_len);
			$bdate = substr($bdate, 0, strpos($bdate, '</a>'));
			if ( $bdate != "" ) {
				//タイトル
				$bschedule_title = substr(strchr($bdate,'title="'), 7);
				$bschedule_title = substr($bschedule_title, 0, strpos($bschedule_title, '">'));
				//sEID
				$bseid = substr(strchr($bdate,'sEID='), 5);
				$bseid = substr($bseid, 0, strpos($bseid, '&amp;C'));

				if ( strpos($bseid_moji,$bseid) === false ){
					$burl = substr(strchr($bdate,CYBOZU_CGI), 6);
					$burl = substr($burl, 0, strpos($burl, '" title'));
					$burl = str_replace("&amp;","&",$burl);
					$burl = CYBOZU_URL.$burl;
					//サイボウズからHTMLデータ取得
					$bwork = file_get_contents($burl, false, stream_context_create($context));
					//文字コードをUTF-8へ変換
					$bwork = mb_convert_encoding($bwork, "UTF-8", CHAR_CODE);
					//日付
					$bhidu = substr(strchr($bwork,'<th align="left" nowrap>日付</th>'), 35);
					$bhidu = substr($bhidu, 0, strpos($bhidu, '</td>'));
					$bhidu = substr(strchr($bhidu,'<td nowrap>'), 11);
					$bhidu_sp = explode('~', $bhidu);

					//開始日、年
					$bbyy = substr(trim($bhidu_sp[0]), 0, 4);
					//開始日、月
					$bbmm = substr(strchr($bhidu_sp[0],'年'), 1);
					$bbmm = substr($bbmm, 0, strpos($bbmm, ' 月'));
					$bbmm = trim(substr($bbmm, -2));
					//開始日、日
					$bbdd = substr(strchr($bhidu_sp[0],'月'), 1);
					$bbdd = substr($bbdd, 0, strpos($bbdd, ' 日'));
					$bbdd = trim(substr($bbdd, -2));
					//開始日
					$bschedule_date_start = $bbyy . sprintf("%02d",$bbmm) . sprintf("%02d",$bbdd);

					//終了日、年
					$beyy = substr(trim($bhidu_sp[1]), 0, 4);
					//終了日、月
					$bemm = substr(strchr($bhidu_sp[1],'年'), 1);
					$bemm = substr($bemm, 0, strpos($bemm, ' 月'));
					$bemm = trim(substr($bemm, -2));
					//終了日、日
					$bedd = substr(strchr($bhidu_sp[1],'月'), 1);
					$bedd = substr($bedd, 0, strpos($bedd, ' 日'));
					$bedd = trim(substr($bedd, -2));
					//終了日
					$bschedule_date_end = $beyy . sprintf("%02d",$bemm) . sprintf("%02d",$bedd);
					//終了日の翌日が終わりでないとダメみたい。
					$bschedule_date_end_tommorow = "";
					$bschedule_date_end_tommorow = Date('Ymd', mktime( 0, 0, 0, (int)$bemm, (int)((int)$bedd + 1), (int)$bbyy ) );
					//メモ
					if ( SCHEDULE_MEMO ) {
						//メモ取得する場合(動作未検証)
						$bschedule_description = substr(strchr($bwork,'<div id="scheduleMemo">'), 23);
						$bschedule_description = substr($bschedule_description, 0, strpos($bschedule_description, '</tt>'));
						//HTMLタグをとる
						$bschedule_description = strip_tags($bschedule_description);
						//記号をとる
						$bschedule_description = str_replace("&nbsp;"," ", $bschedule_description);
						$bschedule_description = str_replace("&amp;","&", $bschedule_description);
						$bschedule_description = str_replace("&gt;",">", $bschedule_description);
						$bschedule_description = str_replace("&lt;","<", $bschedule_description);
						//改行コードとかをとる
						$bschedule_description = str_replace("\n\r","", $bschedule_description);
						$bschedule_description = str_replace("\n","", $bschedule_description);
						$bschedule_description = str_replace("\r","", $bschedule_description);
					} else {
						//メモ取得しない場合
						$bschedule_description = "";
					}
					//配列に入れる前に整頓
					$bschedule_summary     = $bschedule_title;
					$bschedule_from        = ';VALUE=DATE:' . $bschedule_date_start;
					$bschedule_to          = ';VALUE=DATE:' . $bschedule_date_end_tommorow;
					$bschedule_description = $bschedule_title . " " . $bschedule_description;
					$bschedule_dtstamp     = $bschedule_date_start . 'T080000';

					//乱数でUIDを違うようにする
					$bschedule_temp = uniqid();
					//配列に入れる。
					$bschedule_list[] = array('id'    => $bschedule_temp,
										'description' => $bschedule_description,
										'dtstart'     => $bschedule_from,
										'dtend'       => $bschedule_to,
										'summary'     => $bschedule_summary,
										'dtstamp'     => $bschedule_dtstamp);
				}
				//抽出したIDを記録しておく。二回目に出てきたら無視する
				$bseid_moji = $bseid_moji ." ". $bseid;
				//バナータグ、カット
				$bhtml = substr(strchr($dhtml,$bdate_str), $bdate_str_len);
			}
		}
	}
}
//ここから出力
//改行コードは、CRLFとした
header('Content-Type: text/calendar; charset=utf-8');
header('Content-Disposition: filename="file.ics"');
echo 'BEGIN:VCALENDAR'. "\r\n";
echo 'PRODID:' . PRODID. "\r\n";
echo 'VERSION:2.0'. "\r\n";
echo 'METHOD:PUBLISH'. "\r\n";
echo 'CALSCALE:GREGORIAN'. "\r\n";
echo 'X-WR-CALNAME:' . SCHEDULE_TITLE . "\r\n";
echo 'X-WR-CALDESC:' . SCHEDULE_TITLE . "\r\n";
echo 'X-WR-TIMEZONE:Asia/Tokyo'. "\r\n";

//日付
if ( !empty($dschedule_list) ) {
	foreach ( $dschedule_list as $key => $vale ) {
		echo 'BEGIN:VEVENT'. "\r\n";
		echo 'UID:' . SCHEDULE_TITLE . '-' . $vale['id'] . "\r\n";
		echo 'DESCRIPTION:' . $vale['description']. "\r\n";
		echo 'DTSTART;TZID=Asia/Tokyo' . $vale['dtstart'] . "\r\n";
		echo 'DTEND;TZID=Asia/Tokyo' . $vale['dtend'] . "\r\n";
		echo 'SUMMARY:'. $vale['summary']. "\r\n";
		echo 'DTSTAMP:'. $vale['dtstamp']. "\r\n";
		echo 'END:VEVENT'. "\r\n";
	}
}

//バナー
if ( !empty($bschedule_list) ) {
	foreach ( $bschedule_list as $bkey => $bvale ) {
		echo 'BEGIN:VEVENT'. "\r\n";
		echo 'UID:' . SCHEDULE_TITLE . '-' . $bvale['id'] . "\r\n";
		echo 'DESCRIPTION:' . $bvale['description']. "\r\n";
		echo 'DTSTART;TZID=Asia/Tokyo' . $bvale['dtstart'] . "\r\n";
		echo 'DTEND;TZID=Asia/Tokyo' . $bvale['dtend'] . "\r\n";
		echo 'SUMMARY:'. $bvale['summary']. "\r\n";
		echo 'DTSTAMP:'. $bvale['dtstamp']. "\r\n";
		echo 'END:VEVENT'. "\r\n";
	}
}

echo 'BEGIN:VTIMEZONE'. "\r\n";
echo 'TZID:Asia/Tokyo'. "\r\n";
echo 'BEGIN:STANDARD'. "\r\n";
echo 'DTSTART:19700101T000000'. "\r\n";
echo 'TZOFFSETFROM:+0900'. "\r\n";
echo 'TZOFFSETTO:+0900'. "\r\n";
echo 'END:STANDARD'. "\r\n";
echo 'END:VTIMEZONE'. "\r\n";
echo 'END:VCALENDAR'. "\r\n";
?>



この記事が気に入ったらサポートをしてみませんか?