<?php

/**
 * @file
 * Nifty OAuth2 Library Memcache Implementation.
 */

include "MemcacheOAuth2.inc";

/**
 * OAuth2 Library Memcache Implementation.
 */
class PDOOAuth2 extends MemcacheOAuth2 {

	private $db;

	/**
	 * Overrides MemcacheOAuth2::__construct().
	 */
	public function __construct($config = array()) {
		parent::__construct($config);
		date_default_timezone_set('Asia/Tokyo');

		//==============================================================================
		// Initiate MySQL
		$reg_dsn = '/^DBI:mysql:database=(.*);host=(.*);port=(.*);mysql_connect_timeout=(.*)$/';
		if ($this->conf['endpoint'] == 'authorize' || $this->conf['endpoint'] == 'resource' || $this->conf['endpoint'] == 'applist_w') {
			// Database insert/update
			$arr_dsn = explode(" ", $this->conf['dsn']);
		}
		else {
			// $this->conf['endpoint'] == 'token' || $this->conf['endpoint'] == 'applist'
			// Database select
			$arr_dsn = explode(" ", $this->conf['readdsn']);
		}
		$cnt_dsn = count($arr_dsn);
		foreach($arr_dsn as $dsn) {
			$cnt++;
			// get MySQL info
			if (preg_match($reg_dsn, $dsn, $matches)) {
				$db_info_dbname = isset($matches[1]) ? $matches[1] : '';
				$db_info_host = isset($matches[2]) ? $matches[2] : '';
				$db_info_port = isset($matches[3]) ? $matches[3] : '';
				$db_info_timeout = isset($matches[4]) ? $matches[4] : 10;
			}
			if (!$db_info_dbname || !$db_info_host || !$db_info_port) {
				$this->log->crit(logformat("Get database information failed ($cnt/$cnt_dsn)"));
				if ($cnt_dsn == $cnt) {
					if ($this->conf['endpoint'] == 'authorize' || $this->conf['endpoint'] == 'applist') {
						$this->log->err(logformat("OAuth exception occured: Can't connect MySQL"));
						$this->showError('system_error04');
						exit();
					}
					$this->handleException("500 internal server error", 'system_error04');
				}
				else {
					continue;
				}
			}
			// connect to MySQL
			try {
				ini_set('mysql.connect_timeout', $db_info_timeout);
				$this->db = new PDO("mysql:host=$db_info_host;port=$db_info_port;dbname=$db_info_dbname", $this->conf['dbuser'], $this->conf['dbpasswd']);
				break;
			}
			catch (PDOException $e) {
				if ($cnt_dsn == $cnt) {
					if ($this->conf['endpoint'] == 'authorize' || $this->conf['endpoint'] == 'applist' || $this->conf['endpoint'] == 'applist_w') {
						$this->log->err(logformat("OAuth exception occured: Can't connect MySQL"));
						$this->showError('system_error04');
						exit();
					}
					$this->handleException("500 internal server error", 'system_error04');
				}
				else {
					continue;
				}
			}
		}
	}

	/**
	 * Release memcache connection during destruct.
	 */
	function __destruct() {
		$this->db = NULL; // Release db connection
	}


	/**
	 * 連携アプリをデータベースへ新規登録
	 * @param user_id			ユーザID
	 * @param service_id		サービスID
	 * @param scope				スコープ
	 * @param additional_data	入力ID
	 */
	private function addAuthorizedApps($user_id, $service_id, $scope, $additional_data = NULL) {
		$current_timestamp = "'".date("Y-m-d H:i:s")."'";
		if (preg_match('/^([^_]+)_/', $service_id, $matches)) {
			$service_id = $matches[1];
		}
		try {
			$str_sql = "INSERT INTO ".$this->conf['oauth_table']." (user_id, oauth_service_id, scope, additional_data, update_time)";
			$str_sql .= "VALUES('$user_id', '$service_id', '$scope', '$additional_data', $current_timestamp)";
			//$this->log->debug(logformat("DEBUG - PDOOAuth2.addAuthorizedApps: [ $str_sql ]"));
			$stmt = $this->db->prepare($str_sql);
			return $stmt->execute();
		}
		catch (PDOException $e) {
			return FALSE;
		}
	}

	/**
	 * 連携アプリ一覧取得
	 * @param user_id			ユーザID
	 * @param service_id		サービスID
	 * @param deleted			削除フラグ
	 */
	public function getAuthorizedApps($user_id, $service_id = NULL, $deleted = NULL) {
		try {
			$str_sql = "select * from ".$this->conf['oauth_table']." where 1 = 1 ";
			if ($user_id) {
				$str_sql .= "and user_id = :user_id ";
			}
			if ($service_id) {
				if (preg_match('/^([^_]+)_/', $service_id, $matches)) {
					$service_id = $matches[1];
				}
				$str_sql .= "and oauth_service_id = '$service_id' ";
			}
			if ($deleted !== NULL) {
				$str_sql .= "and deleted = '$deleted' ";
			}
			//$this->log->debug(logformat("DEBUG - PDOOAuth2.getAuthorizedApps: [ $str_sql ]"));
			$stmt = $this->db->prepare($str_sql);
			$stmt->bindParam(":user_id", $user_id, PDO::PARAM_STR);
			$stmt->execute();

			$result = $stmt->fetchAll();

			return $result;
		}
		catch (PDOException $e) {
			return FALSE;
		}
	}

	/**
	 * アプリ連携データ作成
	 * @param user_id			ユーザID
	 * @param service_id		サービスID
	 * @param scope				スコープ
	 * @param additional_data	入力ID
	 */
	public function createAuthorizedApps($user_id, $service_id, $scope, $additional_data = NULL) {
		$query_result = $this->getAuthorizedApps($user_id, $service_id);
		if ($query_result === FALSE) {
			return $query_result;
		}

		if (empty($query_result)) {
			$query_result = $this->addAuthorizedApps($user_id, $service_id, $scope, $additional_data);
		}
		else {
			if ($scope === NULL) {
				$scope = '';
			}
	        $query_result = $this->updateAuthorizedApps($user_id, $service_id, $scope, NULL, 0, 1, 0);
	    }
        return $query_result;
	}


	/**
	 * アプリ連携データ更新
	 * @param user_id			ユーザID
	 * @param service_id		サービスID
	 * @param deleted			削除フラグ
	 * @param update_time_flg	最終同意日
	 * @param access_time_flg	最終利用日
	 * @param contents_id		ハッシュユーザID
	 */
	public function updateAuthorizedApps($user_id, $service_id, $scope, $contents_id, $deleted = 0, $update_time_flg = 0, $access_time_flg = 1) {
		$current_timestamp = "'".date("Y-m-d H:i:s")."'";
		try {
    		$str_sql = "UPDATE ".$this->conf['oauth_table']." SET deleted = '$deleted' ";
    		if ($update_time_flg) {
    			$str_sql .= ", update_time = $current_timestamp";
    		}
    		if ($access_time_flg) {
    			$str_sql .= ", access_time = $current_timestamp";
    		}
    		if ($scope !== NULL) {
    			$str_sql .= ", scope = '$scope'";
    		}
    		if ($contents_id) {
    			$str_sql .= ", contents_id = '$contents_id'";
    		}

			if (preg_match('/^([^_]+)_/', $service_id, $matches)) {
				$service_id = $matches[1];
			}
    		$str_sql .= "WHERE user_id = '$user_id' and oauth_service_id = '$service_id'";
			//$this->log->debug(logformat("DEBUG - PDOOAuth2.updateAuthorizedApps: [ $str_sql ]"));

			$stmt = $this->db->prepare($str_sql);
			return $stmt->execute();
		}
		catch (PDOException $e) {
			return FALSE;
		}
	}

	/**
	 * アプリ連携データ論理削除
	 * @param user_id			ユーザID
	 * @param service_id		サービスID
	 * @param deleted			削除フラグ
	 */
	public function removeAuthorizedApps($user_id, $service_id) {
		$query_result = $this->updateAuthorizedApps($user_id, $service_id, NULL, NULL, '1', 0, 0);
		return $query_result;
	}


}
