Skip to content

Instantly share code, notes, and snippets.

@sotarok
Created February 11, 2009 08:36
Show Gist options
  • Save sotarok/61921 to your computer and use it in GitHub Desktop.
Save sotarok/61921 to your computer and use it in GitHub Desktop.
<?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 ()
{
?&gt;
&lt;h2&gt;Hello World&lt;/h2&gt;
&lt;p&gt;This is sample program.&lt;/p&gt;
&lt;?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 &copy; 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