OSB enhancements to date
This commit is contained in:
4
application/classes/block.php
Normal file
4
application/classes/block.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Block extends lnApp_Block {}
|
||||
?>
|
4
application/classes/breadcrumb.php
Normal file
4
application/classes/breadcrumb.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Breadcrumb extends lnApp_Breadcrumb {}
|
||||
?>
|
50
application/classes/company.php
Normal file
50
application/classes/company.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class is for access company informaiton.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Page
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class Company {
|
||||
public static function instance() {
|
||||
return new Company;
|
||||
}
|
||||
|
||||
public static function address($ln='<br/>') {
|
||||
// @todo Company address should be calculated
|
||||
return implode($ln,array('PO Box 149','Bendigo, VIC 3550'));
|
||||
}
|
||||
|
||||
public static function contacts() {
|
||||
// @todo Company phone should be calculated
|
||||
return 'Tel: 03 5410 1135';
|
||||
}
|
||||
|
||||
public static function render() {
|
||||
echo static::name();
|
||||
echo static::address();
|
||||
echo static::contacts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HTML to render the company address
|
||||
*/
|
||||
public function __toString() {
|
||||
try {
|
||||
return static::render();
|
||||
}
|
||||
|
||||
// Display the exception message
|
||||
catch (Exception $e) {
|
||||
Kohana::exception_handler($e);
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
4
application/classes/config.php
Normal file
4
application/classes/config.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Config extends lnApp_Config {}
|
||||
?>
|
4
application/classes/controller/default.php
Normal file
4
application/classes/controller/default.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Controller_Default extends Controller_lnApp_Default {}
|
||||
?>
|
75
application/classes/controller/lnapp/default.php
Normal file
75
application/classes/controller/lnapp/default.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides the default controller for rendering pages.
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Page
|
||||
* @category Abstract/Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
abstract class Controller_lnApp_Default extends Controller {
|
||||
/**
|
||||
* Controls access to this controller.
|
||||
* Can be set to a string or an array, for example 'login' or array('login', 'admin')
|
||||
* Note that in second(array) example, user must have both 'login' AND 'admin' roles set in database
|
||||
*
|
||||
* @var boolean is authenticate required with this controller
|
||||
*/
|
||||
protected $auth_required = FALSE;
|
||||
/**
|
||||
* If redirecting to a login page, which page to redirect to
|
||||
*/
|
||||
protected $noauth_redirect = 'login';
|
||||
/**
|
||||
* Controls access for separate actions, eg:
|
||||
* 'adminpanel' => 'admin' will only allow users with the role admin to access action_adminpanel
|
||||
* 'moderatorpanel' => array('login', 'moderator') will only allow users with the roles login and moderator to access action_moderatorpanel
|
||||
*
|
||||
* @var array actions that require a valid user
|
||||
*/
|
||||
protected $secure_actions = array();
|
||||
|
||||
/**
|
||||
* Check and see if this controller needs authentication
|
||||
*
|
||||
* if $this->auth_required is TRUE, then the user must be logged in only.
|
||||
* if $this->auth_required is FALSE, AND $this->secure_actions has an array of
|
||||
* methods set to TRUE, then the user must be logged in AND a member of the
|
||||
* role.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _auth_required() {
|
||||
// If our global configurable is disabled, then continue
|
||||
if (! Kohana::Config('config.method_security'))
|
||||
return FALSE;
|
||||
|
||||
return (($this->auth_required !== FALSE && Auth::instance()->logged_in() === FALSE) ||
|
||||
(is_array($this->secure_actions) && array_key_exists($this->request->action,$this->secure_actions) &&
|
||||
Auth::instance()->logged_in($this->secure_actions[$this->request->action]) === FALSE));
|
||||
}
|
||||
|
||||
public function before() {
|
||||
parent::before();
|
||||
|
||||
// Check user auth and role
|
||||
if ($this->_auth_required()) {
|
||||
// For AJAX/JSON requests, authorisation is controlled in the method.
|
||||
if (Request::$is_ajax && $this->request->action === 'json') {
|
||||
// Nothing required.
|
||||
|
||||
// For no AJAX/JSON requests, display an access page
|
||||
} elseif (Auth::instance()->logged_in(NULL,get_class($this).'|'.__METHOD__)) {
|
||||
Request::instance()->redirect('login/noaccess');
|
||||
|
||||
} else {
|
||||
Session::instance()->set('afterlogin',Request::instance()->uri());
|
||||
Request::instance()->redirect($this->noauth_redirect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
26
application/classes/controller/lnapp/logout.php
Normal file
26
application/classes/controller/lnapp/logout.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides logout capability
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Page/Logout
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
* @also [login]
|
||||
*/
|
||||
class Controller_lnApp_Logout extends Controller {
|
||||
public function action_index() {
|
||||
# If user already signed-in
|
||||
if (Auth::instance()->logged_in()!= 0) {
|
||||
Auth::instance()->logout();
|
||||
|
||||
Request::instance()->redirect('login');
|
||||
}
|
||||
|
||||
Request::instance()->redirect('welcome/index');
|
||||
}
|
||||
}
|
||||
?>
|
279
application/classes/controller/lnapp/templatedefault.php
Normal file
279
application/classes/controller/lnapp/templatedefault.php
Normal file
@@ -0,0 +1,279 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides the default template controller for rendering pages.
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Page/Template
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
abstract class Controller_lnApp_TemplateDefault extends Controller_Template {
|
||||
/**
|
||||
* @var string page template
|
||||
*/
|
||||
public $template = 'lnapp/default';
|
||||
/**
|
||||
* @var string page media route as per [Route]
|
||||
*/
|
||||
protected $mediaroute = 'default/media';
|
||||
/**
|
||||
* @var object meta object information as per [meta]
|
||||
*/
|
||||
protected $meta;
|
||||
/**
|
||||
* Controls access to this controller.
|
||||
* Can be set to a string or an array, for example 'login' or array('login', 'admin')
|
||||
* Note that in second(array) example, user must have both 'login' AND 'admin' roles set in database
|
||||
*
|
||||
* @var boolean is authenticate required with this controller
|
||||
*/
|
||||
protected $auth_required = FALSE;
|
||||
/**
|
||||
* If redirecting to a login page, which page to redirect to
|
||||
*/
|
||||
protected $noauth_redirect = 'login';
|
||||
/**
|
||||
* Controls access for separate actions, eg:
|
||||
* 'adminpanel' => 'admin' will only allow users with the role admin to access action_adminpanel
|
||||
* 'moderatorpanel' => array('login', 'moderator') will only allow users with the roles login and moderator to access action_moderatorpanel
|
||||
*
|
||||
* @var array actions that require a valid user
|
||||
*/
|
||||
protected $secure_actions = array(
|
||||
'menu' => TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Check and see if this controller needs authentication
|
||||
*
|
||||
* if $this->auth_required is TRUE, then the user must be logged in only.
|
||||
* if $this->auth_required is FALSE, AND $this->secure_actions has an array of
|
||||
* methods set to TRUE, then the user must be logged in AND a member of the
|
||||
* role.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _auth_required() {
|
||||
// If our global configurable is disabled, then continue
|
||||
if (! Kohana::Config('config.method_security'))
|
||||
return FALSE;
|
||||
|
||||
return (($this->auth_required !== FALSE && Auth::instance()->logged_in() === FALSE) ||
|
||||
(is_array($this->secure_actions) && array_key_exists($this->request->action,$this->secure_actions) &&
|
||||
Auth::instance()->logged_in($this->secure_actions[$this->request->action]) === FALSE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the template [View] object.
|
||||
*
|
||||
* Page information is provided by [meta].
|
||||
* @uses meta
|
||||
*/
|
||||
public function before() {
|
||||
// Do not template media files
|
||||
if ($this->request->action === 'media') {
|
||||
$this->auto_render = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
parent::before();
|
||||
|
||||
// Check user auth and role
|
||||
if ($this->_auth_required()) {
|
||||
if (Kohana::$is_cli)
|
||||
throw new Kohana_Exception('Cant run :method, authentication not possible',array(':method'=>$this->request->action));
|
||||
|
||||
// If auth is required and the user is logged in, then they dont have access.
|
||||
// (We have already checked authorisation.)
|
||||
if (Auth::instance()->logged_in(NULL,get_class($this).'|'.__METHOD__)) {
|
||||
if (Config::sitemode() == Kohana::DEVELOPMENT)
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Insufficient Access'),
|
||||
'type'=>'debug',
|
||||
'body'=>Kohana::debug(array('required'=>$this->auth_required,'action'=>$this->request->action,'user'=>Auth::instance()->get_user()->username)),
|
||||
));
|
||||
|
||||
// @todo Login No Access redirects are not handled in JS?
|
||||
if (Request::$is_ajax) {
|
||||
echo _('You dont have enough permissions.');
|
||||
die();
|
||||
} else
|
||||
Request::instance()->redirect('login/noaccess');
|
||||
|
||||
} else {
|
||||
Session::instance()->set('afterlogin',Request::instance()->uri());
|
||||
Request::instance()->redirect($this->noauth_redirect);
|
||||
}
|
||||
}
|
||||
|
||||
// For AJAX calls, we dont need to render the complete page.
|
||||
if (Request::$is_ajax) {
|
||||
$this->auto_render = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Bind our template meta variable
|
||||
$this->meta = new meta;
|
||||
View::bind_global('meta',$this->meta);
|
||||
|
||||
// Our default style sheet
|
||||
Style::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'css/default.css',
|
||||
));
|
||||
|
||||
// Our default scripts
|
||||
// This is in a reverse list, since we push them to the beginging of the scripts to render.
|
||||
foreach (array('file'=>array(
|
||||
'js/jquery.cookie.js',
|
||||
'js/jquery.jstree-1.0rc.js',
|
||||
'js/jquery-1.4.2.js',
|
||||
)) as $type => $datas) {
|
||||
|
||||
foreach ($datas as $data) {
|
||||
Script::add(array(
|
||||
'type'=>$type,
|
||||
'data'=>$data,
|
||||
),TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialise our content
|
||||
$this->template->left = '';
|
||||
$this->template->content = '';
|
||||
$this->template->right = '';
|
||||
}
|
||||
|
||||
public function after() {
|
||||
if ($this->auto_render) {
|
||||
// Application Title
|
||||
$this->meta->title = 'Application Title';
|
||||
$this->template->title = '';
|
||||
|
||||
// Style Sheets Properties
|
||||
$this->meta->styles = Style::factory();
|
||||
|
||||
// Script Properties
|
||||
$this->meta->scripts = Script::factory();
|
||||
|
||||
// Application logo
|
||||
$this->template->logo = Config::logo();
|
||||
|
||||
// Link images on the header line
|
||||
$this->template->headimages = $this->_headimages();
|
||||
|
||||
// Control Line
|
||||
$this->template->control = $this->_control();
|
||||
|
||||
// System Messages line
|
||||
$this->template->sysmsg = $this->_sysmsg();
|
||||
|
||||
// Left Item
|
||||
$this->template->left = $this->_left();
|
||||
|
||||
// Right Item
|
||||
$this->template->right = $this->_right();
|
||||
|
||||
// Footer
|
||||
$this->template->footer = $this->_footer();
|
||||
|
||||
// For any ajax rendered actions, we'll need to capture the content and put it in the response
|
||||
} elseif (Request::$is_ajax && isset($this->template->content) && ! $this->request->response) {
|
||||
// @todo move this formatting to a view?
|
||||
if ($s = $this->_sysmsg() AND (string)$s) {
|
||||
$this->request->response = sprintf('<table class="sysmsg"><tr><td>%s</td></tr></table>',$s);
|
||||
} else
|
||||
$this->request->response = '';
|
||||
|
||||
# In case there any style sheets or scrpits for this render.
|
||||
$this->request->response .= Style::factory();
|
||||
|
||||
# Get the response body
|
||||
$this->request->response .= sprintf('<table class="content"><tr><td>%s</td></tr></table>',$this->template->content);
|
||||
}
|
||||
|
||||
parent::after();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default Method to call from the tree menu
|
||||
*/
|
||||
public function action_menu() {
|
||||
$this->template->content = 'See menu on tree';
|
||||
}
|
||||
|
||||
protected function _headimages() {
|
||||
HeadImages::add(array(
|
||||
'url'=>'http://dev.leenooks.net',
|
||||
'img'=>'img/forum-big.png',
|
||||
'attrs'=>array('onclick'=>"target='_blank';",'title'=>'Link')
|
||||
));
|
||||
|
||||
return HeadImages::factory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render our control menu bar
|
||||
*/
|
||||
protected function _control() {
|
||||
return Breadcrumb::factory();
|
||||
}
|
||||
|
||||
protected function _sysmsg() {
|
||||
return SystemMessage::factory();
|
||||
}
|
||||
|
||||
protected function _left() {
|
||||
return empty($this->template->left) ? Controller_Tree::js() : $this->template->left;
|
||||
}
|
||||
|
||||
protected function _right() {
|
||||
return empty($this->template->right) ? '' : $this->template->right;
|
||||
}
|
||||
|
||||
public function _footer() {
|
||||
return sprintf('© %s',Config::SiteName());
|
||||
}
|
||||
|
||||
/**
|
||||
* This action will render all the media related files for a page
|
||||
* @return void
|
||||
*/
|
||||
final public function action_media() {
|
||||
// Generate and check the ETag for this file
|
||||
$this->request->check_cache(sha1($this->request->uri));
|
||||
|
||||
// Get the file path from the request
|
||||
$file = $this->request->param('file');
|
||||
|
||||
// Find the file extension
|
||||
$ext = pathinfo($file, PATHINFO_EXTENSION);
|
||||
|
||||
// Remove the extension from the filename
|
||||
$file = substr($file, 0, -(strlen($ext) + 1));
|
||||
|
||||
// First try and find media files for the site_id
|
||||
if ($f = Kohana::find_file(sprintf('media/%s',Config::siteid()), $file, $ext)) {
|
||||
// Send the file content as the response
|
||||
$this->request->response = file_get_contents($f);
|
||||
|
||||
// If not found try a default media file
|
||||
} elseif ($f = Kohana::find_file('media', $file, $ext)) {
|
||||
// Send the file content as the response
|
||||
$this->request->response = file_get_contents($f);
|
||||
|
||||
} else {
|
||||
// Return a 404 status
|
||||
$this->request->status = 404;
|
||||
}
|
||||
|
||||
// Set the proper headers to allow caching
|
||||
$this->request->headers['Content-Type'] = File::mime_by_ext($ext);
|
||||
$this->request->headers['Content-Length'] = filesize($f);
|
||||
$this->request->headers['Last-Modified'] = date('r', filemtime($f));
|
||||
}
|
||||
}
|
||||
?>
|
110
application/classes/controller/lnapp/tree.php
Normal file
110
application/classes/controller/lnapp/tree.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends renders OSB menu tree.
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Tree
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_lnApp_Tree extends Controller_Default {
|
||||
// Our tree data
|
||||
protected $treedata;
|
||||
/**
|
||||
* @var string page media route as per [Route]
|
||||
*/
|
||||
protected static $mediaroute = 'default/media';
|
||||
|
||||
public function after() {
|
||||
parent::after();
|
||||
|
||||
$this->request->headers['Content-Type'] = 'application/json';
|
||||
$this->request->response = sprintf('[%s]',json_encode($this->treedata));
|
||||
}
|
||||
|
||||
public static function js() {
|
||||
$mediapath = Route::get(static::$mediaroute);
|
||||
|
||||
return '
|
||||
<div id="tree" class=""></div>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
$("#tree").jstree({
|
||||
themes : {
|
||||
"theme" : "default",
|
||||
"url" : "'.URL::site($mediapath->uri(array('file'=>'css/jquery.jstree.css'))).'",
|
||||
},
|
||||
ui : {
|
||||
"select_limit" : 1,
|
||||
"select_node" : false,
|
||||
},
|
||||
cookies : {
|
||||
"save_selected" : false,
|
||||
},
|
||||
json_data : {
|
||||
"correct_state" : "true",
|
||||
"progressive_render" : "true",
|
||||
"ajax" : {
|
||||
"url" : "'.URL::site('/tree/json').'",
|
||||
"data" : function (n) {
|
||||
return { id : n.attr ? n.attr("id") : "N_"+0 };
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins : [ "themes", "json_data", "ui", "cookies" ],
|
||||
});
|
||||
|
||||
// On selection
|
||||
$("#tree").bind("select_node.jstree", function (e, data) {
|
||||
if (a = data.rslt.obj.attr(\'id\').indexOf(\'_\')) {
|
||||
id = data.rslt.obj.attr(\'id\').substr(a+1);
|
||||
|
||||
if (href = $("#N_"+id).attr("href"))
|
||||
$("#ajBODY").load(href, function(r,s,x) {
|
||||
if (s == "error") {
|
||||
var msg = "Sorry but there was an error: ";
|
||||
$("#ajBODY").html(msg + x.status + " " + x.statusText + r);
|
||||
}
|
||||
});
|
||||
else
|
||||
alert("Unknown: "+id+" HREF:"+href);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the Tree Menu
|
||||
*
|
||||
* The incoming ID is either a Branch B_x or a Node N_x
|
||||
* Where X is actually the module.
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
public function action_json($id=null) {
|
||||
if ($this->_auth_required()) {
|
||||
$this->treedata = array('attr'=>array('id'=>'a_login'),
|
||||
'data'=>array('title'=>_('Please Login').'...','attr'=>array('id'=>'login','href'=>URL::site('/login'))));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->treedata = array();
|
||||
$data = array();
|
||||
|
||||
foreach ($data as $branch) {
|
||||
array_push($this->treedata,array(
|
||||
'attr'=>array('id'=>sprintf('B_%s',$branch['id'])),
|
||||
'state'=>$branch['state'],
|
||||
'data'=>array('title'=>$branch['name']),
|
||||
'attr'=>array('id'=>sprintf('N_%s',$branch['id']),'href'=>empty($branch['attr_href']) ? URL::site(sprintf('/%s/menu',$branch['name'])) : $branch['attr_href']),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
209
application/classes/controller/login.php
Normal file
209
application/classes/controller/login.php
Normal file
@@ -0,0 +1,209 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides login capability
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Page/Login
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
* @also [logout]
|
||||
*/
|
||||
class Controller_Login extends Controller_TemplateDefault {
|
||||
public function action_index() {
|
||||
// If user already signed-in
|
||||
if (Auth::instance()->logged_in()!= 0) {
|
||||
// Redirect to the user account
|
||||
Request::instance()->redirect('welcome/index');
|
||||
}
|
||||
|
||||
// If there is a post and $_POST is not empty
|
||||
if ($_POST) {
|
||||
// Instantiate a new user
|
||||
$user = ORM::factory('account');
|
||||
|
||||
// Check Auth
|
||||
$status = $user->login($_POST);
|
||||
|
||||
// If the post data validates using the rules setup in the user model
|
||||
if ($status) {
|
||||
// Redirect to the user account
|
||||
if ($redir = Session::instance()->get('afterlogin')) {
|
||||
Session::instance()->delete('afterlogin');
|
||||
Request::instance()->redirect($redir);
|
||||
|
||||
} else
|
||||
Request::instance()->redirect('welcome/index');
|
||||
|
||||
} else {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Invalid username or password'),
|
||||
'type'=>'error',
|
||||
'body'=>_('The username or password was invalid.')
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Login to server'),
|
||||
'body'=>View::factory('login'),
|
||||
'style'=>array('css/login.css'=>'screen'),
|
||||
));
|
||||
|
||||
$this->template->control = HTML::anchor($this->request->uri(),'Login',array('id'=>'ajxbody'));
|
||||
$this->template->content = Block::factory();
|
||||
|
||||
Script::add(array('type'=>'stdin','data'=>'
|
||||
$(document).ready(function() {
|
||||
$("#ajxbody").click(function() {$("#ajBODY").load("'.$this->request->uri().'/"); return false;});
|
||||
});'
|
||||
));
|
||||
}
|
||||
|
||||
public function action_register() {
|
||||
// If user already signed-in
|
||||
if (Auth::instance()->logged_in()!= 0) {
|
||||
// Redirect to the user account
|
||||
Request::instance()->redirect('welcome/index');
|
||||
}
|
||||
|
||||
// Instantiate a new user
|
||||
$account = ORM::factory('account');
|
||||
|
||||
// If there is a post and $_POST is not empty
|
||||
if ($_POST) {
|
||||
// Check Auth
|
||||
$status = $account->values($_POST)->check();
|
||||
|
||||
if (! $status) {
|
||||
foreach ($account->validate()->errors() as $f=>$r) {
|
||||
// $r[0] has our reason for validation failure
|
||||
switch ($r[0]) {
|
||||
// Generic validation reason
|
||||
default:
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Validation failed'),
|
||||
'type'=>'error',
|
||||
'body'=>sprintf(_('The defaults on your submission were not valid for field %s (%s).'),$f,$r[0])
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ido = ORM::factory('module')
|
||||
->where('name','=','account')
|
||||
->find();
|
||||
|
||||
$account->id = $ido->record_id->next_id($ido->id);
|
||||
// Save the user details
|
||||
if ($account->save()) {}
|
||||
|
||||
}
|
||||
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Already have an account?'),
|
||||
'type'=>'info',
|
||||
'body'=>_('If you already have an account, please login..')
|
||||
));
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Register'),
|
||||
'body'=>View::factory('bregister')
|
||||
->set('account',$account)
|
||||
->set('errors',$account->validate()->errors()),
|
||||
'style'=>array('css/bregister.css'=>'screen'),
|
||||
));
|
||||
|
||||
$this->template->control = HTML::anchor($this->request->uri(),'Register',array('id'=>'ajxbody'));
|
||||
$this->template->content = Block::factory();
|
||||
$this->template->left = HTML::anchor('login','Login').'...';
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable user password reset
|
||||
*/
|
||||
public function action_reset() {
|
||||
// If user already signed-in
|
||||
if (Auth::instance()->logged_in()!= 0) {
|
||||
// Redirect to the user account
|
||||
Request::instance()->redirect('welcome/index');
|
||||
}
|
||||
|
||||
// If the user posted their details to reset their password
|
||||
if ($_POST) {
|
||||
// If the email address is correct, create a method token
|
||||
if (! empty($_POST['email']) AND ($ao=ORM::factory('account',array('email'=>$_POST['email']))) AND $ao->loaded()) {
|
||||
$mt = ORM::factory('module_method_token');
|
||||
|
||||
// Find out our password reset method id
|
||||
// @todo move this to a more generic method, so that it can be called by other methods
|
||||
$mo = ORM::factory('module',array('name'=>'account'));
|
||||
$mmo = ORM::factory('module_method',array('name'=>'user_resetpassword','module_id'=>$mo->id));
|
||||
|
||||
// Check to see if there is already a token, if so, do nothing.
|
||||
if ($mt->where('account_id','=',$ao->id)->and_where('method_id','=',$mmo->id)->find()) {
|
||||
if ($mt->date_expire < time()) {
|
||||
$mt->delete();
|
||||
$mt->clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (! $mt->loaded()) {
|
||||
$mt->account_id = $ao->id;
|
||||
$mt->method_id = $mmo->id;
|
||||
$mt->date_expire = time() + 15*3600;
|
||||
$mt->token = md5(sprintf('%s:%s:%s',$mt->account_id,$mt->method_id,$mt->date_expire));
|
||||
$mt->save();
|
||||
|
||||
// Send our email with the token
|
||||
$et = EmailTemplate::instance('account_reset_password');
|
||||
$et->to = array($mt->account->email=>sprintf('%s %s',$mt->account->first_name,$mt->account->last_name));
|
||||
$et->variables = array(
|
||||
'SITE'=>URL::base(TRUE,TRUE),
|
||||
'SITE_ADMIN'=>Config::sitename(),
|
||||
'SITE_NAME'=>Config::sitename(),
|
||||
'TOKEN'=>$mt->token,
|
||||
'USER_NAME'=>sprintf('%s %s',$mt->account->first_name,$mt->account->last_name),
|
||||
);
|
||||
$et->send();
|
||||
}
|
||||
|
||||
// Redirect to our password reset, the Auth will validate the token.
|
||||
} elseif (! empty($_REQUEST['token'])) {
|
||||
Request::instance()->redirect(sprintf('user/account/resetpassword?token=%s',$_REQUEST['token']));
|
||||
}
|
||||
|
||||
// Show our token screen even if the email was invalid.
|
||||
if (isset($_POST['email']))
|
||||
Block::add(array(
|
||||
'title'=>_('Reset your password'),
|
||||
'body'=>View::factory('login_reset_sent'),
|
||||
'style'=>array('css/login.css'=>'screen'),
|
||||
));
|
||||
else
|
||||
Request::instance()->redirect('login');
|
||||
|
||||
} else {
|
||||
Block::add(array(
|
||||
'title'=>_('Reset your password'),
|
||||
'body'=>View::factory('login_reset'),
|
||||
'style'=>array('css/login.css'=>'screen'),
|
||||
));
|
||||
}
|
||||
|
||||
$this->template->content = Block::factory();
|
||||
}
|
||||
|
||||
public function action_noaccess() {
|
||||
$this->template->content = ' ';
|
||||
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('No access to requested resource'),
|
||||
'type'=>'error',
|
||||
'body'=>_('You do not have access to the requested resource, please contact your administrator.')
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
4
application/classes/controller/logout.php
Normal file
4
application/classes/controller/logout.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Controller_Logout extends Controller_lnApp_Logout {}
|
||||
?>
|
56
application/classes/controller/templatedefault.php
Normal file
56
application/classes/controller/templatedefault.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides the default template controller for rendering pages.
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Page/Template
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault extends Controller_lnApp_TemplateDefault {
|
||||
/**
|
||||
* Check and see if this controller needs authentication
|
||||
*
|
||||
* if $this->auth_required is TRUE, then the user must be logged in only.
|
||||
* if $this->auth_required is FALSE, AND $this->secure_actions has an array of
|
||||
* methods set to TRUE, then the user must be logged in AND a member of the
|
||||
* role.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _auth_required() {
|
||||
// If our global configurable is disabled, then continue
|
||||
if (! Kohana::Config('config.method_security'))
|
||||
return FALSE;
|
||||
|
||||
return (($this->auth_required !== FALSE && Auth::instance()->logged_in(NULL,get_class($this).'|'.__METHOD__) === FALSE) ||
|
||||
(is_array($this->secure_actions) && array_key_exists($this->request->action,$this->secure_actions) &&
|
||||
Auth::instance()->logged_in($this->secure_actions[$this->request->action],get_class($this).'|'.__METHOD__) === FALSE));
|
||||
}
|
||||
|
||||
protected function _left() {
|
||||
if ($this->template->left)
|
||||
return $this->template->left;
|
||||
|
||||
elseif (Auth::instance()->logged_in(NULL,get_class($this).'|'.__METHOD__))
|
||||
return Controller_Tree::js();
|
||||
}
|
||||
|
||||
protected function _right() {
|
||||
if ($this->template->right)
|
||||
return $this->template->right;
|
||||
else
|
||||
return $this->_cart();
|
||||
}
|
||||
|
||||
private function _cart() {
|
||||
if (! Cart::instance()->contents()->reset(FALSE)->count_all())
|
||||
return '';
|
||||
|
||||
return Cart::instance()->cart_block();
|
||||
}
|
||||
}
|
||||
?>
|
90
application/classes/controller/tree.php
Normal file
90
application/classes/controller/tree.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends renders OSB menu tree.
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Tree
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Tree extends Controller_lnApp_Tree {
|
||||
protected $auth_required = TRUE;
|
||||
|
||||
/**
|
||||
* Draw the Tree Menu
|
||||
*
|
||||
* The incoming ID is either a Branch B_x or a Node N_x
|
||||
* Where X is actually the module.
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
public function action_json($id=null) {
|
||||
if ($this->_auth_required()) {
|
||||
$this->treedata = array('attr'=>array('id'=>'a_login'),
|
||||
'data'=>array('title'=>_('Please Login').'...','attr'=>array('id'=>'N_login','href'=>URL::site('login'))));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the user details
|
||||
$id = (is_null($id) && isset($_REQUEST['id'])) ? substr($_REQUEST['id'],2) : $id;
|
||||
$user = Auth::instance()->get_user();
|
||||
|
||||
if (! $id) {
|
||||
$modules = array();
|
||||
foreach ($user->groups() as $go)
|
||||
$modules = array_merge($modules,Module_Method::groupmodules($go->id));
|
||||
|
||||
ksort($modules);
|
||||
|
||||
$data = array();
|
||||
foreach ($modules as $module => $details)
|
||||
if (! $details['parent_id'])
|
||||
array_push($data,
|
||||
array('id'=>$details['id'],'name'=>$module,'state'=>'closed')
|
||||
);
|
||||
|
||||
} else {
|
||||
$module = preg_replace('/^N_/','',$id);
|
||||
$methods = array();
|
||||
foreach ($user->groups() as $go)
|
||||
$methods = array_merge($methods,Module_Method::groupmethods($go->id,$module));
|
||||
|
||||
ksort($methods);
|
||||
|
||||
$data = array();
|
||||
foreach ($methods as $method => $details) {
|
||||
if (preg_match('/_/',$method)) {
|
||||
list($mode,$action) = explode('_',$method);
|
||||
$url = URL::site(sprintf('/%s/%s/%s',$mode,$details['module'],$action));
|
||||
} else {
|
||||
$url = URL::site(sprintf('/%s/%s',$details['module'],$method));
|
||||
}
|
||||
|
||||
array_push($data,array(
|
||||
'id'=>sprintf('%s_%s',$module,$details['id']),
|
||||
'name'=>$method,
|
||||
'state'=>'none',
|
||||
'attr_id'=>sprintf('%s_%s',$module,$details['id']),
|
||||
'attr_href'=>(empty($details['page']) ? $url : $details['page'])
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$this->treedata = array();
|
||||
|
||||
foreach ($data as $branch) {
|
||||
array_push($this->treedata,array(
|
||||
'attr'=>array('id'=>sprintf('B_%s',$branch['id'])),
|
||||
'state'=>$branch['state'],
|
||||
'data'=>array('title'=>$branch['name']),
|
||||
'attr'=>array('id'=>sprintf('N_%s',$branch['id']),'href'=>empty($branch['attr_href']) ? URL::site(sprintf('/%s/menu',$branch['name'])) : $branch['attr_href']),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
@@ -1,10 +1,39 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Controller_Welcome extends Controller {
|
||||
/**
|
||||
* OSB Main home page
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Page/Home
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class Controller_Welcome extends Controller_TemplateDefault {
|
||||
public function action_index() {
|
||||
$block = new block;
|
||||
$block->add(array(
|
||||
'title'=>'Welcome to lnApp (public)!',
|
||||
'subtitle'=>'Using lnApp',
|
||||
'body'=>'Sample lnApp application',
|
||||
'footer'=>'lnApp makes building websites easy! '.time(),
|
||||
));
|
||||
|
||||
public function action_index()
|
||||
{
|
||||
$this->request->response = 'hello, world!';
|
||||
if (Auth::instance()->logged_in()) {
|
||||
$this->template->control = HTML::anchor('/logout',_('Logout'),array('id'=>'ajxbody'));
|
||||
} else {
|
||||
$this->template->control = HTML::anchor('/login',_('Login'),array('id'=>'ajxbody'));
|
||||
|
||||
Script::add(array('type'=>'stdin','data'=>'
|
||||
$(document).ready(function() {
|
||||
$("#ajxbody").click(function() {$("#ajBODY").load("'.URL::site('/login').'",null,function(x,s,r) {}); return false;});
|
||||
$("#ajBODY").ajaxSend(function() {$(this).html(\''.sprintf('%s <span class="ajaxmsg">%s<\/span>...',HTML::image('media/img/ajax-progress.gif',array('alt'=>_('Loading Login').'...')),_('Loading Login')).'\');return true;});
|
||||
});'
|
||||
));
|
||||
}
|
||||
|
||||
$this->template->content = $block;
|
||||
}
|
||||
|
||||
} // End Welcome
|
||||
}
|
||||
?>
|
||||
|
20
application/classes/database/mysql.php
Normal file
20
application/classes/database/mysql.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* MySQL database connection.
|
||||
*
|
||||
* Modified for OSB, so that ORM can use enhanced SQL queries. This has been
|
||||
* achieved by simply removing the identifier backtick.
|
||||
*
|
||||
* @package OSB/Modifications
|
||||
* @subpackage Database
|
||||
* @category Drivers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license
|
||||
*/
|
||||
class Database_MySQL extends Kohana_Database_MySQL {
|
||||
// MySQL uses a backtick for identifiers
|
||||
protected $_identifier = '';
|
||||
}
|
||||
?>
|
4
application/classes/headimages.php
Normal file
4
application/classes/headimages.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class HeadImages extends lnApp_HeadImages {}
|
||||
?>
|
4
application/classes/htmlrender.php
Normal file
4
application/classes/htmlrender.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class HTMLRender extends lnApp_HTMLRender {}
|
||||
?>
|
81
application/classes/lnapp/block.php
Normal file
81
application/classes/lnapp/block.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class is for rendering HTML body blocks (left, center, right).
|
||||
*
|
||||
* It will provide a header, body and footer.
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Page
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
* @uses Style
|
||||
*/
|
||||
class lnApp_Block extends HTMLRender {
|
||||
protected static $_data = array();
|
||||
protected static $_spacer = '<table><tr class="spacer"><td> </td></tr></table>';
|
||||
protected static $_required_keys = array('body');
|
||||
|
||||
/**
|
||||
* Add a block to be rendered
|
||||
*
|
||||
* @param array Block attributes
|
||||
*/
|
||||
public static function add($block,$prepend=FALSE) {
|
||||
parent::add($block);
|
||||
|
||||
// Detect any style sheets.
|
||||
if (! empty($block['style']) && is_array($block['style']))
|
||||
foreach ($block['style'] as $data=>$media)
|
||||
Style::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>$data,
|
||||
'media'=>$media,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of this class
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public static function factory() {
|
||||
return new Block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render this block
|
||||
*
|
||||
* @see HTMLRender::render()
|
||||
*/
|
||||
protected function render() {
|
||||
$output = '';
|
||||
$styles = array();
|
||||
|
||||
$i = 0;
|
||||
foreach (static::$_data as $value) {
|
||||
if ($i++)
|
||||
$output .= static::$_spacer;
|
||||
|
||||
$output .= '<table class="block" border="0">';
|
||||
|
||||
if (! empty($value['title']))
|
||||
$output .= sprintf('<tr class="title"><td>%s</td></tr>',$value['title']);
|
||||
|
||||
if (! empty($value['subtitle']))
|
||||
$output .= sprintf('<tr class="subtitle"><td>%s</td></tr>',$value['subtitle']);
|
||||
|
||||
$output .= sprintf('<tr class="body"><td>%s</td></tr>',$value['body']);
|
||||
|
||||
if (! empty($value['footer']))
|
||||
$output .= sprintf('<tr class="footer"><td>%s</td></tr>',$value['footer']);
|
||||
|
||||
$output .= '</table>';
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
?>
|
64
application/classes/lnapp/breadcrumb.php
Normal file
64
application/classes/lnapp/breadcrumb.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class is for rendering a breadcrumb menu.
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Page
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class lnApp_Breadcrumb extends HTMLRender {
|
||||
protected static $_data = array();
|
||||
protected static $_spacer = ' » ';
|
||||
protected static $_required_keys = array('body');
|
||||
|
||||
/**
|
||||
* Set the breadcrumb path
|
||||
*
|
||||
* @param array Block attributes
|
||||
*/
|
||||
public static function set($path) {
|
||||
if (is_string($path))
|
||||
static::$_data['path'] = explode('/',$path);
|
||||
else
|
||||
static::$_data['path'] = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable a friendly name to be used for a path
|
||||
*/
|
||||
public static function name($path,$name) {
|
||||
static::$_data['name'][$path] = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of this class
|
||||
*
|
||||
* @return Breadcrumb
|
||||
*/
|
||||
public static function factory() {
|
||||
return new Breadcrumb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render this Breadcrumb
|
||||
*/
|
||||
protected function render() {
|
||||
$output = HTML::anchor('/',_('Home'));
|
||||
|
||||
$data = empty(static::$_data['path']) ? explode('/',Request::instance()->uri) : static::$_data['path'];
|
||||
|
||||
foreach ($data as $k => $v) {
|
||||
$output .= static::$_spacer;
|
||||
|
||||
$p = join('/',array_slice($data,0,$k+1));
|
||||
$output .= HTML::anchor($p,empty(static::$_data['name'][$p]) ? ucfirst($v) : static::$_data['name'][$p]);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
?>
|
129
application/classes/lnapp/config.php
Normal file
129
application/classes/lnapp/config.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends the core Kohana class by adding some core application
|
||||
* specific functions, and configuration.
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Core
|
||||
* @category Overrides
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
abstract class lnApp_Config extends Kohana {
|
||||
/**
|
||||
* Find a list of all database enabled modules
|
||||
*
|
||||
* @uses cache
|
||||
*/
|
||||
public static function appmodules() {
|
||||
$cacheable = TRUE;
|
||||
|
||||
if (array_key_exists('cache',Kohana::modules())) {
|
||||
$cache = Cache::instance(static::cachetype());
|
||||
|
||||
if ($cacheable AND $cache->get('modules'))
|
||||
return $cache->get('modules');
|
||||
|
||||
} else
|
||||
$cache = '';
|
||||
|
||||
$modules = array();
|
||||
$module_table = 'module';
|
||||
|
||||
if (class_exists('Model_'.ucfirst($module_table))) {
|
||||
$mo = ORM::factory($module_table)->where('status','=',1)->find_all()->as_array();
|
||||
|
||||
foreach ($mo as $o)
|
||||
$modules[$o->name] = MODPATH.$o->name;
|
||||
}
|
||||
|
||||
if ($cache)
|
||||
$cache->set('modules',$modules);
|
||||
|
||||
return $modules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return our site name
|
||||
*/
|
||||
public static function site() {
|
||||
if (! empty($_SERVER['SERVER_NAME']))
|
||||
return $_SERVER['SERVER_NAME'];
|
||||
|
||||
if (! $site = CLI::options('site'))
|
||||
throw new Kohana_Exception(_('Cant figure out the site, use --site= for CLI'));
|
||||
|
||||
return $site['site'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out our site ID for multiehosting
|
||||
* @todo Change this to query the DB for site number.
|
||||
*/
|
||||
public static function siteid() {
|
||||
$sites = Kohana::config('config.site');
|
||||
|
||||
// If we havent been configured for sites
|
||||
if (is_null($sites) OR ! is_array($sites) OR ! isset($sites[static::site()]))
|
||||
return 0;
|
||||
else
|
||||
return $sites[static::site()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out our site mode (dev,test,prod)
|
||||
* @todo Change this to query the DB for mode.
|
||||
*/
|
||||
public static function sitemode() {
|
||||
$sites = Kohana::config('config.site_mode');
|
||||
|
||||
// If we havent been configured for sites
|
||||
if (is_null($sites) OR ! is_array($sites) OR ! isset($sites[static::site()]))
|
||||
return Kohana::PRODUCTION;
|
||||
else
|
||||
return $sites[static::site()];
|
||||
}
|
||||
|
||||
public static function sitename() {
|
||||
return Kohana::config('config.site_name');
|
||||
}
|
||||
|
||||
public static function logo() {
|
||||
$mediapath = Route::get('default/media');
|
||||
$logo = $mediapath->uri(array('file'=>'img/logo-small.png'),array('alt'=>static::sitename()));
|
||||
|
||||
return HTML::image($logo,array('class'=>'headlogo','alt'=>_('Logo')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return our caching mechanism
|
||||
*/
|
||||
public static function cachetype() {
|
||||
return is_null(Kohana::config('config.cache_type')) ? 'file' : Kohana::config('config.cache_type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a date using a site configured format
|
||||
*/
|
||||
public static function date($date) {
|
||||
return date(Kohana::config('config.date_format'),$date);
|
||||
}
|
||||
|
||||
/**
|
||||
* See if our emails for the template should be sent to configured admin(s)
|
||||
*
|
||||
* @param string template - Template to test for
|
||||
* @return mixed|array - Email to send test emails to
|
||||
*/
|
||||
public static function testmail($template) {
|
||||
$config = Kohana::config('config.email_admin_only');
|
||||
|
||||
if (is_null($config) OR ! is_array($config) OR empty($config[$template]))
|
||||
return FALSE;
|
||||
else
|
||||
return $config[$template];
|
||||
}
|
||||
}
|
||||
?>
|
45
application/classes/lnapp/headimages.php
Normal file
45
application/classes/lnapp/headimages.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class is for all image icons shown on the page header.
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Page
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class lnApp_HeadImages extends HTMLRender {
|
||||
protected static $_data = array();
|
||||
protected static $_spacer = ' ';
|
||||
protected static $_required_keys = array('url','img');
|
||||
|
||||
/**
|
||||
* Return an instance of this class
|
||||
*
|
||||
* @return HeadImage
|
||||
*/
|
||||
public static function factory() {
|
||||
return new HeadImages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render this Header Image
|
||||
*
|
||||
* @see HTMLRender::render()
|
||||
*/
|
||||
protected function render() {
|
||||
$output = '';
|
||||
$mediapath = Route::get(static::$_media_path);
|
||||
|
||||
foreach (static::$_data as $value) {
|
||||
$i = HTML::image($mediapath->uri(array('file'=>$value['img'])),array('alt'=>isset($value['attrs']['title']) ? $value['attrs']['title'] : ''));
|
||||
$output .= HTML::anchor($value['url'],$i,(isset($value['attrs']) && is_array($value['attrs'])) ? $value['attrs'] : null);
|
||||
$output .= static::$_spacer;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
?>
|
94
application/classes/lnapp/htmlrender.php
Normal file
94
application/classes/lnapp/htmlrender.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class is the base used for common static methods that are used
|
||||
* for rendering.
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Page
|
||||
* @category Abstract/Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
abstract class lnApp_HTMLRender {
|
||||
protected static $_media_path = 'default/media';
|
||||
protected static $_required_keys = array();
|
||||
protected static $_unique_vals = array();
|
||||
|
||||
public function __construct() {
|
||||
if (! isset(static::$_data))
|
||||
throw new Kohana_Exception(':class is missing important static variables',array(':class'=>get_called_class()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to be rendered
|
||||
*
|
||||
* @param array Item to be added
|
||||
*/
|
||||
public static function add($item,$prepend=FALSE) {
|
||||
foreach (static::$_required_keys as $key)
|
||||
if (! isset($item[$key]))
|
||||
throw new Kohana_Exception('Missing key :key for image',array(':key'=>$key));
|
||||
|
||||
// Check for unique keys
|
||||
if (static::$_unique_vals)
|
||||
foreach (static::$_unique_vals as $v=>$u)
|
||||
foreach (static::$_data as $d)
|
||||
if (isset($d[$u]) && $d['data'] == $item['data'])
|
||||
return;
|
||||
|
||||
if ($prepend)
|
||||
array_unshift(static::$_data,$item);
|
||||
else
|
||||
array_push(static::$_data,$item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the space used between rendering output
|
||||
*/
|
||||
public static function setSpacer($spacer) {
|
||||
static::$_spacer = $spacer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Kohana Media Path, used to determine where to find additional
|
||||
* HTML content required for rendering.
|
||||
*/
|
||||
public static function setMediaPath($path) {
|
||||
static::$_media_path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory instance method must be declared by the child class
|
||||
*/
|
||||
public static function factory() {
|
||||
throw new Kohana_Exception(':class is calling :method, when it should have its own method',
|
||||
array(':class'=>get_called_class(),':method'=>__METHOD__));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HTML to render the header images
|
||||
*/
|
||||
public function __toString() {
|
||||
try {
|
||||
return static::render();
|
||||
}
|
||||
|
||||
// Display the exception message
|
||||
catch (Exception $e) {
|
||||
Kohana::exception_handler($e);
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendering must be declared by the child class
|
||||
*/
|
||||
protected function render() {
|
||||
throw new Kohana_Exception(':class is calling :method, when it should have its own method',
|
||||
array(':class'=>get_called_class(),':method'=>__METHOD__));
|
||||
}
|
||||
}
|
||||
?>
|
34
application/classes/lnapp/meta.php
Normal file
34
application/classes/lnapp/meta.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class is for all HTML page attributes.
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Page
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class lnApp_Meta {
|
||||
private $_data = array();
|
||||
private $_array_keys = array();
|
||||
|
||||
public function __get($key) {
|
||||
if (in_array($key,$this->_array_keys) && empty($this->_data[$key]))
|
||||
return array();
|
||||
|
||||
if (empty($this->_data[$key]))
|
||||
return null;
|
||||
else
|
||||
return $this->_data[$key];
|
||||
}
|
||||
|
||||
public function __set($key,$value) {
|
||||
if (in_array($key,$this->_array_keys) && ! is_array($value))
|
||||
throw new Kohana_Exception('Key :key must be an array',array(':key'=>$key));
|
||||
|
||||
$this->_data[$key] = $value;
|
||||
}
|
||||
}
|
||||
?>
|
59
application/classes/lnapp/script.php
Normal file
59
application/classes/lnapp/script.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class is for rendering HTML script tags
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Page
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class lnApp_Script extends HTMLRender {
|
||||
protected static $_data = array();
|
||||
protected static $_spacer = "\n";
|
||||
protected static $_required_keys = array('type','data');
|
||||
protected static $_unique_vals = array('file'=>'type');
|
||||
|
||||
/**
|
||||
* Return an instance of this class
|
||||
*
|
||||
* @return Script
|
||||
*/
|
||||
public static function factory() {
|
||||
return new Script;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the script tag
|
||||
*
|
||||
* @see HTMLRender::render()
|
||||
*/
|
||||
protected function render() {
|
||||
$foutput = $soutput = '';
|
||||
$mediapath = Route::get(static::$_media_path);
|
||||
|
||||
$i = $j = 0;
|
||||
foreach (static::$_data as $value) {
|
||||
|
||||
switch ($value['type']) {
|
||||
case 'file':
|
||||
$foutput .= HTML::script($mediapath->uri(array('file'=>$value['data'])));
|
||||
if ($i++)
|
||||
$foutput .= static::$_spacer;
|
||||
break;
|
||||
case 'stdin':
|
||||
$soutput .= sprintf("<script type=\"text/javascript\">//<![CDATA[\n%s\n//]]></script>",$value['data']);
|
||||
if ($j++)
|
||||
$soutput .= static::$_spacer;
|
||||
break;
|
||||
default:
|
||||
throw new Kohana_Exception('Unknown style type :type',array(':type'=>$value['type']));
|
||||
}
|
||||
}
|
||||
|
||||
return $foutput.static::$_spacer.$soutput;
|
||||
}
|
||||
}
|
||||
?>
|
54
application/classes/lnapp/style.php
Normal file
54
application/classes/lnapp/style.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class is for rendering HTML style tags
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage Page
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class lnApp_Style extends HTMLRender {
|
||||
protected static $_data = array();
|
||||
protected static $_spacer = "\n";
|
||||
protected static $_required_keys = array('type','data');
|
||||
|
||||
/**
|
||||
* Return an instance of this class
|
||||
*
|
||||
* @return Style
|
||||
*/
|
||||
public static function factory() {
|
||||
return new Style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the style tag
|
||||
*
|
||||
* @see HTMLRender::render()
|
||||
*/
|
||||
protected function render() {
|
||||
$output = '';
|
||||
$mediapath = Route::get(static::$_media_path);
|
||||
|
||||
$i = 0;
|
||||
foreach (static::$_data as $value) {
|
||||
if ($i++)
|
||||
$output .= static::$_spacer;
|
||||
|
||||
switch ($value['type']) {
|
||||
case 'file':
|
||||
$output .= HTML::style($mediapath->uri(array('file'=>$value['data'])),
|
||||
array('media'=>(! empty($value['media'])) ? $value['media'] : 'screen'),TRUE);
|
||||
break;
|
||||
default:
|
||||
throw new Kohana_Exception('Unknown style type :type',array(':type'=>$value['type']));
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
?>
|
129
application/classes/lnapp/systemmessage.php
Normal file
129
application/classes/lnapp/systemmessage.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class is for rendering system information messages.
|
||||
*
|
||||
* @package lnApp
|
||||
* @subpackage SystemMessage
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class lnApp_SystemMessage extends HTMLRender {
|
||||
protected static $_data = array();
|
||||
protected static $_spacer = '<table><tr class="spacer"><td> </td></tr></table>';
|
||||
protected static $_required_keys = array('title','body','type');
|
||||
|
||||
/**
|
||||
* Add a system message to be rendered
|
||||
*
|
||||
* @param array System Message attributes
|
||||
*/
|
||||
public static function add($msg,$prepend=FALSE) {
|
||||
if ($msgs = Session::instance()->get('sessionmsgs')) {
|
||||
static::$_data = $msgs;
|
||||
}
|
||||
|
||||
parent::add($msg);
|
||||
|
||||
// Add a gribber popup
|
||||
Style::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'css/jquery.gritter.css',
|
||||
'media'=>'screen',
|
||||
));
|
||||
Script::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'js/jquery.gritter-1.5.js',
|
||||
));
|
||||
Script::add(array(
|
||||
'type'=>'stdin',
|
||||
'data'=>sprintf(
|
||||
'$(document).ready(function() {
|
||||
$.extend($.gritter.options, {
|
||||
fade_in_speed: "medium",
|
||||
fade_out_speed: 2000,
|
||||
time: "3000",
|
||||
sticky: false,
|
||||
});
|
||||
$.gritter.add({
|
||||
title: "%s",
|
||||
text: "%s",
|
||||
image: "%s",
|
||||
});});',$msg['title'],$msg['body'],URL::site().static::image($msg['type'],true))));
|
||||
|
||||
// Save our messages in our session, so that we get them for redirects
|
||||
Session::instance()->set('sessionmsgs',static::$_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of this class
|
||||
*
|
||||
* @return SystemMessage
|
||||
*/
|
||||
public static function factory() {
|
||||
return new SystemMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an image for the System Message
|
||||
*/
|
||||
private static function image($type,$raw=false,$big=false,$alt='') {
|
||||
$mediapath = Route::get(static::$_media_path);
|
||||
|
||||
switch ($type) {
|
||||
case 'error':
|
||||
$file = sprintf('img/dialog-error%s.png',$big ? '-big' : '');
|
||||
break;
|
||||
case 'info':
|
||||
$file = sprintf('img/dialog-information%s.png',$big ? '-big' : '');
|
||||
break;
|
||||
case 'warning':
|
||||
$file = sprintf('img/dialog-warning%s.png',$big ? '-big' : '');
|
||||
break;
|
||||
case 'debug':
|
||||
$file = sprintf('img/dialog-question%s.png',$big ? '-big' : '');
|
||||
break;
|
||||
default:
|
||||
throw new Kohana_Exception('Unknown system message type :type',array(':type'=>$value['type']));
|
||||
}
|
||||
|
||||
if ($raw)
|
||||
return $mediapath->uri(array('file'=>$file));
|
||||
else
|
||||
return HTML::image($mediapath->uri(array('file'=>$file)),array('alt'=>$alt ? $alt : '','class'=>'sysicon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Render this system message
|
||||
*
|
||||
* @see HTMLRender::render()
|
||||
*/
|
||||
protected function render() {
|
||||
$output = '';
|
||||
$mediapath = Route::get(static::$_media_path);
|
||||
|
||||
// Reload our message from the session
|
||||
if ($msgs = Session::instance()->get('sessionmsgs')) {
|
||||
Session::instance()->delete('sessionmsgs');
|
||||
static::$_data = $msgs;
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
foreach (static::$_data as $value) {
|
||||
if ($i++)
|
||||
$output .= static::$_spacer;
|
||||
|
||||
$output .= '<table><tr>';
|
||||
$output .= sprintf('<td class="icon" rowspan="2">%s</td>',static::image($value['type'],false,false,isset($value['alt']) ? $value['alt'] : ''));
|
||||
$output .= sprintf('<td class="head">%s</td>',$value['title']);
|
||||
$output .= '</tr><tr>';
|
||||
$output .= sprintf('<td class="body">%s</td>',$value['body']);
|
||||
$output .= '</tr></table>';
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
?>
|
4
application/classes/meta.php
Normal file
4
application/classes/meta.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Meta extends lnApp_Meta {}
|
||||
?>
|
2
application/classes/model/.htaccess
Normal file
2
application/classes/model/.htaccess
Normal file
@@ -0,0 +1,2 @@
|
||||
order allow,deny
|
||||
deny from all
|
34
application/classes/model/module.php
Normal file
34
application/classes/model/module.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Application Module Model
|
||||
*
|
||||
* This module must remain in applications/ as it is used very early in the
|
||||
* OSB initialisation.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Modules
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class Model_Module extends ORMOSB {
|
||||
// Relationships
|
||||
protected $_has_many = array(
|
||||
'module_method'=>array(),
|
||||
);
|
||||
protected $_has_one = array(
|
||||
'record_id'=>array()
|
||||
);
|
||||
|
||||
protected $_sorting = array(
|
||||
'status'=>'DESC',
|
||||
'name'=>'ASC',
|
||||
);
|
||||
|
||||
protected $_formats = array(
|
||||
'status'=>array('StaticList_YesNo::display'=>array()),
|
||||
);
|
||||
}
|
||||
?>
|
153
application/classes/ormosb.php
Normal file
153
application/classes/ormosb.php
Normal file
@@ -0,0 +1,153 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends Kohana's [ORM] class to create defaults for OSB.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Core
|
||||
* @category ORM
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class ORMOSB extends ORM {
|
||||
/**
|
||||
* @var string Database to connect to
|
||||
*/
|
||||
protected $_db = 'default';
|
||||
protected $_object_formated = array();
|
||||
protected $_formated = FALSE;
|
||||
protected $_formats = array();
|
||||
|
||||
/**
|
||||
* @var boolean Database names plural configuration
|
||||
*/
|
||||
protected $_table_names_plural = false;
|
||||
|
||||
protected $_created_column = array('column'=>'date_orig','format'=>TRUE);
|
||||
protected $_updated_column = array('column'=>'date_last','format'=>TRUE);
|
||||
|
||||
protected $_callbacks = array(
|
||||
'id'=>array('get_next_id'),
|
||||
'site_id'=>array('set_site_id'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Format fields for display purposes
|
||||
*
|
||||
* @param string column name
|
||||
* @return mixed
|
||||
*/
|
||||
protected function _format() {
|
||||
$format = Validate::factory($this->_object);
|
||||
|
||||
foreach ($this->_formats as $column => $formats)
|
||||
$format->filters($column,$formats);
|
||||
|
||||
if ($format->check())
|
||||
foreach ($format as $column => $value)
|
||||
$this->_object_formated[$column] = $value;
|
||||
|
||||
$this->_formated = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a formated columns, as per the model definition
|
||||
*/
|
||||
public function display($column) {
|
||||
// Trigger a load of the record.
|
||||
$value = $this->__get($column);
|
||||
|
||||
// If some of our fields need to be formated for display purposes.
|
||||
if ($this->_loaded AND ! $this->_formated AND $this->_formats)
|
||||
$this->_format();
|
||||
|
||||
if (isset($this->_object_formated[$column]))
|
||||
return $this->_object_formated[$column];
|
||||
else
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Our child models should provide an invoice display, this is shown
|
||||
* on printed invoices.
|
||||
*/
|
||||
public function invoice_display() {
|
||||
throw new Kohana_Exception(':module has not configured an :method, but has made the call',array(':module'=>get_class($this),'method'=>__METHOD__));
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the _load_result() function so that our site ID is automatically
|
||||
* added to the SQL query
|
||||
* @todo This is not picked up by all queries. Need to investigate why
|
||||
* @todo This is not being done by inserts
|
||||
*/
|
||||
protected function _load_result($multiple = FALSE)
|
||||
{
|
||||
$this->_db_builder->where($this->_table_name.'.site_id','=',Config::siteid());
|
||||
|
||||
return parent::_load_result($multiple);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will enhance the [Validate::filter], since it always passes
|
||||
* the value as the first argument and sometimes functions need that to not
|
||||
* be the first argument.
|
||||
*
|
||||
* Currently this implements:
|
||||
* [date()][date-ref]
|
||||
*
|
||||
* [date-ref]: http://www.php.net/date
|
||||
*
|
||||
* This function will throw an exception if called without a function
|
||||
* defined.
|
||||
*
|
||||
* @param mixed $val Value to be processed
|
||||
* @param string $func Name of function to call
|
||||
* @param string $arg Other arguments for the function
|
||||
*/
|
||||
final public static function _filters($val,$func,$arg) {
|
||||
switch ($func) {
|
||||
case 'date':
|
||||
return date($arg,$val);
|
||||
default:
|
||||
throw new Exception(sprintf(_('Unknown function: %s (%s,%s)'),$func,$arg,$val));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Next record id
|
||||
*
|
||||
* @param array Validate object
|
||||
* @param string Primary Key
|
||||
*/
|
||||
public function get_next_id(Validate $array,$field) {
|
||||
if (! is_null($array[$field]))
|
||||
return TRUE;
|
||||
|
||||
$this->_changed[$field] = $field;
|
||||
|
||||
$ido = ORM::factory('module')
|
||||
->where('name','=',$this->_table_name)
|
||||
->find();
|
||||
|
||||
if (! $ido->loaded())
|
||||
throw new Kohana_Exception('Problem getting record_id for :table',array(':table'=>$this->_table_name));
|
||||
|
||||
$array[$field] = $ido->record_id->next_id($ido->id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function set_site_id(Validate $array,$field) {
|
||||
if (! is_null($array[$field]))
|
||||
return TRUE;
|
||||
|
||||
// @todo This should be a config item
|
||||
$this->_changed[$field] = $field;
|
||||
$array[$field] = Config::siteid();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
?>
|
124
application/classes/period.php
Normal file
124
application/classes/period.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class is for calculating date periods.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Utilities
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class Period {
|
||||
/**
|
||||
* Calculate both the start and end dates for a billing period
|
||||
* and the pro-rata percentage.
|
||||
*
|
||||
* See [StaticList_RecurSchedule]
|
||||
*
|
||||
* @param StaticList_RecurSchedule Period Type [StaticList_RecurSchedule]
|
||||
* @param int Starting date if recurring must start on a day of the month
|
||||
* @param datetime Date to start calculating from, otherwise now() is used
|
||||
* @param boolean Show dates in 'Y-m-d' format
|
||||
* @return array
|
||||
*/
|
||||
public static function details($type,$weekday=NULL,$start=NULL,$df=FALSE) {
|
||||
// Our precision for the pro-rata percentage
|
||||
$precision = 4;
|
||||
// Make the period consistent, eg: Quarterly = Jan-Mar,Apr-Jun; HalfYearly = Jan-Jun,Jul-Dec
|
||||
$strict = FALSE;
|
||||
|
||||
// Round the time integer to a whole day.
|
||||
if (is_null($start))
|
||||
$start = strtotime('today');
|
||||
else
|
||||
$start = strtotime(date('Y-m-d',$start));
|
||||
|
||||
switch ($type) {
|
||||
// Weekly
|
||||
// @todo Make Weekly pro-rata to a day of the week
|
||||
case 0:
|
||||
$period_end = $start+(86400*(7-1));
|
||||
return array('start'=>$start,'date'=>$start,'end'=>$period_end,'prorate'=>1);
|
||||
|
||||
# Monthly
|
||||
case 1:
|
||||
$inc_months = 1;
|
||||
break;
|
||||
|
||||
# Quarterly
|
||||
case 2:
|
||||
# @todo Make this configurable.
|
||||
$strict = TRUE;
|
||||
$inc_months = 3;
|
||||
break;
|
||||
|
||||
# Half Yearly
|
||||
case 3:
|
||||
# @todo Make this configurable.
|
||||
$strict = TRUE;
|
||||
$inc_months = 6;
|
||||
break;
|
||||
|
||||
# Yearly
|
||||
case 4:
|
||||
$inc_months = 12;
|
||||
break;
|
||||
|
||||
# Biennial
|
||||
case 5:
|
||||
$inc_months = 24;
|
||||
break;
|
||||
|
||||
# Triennial
|
||||
case 6:
|
||||
$inc_months = 36;
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// If workout a day of week we calculate to.
|
||||
if (is_null($weekday))
|
||||
$weekday = date('d',$start);
|
||||
|
||||
$used_months = 0;
|
||||
if ($strict && $type > 0 && $type < 5)
|
||||
$used_months = $inc_months-(($inc_months-(date('n',$start)%$inc_months))%$inc_months+1);
|
||||
|
||||
$d = mktime(0,0,0,date('m',$start)-$used_months,$weekday,date('y',$start));
|
||||
if ($d <= $start)
|
||||
$period_start = $d;
|
||||
else
|
||||
$period_start = mktime(0,0,0,date('m',$d)-1-$used_months,$weekday,date('y',$d));
|
||||
|
||||
$period_end = mktime(0,0,0,date('m',$period_start)+$inc_months,$weekday,date('y',$period_start));
|
||||
|
||||
$total_time = $period_end-$period_start;
|
||||
$remain_time = $period_end-$start;
|
||||
$used_time = $start-$period_start;
|
||||
|
||||
// Change our end date to the day before
|
||||
$period_end -= 86400;
|
||||
|
||||
$return = array(
|
||||
'start'=>$period_start,
|
||||
'date'=>$start,
|
||||
'end'=>$period_end,
|
||||
'weekday'=>$weekday,
|
||||
'prorata'=>round($remain_time/$total_time,$precision),
|
||||
'total_time'=>sprintf('%3.1f',$total_time/86400),
|
||||
'remain_time'=>sprintf('%3.1f',$remain_time/86400),
|
||||
'used_time'=>sprintf('%3.1f',$used_time/86400));
|
||||
|
||||
// @todo Use the configured data format
|
||||
if ($df)
|
||||
foreach (array('start','date','end') as $key)
|
||||
$return[$key] = date('Y-m-d',$return[$key]);
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
?>
|
4
application/classes/script.php
Normal file
4
application/classes/script.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Script extends lnApp_Script {}
|
||||
?>
|
63
application/classes/staticlist.php
Normal file
63
application/classes/staticlist.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders standard lists and their values
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Utilities
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
abstract class StaticList {
|
||||
// This is our list of items that will be rendered
|
||||
protected $list = array();
|
||||
|
||||
/**
|
||||
* Each static list type must provide the table function that contains
|
||||
* the table of list and values.
|
||||
*/
|
||||
abstract protected function table();
|
||||
|
||||
public static function factory() {
|
||||
throw new Kohana_Exception(':class is calling :method, when it should have its own method',
|
||||
array(':class'=>get_called_class(),':method'=>__METHOD__));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a static name for a value
|
||||
*
|
||||
* @param key $id value to render
|
||||
* @see _display()
|
||||
*/
|
||||
public static function display($value) {
|
||||
return static::_display($value);
|
||||
}
|
||||
|
||||
// Due to static scope, sometimes we need to call this function from the child class.
|
||||
protected static function _display($id) {
|
||||
$table = static::factory()->table();
|
||||
|
||||
if (! $table OR empty($table[$id]))
|
||||
return sprintf('No Value (%s)',$id);
|
||||
else
|
||||
return $table[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders form input
|
||||
*
|
||||
* @param string Form name to render
|
||||
* @param string Default value to populate in the Form input.
|
||||
*/
|
||||
public static function form($name,$default='',$addblank=FALSE) {
|
||||
$table = static::factory()->table();
|
||||
|
||||
if ($addblank)
|
||||
$table = array_merge(array(''=>' '),$table);
|
||||
|
||||
return Form::Select($name,$table,$default);
|
||||
}
|
||||
}
|
||||
?>
|
23
application/classes/staticlist/module.php
Normal file
23
application/classes/staticlist/module.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders responses and forms based on the values from a module.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Utilities
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class StaticList_Module extends StaticListModule {
|
||||
protected function table($module=NULL) {
|
||||
if (is_null($module))
|
||||
throw new Kohana_Exception('Module is a required attribute.');
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_Module;
|
||||
}
|
||||
}
|
||||
?>
|
30
application/classes/staticlist/pricetype.php
Normal file
30
application/classes/staticlist/pricetype.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Price Type responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Utilities
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class StaticList_PriceType extends StaticList {
|
||||
protected function table() {
|
||||
return array(
|
||||
0=>_('One-time Charge'),
|
||||
1=>_('Recurring Membership/Subscription'),
|
||||
2=>_('Trial for Membership/Subscription')
|
||||
);
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_PriceType;
|
||||
}
|
||||
|
||||
public static function display($value) {
|
||||
return static::_display($value);
|
||||
}
|
||||
}
|
||||
?>
|
56
application/classes/staticlist/recurschedule.php
Normal file
56
application/classes/staticlist/recurschedule.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Recurring Schedule Times on responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Utilities
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class StaticList_RecurSchedule extends StaticList {
|
||||
protected function table() {
|
||||
return array(
|
||||
0=>_('Weekly'),
|
||||
1=>_('Monthly'),
|
||||
2=>_('Quarterly'),
|
||||
3=>_('Semi-Annually'),
|
||||
4=>_('Annually'),
|
||||
5=>_('Two years'),
|
||||
6=>_('Three Years')
|
||||
);
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_RecurSchedule;
|
||||
}
|
||||
|
||||
public static function display($value) {
|
||||
return static::_display($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the price display for a product
|
||||
*
|
||||
* @uses product
|
||||
*/
|
||||
public static function form($name,$product='',$addblank=FALSE) {
|
||||
if (empty($product))
|
||||
throw new Kohana_Exception('Product is a required field for :method',array(':method'=>__METHOD__));
|
||||
|
||||
$x = '';
|
||||
$table = static::factory()->table();
|
||||
|
||||
foreach ($product->get_price_array() as $term => $price) {
|
||||
$x[$term] = sprintf('%s %s',Currency::display($price['price_base']),$table[$term]);
|
||||
|
||||
if ($price['price_setup'] > 0)
|
||||
$x[$term] .= sprintf(' + %s %s',Currency::display($price['price_setup']),_('Setup'));
|
||||
}
|
||||
|
||||
return Form::select($name,$x,$product->price_recurr_default);
|
||||
}
|
||||
}
|
||||
?>
|
29
application/classes/staticlist/title.php
Normal file
29
application/classes/staticlist/title.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Person Title responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Utilities
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class StaticList_Title extends StaticList {
|
||||
protected function table() {
|
||||
return array(
|
||||
'mr'=>_('Mr'),
|
||||
'ms'=>_('Ms'),
|
||||
'mrs'=>_('Mrs'),
|
||||
'miss'=>_('Miss'),
|
||||
'dr'=>_('Dr'),
|
||||
'prof'=>_('Prof')
|
||||
);
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_Title;
|
||||
}
|
||||
}
|
||||
?>
|
29
application/classes/staticlist/yesno.php
Normal file
29
application/classes/staticlist/yesno.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Yes/No responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Utilities
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class StaticList_YesNo extends StaticList {
|
||||
protected function table() {
|
||||
return array(
|
||||
0=>_('No'),
|
||||
1=>_('Yes'),
|
||||
);
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_YesNo;
|
||||
}
|
||||
|
||||
public static function display($value) {
|
||||
return static::_display($value);
|
||||
}
|
||||
}
|
||||
?>
|
83
application/classes/staticlistmodule.php
Normal file
83
application/classes/staticlistmodule.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class is renders standard values based on DB table row values.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Utilities
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
abstract class StaticListModule extends StaticList {
|
||||
protected static $record = array();
|
||||
|
||||
/**
|
||||
* Display a static name for a value
|
||||
*/
|
||||
public static function display($id) {
|
||||
// Override our argument list as defined in parent
|
||||
list($table,$key,$skey,$value) = func_get_args();
|
||||
$db = DB::select($key)->from($table)->where($skey,'=',$value)->execute();
|
||||
|
||||
if ($db->count() !== 1)
|
||||
return sprintf('No Value (%s)',$value);
|
||||
else
|
||||
return $db->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is to return the cached value of the current active record
|
||||
* This is so that a follow up call to get an attribute of a value retrieved
|
||||
* can reuse the active record values.
|
||||
* This gets over a limitation where the query to form() to get a default
|
||||
* no longer exists (or is invalid) and you want other attributes of the
|
||||
* remaining active record, which may not be the default record.
|
||||
*/
|
||||
public static function record($table,$attribute,$skey,$value) {
|
||||
if (empty(static::$record[$table]))
|
||||
return static::display($table,$attribute,$skey,$value);
|
||||
else
|
||||
return static::$record[$table][$attribute];
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders form input
|
||||
*/
|
||||
public static function form($name,$default='',$addblank=FALSE) {
|
||||
// Override our argument list as defined in parent
|
||||
list($name,$table,$default,$key,$value,$where) = func_get_args();
|
||||
|
||||
// @todo - our query type should come from our configuration?
|
||||
$db = DB::select()->from($table);
|
||||
|
||||
foreach ($where as $k=>$v) {
|
||||
list ($op,$v) = explode(':',$v);
|
||||
$db->where($k,$op,$v);
|
||||
}
|
||||
|
||||
$db = $db->execute();
|
||||
|
||||
// If we only have one record, dont make a select list
|
||||
if ($db->count() == 1) {
|
||||
static::$record[$table] = $db->as_array();
|
||||
static::$record[$table] = array_shift(static::$record[$table]);
|
||||
|
||||
return Form::hidden($name,$db->get($key)).$db->get($value);
|
||||
}
|
||||
|
||||
// Else we return a select list
|
||||
$x = array();
|
||||
foreach ($db as $record) {
|
||||
$x[$record[$key]] = $record[$value];
|
||||
|
||||
// Save our static record, in case we reference this item again.
|
||||
if ($record[$key] == $default)
|
||||
static::$record[$table] = $record;
|
||||
}
|
||||
|
||||
return Form::select($name,$x,$default);
|
||||
}
|
||||
}
|
||||
?>
|
4
application/classes/style.php
Normal file
4
application/classes/style.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class Style extends lnApp_Style {}
|
||||
?>
|
4
application/classes/systemmessage.php
Normal file
4
application/classes/systemmessage.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
class SystemMessage extends lnApp_SystemMessage {}
|
||||
?>
|
29
application/classes/validate.php
Normal file
29
application/classes/validate.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* Array and variable validation.
|
||||
*
|
||||
* @package OSB/Modifications
|
||||
* @category Classes
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class Validate extends Kohana_Validate {
|
||||
/**
|
||||
* Checks if a field matches the value of another field, if it is set.
|
||||
* Field is ignored if it is blank.
|
||||
*
|
||||
* This function is only invoked anyway when the value is set as per
|
||||
* $this->_empty_rules
|
||||
*
|
||||
* @param string field value
|
||||
* @param string field name to match
|
||||
* @return boolean
|
||||
*/
|
||||
protected function matches_ifset($value, $match)
|
||||
{
|
||||
return ($value === $this[$match]);
|
||||
}
|
||||
}
|
||||
?>
|
Reference in New Issue
Block a user