<repo_name>vaakonecromong/instagram_agaleski<file_sep>/htdocs/includes/functions.php
<?php

	// check if we have SSL connection
	function fnc_is_ssl() {

		// check HTTPS information	 
		if(isset($_SERVER['HTTPS'])) { 

			if('on' == strtolower($_SERVER['HTTPS'])) {
				
				return true;
			}
			
			if('1' == $_SERVER['HTTPS']) {
				
				return true;
			}
			
		} else { 
			
			// check port
			if(isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])) { 
				
				return true;
			}
		}
		
		return false;
	}

	// get url scheme
	function fnc_url_scheme() {

		$scheme = fnc_is_ssl() ? 'https://' : 'http://';
		return $scheme;
	}

?><file_sep>/htdocs/callback.php
<?php
	session_start();

	require_once('includes/functions.php');
	require_once('includes/instagram.php');

	$instagram = new chc_instagram();
	$schame = fnc_url_scheme();

	// if no instagram code
	if(!isset($_GET['code'])){

		// we have some instagram fail
		$_SESSION['instagram_authorized'] = false;
		// go back to homepage
		header('location: '.$schame.$_SERVER['HTTP_HOST']);
	}

	// in other case we are authorized
	$_SESSION['instagram_authorized'] = true;
	$_SESSION['instagram_code'] = $_GET['code'];
	// go back to homepage
	header('location: '.$schame.$_SERVER['HTTP_HOST']);
?><file_sep>/readme.md
# Instagram API Task

- Simple PHP application<file_sep>/htdocs/index.php
<?php
	session_start();
	ob_start();

	require_once('includes/functions.php');
	require_once('includes/instagram.php');

	$schame = fnc_url_scheme();
	$instagram_data = null;
	$file_created = false;
	$file_name = 'result.csv';

	// sort instagram post by likes count, descending order
	function sort_data($a, $b) {

		return $b->likes->count > $a->likes->count;
	}

	// convert instagram post data to array for CSV file
	function convert_obj_to_array($obj) {

		$a = array();
		$a['id'] = $obj->id;
		$a['type'] = $obj->type;
		$a['created_time'] = $obj->created_time;
		$a['link'] = $obj->link;
		$a['likes'] = $obj->likes->count;
		$a['comments'] = $obj->comments->count;
		$a['filter'] = $obj->filter;
		$a['thumbnail_url'] = $obj->images->thumbnail->url;

		return $a;
	}

	// if user clicks "get instagram results"
	if(isset($_POST['get_instagram_results'])) {

		// unset trigger, prvent data resubmiting alert
		unset($_POST['get_instagram_results']);
		// set trigger in session data
		$_SESSION['can_authorize'] = true;
		// redirect to homepage with clear $_POST table
		header('location: '.$schame.$_SERVER['HTTP_HOST']);
	}

	// if we can start to try authorize
	if(isset($_SESSION['can_authorize'])) {

		// create Instagram API object
		$instagram = new chc_instagram();

		// try authorize user
		if(!isset($_SESSION['instagram_authorized'])) {

			$instagram->authorize();
		} else {

			// if user authorized
			if(true === $_SESSION['instagram_authorized'] and isset($_SESSION['instagram_code'])) {

				// get access token
				$data = $instagram->get_access_token($_SESSION['instagram_code']);
				// if access token granted store it in session data
				if(is_object($data) and isset($data->access_token)) {

					$_SESSION['instagram_access_token'] = $data->access_token;
				}
			} else {

				// TODO: authorization fail, display some information to user
				// now we cam just reset data, to give user next chance for authorization, with next page refresh
				session_unset();
				session_destroy();
			}
		}

		// do we have access token?
		if(isset($_SESSION['instagram_access_token'])) {
			
			// if yes we can get post from instragram.com,
			// in sandbox mode there is no possible to get more then 20 posts, or use pagination,
			// so even we will get pagination data from instagram, but this data is not complete and 
			// is just useless for next API call
			$data = $instagram->get_tag_media('natural', 100, $_SESSION['instagram_access_token']);

			// so if we have some real post data
			if(is_object($data) and (isset($data->data) and count($data->data))) {

				// sort posts by likes count, descenting
				usort($data->data, 'sort_data');
				// copy temp data to global variable
				$instagram_data = $data;

				// ok, open/create CVS file
				$file = fopen($file_name, 'w');

				// simple counter
				$counter = 0;
				// for each post from instagram
				foreach($instagram_data->data as $obj) {

					// cover it to associative array
					$a = convert_obj_to_array($obj);

					// if first post, before data write, add to file some columns information
					if(!$counter) {

						fputcsv($file, array_keys($a));	
					}

					// store post data
				    fputcsv($file, array_values($a));
				    $counter++;
				}

				// close file
				fclose($file);
				$file_created = true;
			}

			// destroy session data, for next page refresh, test demo
			session_unset();
			session_destroy();
		}

	}
?>

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<meta name="format-detection" content="telephone=no">
		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
		<title>Instagram API</title>
		<meta name="description" content="Tutorial PHP application.">
		<meta name="keywords" content="Instagram API, CSV, PHP">
		<link rel="icon" href="img/favicon.png">
		<link href="https://fonts.googleapis.com/css?family=Barlow+Condensed:300,400,500,600,700" rel="stylesheet">
		<link rel="stylesheet" href="css/style.css" type="text/css" media="all">
		<script src="js/library/jquery-3.2.1.min.js"></script>
		<script src="js/main.js"></script>
	</head>
	<body>

		<!-- HEADER -->
		<header class="ch-header">
			<div class="wrap-cnt">
				<div class="cnt">
					<h1 class="title">Create a small PHP App using the <span class="color">​Instagram&nbsp;API</span>,​​<br class="hidden"> which receives 100 results for the hashtag<br> <span class="color">​#natural</span></h1>
					<h2 class="subtitle">The application should sort the results by the number of likes<br class="hidden"> and save them to a <span class="color">.CSV</span> file.</h2>
				</div>
			</div>
		</header>

		<!-- ACTION FORM -->
		<section class="ch-action-form">
			<div class="wrap-cnt">
				<div class="cnt">
					<form class="form" action="" method="post">
						<div class="interfce">

							<?php if($file_created) { ?>

								<div class="wrap-control">
									<div class="control">
										<div class="file-logo">
											<div class="logo csv"></div>
										</div>
										<a class="btn btn-download" href="<?php echo $file_name; ?>" download="<?php echo $file_name; ?>">Download result as CSV file</a>
									</div>
								</div>

							<?php } else { ?>

								<div class="wrap-control">
									<div class="control">
										<div class="loader-spinner">
											<div class="spinner"></div>
										</div>										
										<button type="submit" class="btn btn-get" name="get_instagram_results">Get instagram results</button>
									</div>
								</div>

							<?php } ?>									

						</div>
					</form>
				</div>
			</div>
		</section>

		<!-- INSTAGRAM RESULT -->

		<?php 
			// do we have some instagram data?
			if(!is_null($instagram_data)) { 
		?>
		
			<section class="ch-instagram-result">
				<div class="wrap-cnt">
					<div class="cnt">

						<?php 
							
							// do we have post data
							if(isset($instagram_data->data) and count($instagram_data->data)) {

								// store output on the side
								$out = '';
								$out .= '<div class="list">';

									// for each post
									foreach($instagram_data->data as $post) {

										$out .= '<div class="item">';
											$out .= '<div class="item-cnt">';

												// show image as link to oryginal instagram.com post
												$out .= '<figure class="image">';
													$out .= '<a href="'.$post->link.'" target="_blank">';
														$out .= '<img src="'.$post->images->low_resolution->url.'">';
													$out .= '</a>';
												$out .= '</figure>';

												// show number of likes
												$out .= '<div class="likes">';
													$postfix = ($post->likes->count == 1) ? 'like' : 'likes';
													$out .= '<h6 class="count">'.$post->likes->count.'&nbsp'.$postfix.'</h6>';
												$out .= '</div>';
											$out .= '</div>';											

										$out .= '</div>';
									}

								$out .= '</div>';
								echo $out;
							}
						?>

					</div>
				</div>
			</section>

		<?php } ?>


		<!-- FOOTER -->
		<footer class="ch-footer">
			<div class="wrap-cnt">
				<div class="cnt">
					<h6 class="copyright">Demo by <NAME></h1>
				</div>
			</div>
		</footer>

	</body>
</html>

<?php 

	$cnt = ob_get_clean();
	echo $cnt;
?><file_sep>/htdocs/includes/instagram.php
<?php

class chc_instagram {

	// some private data
	private $INSTAGRAM_CLIENT_ID = '4a5f1c7815a444468ed4f019c625594a';
	private $INSTAGRAM_CLIENT_SECRET = '08572eeeae424d57951afe4569c668ab';
	private $INSTAGRAM_API_URL = 'https://api.instagram.com/v1/';
	private $INSTAGRAM_API_OAUTH_URL = 'https://api.instagram.com/oauth/authorize';
	private $INSTAGRAM_API_OAUTH_ACCESS_TOKEN_URL = 'https://api.instagram.com/oauth/access_token';
	private $INSTAGRAM_REDIRECT_URL = '';

	// constructor
	public function __construct() {

		// create callback URL
		$this->INSTAGRAM_REDIRECT_URL = fnc_url_scheme().$_SERVER['HTTP_HOST'].'/callback.php';		
	}

	// authorize user
	public function authorize() {

		$url = $this->INSTAGRAM_API_OAUTH_URL.'?client_id='.$this->INSTAGRAM_CLIENT_ID.'&redirect_uri='.urlencode($this->INSTAGRAM_REDIRECT_URL).'&scope=public_content'.'&response_type=code';
		header('location:'.$url);
	}
 
	// get access token
	public function get_access_token($code) {

		$params = array();
		$params['client_id'] = $this->INSTAGRAM_CLIENT_ID;
		$params['client_secret'] = $this->INSTAGRAM_CLIENT_SECRET;
		$params['grant_type'] = 'authorization_code';
		$params['redirect_uri'] = $this->INSTAGRAM_REDIRECT_URL;
		$params['code'] = $code;

		$curl = curl_init();
		curl_setopt($curl, CURLOPT_URL, $this->INSTAGRAM_API_OAUTH_ACCESS_TOKEN_URL);
		curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json'));
		curl_setopt($curl, CURLOPT_POST, count($params));
		curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));        
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
		
		$result = curl_exec($curl);
		$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);

		curl_close($curl);

		return json_decode($result);
	}

	// get recent instagram media by tag name
	public function get_tag_media($tag, $count, $access_token) {

		$params = array();
		$params['access_token'] = $access_token;
		$params['count'] = $count;

		$curl = curl_init();
		curl_setopt($curl, CURLOPT_URL, $this->INSTAGRAM_API_URL.'tags/'.$tag.'/media/recent?'.http_build_query($params));
		curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json'));
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

		$result = curl_exec($curl);
		$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
		
		curl_close($curl);

		return json_decode($result);
	}
}