Try   HackMD

2021-06-24 Google Calendar api 程式範例

與 api 綁定

  • 將產生的token 存在 $_SESSION中,這樣就不用每次綁定
  • credentials.json是[[Google Calendar api 設定]]憑證設定好後,下載到PHP 使用
// credentials.json
{
    "web": {
        "client_id": "786168007234-p7a9soquf9v8tmkga8t429gb0vur60o4.apps.googleusercontent.com",
        "project_id": "ambient-union-317703",
        "auth_uri": "https://accounts.google.com/o/oauth2/auth",
        "token_uri": "https://oauth2.googleapis.com/token",
        "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
        "client_secret": "vhvTnbJDqh9bQJFd08pDWT6N",
        "redirect_uris": [
            "http://127.0.0.1:20089/linkCalendars.php"
        ]
    }
}
// linkCalendars.php
$calendar = new Calendar();
if (!empty($_GET['code'])) {
    $calendar->Authenticate($_GET['code']); // 產生 access_token
} else {
    echo "<a href='" . $calendar->GetCalendarAccessUrl() . "'>Google Login</a>";
}

// class\calendar.php
class Calendar {
    private $client;

    function __construct() {
        $client = new Google_Client();
        $client->setApplicationName('Google Calendar API PHP Quickstart');
        $client->setAuthConfig('credentials.json');
        $client->setAccessType('offline');
        $client->setPrompt('select_account consent');
        $client->setScopes(array('https://www.googleapis.com/auth/calendar','https://www.googleapis.com/auth/userinfo.email','https://www.googleapis.com/auth/userinfo.profile'));
        $this->client=$client;
        $this->google_oauth =new Google_Service_Oauth2($this->client);
    }

    // 產生 google api 綁定連結
    public function GetCalendarAccessUrl() {  // Generate Google calendar access url and login url
        return $this->client->createAuthUrl();
    }

    # 產生 access_token
    # 經由 Auth綁定後,會回傳對應code,使用code 產生 access_token
    # 若沒有傳code,每次呼叫時重新 refresh token
    public function Authenticate($code=NULL) {

        if(!empty($code)) {

            $this->client->authenticate($code); //  Authonticate Auth code
            $access_token = $this->client->getAccessToken(); // Get Access token
            $refresh_token=$this->client->getRefreshToken();  // Get Refresh token

            if(!empty($access_token)) {
                $_SESSION['access_token']=$access_token;
            }
            if(!empty($refresh_token)) {
                $_SESSION['refresh_token']=$refresh_token;
            }
        }
        $this->client->setAccessToken($_SESSION['access_token']); // set the access token

        // check the access token is expired or not if expired fetcg new one using refresh token
        if ($this->client->isAccessTokenExpired()) {
            $access_stoken =$this->client->fetchAccessTokenWithRefreshToken($this->client->getRefreshToken());
        }

        return $this->client;
    }
}

顯示 日曆清單

顯示所有日曆清單

// queryCalendars.php
$calendar = new Calendar();
$client=$calendar->Authenticate(); // 憑證 refresh
$calendars = $calendar->queryCalendars($client); // google api 取得日曆清單

$calendarview = new CalendarView( $calendars, $client );
$calendarview->showCalendars(); // 顯示日曆清單


// class\calendar.php
class Calendar {
    public static function queryCalendars($client) {

        $service = new Google_Service_Calendar($client);
        $calendars = $service->calendarList->listCalendarList()->getItems();

        // 篩出 user 擁有的 calendars
        $owner_calendars = array_filter($calendars, function($calendar) {
            return $calendar->accessRole === "owner"; // 只顯示自己可以管理的日曆,像是國定假日、農民曆就是外部關聯的,不要抓。
        });

        return $owner_calendars;
    }
}
// class\CalendarView.php
class CalendarView {

    private $calendars;
    private $client;

    function __construct( $calendars, $client ) {
        $this->calendars=$calendars;
        $this->client   =$client;
    }

    /**
     * 顯示 User 所有 calendar
     */
    public function showCalendars() {
        // 篩出 user 擁有的 calendars
        $owner_calendars = array_filter($this->calendars, function($calendar) {
            return $calendar->accessRole === "owner";
        });

        echo "<table border=1>";
        echo "    <thead>";
        echo "    <tr>";
        echo "        <th>id</th>";
        echo "        <th>title</th>";
        echo "        <th>event url</th>";
        echo "    </tr>";
        echo "    </thead>";
        echo "    <tbody>";
        foreach ($owner_calendars as $tmp => $calendar) {
            echo "    <tr>";
            echo "        <td>";
            echo            $calendar->getId();
            echo "        </td>";
            echo "        <td>";
            echo            $calendar->getSummary();
            echo "        </td>";
            echo "        <td>";
            echo "            <a href='queryCalendars.php?calendarId=". $calendar->getId(). "'>events</a>";
            echo "        </td>";
            echo "    </tr>";
        }
        echo "    </tbody>";
        echo "</table>";
    }
}

顯示 事件清單

// queryCalendars.php
$events = $calendar->queryEvents($client, $_GET['calendarId'], '2021');
$calendarview->showCalendarEvents($events);

// class\calendar.php
/**
 * 查詢 Calendar events
 * @param type $client
 * @param type $calendar_id 日曆代碼
 * @param type $start_year 開始搜尋的年份
 * @return type
 */
public static function queryEvents($client, $calendar_id, $start_year) {
    $service = new Google_Service_Calendar($client);
    $query_events = [];

    // 逐年讀取 events
    for ($year = $start_year; $year < date('Y', strtotime('+1 years')); $year++) {
        $start = date(DATE_ATOM, mktime(0, 0, 0, 1, 1, $year));
        $end = date(DATE_ATOM, mktime(0, 0, 0, 12, 31, $year));
        $params = array(
            'singleEvents' => 'true',
            'orderBy' => 'startTime',
            'timeMin' => $start,
            'timeMax' => $end
        );
        try {
            $query = $service->events->listEvents($calendar_id, $params)->getItems();
        } catch (\Exception $e) {
            return $e->getCode();
        }
        $query_events = array_merge($query_events, $query);

        // 延遲向 API request 的速度 (單位 second)
        sleep(1);
    }
    return $query_events;
}

// class\CalendarView.php
/**
 * 顯示 calendar 的所有事件
 * @param $events
 */
public function showCalendarEvents($events) {

    $result = array_map(function($event) {
        $_result = [
            'event_id'         => $event->getId(),
            'title'            => $event->getSummary(),
            'where'            => $event->getLocation(),
            'description'      => $event->getDescription(),
            'startAt'          => $event->getStart()->getDate() !== null ? $event->getStart()->getDate() : $event->getStart()->getDateTime(),
            'endAt'            => $event->getEnd()->getDate() !== null ? $event->getEnd()->getDate() : $event->getEnd()->getDateTime(),
            '_editeteEventUrl' => "editCalendars.php?calendarId=". $_GET['calendarId']. "&event_id=". $event->getId(),
            '_deleteEventUrl'  => "delCalendars.php?calendarId=". $_GET['calendarId']. "&event_id=". $event->getId(),
        ];
        $_result['startAt'] = date("Y-m-d H:i", strtotime($_result['startAt']));
        $_result['endAt']   = date("Y-m-d H:i", strtotime($_result['endAt']));

        return $_result;

    }, $events);
    krsort($result);

    echo "<h1>List Calendar's Event</h1>";
    echo '<a href="editCalendars.php" target="_blank" >新增日曆事件</a><br>';
    echo "<table border=1>";
    echo "    <thead>";
    echo "    <tr>";
    echo "        <th>Title/Description</th>";
    echo "        <th>Start/End Datetime</th>";
    echo "        <th>Edit!</th>";
    echo "        <th>Delete!</th>";
    echo "    </tr>";
    echo "    </thead>";
    echo "    <tbody>";
    foreach ($result as $tmp => $event) {
        echo "    <tr>";
        echo "        <td>";
        echo "            <div>Title:<br/>". $event['title']. "</div>";
        echo "            <div>Description:<br/>". nl2br($event['description']). "</div>";
        echo "        </td>";
        echo "        <td>";
        echo "            <div>Start at:<br/>". $event['startAt']. "</div>";
        echo "            <div>End at:<br/>". $event['endAt']. "</div>";
        echo "        </td>";
        echo "        <td><a href='". $event['_editeteEventUrl']. "' target='_blank'>修改</a></td>";
        echo "        <td><a href='". $event['_deleteEventUrl']. "' target='_blank'>刪除</a></td>";
        echo "    </tr>";
    }
    echo "    </tbody>";
    echo "</table>";
}

新增&&修改 事件

  • 新增&& 修改
// class\CalendarView.php
echo '<a href="editCalendars.php" target="_blank" >新增日曆事件</a><br>';
echo '<a href="editCalendars.php?calendarId=calendarId&event_id=event_id" target="_blank" >修改日曆事件</a><br>';
/**
 * 顯示 calendar 所屬id的事件
 * @param $events
 */
public function getCalendarEvents( $event, $calendarId="" ) {

    $result = [];
    if (empty($calendarId)) { $calendarId="primary"; } // 若未選擇日曆,則帶入預設日曆
    if (!empty($event)) {

        $result = [
            'eventid'     => $event->getId(),
            'title'       => $event->getSummary(),
            'where'       => $event->getLocation(),
            'attendees'   => "",
            'description' => nl2br($event->getDescription()),
            'startAt'     => $event->getStart()->getDate() !== null ? $event->getStart()->getDate() : $event->getStart()->getDateTime(),
            'endAt'       => $event->getEnd()->getDate() !== null ? $event->getEnd()->getDate() : $event->getEnd()->getDateTime(),
        ];
        $result['startAt'] = date("Y-m-d H:i", strtotime($result['startAt']));
        $result['endAt']   = date("Y-m-d H:i", strtotime($result['endAt']));
    }

    echo '<form action="saveCalendars.php" method="post">';
    echo '<input type="text" name="calendarId" value="'. $calendarId. '">';
    echo '<input type="text" name="eventId" value="'. $result['eventid']. '">';
    echo '<br/>';
    echo '<br/>';
    echo '標題<input type="text" name="title" value="'. $result['title']. '"><br/>';
    echo '地點<input type="text" name="where" value="'. $result['where']. '"><br/>';
    echo '與會者<input type="text" name="attendees" placeholder="example@abc.com" value="'. $result['attendees']. '"><br/>';
    echo '敘述<textarea name="description" cols="30" rows="10">'. $result['description']. '</textarea><br/>';
    echo '起始時間<input type="text" name="start" id="datetimepicker1" placeholder="click me" value="'. $result['startAt']. '"><br/>';
    echo '結束時間<input type="text" name="end" id="datetimepicker2" placeholder="click me" value="'. $result['endAt']. '"><br/>';
    echo 'popup 提醒時間<input type="number" name="reminderTime" placeholder="留白會套用預設提醒時間" value="'. $result['id']. '"><br/>';
    echo '<input type="submit" value="提交">';
    echo '</form>';
}

// editCalendars.php
$client=$calendar->Authenticate();

$calendars = $calendar->queryCalendars($client);
$calendarview = new CalendarView( $calendars, $client );

if(!empty($_GET['calendarId']) && !empty($_GET['event_id'])) { // 若有傳送 event_id,則取出該event 資料
    $events = $calendar->queryEvent( $client, $_GET['calendarId'], $_GET['event_id']);
}
$calendarview->getCalendarEvents( $events, $_GET['calendarId'] ); // 顯示新增日曆畫面

  • 保存
    先在 saveCalendars.php 整理資料,整理後呼叫google api 保存。
// saveCalendars.php
$client=$calendar->Authenticate();

$calendarId    = $_POST['calendarId'];    // string
$eventId       = $_POST['eventId'];       // string
$title         = $_POST['title'];         // string
$where         = $_POST['where'];         // string
$description   = $_POST['description'];   // string
$startDatetime = $_POST['start'];         // string: '2016-05-17 08:00'
$endDatetime   = $_POST['end'];           // string: '2016-05-17 10:00'
$attendees     = $_POST['attendees'];     // string: 'abc@mail.com;xyz@mail.com' (多個 email 以 ; 分隔)
$reminderTime  = $_POST['reminderTime'];  // integers: 50

$result = $calendar->saveEvent($client, $calendarId, $eventId, $title, $where, $description, $attendees, $startDatetime, $endDatetime, $reminderTime);

// class\calendar.php
public static function saveEvent($client, $calendar_id, $event_id, $title, $where, $description, $attendees, $startAt, $endAt, $reminderTime) {
    // 若有 event_id 時就做update,不然就insert
    try {
        if (!empty($event_id)) {
            $createdEvent = $service->events->update($calendar_id, $event_id, $event, $optParams); // 更新事件
        } else {
            $createdEvent = $service->events->insert($calendar_id, $event, $optParams); // 寫入事件
        }

    } catch (\Exception $e) {
        return $e->getCode();
    }
    $eventId = $createdEvent->getId(); // 取得產生後的 event id
}

刪除 事件

// class\CalendarView.php
echo '<a href="delCalendars.php?calendarId=calendarId&event_id=event_id" target="_blank" >修改日曆事件</a><br>';

// class\delCalendars.php
$result = $calendar->deleteEvent( $client, $_GET['calendarId'], $_GET['event_id']);

// class\calendar.php
$service = new Google_Service_Calendar($client);
$service->events->delete($calendar_id, $event_id);

相關連結