WP Facebook Portalを復活させるまでのメモ

8 min read

ホームページ制作の副業をやっていたときに作成した Wordpress サイトで、 WP Facebook Portal というプラグインを使ってました。

https://wordpress.org/plugins/wp-facebook-portal/

Facebook pages の投稿内容を自動で取得して、Wordpress のブログを投稿してくれるという便利なプラグインです。Wordpress のブログ投稿は面倒だけど、Facebook Pages にはよく投稿しているというお客様用としてかなり重宝していました。

しかし、2021 年の 4 月頃から投稿情報の取得に失敗して動かなくなりました。
プラグインの開発自体 2019 年の 9 月で終了しています。開発者に改修を依頼するわけにもいかないので、プラグインのコードを読みながら、なんとか修正できないかと試行錯誤して復活までこぎつけたので記します。

復活方法

wp-content/plugins/wp-facebook-portalの以下コードを修正すれば動作するようになります。
動かなくなった理由は Facebook の Graph API のバージョンアップで、リクエストパラメータが変わったことが原因のようです。

wp-facebook-portal/libraries/facebook.php

wp-facebook-portal/libraries/facebook.php
/**
 * Facebook API URL.
 *
 * @var string
 */
-   public $requestUrl = 'https://graph.facebook.com/v2.8';
+   public $requestUrl = 'https://graph.facebook.com/v11.0';
wp-facebook-portal/libraries/facebook.php
/**
 * Facebook の投稿記事を取得
 *
 * @param integer $page_id Facebook Page ID
 * @param integer $since Search of created time (timestamp)
 * @param integer $until Search of created time (timestamp)
 * @return array
 */
    public function getFacebookFeed($page_id = null, $since = null, $until = null)
    {
        if (empty($page_id)) return false;

-       $path = '/' . $page_id . '/posts';
+       $path = '/' . $page_id . '/feed';
        $params = array(
-           'fields' => 'id,message,created_time,type,link,object_id',
+           'fields' => 'id,message,created_time,attachments{media_type, unshimmed_url,target{id},media{image{src}}}',
            'since' => $since,
            'until' => $until,
            'access_token' => $this->getAccessToken()
        );
        $response = $this->apiRequest($path, $params);

        if ((is_array($response)) && (!empty($response))) {
            $_data = array();
            foreach ($response['data'] as $i => $data) {
                if (empty($data['message'])) {
                    continue;
                }
                $response['data'][$i]['permalink'] = vsprintf($this->postUrlFormat, explode($this->idDelimiter, $response['data'][$i]['id']));
+               $_attachments = $response['data'][$i]["attachments"]["data"][0];
+               if(!is_null($_attachments)) {
+                   $response['data'][$i]['object_id'] = $_attachments["target"]["id"] ?? NULL;
+                   $response['data'][$i]['link'] = $_attachments["unshimmed_url"] ?? NULL;
+                   $response['data'][$i]['type'] = $_attachments["media_type"] ?? NULL;
+                   $response['data'][$i]['image_url'] = $_attachments["media"]["image"]["src"] ?? NULL;
+               }
                $_data[] = $response['data'][$i];
            }
            $response = $_data;
        }
        return $response;
    }

wp-facebook-portal/libraries/facebook.php

wp-facebook-portal/core/controller-admin.php
/**
 * 更新
 * Facebook ページの記事を取得
 */
    public function update($id = null)
    {
        if ((is_null($id)) || (!is_numeric($id))) {
            die(__('Security check', FacebookPortal::TEXT_DOMAIN));
        }
        global $wpdb;
        $facebook_post_ids = $wpdb->get_col("SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = 'facebook_post_id'");

        if (($_SERVER['REQUEST_METHOD'] == 'POST') && (!empty($_POST))) {
            if (!check_admin_referer('wpfb_admin_update')) die(__('Security check', FacebookPortal::TEXT_DOMAIN));

            // 保存処理
            $ids = $_POST['ids'];
            if (is_array($ids)) {
                $_post = $_SESSION['feeds'];
                unset($_SESSION['feeds']);
                $post_ids = array();
                foreach ($ids as $fb_post_id) {
                    if (in_array($fb_post_id, $facebook_post_ids)) {
                        continue;
                    }

                    // 投稿保存
                    if ($_data = $this->Common->savePost($_post[$fb_post_id])) {
                        $post_ids[] = $_data['ID'];
-                       if (($_post[$fb_post_id]['type'] === 'photo') && (isset($_post[$fb_post_id]['object_id']))) {
+                       if (($_post[$fb_post_id]['type'] === 'photo' or $_post[$fb_post_id]['type'] === 'album') && (isset($_post[$fb_post_id]['object_id']))) {
                            // 添付画像の取り扱い設定がなければ処理をスキップ
                            if (empty($_post[$fb_post_id]['image_type'])) {
                                continue;
                            }

                            // 添付画像取得保存
-                           if ($photoUrls = $this->Facebook->getPhotoUrl($_post[$fb_post_id]['object_id'])) {
+                           if ($photoUrls = array($_post[$fb_post_id]['image_url'])) {
                                $attachment_ids = array();
                                foreach ($photoUrls as $photoUrl) {
                                    if ($attachment_id = $this->Common->savePhoto($photoUrl, $_data['ID'], $_data['post_author'])) {
                                        $attachment_ids[] = $attachment_id;
                                    }
                                }

wp-facebook-portal/core/class-cron.php

wp-facebook-portal/core/class-cron.php
/**
 * 記事更新
 * 
 * @return boolean
 */
    public function main()
    {
        // ページ情報を取得
        $fields = 'id,facebook_page_id,post_author,post_category,image_type,image_size,link_text,auto_link,post_updated';

        if ($results = $this->Model->getAll($fields)) {
            global $wpdb;
            $facebook_post_ids = $wpdb->get_col("SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = 'facebook_post_id'");
            // Facebook ページの数だけ繰り返し
            foreach ($results as $result) {
                // 記事取得
                $since = ($result['post_updated']) ? $result['post_updated'] : null;
                if (!$response = $this->Facebook->getFacebookFeed($result['facebook_page_id'], $since)) {
                    continue;
                } else {
                    $created_time = array();
                    foreach ($response as $feed) {
                        if (in_array($feed['id'], $facebook_post_ids)) {
                            continue;
                        }

                        // 投稿日をタイムスタンプに変換
                        $feed['timestamp'] = FacebookPortal::strtotime($feed['created_time']);

                        // デフォルト設定を代入
                        $feed['post_author'] = $result['post_author'];
                        $feed['post_category'] = $result['post_category'];
                        $feed['link_text'] = $result['link_text'];
                        $feed['auto_link'] = $result['auto_link'];
                        $feed['facebook_page_id'] = $result['facebook_page_id'];

                        // 投稿保存
                        if ($_data = $this->Common->savePost($feed)) {
                            // 更新確認用タイムスタンプ
                            $created_time[] = $feed['timestamp'];
-                           if (($feed['type'] === 'photo') && (isset($feed['object_id']))) {
+                           if (($feed['type'] === 'photo' or $feed['type'] === 'album') && (isset($feed['object_id']))) {
                                // 添付画像の取り扱い設定がなければ処理をスキップ
                                if (empty($result['image_type'])) {
                                    continue;
                                }

                                // 添付画像取得保存
-                               if ($photoUrls = $this->Facebook->getPhotoUrl($feed['object_id'])) {
+                               if ($photoUrls = array($feed['image_url'])) {
                                    $attachment_ids = array();
                                    foreach ($photoUrls as $photoUrl) {
                                        if ($attachment_id = $this->Common->savePhoto($photoUrl, $_data['ID'], $_data['post_author'])) {
                                            $attachment_ids[] = $attachment_id;
                                        }
                                    }

Discussion

ログインするとコメントできます