<?
/*

1.1 .pug 가 .htm 에 우선함
1.0 pug 추가

0.95 viewpath 강제 설정 동작하도록

0.94 windows 환경에서도 잘 돌아가도록 함 (c://문제)

0.93_88 PATH_INFO -> REQUEST_URI 로 수정 (PATH_INFO 는 일부 우분투 php 5.3에서 안나옴)

0.92b
php 5.3에서 동작하도록 함

0.91b
Home 메소드를 지정해도 호출 안되고 바로 Home.htm 렌더링 되는 문제 해결

FLY2 프레임웍 0.9b
goal 
url에서 /view/ 삭제
리소스 없을때 에러처리
argument 기능 삭제? 표준 get, put으로만 동작X


html 과 php 가 혼합되지 않는 프레임웍
파리처럼 가벼운 프레임웍을 목표로한다
backbone.js 사용을 권장


URL http://test.com/API/crud/45/23 를 이용해서 접근할때


API.Class.php 파일이 존재할 경우
	API.Clas.php 파일 로드
	API class 의 crud 메소드 호출, args(0) 은 45 args(1) 은 23

API.Class 파일이 존재하지 않을 경우
	Index.Class.php 파일을 로드
	Index class 의 API 메소드 호출, args crud, 45, 23
	
메소드명이 존재하지 않을 경우
	execute 함수 실행
	
기본 execute 함수 동작
	메소드명에 해당하는 htm 파일을 로딩
	즉, crud.htm

layout
	#output# -> output 에서 지정한 파일로 치환 (#body#사용가능)
	##a.htm## -> 해당 부분을 a.htm으로 치환

include 
	fly 디렉토리
	project 디렉토리 (class파일 있는 디렉토리는 기본 인클루드 디렉토리가 됨)

crudskeleton override
	Create, Read, Update, Delete 순서로 closure 작성하면 됨. 
	closure에서 array 를 리턴하면 JSON 인코드 하여 클라이언트에 돌려줌
	
*/
/*
spl_autoload_register(function ($class) use ($srcPath) {
	if (
		strstr($class, 'Pug')  ||
		strstr($class, 'Jade') 
	) {
		error_log("loading $class\n");
		//die();
		include(str_replace("\\", DIRECTORY_SEPARATOR, $class) . '.php');
	}
});	
*/
spl_autoload_register(function ($class) use ($srcPath) {
	if (
		strstr($class, 'Pug') /* new name */ ||
		strstr($class, 'Jade') /* old name */
	) {
		$srcPath = __DIR__ . '/../pug/';
		include($srcPath . str_replace("\\", DIRECTORY_SEPARATOR, $class) . '.php');
	}
});

class Fly2
{
	var $args = null;
	var $documentroot = './';
	var $rootpath = '';
	var $viewpath = '';
	var $layout = null;
	var $nousephpview = null;
	var $subpages = array(); // [top=>'top.htm', bottom=>'bottom.htm'] 과 같은 방식으로 지정
	var $pug = null; // pug-php
	
	function __construct()
	{
		mb_internal_encoding("UTF-8");
	}
	
	function initialize()
	{
	}
	
	function filllayout($filename)
	{
		$html = $this->loadhtml($this->viewpath.$this->layout);
		$replace = $this->loadhtml($this->viewpath.$filename);
		
		$html = str_replace('#body#', $replace, $html); 
		$html = str_replace('#output#', $replace, $html); // #body#, #output# 둘 다 사용가능
		
		foreach ($this->subpages as $k=>$filename)
		{
			$replace = $this->loadhtml($this->viewpath.$filename);
			$html = str_replace("#$k#", $replace, $html);
		}		
		return $html;
	}
	
	function pug()
	{
		if ($this->pug == null)
			$this->pug = new Pug\Pug(array(
				prettyprint=>true
			));
		return $this->pug;
	}
	
	function loadhtml($fn)
	{
		$fn = iconv('utf-8', 'euc-kr', $fn);
		
		$html = file_get_contents($fn);
		
		if (pathinfo($fn, PATHINFO_EXTENSION) == 'pug') {
			$pug = $this->pug();
			$html = $pug->render($html);
		}
		
		if ($this->nousephpview)
		{
			return $html;
		}
		
		
		ob_start();
		
		eval(' ?>'.$this->applyTemplate($html).'<?php ');
		/*eval(' ?>'.$html.'<?php ');*/
		//include($fn);
		$html = ob_get_contents();
		ob_end_clean();
		//echo $fn;
		//echo $html;
		return $html;
	}
	
	/*
	
	function loadhtml($fn)
	{
		$fn = iconv('utf-8', 'euc-kr', $fn);
		
		$html = file_get_contents($fn);
		
		if ($this->nousephpview)
		{
			return $html;
		}
		$html = eval(' ?>'.$this->applyTemplate($html).'<?php ');
		
		
		ob_start();
		echo $html;
		//include($fn);
		$html = ob_get_contents();
		ob_end_clean();
		//echo $fn;
		//echo $html;
		return $html;
	}
	
	*/
	
	
	
	function applyTemplate($contents) {
		$tag_start			= "\{\{";
		$tag_end			= "\}\}";

		$pattern[] 		= '/'.$tag_start.'\s*([\x{ac00}-\x{d7af}a-zA-Z0-9_\[\]\'\"\.\(\)\/]+)\s*'.$tag_end.'/u'; /* {{a}} => <? $this->a ?> 로 변환 */
		$replacement[] 	= '<?= $this->\\1 ?>';
		
		$pattern[] 		= '/'.$tag_start.'\$([\x{ac00}-\x{d7af}a-zA-Z0-9_\->\[\]]+)\.([\x{ac00}-\x{d7af}a-zA-Z0-9_]+)'.$tag_end.'/u';  /* {{a.b}} => <?=a[b] ?> 로 변환 */
		$replacement[] 	= '<?= $this->\\1[\\2] ?>';
		
		$contents = preg_replace($pattern, $replacement ,$contents);
		
		return $contents;
	}
	
	function render($filename)
	{
		if ($this->layout != null)
		{
			$html = $this->filllayout($filename);
		} else
		{
			$html = $this->loadhtml($this->viewpath.$filename);
		}
			
		preg_match_all('/##.+##/', $html, $a);
		foreach($a[0] as $x)
		{
			$filename = substr($x, 2, strlen($x)-4);
			$h = $this->loadhtml($this->viewpath.$filename);
			$html = str_replace($x, $h, $html);
		}
		echo $html;
	}
	
	function get_url_no()
	{
		$strip =  basename($_SERVER[REQUEST_URI]);
		$strip = explode( "?", $strip );

		if( count($strip) > 0 )
		{
			if ($strip[0]*1 == 0)
				return null;
			return $strip[0];
		}
		return NULL;
	}
	
	function crudskeleton($create, $read, $update, $delete)
	{	
		$cmd = $_SERVER[REQUEST_METHOD];
		switch($cmd)
		{
		case 'POST':
			$a = json_decode(file_get_contents('php://input'), true);
			echo json_encode($create($a));			
			break;
			
		case 'GET':
			echo json_encode($read($this->get_url_no()));
			break;

		case 'PUT':
			$a = json_decode(file_get_contents('php://input'), true);
			echo json_encode($update($a));
			break;
			
		case 'DELETE':
			echo json_encode($delete($this->get_url_no()));
			break;
		}
	}
	
	function response($x)
	{
		if ($x instanceof PDOStatement)
		{
			$result = array();
			foreach ($x as $r)
			{
				array_push($result, $r);
			}
			echo json_encode($result);
		} else
			echo json_encode($x);
	}
	
	function execute()
	{
		$page = $this->args[0];
		//echo $page;
		//print_r($_SERVER);//this->args);
		//die();
		//if ($page == '')
			//$page = 'Home';
		if (pathinfo($page, PATHINFO_EXTENSION) == ''){
			if (file_exists($page.'.pug'))
				$fn = $page.'.pug';
			else
				$fn = $page.'.htm';
		}
		$this->render($fn);
	}	
}

class FlyApp{
	function addincludepath($path)
	{
		set_include_path(get_include_path() . PATH_SEPARATOR . $path);
	}
	
	function loadclass($uri, &$method, &$args)
	{
		$path = '../';
		$a = explode('/', $uri); // Array ( [0] => [1] => xacom [2] => KJApp [3] => UserRegister )
		$acc = '';
		$found = false;
		$method = '';
		foreach ($a as $s)
		{
			if ($s == '')
				continue;

			if (!$found)
				$viewpath = $acc;
			$acc .= '/'.$s;
			$file = $path.$acc.'.Class.php';
			//echo $file.'<br>';
			if (!$found && file_exists($file))
			{
				$found = true;
				$class = $s;
				$classpath = $acc;				
				$this->addincludepath(pathinfo($file, PATHINFO_DIRNAME));
				require_once $file;				
			} else
			if ($found)
			{
				if ($classpath.'/'.$s == $acc)
				{	
					$method = $s;
				} else
				{
					array_push($args, $s);
				}				
				//echo $acc.' found '.$method;
			}
		}
		if ($class == '')
			$class = null;
		return $class;		
	}
	function getmna()
	{
		//print_r($_SERVER);
		$a = explode('/', $_SERVER[REQUEST_URI]);
		$script_dir = explode('/', dirname($_SERVER[SCRIPT_FILENAME]));
			
		//print_r($a);	print_r($script_dir);
		$found = false;
		$mna = '/';
		foreach($a as $u)
		{
			if ($u == '')
				continue;
			//echo $u."\n";
			if (in_array($u, $script_dir) === false)
			{
				//echo "Method : $u\n";
				$found = true;
			}
			if ($found)
				$mna .= $u.'/';
		}
		$a = explode('?', $mna);
		if (count($a) > 1)
			return $a[0];
		//die($mna);
		return $mna;
	}
	function main()
	{
		$this->addincludepath('../fly2'); //fly2 와 project path를 기본 include path로
		
		$mna = $this->getmna();//$_SERVER[REQUEST_URI]; // $_SERVER[REQUEST_URI] = /xacom/KJApp/UserRegister
		//die('aaa'.$mna);
		$args = array();
		$method = '';
		
		$class = $this->loadclass($mna, $method, $args);
		if ($class == null)
		{
			$class = $this->loadclass('/Index'.$mna, $method, $args);
		}
		//die($class);
		
		$fly = new $class;
		$fly->args = $args;
		if ($fly->viewpath == '')
			$fly->viewpath = $fly->documentroot.$viewpath.'/';
		$fly->initialize();
		
		if ($method != '' /*&& $method != 'Home'*/) {
			if (method_exists($fly, $method)) {
				$fly->$method();
				return;
			}
			if(!file_exists($method.'.htm') && !file_exists($method.'.pug')) {
				header("HTTP/1.0 404 Not Found");
				die("method [$method] was not found.");	
			}
		} 		
		else
		if (method_exists($fly, 'Home'))
		{
			$fly->Home();
			return;
		} 
		if (method_exists($fly, 'execute'))
		{
			if ($method != '')
			{
				array_unshift($fly->args, $method);
			}
			$fly->execute();
		}
		/*
		if ($method != '' && method_exists($fly, $method))
			$fly->$method();
		else
		if (method_exists($fly, 'execute'))
		{
			if ($method != '')
			{
				array_unshift($fly->args, $method);
			}
			$fly->execute();
		}
		*/
	}
	function __construct()
	{
	}
}

//(new FlyApp())->main();
$app = new FlyApp();
$app->main();

?>