Created
February 11, 2009 08:36
-
-
Save sotarok/61921 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* | |
* The MIT License | |
* | |
* Copyright (c) 2009 Sotaro KARASAWA a.k.a. sotarok <sotaro.k [at] gmail.com> | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy | |
* of this software and associated documentation files (the "Software"), to deal | |
* in the Software without restriction, including without limitation the rights | |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the Software is | |
* furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in | |
* all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
* THE SOFTWARE. | |
* | |
* @category Framework | |
* @package Monologue Framework - An Only One File Lightweight PHP Framework | |
* @url http://monologue.nequal.jp/ | |
* @author sotarok | |
* @license The MIT License http://www.opensource.org/licenses/mit-license.php | |
* @copyright 2009 sotarok | |
*/ | |
define("DEVEL", true); | |
define("AUTO_INITIALIZE", 0x0002); | |
if (!debug_backtrace()) : | |
/** | |
* Your application controller | |
* | |
* @category Framework | |
* @package Mlg Framework | |
* @author sotarok | |
*/ | |
class AppCtl extends DefaultCtl | |
{ | |
public function __construct() | |
{ | |
parent::__construct(); | |
//$this->html_header(array('css', '')); | |
//$this->html_header(array('js', '')); | |
} | |
//public static $url = null; | |
/* | |
*/ | |
public function action_index() | |
{ | |
return array('redirect', 'sample'); | |
} | |
public function action_sample() | |
{ | |
$this->set('hello', 'Hello'); | |
$this->set('world', '<strong>World!</strong>'); // to not escaped string | |
return 'sample'; | |
} | |
public function view_sample() | |
{ | |
?> | |
<h2>Sample Page</h2> | |
<p> | |
<?php echo $this->get('hello'); ?> <?php echo $this->get('world', false); ?> <br /> | |
Congratulations! You are now installed "Single is Beautiful Framework". | |
</p> | |
<h2>How to use?</h2> | |
<ol> | |
<li>First, access <a href="<?php echo MlgCtl::$url ?>admin">admin page</a> and change admin password.</li> | |
<li>Create new page | |
<ol> | |
<li>Define action method named access URL with "action_" prefix to AppCtl class. For example: | |
<pre> | |
public function action_foo () | |
{ | |
return 'foo'; | |
}</pre> | |
</li> | |
<li>Define view method named action's returned value with "view_" prefix to AppCtl class. For example: | |
<pre> | |
public function view_foo () | |
{ | |
?> | |
<h2>Hello World</h2> | |
<p>This is sample program.</p> | |
<?php | |
}</pre> | |
</li> | |
<li> | |
Then, you can access following URL: | |
<blockquote> | |
<?php echo MlgCtl::$url ?>foo | |
</blockquote> | |
</li> | |
</ol> | |
</li> | |
</ol> | |
<h2>Links</h2> | |
<dl> | |
<dt>Single is Beautiful Framework Official Website</dt> | |
<dd><a href="http://monologue.nequal.jp/">http://monologue.nequal.jp/</a></dd> | |
<dt>Documentations</dt> | |
<dd><a href="http://monologue.nequal.jp/docs/">http://monologue.nequal.jp/docs/</a></dd> | |
<dt>Sample Applications</dt> | |
<dd><a href="http://monologue.nequal.jp/apps/">http://monologue.nequal.jp/apps/</a></dd> | |
</dl> | |
<h2>info</h2> | |
<table class="info-table"> | |
<tr><th>URL</th> | |
<td> | |
<?php echo MlgCtl::$url ?> | |
</td></tr> | |
<tr><th>Action</th> | |
<td> | |
<?php echo $this->_action ?><br /> | |
</td></tr> | |
<tr><th>Params</th> | |
<td> | |
<?php echo $this->get('param') ?><br /> | |
</td></tr> | |
<tr><th>Develper Mode</th> | |
<td> | |
<?php if (DEVEL): ?> | |
On | |
<?php else: ?> | |
Off | |
<?php endif; ?> | |
</td></tr> | |
</table> | |
<?php | |
return null; | |
} | |
} | |
endif; | |
/** | |
* Monologue Framework Controller | |
* | |
* @category Framework | |
* @package Monologue Framework | |
* @author sotarok | |
* @date 11/2/2009 | |
*/ | |
class MlgCtl | |
{ | |
const version = "0.1.0-alpha"; | |
/* | |
* singleton object of Controller | |
*/ | |
public static $singleton = null; | |
public static $__file__ = null; | |
public static $__script__ = null; | |
public static $__data__ = null; | |
/* | |
*/ | |
public static $url = null; | |
public static $time = null; | |
protected $_http; | |
protected $_store; | |
protected $_layout; | |
protected $_action = null; | |
protected $_action_args = array(); | |
protected $_html_header = array(); | |
protected $_view_val = array(); | |
protected $_view_content = ""; | |
/** | |
* constantor | |
* | |
* @access public | |
*/ | |
public function __construct() | |
{ | |
self::$__file__ = file_get_contents(__FILE__); | |
self::$__script__ = substr(self::$__file__, 0, strpos(self::$__file__, "__" . "halt_compiler();") + 19) . "\n"; | |
self::$__data__ = trim(substr(self::$__file__, strpos(self::$__file__, "__" . "halt_compiler();") + 19)); | |
$this->_store = new MlgStore($this); | |
// TODO | |
//$this->logger = new MlgLogger($this); | |
if (self::$url === null) { | |
self::$url = sprintf("http://%s%s/", $_SERVER['HTTP_HOST'], $_SERVER['SCRIPT_NAME']); | |
} | |
self::$time = time(); | |
MlgUtil::dev_mode(DEVEL); | |
} | |
/** | |
* get_instance | |
* | |
* @access public | |
* @return Object Controller Object | |
*/ | |
public static function get_instance() | |
{ | |
if (AppCtl::$singleton !== null) { | |
return AppCtl::$singleton; | |
} | |
else { | |
return new AppCtl(); | |
} | |
} | |
/** | |
* execute | |
* call action method according to access URL. | |
* | |
* @access public | |
* @return mixed string view name | |
* array view name and arguments | |
*/ | |
public function execute() | |
{ | |
// detect action name | |
list($action, $action_args) = $this->detect_action(); | |
$action_name = 'action_' . $action; | |
$post_action_name = 'post_' . $action; | |
if ($_SERVER['REQUEST_METHOD'] == 'post' && method_exists($this, $post_action_name)) { | |
$render = call_user_func_array(array($this, $post_action_name), $action_args); | |
} | |
else if (method_exists($this, $action_name)) { | |
$render = call_user_func_array(array($this, $action_name), $action_args); | |
} | |
else { | |
throw new MlgException("Not exists action"); | |
} | |
return $render; | |
} | |
/** | |
* detect_action | |
* detect action name according to URL, and mapping action arguments with URL. | |
* | |
* @access protected | |
* @return array action name and arguments | |
*/ | |
protected function detect_action() | |
{ | |
//if (is_null($_SERVER['PATH_INFO'])) { | |
if (!isset($_SERVER['PATH_INFO']) | |
|| strlen(trim($_SERVER['PATH_INFO'], '/')) == 0) { | |
return array('index', array()); | |
} | |
else { | |
$path = explode("/", trim($_SERVER['PATH_INFO'], '/')); | |
$action = array_shift($path); | |
$action_args = array(); | |
$action_args_keyword = array(); | |
if (!empty($path)) { | |
foreach ($path as $v) { | |
if (count(explode(":", $v)) >= 2) { | |
list($keyword, $value) = explode(":", $v); | |
$action_args_keyword[$keyword] = $value; | |
} | |
else { | |
$action_args[] = $v; | |
} | |
} | |
if (!empty($action_args_keyword)) { | |
$action_args[] = $action_args_keyword; | |
} | |
} | |
$this->_action = $action; | |
$this->_action_args = $action_args; | |
return array($action, $action_args); | |
} | |
} | |
public function render($view, $args = array()) | |
{ | |
if (is_null($view)) { | |
$view = 'sample'; | |
} | |
$view_name = "view_" . $view; | |
if (!method_exists($this, $view_name)) { | |
throw new MlgException("Undefined view method"); | |
} | |
ob_start(); | |
call_user_func_array(array($this, $view_name), $args); | |
$_view_content = ob_get_contents(); | |
ob_end_clean(); | |
$this->_view_content = $_view_content; | |
ob_start(); | |
$this->default_view_layout(); | |
$_view_layout = ob_get_contents(); | |
ob_end_clean(); | |
return $_view_layout; | |
} | |
public function set($name, $content) | |
{ | |
// TODO | |
// $name = hoge.fuga とか | |
return $this->_set_val($name, $content); | |
} | |
public function get($name, $escaped = true) | |
{ | |
if ($escaped) { | |
return htmlspecialchars($this->_get_val($name), ENT_QUOTES); | |
} | |
else { | |
return $this->_get_val($name); | |
} | |
} | |
private function _set_val($name, $content) | |
{ | |
$this->_view_val[$name] = $content; | |
return true; | |
} | |
private function _get_val($name) | |
{ | |
if (isset($this->_view_val[$name])) { | |
return $this->_view_val[$name]; | |
} | |
else { | |
return ""; | |
} | |
} | |
public function html_header($header = null) | |
{ | |
if ($header === null) | |
{ | |
return join("\n", $this->_html_header); | |
} | |
else { | |
$this->_html_header[] = $header; | |
} | |
} | |
public function load_css($file) | |
{ | |
if (MlgUtil::is_absolute_url($file)) | |
{ | |
$this->html_header('<link rel="stylesheet" href="'. $file .'" type="text/css" media="all" />'); | |
} | |
} | |
public function load_js($file) | |
{ | |
if (MlgUtil::is_absolute_url($file)) | |
{ | |
$this->html_header('<script type="text/javascript" src="'. $file .'"></script>'); | |
} | |
} | |
public function run() | |
{ | |
$view = $this->execute(); | |
if (is_array($view)) { | |
$view_name = array_shift($view); | |
$view_args = $view; | |
} | |
else { | |
$view_name = $view; | |
$view_args = array(); | |
} | |
$content = $this->render($view_name, $view_args); | |
$content = $this->post_filter($content); | |
echo $content; | |
/* | |
$this->pre_check(); | |
//$this->pre_filter(); | |
*/ | |
} | |
} | |
class DefaultCtl extends MlgCtl | |
{ | |
public function post_filter($content) | |
{ | |
return $content; | |
} | |
// default action, view | |
public function action_admin() | |
{ | |
return 'admin'; | |
} | |
public function action_admin_login() | |
{ | |
} | |
public function post_admin_login() | |
{ | |
} | |
public function action_page() | |
{ | |
} | |
public function view_admin() | |
{ | |
} | |
public function view_page() | |
{ | |
} | |
public function view_flush($url, $second = 5) | |
{ | |
$this->html_header(""); | |
} | |
public function view_redirect($url) | |
{ | |
if (is_null($url)) { | |
header("Location: " . MlgCtl::$url); | |
} | |
else { | |
if (MlgUtil::is_absolute_url($url)) { | |
header("Location: " . $url); | |
} | |
else { | |
header("Location: " . MlgCtl::$url . $url); | |
} | |
} | |
} | |
protected function default_view_layout() | |
{ | |
?> | |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" | |
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja"> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<meta http-equiv="Content-Style-Type" content="text/css" /> | |
<meta http-equiv="Content-Script-Type" content="text/javascript" /> | |
<meta name="robots" content="INDEX,FOLLOW" /> | |
<meta name="keywords" content="" /> | |
<meta name="description" content="" /> | |
<?php $this->load_css("http://monologue.nequal.jp/css/style.css"); ?> | |
<!-- additinal header | |
<script type="text/javascript" src="/js/script.js"></script> | |
<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="/rss" /> | |
<link rel="stylesheet" href="/css/print.css" type="text/css" media="print" /> | |
--> | |
<title>Monologue Framework</title> | |
<?php echo $this->html_header(); ?> | |
</head> | |
<body> | |
<div id="preheader"> | |
<a href="http://nequal.jp/">powered by nequal</a> | |
</div> | |
<div id="frame"> | |
<div id="container"> | |
<div id="header"> | |
<h1><a href="<?php echo MlgCtl::$url ?>">Monologue Framework</a></h1> | |
</div> | |
<div id="main"> | |
<?php echo $this->_view_content ?> | |
</div> | |
<div id="footer"> | |
<p>Copyright © 2009 sotarok with nequal, All Rights Reserved.</p> | |
<p>Powered by Monologue Framework <?php echo MlgCtl::version ?>.</p> | |
</div> | |
</div> | |
</div> | |
</body> | |
</html> | |
<?php | |
return $this->_layout; | |
} | |
} | |
class MlgUtil | |
{ | |
public static function is_absolute_url($url) | |
{ | |
if (preg_match("@^(https?|ftp)://.+@", $url)) { | |
return true; | |
} | |
else { | |
return false; | |
} | |
} | |
public static function dev_mode($bool) | |
{ | |
if ($bool) { | |
ini_set("display_errors", 1); | |
} | |
else { | |
ini_set("display_errors", 0); | |
} | |
} | |
} | |
class MlgStore | |
{ | |
protected $_ctl; | |
protected $_data = null; | |
/** | |
* default constantor | |
* | |
* @param object Mlg Controller | |
* @access public | |
*/ | |
public function __construct($ctl) | |
{ | |
$this->_ctl = $ctl; | |
$this->_wakeup_data(); | |
} | |
/** | |
* @param string namespace | |
* @oaram int max data store | |
* @access public | |
* @return boolean | |
*/ | |
public function initialize($ns = "default", $max = 50) | |
{ | |
} | |
/** | |
* @param string content | |
* @param string namespace | |
* @oaram array options | |
* @access public | |
* @return id | |
*/ | |
public function write($content, $ns = "default", $options = array(FILE_APPEND => true, AUTO_INITIALIZE => true)) | |
{ | |
if ($options[FILE_APPEND]) { | |
} | |
else { | |
} | |
return 0; | |
} | |
/** | |
* @param int record id | |
* @param string namespace | |
* @access public | |
* @return array record array | |
*/ | |
public function read($id, $ns = "default") | |
{ | |
$data = $this->read_all($ns); | |
if (array_key_exists($id, $data)) { | |
return $data[$id]; | |
} | |
else { | |
return false; | |
} | |
} | |
/** | |
* @param string namespace | |
* @access public | |
* @return array record array | |
*/ | |
public function read_all($ns = "default") | |
{ | |
if (!array_key_exists($ns, $this->_data)) { | |
throw new MlgException("There's no namespace $ns, must initialize."); | |
} | |
else { | |
return $this->_data[$ns]['data']; | |
} | |
} | |
public function __destruct() | |
{ | |
$this->_sleep_data(); | |
} | |
protected function _wakeup_data() | |
{ | |
$this->_data = unserialize(MlgCtl::$__data__); | |
} | |
protected function _sleep_data() | |
{ | |
$serialized_data = serialize($this->_data); | |
if ($serialized_data == MlgCtl::$__data__) { | |
return true; | |
} | |
else { | |
if (file_put_contents(__FILE__, MlgCtl::$__script__ . $serialized_data, LOCK_EX)) { | |
return true; | |
} | |
else { | |
return false; | |
} | |
} | |
} | |
} | |
class MlgException extends Exception | |
{ | |
} | |
// run application | |
if (!debug_backtrace()) { | |
try { | |
AppCtl::get_instance()->run(); | |
} | |
catch(MlgException $e) { | |
echo $e->getMessage(); | |
} | |
catch(Exception $e) { | |
echo $e->getMessage(); | |
} | |
} | |
__halt_compiler(); | |
a:1:{s:7:"default";a:2:{s:4:"meta";a:0:{}s:4:"data";a:0:{}}} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment