IT女子のお気に入りフォルダ

管理人の備忘録と実践を兼ねた(出来るだけ)役に立つ情報を配信するブログです。

[EC-CUBE 2.13]管理画面で「更新情報の取得に失敗しました」が出た時の対処

私は今回初めて見たエラーだったけど、調べてみると情報も多く、よくあるエラーのようです。

getinfo_error_01

「更新情報の取得に失敗しました」とは?

本来なら管理画面の右側に表示される更新情報を「file_get_contents()」で取得しているのですが、うまくいかず、失敗してエラーが出ているという状態です。

なのでエラー対処できたら、以下のように右側に更新情報が表示されるようになります。

getinfo_error_02

すでに紹介されている対処法はあまりおすすめ出来ない

更新情報の取得に失敗しました というメッセージが表示される

「file_get_contents()」で取得を失敗した場合に「fsockopen()」を使って更新情報を取得するという方法が、上記のコミュニティに紹介してありますが、これでは対処しきれずエラーが消えないことがあるようです。

EC-CUBEの管理画面で「更新情報の取得に失敗しました。」というエラーが出たら?

こちらの記事によると、更新情報取得後のHTTPステータスコードによる分岐でコミュニティの修正コードには想定されていない「HTTP/1.1 302 Found」が起こりうるからだそうです。

それと、classファイルを直接編集してしまっています。ここはclass_extendsの拡張クラスを編集する方が望ましいと思います。

というわけでそれらを踏まえた対処法

LC_Page_Admin_Home.phpファイルをオーバーライド

data/class/pages/admin/LC_Page_Admin_Home.php ファイルにある「lfGetInfo()」をごっそり丸ごと、コピーします。

コピー先: data/class_extends/page_extends/admin/LC_Page_Admin_Home_Ex.php

取得失敗時の分岐文追加とクラスを追加

「file_get_contents()」で取得を失敗した場合の分岐文を追加します。

/**
 * リリース情報を取得する.
 *
 * @return array 取得した情報配列
 */
public function lfGetInfo()
{
	// 更新情報の取得ON/OFF確認
	if (!ECCUBE_INFO) return array();

	// パラメーター「UPDATE_HTTP」が空文字の場合、処理しない。
	// XXX これと別に on/off を持たせるべきか。
	if (strlen(UPDATE_HTTP) == 0) return array();

	$query = '';
	// サイト情報の送信可否設定
	// XXX インストール時に問い合わせて送信可否設定を行うように設定すべきか。
	// XXX (URLは強制送信すべきではないと思うが)バージョンは強制送信すべきか。
	if (UPDATE_SEND_SITE_INFO === true) {
		$query = '?site_url=' . HTTP_URL . '&eccube_version=' . ECCUBE_VERSION;
	}

	$url = UPDATE_HTTP . $query;

	// タイムアウト時間設定
	$context = array('http' => array('timeout' => HTTP_REQUEST_TIMEOUT));

	$jsonStr = @file_get_contents($url, false, stream_context_create($context));

	// *** Error「更新情報の取得に失敗しました」対応 --- ここから
	if ( empty($jsonStr) ) {
		$jsonStr = $this->do_get($url);
	}
	// *** Error「更新情報の取得に失敗しました」対応 --- ここまで

	$arrTmpData = is_string($jsonStr) ? SC_Utils_Ex::jsonDecode($jsonStr) : null;

	if (empty($arrTmpData)) {
		SC_Utils_Ex::sfErrorHeader('>> 更新情報の取得に失敗しました。');

		return array();
	}
	$arrInfo = array();
	foreach ($arrTmpData as $objData) {
		$arrInfo[] = get_object_vars($objData);
	}

	return $arrInfo;
}

新しいクラスを2つ追加する

LC_Page_Admin_Home_Ex.phpにコピーした「lfGetInfo()」に続けて以下を追記します。

// *** Error「更新情報の取得に失敗しました」対応 --- ここから
function do_get($url) {
	$res = $this->get_contents($url);
	$res_array = explode("\r\n", $res);
	switch ($res_array[0]) {
		case 'HTTP/1.0 200 OK':
		case 'HTTP/1.1 200 OK':
			$ra = explode("\r\n\r\n", $res, 2);
			$res = $ra[1];
			break;
		case 'HTTP/1.1 302 Found':
		case 'HTTP/1.1 302 MovedTemporarily':
			foreach ($res_array as $res_row) {
				if (strstr($res_row, 'Location: ')) {
					$crr_url = str_replace('Location: ', '', $res_row);
					break;
				}
			}
			$res = $this->get_contents($crr_url);
	 
			$ra = explode("\r\n\r\n", $res, 2);
			$res = $ra[1];
			break;
		default:
			$res = '';
	}
	 
	return $res;
	 
}
 
function get_contents($url) {
	$url_array = parse_url($url);
	$host = $url_array['host'];
	$path = $url_array['path'];
	if (array_key_exists('port', $url_array)) {
		$port = $url_array['port'];
	} else {
		switch ($url_array['scheme']) {
			case 'http':
				$port = 80;
				break;
		}
	}
	$query = $url_array['query'];
	 
	$res = false;
	if (isset($host) && isset($port)) {
		$fp = fsockopen($host, $port, $errno, $errstr, 30);
		if ($fp) {
			$req
				= "GET " . $path . "?" . $query . " HTTP/1.0\r\n"
				. "Host: " . $host . "\r\n"
				. "\r\n";
			 
			socket_set_timeout($fp, 10);
			if (fputs($fp, $req, strlen($req))) {
				$res = '';
				while (!feof($fp)) {
					$res .= fgets($fp);
				}
			}
			fclose($fp);
		}
	}
	return $res;
}
// *** Error「更新情報の取得に失敗しました」対応 --- ここまで

これでOKです。