OXY NOTES

Question2Answerを1.6.1から1.7.4へアップデートする方法

エンジニア向けアップデート作業メモ

前回の解説でも説明しましたが、SUKEGRAというQ&Aサイトを運営しています。このサイトはQuestion2AnswerというCMSを利用して運営しています。

今回、スパム対策にreCAPTCHAを導入することをきっかけに「1.6.1」から「1.7.4」へバージョンアップしました。

アップデート作業は公式の解説通りに進めれば問題ありませんでしたが、Oauthの対応に苦労しました。せっかくなので備忘録として残しておきます。

内容的にエンジニアの方しか見ないと思うので、ざっくりと解説します。


Question2Answerをアップグレードする方法

基本的には公式のアップグレードの方法の解説の通り進めれば問題ありません。

簡単に解説すれば、

    1.全体のファイルとデータベースをバックアップ。
    2.Question2Answerの最新バージョンをダウンロード。githubにあります。
    3.管理パネルでメンテナンスモードにしてから解凍した最新版のファイルと入れ替える。
    4.管理ページでデータベースのアップデートを促す表示が出ていれば実行。

以上が通常のアップデートの流れです。


PHPの関数mysql系のDeprecatedエラー

ファイルを置き換えた後に表示されたmysql_connect()エラー。(XAMPP上で実行)

Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in C:\xampp\htdocs\xampp\sukegra\php\qa-external\qa-external-users.php on line 236
Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in C:\xampp\htdocs\xampp\sukegra\php\qa-external\qa-external-users.php on line 721

シングルサインオンを導入しているため手を加えていたqa-external-users.phpのDeprecatedエラーが出ています。このエラー自体はPHPのバージョン変更時によく見るもので、mysql系の関数がサポート終了するので、mysqliかPDOを使えとのこと。
手間を掛けずにさくっと終わらせたいのでmysqliに置き換えます。

修正の一例

//接続のための各種情報の格納
$qa_db_connection = mysql_connect( $host, $username, $password );

//指定したデータベースへ接続
mysql_select_db( $database, $qa_db_connection );
mysql_set_charset('utf8');

$result=mysql_fetch_assoc(
	mysql_query(
		"SELECT * FROM qa_users WHERE userid='" . mysql_real_escape_string($userid) . "'"
	)
);

以下のように変更します。

//接続のための各種情報の格納
$qa_db_connection = mysqli_connect( $host, $username, $password, $database );

//指定したデータベースへ接続
mysqli_select_db( $qa_db_connection, $database );
mysqli_set_charset( $qa_db_connection, 'utf8' );

$result=mysqli_fetch_assoc(
	mysqli_query(
		$qa_db_connection, 
		"SELECT * FROM qa_users WHERE userid='" . mysqli_real_escape_string( $qa_db_connection, $userid ) . "'"
	)
);

基本mysqli系はmysqli_connectではデータベース名を、その他では第一引数に接続したデータベースを指定する必要があります。
といった、修正をファイル全てで行います。

あとは直接アップデートと関係ありませんが、テスト環境とサーバ用でqa-external-users.phpを置き換えるのが面倒なので以下のようにしてどちらにも対応できるようにすると楽です。

$site_url = __FILE__;

if( strpos( $site_url, 'xampp' ) !== false ){
	$site_url = "http://localhost/xampp/example/";
} else {
	$site_url = "http://example.com/";
}

Open Login 3.0のエラー

oauthをサポートするプラグインのOpen Loginがバージョン3.0にアップデートされていますが、残念ながら、このままでは動作しません。

Google+実行時の400 invalid_scopeエラー

一部のスコープへのアクセス権限がありません。このプロジェクトは、確認プロセスを完了するために必要な次のスコープにアクセスしようとしています: {invalid = [https://www.googleapis.com/auth/contacts]}。このスコープのいずれかを使用する必要がある場合は、確認リクエストを送信してください。

とのこと。何を言ってるのかわかりませんね。とりあえずヘルプをクリックしてください。

以下のページで登録が必要とのこと。
https://support.google.com/code/contact/oauth_app_verification

承認済みのリダイレクト URIに以下を追加。(古いバージョンではhttp://example.com/oauth2callbackだった)

http://example.com/single_sign_on/index.php?hauth.done=Google

これでもまだエラーが出続けます。
このプラグインはエラーメッセージを書き出さない設定になっているので、検証ができません。
そこでqa-open-login.phpException $eの部分を編集。
URLに追加する部分を利用して無理やり書き出してみます。

ずら~っと書き出されるが、以下の部分が肝要。

object(Exception)#14 (7) {
  ["message":protected]=>
  string(1199) "User profile request failed! Google returned an invalid response:stdClass::__set_state(array(
   'error' => 
  stdClass::__set_state(array(
     'errors' => 
    array (
      0 => 
      stdClass::__set_state(array(
         'domain' => 'usageLimits',
         'reason' => 'accessNotConfigured',
         'message' => 'Project 491600025622 is not found and cannot be used for API calls. If it is recently created, enable Google+ API by visiting https://console.developers.google.com/apis/api/plus.googleapis.com/overview?project=491600025622 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.',
         'extendedHelp' => 'https://console.developers.google.com/apis/api/plus.googleapis.com/overview?project=491600025622',
      )),
    ),

Google+ APIを有効にしろとのこと。
どうやらoauthが2.0になってから有効にしないと動作しないようになったらしい。

以下へアクセスする。
https://console.developers.google.com/apis/api/plus.googleapis.com/

APIとサービスの有効化」をクリック。
「Social API」の「Google+ API」をクリック。
タイトル横にある「有効にする」をクリック。

以上の作業で無事にGoogle+でログインできるようになる。

Facebookで何度もリダイレクトされるエラー

まずQuestion2AnswerにはデフォルトでFacebookのoauthをサポートするプラグインが同梱されています。これを削除しないとプラグインのOpen Login 3.0は有効になりません。

ただし、公式Facebookプラグインを無効にしても、以下のURLにリダイレクトされます。

http://sukegra.com/single_sign_on/index.php?qa=register&provider=Facebook&code=5#_=_

code=5」の部分がこのプラグインのエラーメッセージ。プラグインの解説によると以下の意味らしいです。

5 : Authentification failed. The user has canceled the authentication or the provider refused the connection.

どうやらユーザーがキャンセルしたか、Facebook側がキャンセルしたとのこと。
このメッセージではエラーの原因究明には何の役にもたちません。過去のバージョンでは動作していたので、恐らくFacebook側の仕様変更だろうとあたりを付けて検索していると、SDK2.2から2.3へアップデート時にトークンの渡し方がjson形式になったとか。(それまでは配列だった)

以下のファイルを編集する。

qa-plugin\q2a-open-login-master\Hybrid\thirdparty\Facebook\base_facebook.php

425行目あたり

$response_params = array();
parse_str($access_token_response, $response_params);

これを以下のように変更。

$response_params = json_decode($access_token_response, true);

842行目あたり

$response_params = array();
parse_str($access_token_response, $response_params);

これを以下のように変更。

$response_params = json_decode($access_token_response, true);

この2点を編集してアップし直す。
これでFacebookログインが可能になりました。


海外の解説を見ても「できない」という声ばかりで、解決策が示されていなかったので、作業メモを公開しました。