<?php
class Fotolia_Api{
	const FOTOLIA_REST_URI = 'api.fotolia.com/Rest/1';
	const LANGUAGE_ID_FR_FR = 1;
	const LANGUAGE_ID_EN_US = 2;
	const LANGUAGE_ID_EN_GB = 3;
	const LANGUAGE_ID_DE_DE = 4;
	const LANGUAGE_ID_ES_ES = 5;
	const LANGUAGE_ID_IT_IT = 6;
	const LANGUAGE_ID_PT_PT = 7;
	const LANGUAGE_ID_PT_BR = 8;
	const LANGUAGE_ID_JA_JP = 9;
	const LANGUAGE_ID_PL_PL = 11;
	const LANGUAGE_ID_RU_RU = 12;
	const LANGUAGE_ID_ZH_CN = 13;
	const LANGUAGE_ID_TR_TR = 14;
	const LANGUAGE_ID_KO_KR = 15;
	private $_api_key;
	public function __construct( $api_key ){
		$this->_api_key = $api_key;
	}
	/**
	 * This method makes possible to search media in fotolia image bank.
	 * Full search capabilities are available through the API
	 *
	 * @param  array  $search_params
	 * @param  array  $result_columns if specified, a list a columns you want in the resultset
	 * @return array
	 */
	public function getSearchResults( array $search_params, array $result_columns = NULL ){
		return $this->_api( 'getSearchResults', array( 'search_parameters' => $search_params, 'result_columns' => $result_columns ) );
	}
	/**
	 * This method returns childs of a parent category in fotolia representative category system.
	 * This method could be used to display a part of the category system or the all tree.
	 * Fotolia categories system counts three levels.
	 *
	 * @param  int    $language_id
	 * @param  int    $id
	 * @param  int    $category_type_id
	 * @return array
	 */
	public function getCategories1( $language_id = Fotolia_Api::LANGUAGE_ID_EN_US, $id = 0 ){
		return $this->_api( 'getCategories1', array( 'language_id' => $language_id, 'id' => $id, ) );
	}
	/**
	 * This method returns childs of a parent category in fotolia conceptual category system.
	 * This method could be used to display a part of the category system or the all tree.
	 * Fotolia categories system counts three levels.
	 *
	 * @param  int    $language_id
	 * @param  int    $id
	 * @return array
	 */
	public function getCategories2( $language_id = Fotolia_Api::LANGUAGE_ID_EN_US, $id = 0 ){
		return $this->_api( 'getCategories2', array( 'language_id' => $language_id, 'id' => $id, ) );
	}
	/**
	 * This method returns most searched tag and most used tag on fotolia website.
	 * This method may help you to create a tags cloud.
	 *
	 * @param  int    $language_id
	 * @param  string $type
	 * @return array
	 */
	public function getTags( $language_id = Fotolia_Api::LANGUAGE_ID_EN_US, $type = 'Used' ){
		return $this->_api( 'getTags', array( 'language_id' => $language_id, 'type' => $type ) );
	}
	/**
	 * This method returns public galleries for a defined language
	 *
	 * @param  int    $language_id
	 * @return array
	 */
	public function getGalleries( $language_id = Fotolia_Api::LANGUAGE_ID_EN_US ){
		return $this->_api( 'getGalleries', array( 'language_id' => $language_id ) );
	}
	/**
	 * This method returns childs of a parent colors in the Fotolia color scheme.
	 * If no parent is provided first level colors are returned.
	 * This method can be used to display color and subcolors for color search queries.
	 *
	 * @param  int    $id
	 * @return array
	 */
	public function getColors( $id = '' ){
		return $this->_api( 'getColors', array( 'id' => $id, ) );
	}
	/**
	 * This method returns Fotolia list of countries.
	 *
	 * @param  int    $language_id
	 * @return array
	 */
	public function getCountries( $language_id = Fotolia_Api::LANGUAGE_ID_EN_US ){
		return $this->_api( 'getCountries', array( 'language_id' => $language_id, ) );
	}
	/**
	 * This method returns fotolia data
	 *
	 * @return array
	 */
	public function getData( ){
		return $this->_api( 'getData', array( ) );
	}
	/**
	 * This method is a test method which returns success if connexion is valid
	 *
	 * @return array
	 */
	public function test( ){
		return $this->_api( 'test', array( ) );
	}
	/**
	 * This method return all information about a media
	 *
	 * @param  int    $id
	 * @param  int    $thumbnail_size
	 * @param  int    $language_id
	 * @return array
	 */
	public function getMediaData( $id, $thumbnail_size = 110, $language_id = Fotolia_Api::LANGUAGE_ID_EN_US ){
		return $this->_api( 'getMediaData', array( 'id' => $id, 'thumbnail_size' => $thumbnail_size, 'language_id' => $language_id, ) );
	}
	/**
	 * This method return private galleries for logged user
	 *
	 * @param  int    $id
	 * @param  int    $language_id
	 * @param  int    $thumbnail_size
	 * @return array
	 */
	public function getMediaGalleries( $id, $language_id = Fotolia_Api::LANGUAGE_ID_EN_US, $thumbnail_size = 110 ){
		return $this->_api( 'getMediaGalleries', array( 'id' => $id, 'language_id' => $language_id, 'thumbnail_size' => $thumbnail_size, ) );
	}
	/**
	 * This method allows to purchase a media and returns url to the purchased file
	 *
	 * @param  int    $id
	 * @param  string $license_name
	 * @param  int    $subaccount_id
	 * @return array
	 */
	public function getMedia( $id, $license_name, $subaccount_id = NULL ){
		return $this->_api( 'getMedia', array( 'id' => $id, 'license_name' => $license_name, 'subaccount_id' => $subaccount_id, ) );
	}
	/**
	 * Download a media and write it to a file if necessary
	 *
	 * @param  string $download_url URL as returned by getMedia()
	 * @param  string $output_file if null the downloaded file will be echoed on standard output
	 */
	public function downloadMedia( $download_url, $output_file = NULL ){
		$ch = $this->_getCurlHandler( $download_url );
		if( $output_file === NULL ){
			$output_file = 'php://stdout';
		}
		$output_fd = fopen( $output_file, 'w' );
		if( $output_fd === FALSE ){
			throw new Fotolia_Api_Exception( 'Cannot open ' . $output_file . ' for writing' );
		}
		curl_setopt( $ch, CURLOPT_FILE, $output_fd );
		curl_setopt( $ch, CURLOPT_USERPWD, $this->_getHttpAuth( TRUE, TRUE ) );
		$response = curl_exec( $ch );
		fclose( $output_fd );
		if( !$response ){
			throw new Fotolia_Api_Exception( 'Failed to reach URL "' . $uri . '": ' . curl_error( $ch ) );
		}
		$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
		$content_type = curl_getinfo( $ch, CURLINFO_CONTENT_TYPE );
		curl_close( $ch );
		if( empty( $content_type ) ){
			throw new Fotolia_Api_Exception( 'Invalid response, no content type returned' );
		}
		if( strstr( $content_type, ';' ) !== FALSE ){
			list( $content_type, $charset ) = explode( ';', $content_type );
		}
		list( $major_mime, $minor_mime ) = explode( '/', $content_type );
		if( $major_mime == 'application' ){
			if( $minor_mime == 'json' ){
				$res = json_decode( $response, TRUE );
				if( isset( $res['error'] ) ){
					throw new Fotolia_Api_Exception( $res['error'], !empty( $res['code'] ) ? $res['code'] : 0 );
				}
			}
			throw new Fotolia_Api_Exception( 'Unknown API error' );
		} elseif( $http_code != 200 ){
			throw new Fotolia_Api_Exception( 'Invalid response HTTP code: ' . $http_code );
		}
	}
	/**
	 * This method returns comp images. Comp images can ONLY be used to evaluate the image
	 * as to suitability for a project, obtain client or internal company approvals,
	 * or experiment with layout alternatives.
	 *
	 * @param  int    $id
	 * @return array
	 */
	public function getMediaComp( $id ){
		return $this->_api( 'getMediaComp', array( 'id' => $id, ) );
	}
	protected function _api( $method, $params ){
		$url = 'http://' . Fotolia_Api::FOTOLIA_REST_URI . '/' . $this->_getNamespace( $method ) . '/' . $method;
		if( is_array( $params ) && !empty( $params ) ){
			$url.= '?';
			$sParams = null;
			foreach( $params as $sParamName => $sParamValue ){
				if( is_array( $sParamValue ) ){
					foreach( $sParamValue as $sSubParamName => $sSubParamValue ){
						$sParams.= '&' . $sParamName . '[' . $sSubParamName . ']=' . $sSubParamValue;
					}
				} else{
					$sParams.= '&' . $sParamName . '=' . $sParamValue;
				}
			}
			$url.= substr( $sParams, 1 );
		}
		return json_decode( $this->_getUrlContents( $url, false, $this->_api_key ), true );
	}
	protected function _getNamespace( $method ){
		switch( $method ){
			case 'getSearchResults':
			case 'getCategories1':
			case 'getCategories2':
			case 'getTags':
			case 'getGalleries':
			case 'getColors':
			case 'getCountries':
				return 'search';
			case 'getMediaData':
			case 'getMediaGalleries':
			case 'getMedia':
			case 'getMediaComp':
				return 'media';
			case 'loginUser':
			case 'refreshToken':
			case 'logoutUser':
			case 'getUserData':
			case 'getUserGalleries':
			case 'getUserGalleryMedias':
			case 'deleteUserGallery':
			case 'createUserGallery':
			case 'addToUserGallery':
			case 'removeFromUserGallery':
			case 'moveUpMediaInUserGallery':
			case 'moveDownMediaInUserGallery':
			case 'moveMediaToTopInUserGallery':
			case 'getUserAdvancedStats':
			case 'getUserStats':
				return 'user';
			case 'getData':
			case 'test':
				return 'main';
			case 'user/subaccount/create':
			case 'user/subaccount/edit':
			case 'user/subaccount/delete':
			case 'user/subaccount/getIds':
			case 'user/subaccount/get':
			case 'user/subaccount/getPurchasedContents':
			case 'shoppingcart/getList':
			case 'shoppingcart/add':
			case 'shoppingcart/update':
			case 'shoppingcart/remove':
			case 'shoppingcart/clear':
				return '';
			default:
				throw new Fotolia_Api_Exception( 'Unknown or unsuported method: ' . $method );
		}
	}
	protected function _getUrlContents( $url, $file_path = null, $login = null, $pass = null ){
		$requestcounter = 0;
		$httpcode = null;
		do{
			$requestcounter++;
			if( $requestcounter > 5 ) die( 'Over 5 requests - possibly an error occured: ' . $url );
			if( !empty( $httpcode ) && ( $httpcode != 401 ) && ( $httpcode < 300 || $httpcode > 400 ) ){
				echo ( 'Error during downloading file - unhandled response status' );
				echo ( '<pre>' );
				echo ( $headers );
				echo ( '</pre>' );
				die( );
			}
			if( $httpcode >= 300 && $httpcode < 400 ){
				if( preg_match( '/^Location: (http\:\\/\\/([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(\\/($|[a-zA-Z0-9\.\,\?\'\\\+&amp;%\$#\=~_\-]+))*)/m', $headers, $matches ) ) $url = $matches[1];
				else die( 'Invalid redirection!' );
			}
			$url_parsed = parse_url( $url );
			$host = $url_parsed['host'];
			if( $url == '' || $host == '' ){
				return false;
			}
			$port = ( empty( $url_parsed['port'] ) ? 80 : $url_parsed['port'] );
			$path = ( empty( $url_parsed['path'] ) ? '/' : $url_parsed['path'] );
			$path.= ( !empty( $url_parsed['query'] ) ? '?' . $url_parsed['query'] : '' );
			$out = "GET " . $path . " HTTP/1.0\r\nHost: " . $host . "\r\n";
			if( $httpcode == 401 ){
				if( !empty( $login ) ) $out.= 'Authorization: Basic ' . base64_encode( $login . ':' . $pass ) . "\r\n";
				else die( 'Authentication required, but no username and password supplied!' );
			}
			$out.= "Connection: Close\r\n\r\n";
			$fp = fsockopen( $host, $port, $errno, $errstr, 30 );
			fwrite( $fp, $out );
			$headers = '';
			$content = '';
			$buf = '';
			$isBody = false;
			while( !feof( $fp ) and !$isBody ){
				$buf = fgets( $fp );
				if( $buf == "\r\n" ){
					$isBody = true;
				} else{
					$headers.= $buf;
				}
			}
			if( preg_match( '|^HTTP/1.\\d (\\d+) |', $headers, $matches ) ) $httpcode = $matches[1];
			else die( 'Invalid server response!' );
		}
		while( $httpcode != 200 );
		if( $file_path === false ){
			$buf = '';
			while( !feof( $fp ) ){
				$buf.= fgets( $fp );
			}
			return $buf;
		} else{
			$file = fopen( empty( $file_path ) ? basename( $url_parsed['path'] ) : $file_path, 'w' );
			$bytes = stream_copy_to_stream( $fp, $file );
			fclose( $fp );
			return $bytes;
		}
	}
}
/**
 * API Exception
 */
class Fotolia_Api_Exception extends Exception{
}
