Open Source Billing
This commit is contained in:
22
application/classes/Auth/ORM.php
Normal file
22
application/classes/Auth/ORM.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's Auth
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Auth_ORM extends Kohana_Auth_ORM {
|
||||
// Override Kohana Auth requirement to have a hash_key
|
||||
public function hash($str) {
|
||||
switch ($this->_config['hash_method']) {
|
||||
case '' : return $str;
|
||||
case 'md5': return md5($str);
|
||||
default: return hash_hmac($this->_config['hash_method'], $str, $this->_config['hash_key']);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
275
application/classes/Auth/OSB.php
Normal file
275
application/classes/Auth/OSB.php
Normal file
@@ -0,0 +1,275 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Auth driver.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Auth_OSB extends Auth_ORM {
|
||||
/**
|
||||
* OSB authentication is controlled via database queries.
|
||||
*
|
||||
* This method can be used to test two situations:
|
||||
* 1) Is the user logged in? ($role == FALSE)
|
||||
* 2) Can the user run the current controller->action ($role == TRUE)
|
||||
*
|
||||
* @param boolean If authentication should be done for this module:method (ie: controller:action).
|
||||
* @return boolean
|
||||
*/
|
||||
public function logged_in($role=NULL,$debug=NULL) {
|
||||
$status = FALSE;
|
||||
|
||||
// Get the user from the session
|
||||
$uo = $this->get_user();
|
||||
|
||||
// If we are not a valid user object, then we are not logged in
|
||||
if (is_object($uo) AND ($uo instanceof Model_Account) AND $uo->loaded()) {
|
||||
if (Config::sitemode() == Kohana::DEVELOPMENT)
|
||||
SystemMessage::add(array('title'=>'Debug','type'=>'debug','body'=>Debug::vars(array('user'=>$uo->username,'r'=>$role))));
|
||||
|
||||
if (! empty($role)) {
|
||||
// Get the module details
|
||||
$mo = ORM::factory('Module',array('name'=>Request::current()->controller()));
|
||||
if (! $mo->loaded() OR ! $mo->status) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Module is not defined or active in the Database',
|
||||
'type'=>'warning',
|
||||
'body'=>sprintf('Module not defined: %s',Request::current()->controller()),
|
||||
));
|
||||
|
||||
} else {
|
||||
if (Request::current()->directory())
|
||||
$method_name = sprintf('%s_%s',Request::current()->directory(),Request::current()->action());
|
||||
else
|
||||
$method_name = Request::current()->action();
|
||||
|
||||
// Get the method number
|
||||
$mmo = ORM::factory('Module_Method',array('module_id'=>$mo->id,'name'=>$method_name));
|
||||
if (! $mmo->loaded()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Method is not defined or active in the Database',
|
||||
'type'=>'warning',
|
||||
'body'=>sprintf('Method not defined: %s for %s',Request::current()->action(),$mo->name),
|
||||
));
|
||||
|
||||
} else {
|
||||
// If the role has the authorisation to run the method
|
||||
$gmo = ORM::factory('Group_Method')
|
||||
->where('method_id','=',$mmo->id);
|
||||
|
||||
$roles = '';
|
||||
foreach ($gmo->find_all() as $gm) {
|
||||
$roles .= ($roles ? '|' : '').$gm->group->name;
|
||||
|
||||
// $gm->group->id == 0 means all users.
|
||||
if ($gm->group->id == 0 OR $uo->has_any('group',$gm->group->list_childgrps(TRUE))) {
|
||||
$status = TRUE;
|
||||
$roles = '';
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $status) {
|
||||
if (Config::sitemode() == Kohana::DEVELOPMENT)
|
||||
SystemMessage::add(array(
|
||||
'title'=>'User is not authorised in Database',
|
||||
'type'=>'debug',
|
||||
'body'=>sprintf('Role(s) checked: %s<br/>User: %s</br>Module: %s<br/>Method: %s',$roles,$uo->username,$mo->name,$mmo->name),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Config::sitemode() == Kohana::DEVELOPMENT)
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Debug',
|
||||
'type'=>'debug',
|
||||
'body'=>sprintf('User: <b>%s</b>, Module: <b>%s</b>, Method: <b>%s</b>, Role: <b>%s</b>, Status: <b>%s</b>, Data: <b>%s</b>',
|
||||
$uo->username,Request::current()->controller(),Request::current()->action(),$role,$status,$debug)));
|
||||
|
||||
// There is no role, so the method should be allowed to run as anonymous
|
||||
} else {
|
||||
if (Config::sitemode() == Kohana::DEVELOPMENT)
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Debug',
|
||||
'type'=>'debug',
|
||||
'body'=>sprintf('User: <b>%s</b>, Module: <b>%s</b>, Method: <b>%s</b>, Status: <b>%s</b>, Data: <b>%s</b>',
|
||||
$uo->username,Request::current()->controller(),Request::current()->action(),'No Role Default Access',$debug)));
|
||||
|
||||
$status = TRUE;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (Config::sitemode() == Kohana::DEVELOPMENT)
|
||||
SystemMessage::add(array('title'=>'Debug','type'=>'debug','body'=>'No user logged in'));
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currently logged in user from the session.
|
||||
* Returns NULL if no user is currently logged in.
|
||||
*
|
||||
* @param boolean Check token users too
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_user($default=NULL,$tokenuser=TRUE) {
|
||||
// Get the current user
|
||||
$uo = parent::get_user($default);
|
||||
|
||||
// If we are not logged in, see if there is token for the user
|
||||
if (is_null($uo) AND $tokenuser AND ($token=Session::instance()->get('token')) OR (! empty($_REQUEST['token']) AND $token=$_REQUEST['token']))
|
||||
$uo = $this->_get_token_user($token);
|
||||
|
||||
return $uo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user that a token applies to
|
||||
*
|
||||
* This will check that the token is valid (not expired and for the request)
|
||||
*
|
||||
* @param $token The token
|
||||
* @return Model_Account|NULL The user that the token is valid for.
|
||||
*/
|
||||
private function _get_token_user($token) {
|
||||
// This has been implemented, as we sometimes we seem to come here twice
|
||||
static $uo = NULL;
|
||||
|
||||
if (! is_null($uo))
|
||||
return $uo;
|
||||
|
||||
$mmto = ORM::factory('Module_Method_Token',array('token'=>$token));
|
||||
|
||||
// Ignore the token if it doesnt exist.
|
||||
if ($mmto->loaded()) {
|
||||
// Check that the token is for this URI
|
||||
$mo = ORM::factory('Module',array('name'=>Request::current()->controller()));
|
||||
$mmo = ORM::factory('Module_Method',array(
|
||||
'module_id'=>$mo->id,
|
||||
'name'=>Request::current()->directory() ? sprintf('%s_%s',Request::current()->directory(),Request::current()->action()) : Request::current()->action()
|
||||
));
|
||||
|
||||
// Ignore the token if this is not the right method.
|
||||
if ($mmo->id == $mmto->method_id) {
|
||||
if (! is_null($mmto->date_expire) AND $mmto->date_expire < time()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Token Not Valid'),
|
||||
'type'=>'warning',
|
||||
'body'=>_('Token expired')));
|
||||
|
||||
// @todo Log the token deletion
|
||||
Session::instance()->delete('token');
|
||||
$mmto->delete();
|
||||
|
||||
} elseif (! is_null($mmto->uses) AND $mmto->uses < 1) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Token Not Valid'),
|
||||
'type'=>'warning',
|
||||
'body'=>_('Token expired')));
|
||||
|
||||
// @todo Log the token deletion
|
||||
Session::instance()->delete('token');
|
||||
$mmto->delete();
|
||||
|
||||
} else {
|
||||
// If this is a usage count token, reduce the count.
|
||||
if (! is_null($mmto->uses))
|
||||
$mmto->uses -= 1;
|
||||
|
||||
// Record the date this token was used
|
||||
$mmto->date_last = time();
|
||||
$mmto->save();
|
||||
|
||||
Session::instance()->set('token',$token);
|
||||
|
||||
$uo = ORM::factory('Account',$mmto->account_id);
|
||||
$uo->log(sprintf('Token %s used for method %s [%s]',$mmto->token,$mmto->module_method->name(),Request::current()->param('id')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $uo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a user in.
|
||||
*
|
||||
* @param string username
|
||||
* @param string password
|
||||
* @param boolean enable autologin
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _login($user,$password,$remember) {
|
||||
if (! is_object($user)) {
|
||||
$username = $user;
|
||||
|
||||
// Load the user
|
||||
$user = ORM::factory('Account');
|
||||
$user->where('username','=',$username)->find();
|
||||
|
||||
// If no user loaded, return
|
||||
if (! $user->loaded())
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Create a hashed password
|
||||
if (is_string($password))
|
||||
$password = $this->hash($password);
|
||||
|
||||
// If the passwords match, perform a login
|
||||
if ($user->status AND $user->has_any('group',ORM::factory('Group',array('name'=>'Registered Users'))->list_childgrps(TRUE)) AND $user->password === $password) {
|
||||
|
||||
// @todo This is not currently used.
|
||||
if ($remember === TRUE) {
|
||||
// Create a new autologin token
|
||||
$token = ORM::factory('User_Token');
|
||||
|
||||
// Set token data
|
||||
$token->user_id = $user->id;
|
||||
$token->expires = time() + $this->_config['lifetime'];
|
||||
$token->save();
|
||||
|
||||
// Set the autologin cookie
|
||||
Cookie::set('authautologin', $token->token, $this->_config['lifetime']);
|
||||
}
|
||||
|
||||
// Record our session ID, we may need to update our DB when we get a new ID
|
||||
$oldsess = session_id();
|
||||
|
||||
// Finish the login
|
||||
$this->complete_login($user);
|
||||
|
||||
// Do we need to update databases with our new sesion ID
|
||||
$sct = Kohana::$config->load('config')->session_change_trigger;
|
||||
if (session_id() != $oldsess AND count($sct))
|
||||
foreach ($sct as $t => $c)
|
||||
if (Config::module_exist($t))
|
||||
foreach (ORM::factory(ucwords($t))->where($c,'=',$oldsess)->find_all() as $o)
|
||||
$o->set('session_id',session_id())
|
||||
->update();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Login failed
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a user is authorised to view an account
|
||||
*
|
||||
* @param Model_Account Account Ojbect to validate if the current user has access
|
||||
* @return boolean TRUE if authorised, FALSE if not.
|
||||
*/
|
||||
public function authorised(Model_Account $ao) {
|
||||
return (($uo = $this->get_user()) AND $uo->loaded() AND ($uo == $ao OR in_array($ao->id,$uo->RTM->customers($uo->RTM))));
|
||||
}
|
||||
}
|
||||
?>
|
139
application/classes/Company.php
Normal file
139
application/classes/Company.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class is for access company information.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Company {
|
||||
// Our Company Setup object
|
||||
private $so;
|
||||
|
||||
public function __construct(Model_Setup $so) {
|
||||
$this->so = $so;
|
||||
|
||||
if (! $this->so->loaded())
|
||||
throw new Kohana_Exception(_('Site [:site] not defined in DB?'),array(':site'=>URL::base('http')));
|
||||
|
||||
Kohana::$environment = (int)$this->so->status;
|
||||
}
|
||||
|
||||
public static function instance() {
|
||||
return new Company(ORM::factory('Setup',array('url'=>URL::base('http'))));
|
||||
}
|
||||
|
||||
public function admin() {
|
||||
return $this->so->account->name();
|
||||
}
|
||||
|
||||
public function address($ln='<br/>') {
|
||||
return implode($ln,array($this->street($ln),sprintf('%s, %s %s',$this->city(),$this->state(),$this->pcode())));
|
||||
}
|
||||
|
||||
public function city() {
|
||||
return $this->so->site_details('city');
|
||||
}
|
||||
|
||||
public function contacts() {
|
||||
return 'Tel: '.$this->phone();
|
||||
}
|
||||
|
||||
public function country() {
|
||||
return $this->so->country;
|
||||
}
|
||||
|
||||
public function date_format() {
|
||||
return $this->so->date_format;
|
||||
}
|
||||
|
||||
public function decimals() {
|
||||
return $this->so->decimal_place;
|
||||
}
|
||||
|
||||
public function email() {
|
||||
return $this->so->site_details('email');
|
||||
}
|
||||
|
||||
public function fax() {
|
||||
return $this->so->site_details('fax');
|
||||
}
|
||||
|
||||
public function language() {
|
||||
return $this->so->language->iso;
|
||||
}
|
||||
|
||||
public function logo() {
|
||||
return Config::logo();
|
||||
}
|
||||
|
||||
public function logo_file() {
|
||||
list ($path,$suffix) = explode('.',Config::$logo);
|
||||
|
||||
return ($x=Kohana::find_file(sprintf('media/site/%s',$this->site()),$path,$suffix)) ? $x : Kohana::find_file('media',$path,$suffix);
|
||||
}
|
||||
|
||||
public function name() {
|
||||
return $this->so->site_details('name');
|
||||
}
|
||||
|
||||
public function module_config($item) {
|
||||
return $this->so->module_config($item);
|
||||
}
|
||||
|
||||
public function pcode() {
|
||||
return $this->so->site_details('pcode');
|
||||
}
|
||||
|
||||
public function phone() {
|
||||
return $this->so->site_details('phone');
|
||||
}
|
||||
|
||||
public function site($format=FALSE) {
|
||||
return $format ? sprintf('%02s',$this->so->id) : $this->so->id;
|
||||
}
|
||||
|
||||
public function so() {
|
||||
return $this->so;
|
||||
}
|
||||
|
||||
public function state() {
|
||||
return $this->so->site_details('state');
|
||||
}
|
||||
|
||||
public function street($ln='<br/>') {
|
||||
return $this->so->site_details('address2') ? implode($ln,array($this->so->site_details('address1'),$this->so->site_details('address2'))) : $this->so->site_details('address1');
|
||||
}
|
||||
|
||||
public function sitemode() {
|
||||
return $this->so->status;
|
||||
}
|
||||
|
||||
public function taxid() {
|
||||
// Tax ID details are stored in invoice config
|
||||
$mc = $this->so->module_config('invoice');
|
||||
|
||||
if (empty($mc['TAX_ID_NAME']))
|
||||
return empty($mc['TAX_ID']) ? '' : $mc['TAX_ID'];
|
||||
else
|
||||
return sprintf('%s: %s',$mc['TAX_ID_NAME'],empty($mc['TAX_ID']) ? '' : $mc['TAX_ID']);
|
||||
}
|
||||
|
||||
public function time_format() {
|
||||
return $this->so->time_format;
|
||||
}
|
||||
|
||||
public static function bsb() {
|
||||
// @todo Details should be obtained from DB
|
||||
return Kohana::$config->load('config')->bsb;
|
||||
}
|
||||
|
||||
public static function account() {
|
||||
// @todo Details should be obtained from DB
|
||||
return Kohana::$config->load('config')->accnum;
|
||||
}
|
||||
}
|
||||
?>
|
177
application/classes/Config.php
Normal file
177
application/classes/Config.php
Normal file
@@ -0,0 +1,177 @@
|
||||
<?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 OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Config extends Kohana_Config {
|
||||
// Our default logo, if there is no site logo
|
||||
public static $logo = 'img/logo-small.png';
|
||||
|
||||
/**
|
||||
* @compat Restore KH 3.1 functionality
|
||||
* @var Kohana_Config Singleton static instance
|
||||
*/
|
||||
protected static $_instance;
|
||||
|
||||
/**
|
||||
* Some early initialisation
|
||||
*
|
||||
* At this point, KH hasnt been fully initialised either, so we cant rely on
|
||||
* too many KH functions yet.
|
||||
*
|
||||
* NOTE: Kohana doesnt provide a parent construct for the Kohana_Config class.
|
||||
*/
|
||||
public function __construct() {
|
||||
if (defined('PHPUNITTEST'))
|
||||
$_SERVER['SERVER_NAME'] = PHPUNITTEST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singleton instance of Config.
|
||||
*
|
||||
* $config = Config::instance();
|
||||
*
|
||||
* @return Config
|
||||
* @compat Restore KH 3.1 functionality
|
||||
*/
|
||||
public static function instance() {
|
||||
if (Config::$_instance === NULL)
|
||||
// Create a new instance
|
||||
Config::$_instance = new Config;
|
||||
|
||||
return Config::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return our caching mechanism
|
||||
*/
|
||||
public static function cachetype() {
|
||||
return is_null(Kohana::$config->load('config')->cache_type) ? 'file' : Kohana::$config->load('config')->cache_type;
|
||||
}
|
||||
|
||||
public static function copywrite() {
|
||||
return '(c) Open Source Billing Development Team';
|
||||
}
|
||||
|
||||
public static function country() {
|
||||
return Company::instance()->country();
|
||||
}
|
||||
|
||||
public static function date($date) {
|
||||
return date(Company::instance()->date_format(),($date ? $date : time()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a date using a site configured format
|
||||
* @note We need this function here, since we call static:: methods, which need to resolve to the child class.
|
||||
*/
|
||||
public static function datetime($date) {
|
||||
return sprintf('%s %s',static::date($date),static::time($date));
|
||||
}
|
||||
|
||||
public static function language() {
|
||||
return Company::instance()->language();
|
||||
}
|
||||
|
||||
/**
|
||||
* The URI to show for the login prompt.
|
||||
* Normally if the user is logged in, we can replace it with something else
|
||||
*/
|
||||
public static function login_uri() {
|
||||
return ($ao = Auth::instance()->get_user() AND is_object($ao)) ? HTML::anchor(URL::link('user','account/edit'),$ao->name()) : HTML::anchor('login',_('Login'));
|
||||
}
|
||||
|
||||
public static function logo() {
|
||||
return HTML::image(static::logo_uri(),array('class'=>'headlogo','alt'=>_('Logo')));
|
||||
}
|
||||
|
||||
public static function logo_uri($protocol=NULL) {
|
||||
list ($path,$suffix) = explode('.',static::$logo);
|
||||
|
||||
return URL::site(Route::get('default/media')->uri(array('file'=>$path.'.'.$suffix),array('alt'=>static::sitename())),$protocol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a list of all database enabled modules
|
||||
*
|
||||
* Our available modules are defined in the DB (along with method
|
||||
* security).
|
||||
*/
|
||||
public static function modules() {
|
||||
static $result = array();
|
||||
|
||||
if (! count($result)) {
|
||||
// We need to know our site here, so that we can subsequently load our enabled modules.
|
||||
if (PHP_SAPI === 'cli') {
|
||||
if (! $site = Minion_CLI::options('site'))
|
||||
// @todo Need to figure out how to make this CLI error nicer.
|
||||
throw new Minion_Exception_InvalidTask(_('Cant figure out the site, use --site= for CLI'));
|
||||
else
|
||||
$_SERVER['SERVER_NAME'] = $site;
|
||||
}
|
||||
|
||||
foreach (ORM::factory('Module')->list_external() as $mo)
|
||||
$result[$mo->name] = MODPATH.$mo->name;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function module_config($item) {
|
||||
return Company::instance()->module_config($item);
|
||||
}
|
||||
|
||||
public static function module_exist($module) {
|
||||
return array_key_exists(strtolower($module),static::modules()) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
public static function siteid($format=FALSE) {
|
||||
return Company::instance()->site($format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out our site mode (dev,test,prod)
|
||||
*/
|
||||
public static function sitemode() {
|
||||
return Company::instance()->sitemode();
|
||||
}
|
||||
|
||||
public static function sitename() {
|
||||
return Company::instance()->name();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->load('config')->email_admin_only;
|
||||
|
||||
if (is_null($config) OR ! is_array($config) OR empty($config[$template]))
|
||||
return FALSE;
|
||||
else
|
||||
return $config[$template];
|
||||
}
|
||||
|
||||
public static function theme() {
|
||||
// If we are using user admin pages (and login), we'll choose the admin theme.
|
||||
if (! empty(URL::$method_directory[strtolower(Request::current()->directory())]) OR in_array(strtolower(Request::current()->controller()),array('login')))
|
||||
return 'theme/'.Kohana::$config->load('config')->theme_admin;
|
||||
else
|
||||
return 'theme/'.Kohana::$config->load('config')->theme;
|
||||
}
|
||||
|
||||
public static function time($date) {
|
||||
return date(Company::instance()->time_format(),($date ? $date : time()));
|
||||
}
|
||||
}
|
||||
?>
|
33
application/classes/Controller/Account.php
Normal file
33
application/classes/Controller/Account.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides account management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Account extends Controller_TemplateDefault {
|
||||
public function action_group() {
|
||||
$output = '';
|
||||
|
||||
$cg = $this->ao->group->find_all();
|
||||
|
||||
foreach ($cg as $go) {
|
||||
$output .= sprintf('Group %s: %s<br/>',$go->id,$go->display('name'));
|
||||
|
||||
foreach ($go->list_childgrps(TRUE) as $cgo)
|
||||
$output .= sprintf('- %s: %s (%s)<br/>',$cgo->id,$cgo->display('name'),$cgo->parent_id);
|
||||
|
||||
$output .= sprintf('END Group %s<br/><br/>',$go->id);
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'title'=>'Group Structure',
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
17
application/classes/Controller/Admin/Account.php
Normal file
17
application/classes/Controller/Admin/Account.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Admin Account management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Account extends Controller_Account {
|
||||
protected $secure_actions = array(
|
||||
'group'=>FALSE, // @todo Testing
|
||||
);
|
||||
}
|
||||
?>
|
130
application/classes/Controller/Admin/Module.php
Normal file
130
application/classes/Controller/Admin/Module.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides MODULE management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Module extends Controller_Module {
|
||||
protected $secure_actions = array(
|
||||
'add'=>TRUE,
|
||||
'edit'=>TRUE,
|
||||
'list'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the list of methods for a class
|
||||
*/
|
||||
protected function _methods($class) {
|
||||
// Get a list of methods this module has
|
||||
$ch = 'Controller_%s';
|
||||
$methods = array();
|
||||
|
||||
// List of classes where all our methods are, including this one.
|
||||
$classes = URL::$method_directory;
|
||||
array_unshift($classes,'');
|
||||
|
||||
foreach ($classes as $c) {
|
||||
$cn = Kohana::classname('Controller_'.$c ? $c.'_'.$class : $class);
|
||||
|
||||
if (class_exists($cn)) {
|
||||
$r = new ReflectionClass($cn);
|
||||
|
||||
foreach ($r->getMethods() as $method)
|
||||
if (preg_match('/^Controller_(.*_)?'.$class.'$/i',$method->class) AND ! preg_match('/^_/',$method->name))
|
||||
array_push($methods,str_replace('action_',($c ? $c.'_' : $c),$method->name));
|
||||
}
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* List our installed modules
|
||||
*/
|
||||
public function action_list() {
|
||||
$mo = ORM::factory('Module');
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Defined Modules'),
|
||||
'body'=>Table::display(
|
||||
$mo->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('admin','module/edit/')),
|
||||
'name'=>array('label'=>'Name'),
|
||||
'status'=>array('label'=>'Active'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'list',
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a Module Configuration
|
||||
*
|
||||
* @todo Highlight those methods that have security, but the class does not have auth_required set to YES or the method isnt defined in secure_actions
|
||||
*/
|
||||
public function action_edit() {
|
||||
$mid = $this->request->param('id');
|
||||
$mo = ORM::factory('Module',$mid);
|
||||
|
||||
if (! $mo->loaded()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Invalid Module ID'),
|
||||
'type'=>'error',
|
||||
'body'=>sprintf(_('Module with ID %s doesnt appear to exist?'),$mid),
|
||||
));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$output = '';
|
||||
$methods = $this->_methods($mo->name);
|
||||
|
||||
// Show methods defined in the DB already.
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s ',_('Defined Module Methods For'),$mo->display('name')),
|
||||
'body'=>Table::display(
|
||||
$mo->module_method->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('admin','module_method/edit/')),
|
||||
'name'=>array('label'=>'Name'),
|
||||
'notes'=>array('label'=>'Notes'),
|
||||
'menu_display'=>array('label'=>'Menu'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'list',
|
||||
)),
|
||||
));
|
||||
|
||||
// Show new methods NOT defined in the DB already.
|
||||
foreach ($mo->module_method->find_all() as $meo)
|
||||
if (($method = array_search($meo->name,$methods)) !== false)
|
||||
unset($methods[$method]);
|
||||
|
||||
if (count($methods))
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s ',_('Undefined Module Methods For'),$mo->display('name')),
|
||||
'body'=>Table::display(
|
||||
$methods,
|
||||
25,
|
||||
array(
|
||||
'__VALUE__'=>array('label'=>'Name','url'=>URL::link('admin','module_method/add/'.$mo->id)),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'list',
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
137
application/classes/Controller/Admin/Module/Method.php
Normal file
137
application/classes/Controller/Admin/Module/Method.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides MODULE management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Module_Method extends Controller_Admin_Module {
|
||||
/**
|
||||
* Add a method to the database
|
||||
*/
|
||||
public function action_add() {
|
||||
$id = $this->request->param('id');
|
||||
$method = $this->request->param('sid');
|
||||
|
||||
$mo = ORM::factory('Module',$id);
|
||||
$mmo = ORM::factory('Module_Method');
|
||||
|
||||
if (! $mo->loaded() OR ! in_array($method,$this->_methods($mo->name)))
|
||||
throw new Kohana_Exception('Method (:method) does not exist in :class',array(':method'=>$method,':class'=>$mo->name));
|
||||
|
||||
$mmo->name = $method;
|
||||
$mmo->module_id = $mo->id;
|
||||
$mmo->values($_POST);
|
||||
|
||||
$output = '';
|
||||
|
||||
if ($_POST AND $mmo->values($_POST)->check()) {
|
||||
$mmo->save();
|
||||
|
||||
if ($mmo->saved()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Method Added'),
|
||||
'type'=>'info',
|
||||
'body'=>sprintf(_('Method %s defined to database'),$mmo->name),
|
||||
));
|
||||
|
||||
HTTP::redirect(URL::link('admin','/module/edit/'.$mo->id));
|
||||
|
||||
} else {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Method Not Saved'),
|
||||
'type'=>'error',
|
||||
'body'=>sprintf(_('Unable to define Method %s to database?'),$mmo->name),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$output .= View::factory('module/admin/method_add')
|
||||
->set('module',$mo)
|
||||
->set('method',$mmo);
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf(_('Add Method (%s) to Database for (%s)'),strtoupper($mmo->name),strtoupper($mo->name)),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a Module Configuration
|
||||
*
|
||||
* @param int $mid Module ID
|
||||
*/
|
||||
public function action_edit() {
|
||||
$mid = $this->request->param('id');
|
||||
$mmo = ORM::factory('Module_Method',$mid);
|
||||
|
||||
if (! $mmo->loaded()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Invalid Method ID'),
|
||||
'type'=>'error',
|
||||
'body'=>sprintf(_('Method with ID %s doesnt appear to exist?'),$mid),
|
||||
));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$output = '';
|
||||
|
||||
// The groups that can run this method.
|
||||
$groups = ORM::factory('Group');
|
||||
|
||||
if ($_POST) {
|
||||
foreach ($groups->find_all() as $go) {
|
||||
// If the group was defined and no longer
|
||||
if ($mmo->has('group',$go) AND (! isset($_POST['groups']) OR ! in_array($go->id,$_POST['groups']))) {
|
||||
$gm = ORM::factory('Group_Method',array('method_id'=>$mmo->id,'group_id'=>$go->id));
|
||||
|
||||
if (! $gm->delete())
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Unable to DELETE Group Method'),
|
||||
'type'=>'error',
|
||||
'body'=>sprintf(_('Unable to delete Group Method for method %s and group %s'),$mmo->name,$go->name),
|
||||
));
|
||||
|
||||
// If the group was not defined and now is
|
||||
} elseif (! $mmo->has('group',$go) AND isset($_POST['groups']) AND in_array($go->id,$_POST['groups'])) {
|
||||
$gm = ORM::factory('Group_Method')
|
||||
->values(array(
|
||||
'method_id'=>$mmo->id,
|
||||
'group_id'=>$go->id,
|
||||
));
|
||||
|
||||
if (! $gm->check() OR ! $gm->save())
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Unable to SAVE Group Method'),
|
||||
'type'=>'error',
|
||||
'body'=>sprintf(_('Unable to save Group Method for method %s and group %s'),$mmo->name,$go->name),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$output .= Form::open();
|
||||
|
||||
$output .= View::factory('module/admin/method_detail_head');
|
||||
foreach ($groups->find_all() as $go) {
|
||||
$output .= View::factory('module/admin/method_detail_body')
|
||||
->set('group',$go)
|
||||
->set('defined',$mmo->has('group',$go));
|
||||
}
|
||||
$output .= View::factory('module/admin/method_detail_foot');
|
||||
|
||||
$output .= '<div>'.Form::submit('submit',_('Update'),array('class'=>'form_button')).'</div>';
|
||||
$output .= Form::close();
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf(_('%s->%s Method'),strtoupper($mmo->module->name),strtoupper($mmo->name)),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
73
application/classes/Controller/Admin/Setup.php
Normal file
73
application/classes/Controller/Admin/Setup.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Siet Configuration Setup
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Setup extends Controller_TemplateDefault {
|
||||
protected $secure_actions = array(
|
||||
'edit'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* View/Update the site configuration
|
||||
*/
|
||||
public function action_edit() {
|
||||
$o = Company::instance()->so();
|
||||
$output = '';
|
||||
|
||||
if ($_POST) {
|
||||
// Entry updated
|
||||
if ($o->values($_POST)->check() AND $o->save())
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Site Configuration Recorded',
|
||||
'type'=>'info',
|
||||
'body'=>'Site Config successfully recorded.',
|
||||
));
|
||||
}
|
||||
|
||||
$output .= Form::open();
|
||||
|
||||
// site_details
|
||||
$output .= View::factory($this->viewpath())
|
||||
->set('o',$o);;
|
||||
|
||||
$output .= '<div>'.Form::submit('submit','submit',array('class'=>'form_button')).'</div>';
|
||||
$output .= Form::close();
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Update Site Configuration'),
|
||||
'body'=>$output,
|
||||
));
|
||||
|
||||
// module_config
|
||||
$output = '';
|
||||
$output .= View::factory($this->viewpath().'/module/head');
|
||||
|
||||
foreach ($o->module_config as $mid => $detail) {
|
||||
$mo = ORM::factory('Module',$mid);
|
||||
|
||||
$output .= View::factory($this->viewpath().'/module/body')
|
||||
->set('mo',$mo);
|
||||
|
||||
Script::add(array('type'=>'stdin','data'=>'
|
||||
$(document).ready(function() {
|
||||
$("div[id='.$mo->name.']").load("'.URL::link('admin',$mo->name.'/setup',TRUE).'");
|
||||
});'
|
||||
));
|
||||
}
|
||||
|
||||
$output .= View::factory($this->viewpath().'/module/foot');
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Update Module Specific Configuration'),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
130
application/classes/Controller/Admin/Welcome.php
Normal file
130
application/classes/Controller/Admin/Welcome.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Admin Main home page
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Welcome extends Controller_Welcome {
|
||||
protected $auth_required = TRUE;
|
||||
public $secure_actions = array(
|
||||
'index'=>TRUE,
|
||||
);
|
||||
|
||||
public function action_index() {
|
||||
$t = time();
|
||||
|
||||
// Show outstanding invoices
|
||||
$o = ORM::factory('Invoice');
|
||||
|
||||
Block_Sub::add(array(
|
||||
'title'=>'Invoices Overdue - No Auto Billing',
|
||||
'body'=>Table::display(
|
||||
$o->list_overdue_billing($t),
|
||||
25,
|
||||
array(
|
||||
'due_date'=>array('label'=>'Due Date'),
|
||||
'account->accnum()'=>array('label'=>'Num'),
|
||||
'account->name()'=>array('label'=>'Account'),
|
||||
'account->display("status")'=>array('label'=>'Active'),
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','invoice/view/')),
|
||||
'total(TRUE)'=>array('label'=>'Total','class'=>'right'),
|
||||
'due(TRUE)'=>array('label'=>'Amount Due','class'=>'right'),
|
||||
),
|
||||
array('page'=>TRUE)),
|
||||
'position'=>1,
|
||||
'order'=>1,
|
||||
));
|
||||
|
||||
Block_Sub::add(array(
|
||||
'title'=>'Invoices Overdue - Auto Billing',
|
||||
'body'=>Table::display(
|
||||
$o->list_overdue_billing($t,TRUE),
|
||||
25,
|
||||
array(
|
||||
'due_date'=>array('label'=>'Due Date'),
|
||||
'account->accnum()'=>array('label'=>'Num'),
|
||||
'account->name()'=>array('label'=>'Account'),
|
||||
'account->display("status")'=>array('label'=>'Active'),
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','invoice/view/')),
|
||||
'total(TRUE)'=>array('label'=>'Total','class'=>'right'),
|
||||
'due(TRUE)'=>array('label'=>'Amount Due','class'=>'right'),
|
||||
),
|
||||
array('page'=>TRUE)),
|
||||
'position'=>2,
|
||||
'order'=>1,
|
||||
));
|
||||
|
||||
Block_Sub::add(array(
|
||||
'title'=>'Invoices Due',
|
||||
'body'=>Table::display(
|
||||
$o->list_due(),
|
||||
25,
|
||||
array(
|
||||
'due_date'=>array('label'=>'Due Date'),
|
||||
'account->accnum()'=>array('label'=>'Num'),
|
||||
'account->name()'=>array('label'),
|
||||
'account->display("status")'=>array('label'=>'Active'),
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','invoice/view/')),
|
||||
'total(TRUE)'=>array('label'=>'Total','class'=>'right'),
|
||||
'due(TRUE)'=>array('label'=>'Amount Due','class'=>'right'),
|
||||
),
|
||||
array('show_other'=>'due()')),
|
||||
'position'=>3,
|
||||
'order'=>1,
|
||||
));
|
||||
|
||||
// Show un-applied payments
|
||||
Block_Sub::add(array(
|
||||
'title'=>'Unapplied Payments',
|
||||
'body'=>Table::display(
|
||||
ORM::factory('Payment')->list_unapplied(),
|
||||
25,
|
||||
array(
|
||||
'date_payment'=>array('label'=>'Pay Date'),
|
||||
'account->accnum()'=>array('label'=>'Num'),
|
||||
'account->name()'=>array('label'=>'Account'),
|
||||
'account->display("status")'=>array('label'=>'Active'),
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('admin','payment/view/')),
|
||||
'total_amt'=>array('label'=>'Total','class'=>'right'),
|
||||
'balance(TRUE)'=>array('label'=>'Balance','class'=>'right'),
|
||||
),
|
||||
array('show_other'=>'balance()')),
|
||||
'position'=>1,
|
||||
'order'=>2,
|
||||
));
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s %s',$this->ao->accnum(),$this->ao->first_name,$this->ao->last_name),
|
||||
'subtitle'=>_('Administrator Overview'),
|
||||
'body'=>(string)Block_Sub::factory(),
|
||||
));
|
||||
|
||||
// We are a site administrator
|
||||
$output = '';
|
||||
if ($this->ao->rtm_id == NULL) {
|
||||
$rtmo = ORM::factory('RTM',array('account_id','=',$this->ao->id))->find();
|
||||
|
||||
// Quick validation, if we are an admin, we should have an entry in the RTM table.
|
||||
if (! $rtmo->loaded())
|
||||
throw new Kohana_Exception('User :aid not set up properly',array(':aid'=>$this->ao->id));
|
||||
|
||||
$output = View::factory('welcome/admin')
|
||||
->set('o',$rtmo);
|
||||
|
||||
} else {
|
||||
$rtmo = ORM::factory('RTM',$this->ao->rtm_id);
|
||||
}
|
||||
|
||||
if ($output)
|
||||
Block::add(array(
|
||||
'title'=>sprintf('Reseller %s',$this->ao->display('company')),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
36
application/classes/Controller/Debug.php
Normal file
36
application/classes/Controller/Debug.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Debug extends Controller_TemplateDefault {
|
||||
public function before() {
|
||||
if (! in_array(Config::sitemode(),array(Kohana::DEVELOPMENT,Kohana::TESTING)))
|
||||
HTTP::redirect();
|
||||
|
||||
parent::before();
|
||||
}
|
||||
|
||||
public function action_site() {
|
||||
$output = '';
|
||||
|
||||
$output .= debug::vars(array(
|
||||
'm'=>__METHOD__,
|
||||
'site'=>Config::site(),
|
||||
'siteID'=>Company::instance()->site(),
|
||||
'siteMode'=>Config::sitemodeverbose(),
|
||||
'modules'=>Config::appmodules(),
|
||||
));
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Site debug'),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
92
application/classes/Controller/Login.php
Normal file
92
application/classes/Controller/Login.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides login capability
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
* @also [logout]
|
||||
*/
|
||||
class Controller_Login extends lnApp_Controller_Login {
|
||||
/**
|
||||
* Enable site registration
|
||||
*
|
||||
* @todo Needs to be written
|
||||
*/
|
||||
public function action_register() {
|
||||
// If user already signed-in
|
||||
if (Auth::instance()->logged_in())
|
||||
HTTP::redirect('welcome/index');
|
||||
|
||||
HTTP::redirect('login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable user password reset
|
||||
*/
|
||||
public function action_reset() {
|
||||
// Minutes to keep our token
|
||||
$token_expire = 15;
|
||||
|
||||
// If user already signed-in
|
||||
if (Auth::instance()->logged_in())
|
||||
HTTP::redirect('welcome/index');
|
||||
|
||||
// If the user posted their details to reset their password
|
||||
if ($_POST) {
|
||||
// If the username is correct, create a method token
|
||||
if (! empty($_POST['username']) AND ($ao=ORM::factory('Account',array('username'=>$_POST['username']))) AND $ao->loaded()) {
|
||||
$mmto = ORM::factory('Module_Method_Token')
|
||||
->method(array('account','user_resetpassword'))
|
||||
->account($ao)
|
||||
->uses(2)
|
||||
->expire(time()+$token_expire*60);
|
||||
|
||||
if ($mmto->generate()) {
|
||||
// Send our email with the token
|
||||
// @todo Need to provide an option if Email_Template is not installed/activited.
|
||||
// @todo Need to provide an option if account_reset_password template doesnt exist.
|
||||
$et = Email_Template::instance('account_reset_password');
|
||||
$et->to = array('account'=>array($mmto->account_id));
|
||||
$et->variables = array(
|
||||
'SITE'=>URL::base(TRUE,TRUE),
|
||||
'SITE_ADMIN'=>Company::instance()->admin(),
|
||||
'SITE_NAME'=>Company::instance()->name(),
|
||||
'TOKEN'=>$mmto->token,
|
||||
'TOKEN_EXPIRE_MIN'=>$token_expire,
|
||||
'USER_NAME'=>sprintf('%s %s',$mmto->account->first_name,$mmto->account->last_name),
|
||||
);
|
||||
$et->send();
|
||||
|
||||
// Log the password reset
|
||||
$ao->log('Password reset token sent');
|
||||
}
|
||||
|
||||
// Redirect to our password reset, the Auth will validate the token.
|
||||
} elseif (! empty($_REQUEST['token'])) {
|
||||
HTTP::redirect(URL::link('user','account/resetpassword?token='.$_REQUEST['token']));
|
||||
}
|
||||
|
||||
// Show our token screen even if the email was invalid.
|
||||
if (isset($_POST['username']))
|
||||
Block::add(array(
|
||||
'title'=>_('Reset your password'),
|
||||
'body'=>View::factory('login_reset_sent'),
|
||||
'style'=>array('css/login.css'=>'screen'),
|
||||
));
|
||||
else
|
||||
HTTP::redirect('login');
|
||||
|
||||
} else {
|
||||
Block::add(array(
|
||||
'title'=>_('Reset your password'),
|
||||
'body'=>View::factory('login_reset'),
|
||||
'style'=>array('css/login.css'=>'screen'),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
14
application/classes/Controller/Module.php
Normal file
14
application/classes/Controller/Module.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides MODULE management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Module extends Controller_TemplateDefault {
|
||||
}
|
||||
?>
|
81
application/classes/Controller/Reseller/Account.php
Normal file
81
application/classes/Controller/Reseller/Account.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Reseller Account management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Reseller
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Reseller_Account extends Controller_Account {
|
||||
protected $secure_actions = array(
|
||||
'ajaxlist'=>TRUE,
|
||||
'list'=>TRUE,
|
||||
'listlog'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Used by AJAX calls to find accounts
|
||||
* @note list_autocomplete() will limit to authorised accounts
|
||||
*/
|
||||
public function action_ajaxlist() {
|
||||
$result = array();
|
||||
|
||||
if (isset($_REQUEST['term']) AND trim($_REQUEST['term']))
|
||||
$result += ORM::factory('Account')->list_autocomplete($_REQUEST['term']);
|
||||
|
||||
$this->auto_render = FALSE;
|
||||
$this->response->headers('Content-Type','application/json');
|
||||
$this->response->body(json_encode(array_values($result)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of accounts
|
||||
*/
|
||||
public function action_list() {
|
||||
Block::add(array(
|
||||
'title'=>_('Customer List'),
|
||||
'body'=>Table::display(
|
||||
$this->filter(ORM::factory('Account')->list_active(),$this->ao->RTM->customers($this->ao->RTM),'sortkey(TRUE)','id'),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('reseller','invoice/list/')),
|
||||
'accnum()'=>array('label'=>'Num'),
|
||||
'name(TRUE)'=>array('label'=>'Account'),
|
||||
'email'=>array('label'=>'Email'),
|
||||
'invoices_due_total(NULL,TRUE)'=>array('label'=>'Invoices','class'=>'right'),
|
||||
'services_count(TRUE)'=>array('label'=>'Services','class'=>'right'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('reseller','invoice/list'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of account logins
|
||||
*/
|
||||
public function action_listlog() {
|
||||
Block::add(array(
|
||||
'title'=>_('Account Login Log'),
|
||||
'body'=>Table::display(
|
||||
$this->filter(ORM::factory('Account_Log')->find_all(),$this->ao->RTM->customers($this->ao->RTM),NULL,'account_id'),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID'),
|
||||
'date_orig'=>array('label'=>'Date'),
|
||||
'account->name()'=>array('label'=>'Account'),
|
||||
'ip'=>array('label'=>'IP Address'),
|
||||
'details'=>array('label'=>'Details'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
25
application/classes/Controller/Reseller/Welcome.php
Normal file
25
application/classes/Controller/Reseller/Welcome.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* lnApp Main home page
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Reseller
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Reseller_Welcome extends Controller_Welcome {
|
||||
protected $auth_required = TRUE;
|
||||
protected $secure_actions = array(
|
||||
'index'=>TRUE,
|
||||
);
|
||||
|
||||
public function action_index() {
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s',$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>View::factory('welcome/reseller'),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
134
application/classes/Controller/TemplateDefault.php
Normal file
134
application/classes/Controller/TemplateDefault.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides the default template controller for rendering pages.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault extends lnApp_Controller_TemplateDefault {
|
||||
protected $auth_required = TRUE;
|
||||
|
||||
// Our acccount object
|
||||
protected $ao;
|
||||
|
||||
public function __construct(Request $request, Response $response) {
|
||||
if (Config::theme())
|
||||
$this->template = Config::theme().'/page';
|
||||
|
||||
return parent::__construct($request,$response);
|
||||
}
|
||||
|
||||
protected function _headimages() {
|
||||
// This is where we should be able to change our country
|
||||
// @todo To implement
|
||||
$co = Config::country();
|
||||
HeadImages::add(array(
|
||||
'img'=>sprintf('img/country/%s.png',strtolower($co->two_code)),
|
||||
'attrs'=>array('onclick'=>"target='_blank';",'title'=>$co->display('name'))
|
||||
));
|
||||
|
||||
return HeadImages::factory();
|
||||
}
|
||||
|
||||
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() {
|
||||
return ($this->template->right) ? $this->template->right : '';
|
||||
}
|
||||
|
||||
public function before() {
|
||||
// If our action doesnt exist, no point processing any further.
|
||||
if (! method_exists($this,'action_'.Request::current()->action()))
|
||||
return;
|
||||
|
||||
if ($this->auth_required) {
|
||||
if (! count($this->secure_actions) OR (! isset($this->secure_actions[Request::current()->action()])))
|
||||
throw new Kohana_Exception('Class has no security defined :class, or no security configured for :method',array(':class'=>get_class($this),':method'=>Request::current()->action()));
|
||||
|
||||
$this->ao = Auth::instance()->get_user();
|
||||
|
||||
if (! is_null($this->ao) AND (is_string($this->ao) OR ! $this->ao->loaded()))
|
||||
throw HTTP_Exception::factory(501,'Account doesnt exist :account ?',array(':account'=>(is_string($this->ao) OR is_null($this->ao)) ? $this->ao : Auth::instance()->get_user()->id));
|
||||
}
|
||||
|
||||
parent::before();
|
||||
}
|
||||
|
||||
public function after() {
|
||||
$dc = Kohana::$config->load('config','user_default_method');
|
||||
$m = sprintf('%s/%s',Request::current()->directory(),Request::current()->controller());
|
||||
|
||||
BreadCrumb::URL(Request::current()->directory(),sprintf('%s/%s',Request::current()->directory(),$dc),FALSE);
|
||||
BreadCrumb::URL($m,method_exists($this,'action_menu') ? $m.'/menu' : sprintf('%s/%s',Request::current()->directory(),$dc),FALSE);
|
||||
|
||||
parent::after();
|
||||
}
|
||||
|
||||
/**
|
||||
* This will filter a search query to only return those accounts for a reseller
|
||||
*/
|
||||
protected function filter($o,$af,$sort=NULL,$afid=NULL) {
|
||||
$result = array();
|
||||
|
||||
foreach ($o as $x) {
|
||||
if (! is_null($afid) AND isset($x->$afid)) {
|
||||
if ((is_array($af) AND in_array($x->$afid,$af)) OR ($x->$afid == $af))
|
||||
array_push($result,$x);
|
||||
|
||||
} elseif (method_exists($x,'list_reseller')) {
|
||||
if (in_array($af,$x->list_reseller()))
|
||||
array_push($result,$x);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ($sort)
|
||||
Sort::MAsort($result,$sort);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function setup(array $config_items=array()) {
|
||||
$module = Request::current()->controller();
|
||||
|
||||
if ($_POST AND isset($_POST['module_config'][$module]))
|
||||
Config::instance()->module_config($module,$_POST['module_config'][$module])->save();
|
||||
|
||||
if ($config_items) {
|
||||
$output = '';
|
||||
$mc = Config::instance()->module_config($module);
|
||||
|
||||
$output .= Form::open();
|
||||
$output .= View::factory('setup/admin/module/head');
|
||||
|
||||
foreach ($config_items as $k=>$v)
|
||||
$output .= View::factory('setup/admin/module/body')
|
||||
->set('module',$module)
|
||||
->set('mc',$mc)
|
||||
->set('key',$k)
|
||||
->set('info',$v)
|
||||
->set('val',isset($mc[$k]) ? $mc[$k] : '');
|
||||
|
||||
$output .= View::factory('setup/admin/module/foot');
|
||||
|
||||
$output .= Form::submit('submit',_('Submit'),array('class'=>'form_button'));
|
||||
$output .= Form::close();
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s',strtoupper($module),_('Configuration')),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
23
application/classes/Controller/TemplateDefault/Admin.php
Normal file
23
application/classes/Controller/TemplateDefault/Admin.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* lnApp User Main home page controller
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault_Admin extends Controller_TemplateDefault_User {
|
||||
public function after() {
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Retire this class extension',
|
||||
'type'=>'info',
|
||||
'body'=>__METHOD__,
|
||||
));
|
||||
|
||||
return parent::after();
|
||||
}
|
||||
}
|
||||
?>
|
23
application/classes/Controller/TemplateDefault/Affiliate.php
Normal file
23
application/classes/Controller/TemplateDefault/Affiliate.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB User Main home page controller
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Affiliate
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault_Affiliate extends Controller_TemplateDefault_User {
|
||||
public function after() {
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Retire this class extension',
|
||||
'type'=>'info',
|
||||
'body'=>__METHOD__,
|
||||
));
|
||||
|
||||
return parent::after();
|
||||
}
|
||||
}
|
||||
?>
|
14
application/classes/Controller/TemplateDefault/User.php
Normal file
14
application/classes/Controller/TemplateDefault/User.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* lnApp User Main home page controller
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/User
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault_User extends Controller_TemplateDefault {
|
||||
}
|
||||
?>
|
131
application/classes/Controller/Tree.php
Normal file
131
application/classes/Controller/Tree.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends renders OSB menu tree.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Tree extends lnApp_Controller_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 array $data Tree data passed in by inherited methods
|
||||
*/
|
||||
public function action_json(array $data=array()) {
|
||||
// Get the user details
|
||||
$id = (is_null($this->request->param('id')) AND isset($_REQUEST['id'])) ? substr($_REQUEST['id'],2) : $this->request->param('id');
|
||||
$user = Auth::instance()->get_user();
|
||||
|
||||
if ($user) {
|
||||
if (! $id) {
|
||||
$modules = array();
|
||||
foreach ($user->groups() as $go)
|
||||
foreach ($go->list_parentgrps(TRUE) as $cgo)
|
||||
foreach ($cgo->module_method->find_all() as $mmo)
|
||||
if ($mmo->menu_display AND empty($modules[$mmo->module_id]))
|
||||
$modules[$mmo->module_id] = $mmo->module;
|
||||
|
||||
Sort::MAsort($modules,'name');
|
||||
|
||||
foreach ($modules as $id => $mo)
|
||||
if (! $mo->parent_id)
|
||||
array_push($data,array('id'=>$id,'name'=>$mo->name,'state'=>'closed'));
|
||||
|
||||
} else {
|
||||
$idx = NULL;
|
||||
if (preg_match('/_/',$id))
|
||||
list($id,$idx) = explode('_',$id,2);
|
||||
|
||||
$mo = ORM::factory('Module',$id);
|
||||
|
||||
$methods = array();
|
||||
if ($mo->loaded()) {
|
||||
foreach ($mo->module_method->find_all() as $mmo)
|
||||
if ($mmo->menu_display)
|
||||
foreach ($mmo->group->find_all() as $gmo)
|
||||
if ($user->has_any('group',$gmo->list_childgrps(TRUE)))
|
||||
$methods[$mmo->id] = $mmo;
|
||||
|
||||
Sort::MASort($modules,'name');
|
||||
|
||||
$subdata = array();
|
||||
foreach ($methods as $id => $mmo) {
|
||||
if (preg_match('/_/',$mmo->name)) {
|
||||
list($mode,$action) = explode('_',$mmo->name);
|
||||
|
||||
$url = URL::link($mode,$mmo->module->name.'/'.$action,TRUE);
|
||||
|
||||
} else {
|
||||
$url = URL::site($mmo->module->name.'/'.$mmo->name);
|
||||
}
|
||||
|
||||
// We can split our menus into sub menus using the _ char.
|
||||
if (preg_match('/_/',$mmo->name)) {
|
||||
list($sub,$name) = explode('_',$mmo->name,2);
|
||||
$subdata[$sub][$name]['name'] = preg_replace('/^(.*: )/','',$mmo->notes);
|
||||
$subdata[$sub][$name]['id'] = sprintf('%s_%s',$mmo->module_id,$id);
|
||||
$subdata[$sub][$name]['href'] = (empty($details['page']) ? $url : $details['page']);
|
||||
|
||||
} else {
|
||||
// We dont want to show these items again, if we can through on a submenu
|
||||
if (! $idx)
|
||||
array_push($data,array(
|
||||
'id'=>sprintf('%s_%s',$mmo->module_id,$id),
|
||||
'name'=>$mmo->name,
|
||||
'state'=>'none',
|
||||
'attr_id'=>sprintf('%s_%s',$mmo->module->name,$id),
|
||||
'attr_href'=>(empty($details['page']) ? $url : $details['page'])
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// If our sub menus only have 1 branch, then we'll display it as normal.
|
||||
if (count($subdata) == 1) {
|
||||
$sk = array_keys($subdata);
|
||||
$idx = array_shift($sk);
|
||||
}
|
||||
|
||||
if ($idx)
|
||||
foreach ($subdata[$idx] as $k=>$v) {
|
||||
array_push($data,array(
|
||||
'id'=>$v['id'],
|
||||
'name'=>$v['name'],
|
||||
'state'=>'none',
|
||||
'attr_id'=>$v['id'],
|
||||
'attr_href'=>$v['href']
|
||||
));
|
||||
}
|
||||
|
||||
else
|
||||
foreach ($subdata as $t=>$x)
|
||||
array_push($data,array('id'=>$mmo->module_id.'_'.$t,'name'=>$t,'state'=>'closed'));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->output = array();
|
||||
|
||||
foreach ($data as $branch) {
|
||||
array_push($this->output,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']),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return parent::action_json($data);
|
||||
}
|
||||
}
|
||||
?>
|
104
application/classes/Controller/User/Account.php
Normal file
104
application/classes/Controller/User/Account.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides User Account Update functions
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/User
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_User_Account extends Controller_Account {
|
||||
protected $secure_actions = array(
|
||||
'edit'=>TRUE,
|
||||
'resetpassword'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Enable User to Edit their Account Details
|
||||
*/
|
||||
public function action_edit() {
|
||||
// Store our new values
|
||||
$this->ao->values($_POST);
|
||||
|
||||
// Run validation and save
|
||||
if ($this->ao->changed())
|
||||
if ($this->ao->check()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record updated'),
|
||||
'type'=>'info',
|
||||
'body'=>_('Your account record has been updated.')
|
||||
));
|
||||
|
||||
$this->ao->save();
|
||||
|
||||
} else {
|
||||
$output = '';
|
||||
foreach ($this->ao->validation()->errors('forms/login') as $field => $error)
|
||||
$output .= sprintf('<li><b>%s</b> %s</li>',$field,$error);
|
||||
|
||||
if ($output)
|
||||
$output = sprintf('<ul>%s</ul>',$output);
|
||||
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record NOT updated'),
|
||||
'type'=>'error',
|
||||
'body'=>_('Your updates didnt pass validation.').'<br/>'.$output,
|
||||
));
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s - %s',_('Account Edit'),$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>View::factory($this->viewpath())
|
||||
->set('record',$this->ao),
|
||||
));
|
||||
}
|
||||
|
||||
public function action_resetpassword() {
|
||||
// @todo Fix this next logic, since matches_ifset is not being called when the value is on the form, but empty
|
||||
if (empty($_POST['password_confirm']))
|
||||
$_POST['password_confirm'] = ' ';
|
||||
|
||||
// Store our new values
|
||||
$this->ao->values($_POST);
|
||||
|
||||
// Run validation and save
|
||||
if ($this->ao->changed())
|
||||
if ($this->ao->check()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record updated'),
|
||||
'type'=>'info',
|
||||
'body'=>_('Your account record has been updated.')
|
||||
));
|
||||
|
||||
$this->ao->save();
|
||||
|
||||
// Log the password reset
|
||||
$this->ao->log('Password reset');
|
||||
|
||||
HTTP::redirect('login');
|
||||
|
||||
} else {
|
||||
$output = '';
|
||||
foreach ($this->ao->validation()->errors('forms/login') as $field => $error)
|
||||
$output .= sprintf('<li><b>%s</b> %s</li>',$field,$error);
|
||||
|
||||
if ($output)
|
||||
$output = sprintf('<ul>%s</ul>',$output);
|
||||
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record NOT updated'),
|
||||
'type'=>'error',
|
||||
'body'=>_('Your updates didnt pass validation.').'<br/>'.$output,
|
||||
));
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Password Reset'),
|
||||
'body'=>View::factory($this->viewpath())
|
||||
->set('record',$this->ao),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
25
application/classes/Controller/User/Welcome.php
Normal file
25
application/classes/Controller/User/Welcome.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* lnApp Main home page
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/User
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_User_Welcome extends Controller_Welcome {
|
||||
protected $auth_required = TRUE;
|
||||
protected $secure_actions = array(
|
||||
'index'=>TRUE,
|
||||
);
|
||||
|
||||
public function action_index() {
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s',$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>View::factory('welcome/user'),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
29
application/classes/Controller/Welcome.php
Normal file
29
application/classes/Controller/Welcome.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Main home page
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Welcome extends Controller_TemplateDefault {
|
||||
protected $auth_required = FALSE;
|
||||
|
||||
public function action_index() {
|
||||
if (! Kohana::$config->load('config')->appname)
|
||||
HTTP::redirect('guide/app');
|
||||
|
||||
// @todo This should be in the DB or something.
|
||||
HTTP::redirect('product/categorys');
|
||||
}
|
||||
|
||||
public function action_breadcrumb() {
|
||||
$this->auto_render = FALSE;
|
||||
|
||||
$this->response->body(Session::instance()->get_once('breadcrumb'));
|
||||
}
|
||||
}
|
||||
?>
|
15
application/classes/Cookie.php
Normal file
15
application/classes/Cookie.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's Cookie
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Cookie extends Kohana_Cookie {
|
||||
public static $salt = 'OSB';
|
||||
}
|
||||
?>
|
19
application/classes/Country.php
Normal file
19
application/classes/Country.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Country routines
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Country {
|
||||
public static function icon($cid) {
|
||||
$co = ORM::factory('Country',$cid);
|
||||
|
||||
return HTML::image(sprintf('media/img/country/%s.png',strtolower($co->two_code)),array('alt'=>$co->currency()->symbol));
|
||||
}
|
||||
}
|
||||
?>
|
21
application/classes/Currency.php
Normal file
21
application/classes/Currency.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class is for all page attributes.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Currency {
|
||||
public static function display($amount) {
|
||||
return Num::format($amount,Company::instance()->decimals(),TRUE);
|
||||
}
|
||||
|
||||
public static function round($amount) {
|
||||
return Num::round($amount,Company::instance()->decimals());
|
||||
}
|
||||
}
|
||||
?>
|
35
application/classes/DB.php
Normal file
35
application/classes/DB.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's DB
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class DB extends Kohana_DB {
|
||||
// Add the site_id to the delete query
|
||||
public static function delete($table = NULL)
|
||||
{
|
||||
$db = new Database_Query_Builder_Delete($table);
|
||||
|
||||
if (! in_array($table,ORM::$no_site_id_tables))
|
||||
return $db->where($table.'.site_id','=',Company::instance()->site());
|
||||
else
|
||||
return $db;
|
||||
}
|
||||
|
||||
// Add the site_id to the update query
|
||||
final public static function update($table = NULL)
|
||||
{
|
||||
$db = new Database_Query_Builder_Update($table);
|
||||
|
||||
if (! in_array($table,ORM::$no_site_id_tables))
|
||||
return $db->where($table.'.site_id','=',Company::instance()->site());
|
||||
else
|
||||
return $db;
|
||||
}
|
||||
}
|
||||
?>
|
19
application/classes/Database/Mysql.php
Normal file
19
application/classes/Database/Mysql.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?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
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Database_MySQL extends Kohana_Database_MySQL {
|
||||
// MySQL uses a backtick for identifiers
|
||||
protected $_identifier = '';
|
||||
}
|
||||
?>
|
52
application/classes/Editor.php
Normal file
52
application/classes/Editor.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class is for rendering the tinyMCE editor
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Editor {
|
||||
private static $added = FALSE;
|
||||
|
||||
public static function add() {
|
||||
if (static::$added)
|
||||
return;
|
||||
|
||||
static::$added = TRUE;
|
||||
|
||||
Script::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'js/jquery-1.4.2.js',
|
||||
));
|
||||
Script::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'js/tiny_mce/tiny_mce.js',
|
||||
));
|
||||
Script::add(array(
|
||||
'type'=>'stdin',
|
||||
'data'=>'
|
||||
tinyMCE.init({
|
||||
mode : "specific_textareas",
|
||||
editor_selector : "mceEditor",
|
||||
theme : "advanced",
|
||||
plugins : "table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,preview,media,searchreplace,print",
|
||||
theme_advanced_buttons1_add : "fontselect,fontsizeselect",
|
||||
theme_advanced_buttons2_add : "separator,insertdate,inserttime,preview,separator,forecolor,backcolor",
|
||||
theme_advanced_buttons2_add_before: "cut,copy,paste,separator,search,replace,separator",
|
||||
theme_advanced_buttons3_add_before : "tablecontrols,separator",
|
||||
theme_advanced_buttons3_add : "iespell,media,advhr",
|
||||
theme_advanced_toolbar_location : "bottom",
|
||||
theme_advanced_toolbar_align : "center",
|
||||
plugin_insertdate_dateFormat : "%Y-%m-%d",
|
||||
plugin_insertdate_timeFormat : "%H:%M:%S",
|
||||
extended_valid_elements : "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",
|
||||
relative_urls: "true",
|
||||
width : "100%"
|
||||
});'));
|
||||
}
|
||||
}
|
||||
?>
|
18
application/classes/Form.php
Normal file
18
application/classes/Form.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's Form
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Form extends Kohana_Form {
|
||||
// Enable 3.0 features, default to current URI for empty Form::open()
|
||||
public static function open($action = NULL, array $attributes = NULL) {
|
||||
return parent::open(is_null($action) ? Request::detect_uri() : $action,$attributes);
|
||||
}
|
||||
}
|
||||
?>
|
25
application/classes/HTTP/Exception/404.php
Normal file
25
application/classes/HTTP/Exception/404.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's 404 Exception
|
||||
*
|
||||
* @package OSB
|
||||
* @category Exceptions
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class HTTP_Exception_404 extends Kohana_HTTP_Exception_404 {
|
||||
public function get_response() {
|
||||
$response = Response::factory();
|
||||
$response->status($this->_code);
|
||||
|
||||
$view = View::factory('errors/404');
|
||||
$view->message = $this->getMessage();
|
||||
|
||||
$response->body($view->render());
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
?>
|
34
application/classes/HTTP/Exception/501.php
Normal file
34
application/classes/HTTP/Exception/501.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides a custom 501 Exception to catch OSB specific errors.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Exceptions
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class HTTP_Exception_501 extends Kohana_HTTP_Exception {
|
||||
protected $_code = 501;
|
||||
|
||||
public function __construct($message='',array $variables=NULL,$code=0) {
|
||||
parent::__construct($message,$variables,$code);
|
||||
|
||||
$response = Response::factory();
|
||||
$response->status($this->_code);
|
||||
|
||||
// @todo This is not working as cleanly as I would like - ie: we shouldnt need to publish the headers ourselves?
|
||||
header(':', true, 501);
|
||||
|
||||
if (Kohana::$config->load('debug')->show_errors)
|
||||
$response->body(View::factory('errors/501')->set('message',$this->getMessage())->render());
|
||||
else
|
||||
$response->body('Dang, something went wrong, tell us how we got here...');
|
||||
|
||||
echo $response->render();
|
||||
|
||||
exit (501);
|
||||
}
|
||||
}
|
||||
?>
|
56
application/classes/Kohana.php
Normal file
56
application/classes/Kohana.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's Core
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class Kohana extends Kohana_Core {
|
||||
/**
|
||||
* @compat Restore KH 3.1 functionality
|
||||
* @var boolean True if Kohana is running from the command line
|
||||
*/
|
||||
public static $is_cli = FALSE;
|
||||
|
||||
/**
|
||||
* @compat Restore KH 3.1 functionality
|
||||
*/
|
||||
public static function init(array $settings = NULL) {
|
||||
parent::init($settings);
|
||||
|
||||
// Determine if we are running in a command line environment
|
||||
Kohana::$is_cli = (PHP_SAPI === 'cli');
|
||||
}
|
||||
|
||||
/**
|
||||
* Override Kohana's shutdown_handler()
|
||||
*
|
||||
* When set up for multi-site, we need to disable Kohana's caching
|
||||
* unless each site has exactly the same modules enabled.
|
||||
* This is because Kohana::$file is cached with the enabled modules
|
||||
* and is not OSB multi-site aware.
|
||||
*/
|
||||
public static function shutdown_handler() {
|
||||
// If caching isnt enabled, we can skip this anyway
|
||||
if (! Kohana::$caching)
|
||||
return parent::shutdown_handler();
|
||||
|
||||
Kohana::$caching = FALSE;
|
||||
$result = parent::shutdown_handler();
|
||||
Kohana::$caching = TRUE;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out our Class Name as per Kohana's standards
|
||||
*/
|
||||
public static function classname($name) {
|
||||
return str_replace(' ','_',ucwords(strtolower(str_replace('_',' ',$name))));
|
||||
}
|
||||
}
|
||||
?>
|
64
application/classes/Kohana/Exception.php
Normal file
64
application/classes/Kohana/Exception.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access');
|
||||
/**
|
||||
* Kohana exception class. Translates exceptions using the [I18n] class.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Kohana_Exception extends Kohana_Kohana_Exception {
|
||||
/**
|
||||
* Logs an exception in the database. If that fails fall back to Kohana's Logging.
|
||||
*
|
||||
* @uses Kohana_Exception::text
|
||||
* @param Exception $e
|
||||
* @param int $level
|
||||
* @return void
|
||||
*/
|
||||
public static function log(Exception $e,$level=Log::EMERGENCY) {
|
||||
try {
|
||||
$eo = ORM::factory('Log_Error');
|
||||
$eo->message = Kohana_Exception::text($e);
|
||||
$eo->account_id = Auth::instance()->get_user()->id;
|
||||
$eo->module = (Request::current()->directory() ? Request::current()->directory().'_' : '').Request::current()->controller();
|
||||
$eo->method = Request::current()->action();
|
||||
$eo->save();
|
||||
|
||||
} catch (Exception $x) {
|
||||
return parent::log($e,$level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect errors to the main page after showing a system message.
|
||||
* The error should be logged in the DB.
|
||||
*
|
||||
* @param Exception $e
|
||||
* @return Response
|
||||
*/
|
||||
public static function response(Exception $e) {
|
||||
try {
|
||||
if (Kohana::$config->load('debug')->show_errors) {
|
||||
return parent::response($e);
|
||||
} else {
|
||||
SystemMessage::add(array(
|
||||
'title'=>'An Error Occured.',
|
||||
'type'=>'error',
|
||||
'body'=>'Dont panic, its been logged.',
|
||||
));
|
||||
|
||||
// We'll redirect to the main page.
|
||||
$response = Response::factory();
|
||||
$response->status(302);
|
||||
$response->headers('Location',URL::site());
|
||||
return $response;
|
||||
}
|
||||
|
||||
} catch (Exception $x) {
|
||||
return parent::response($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
17
application/classes/Minion/Task.php
Normal file
17
application/classes/Minion/Task.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's Minion CLI Module
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class Minion_Task extends Kohana_Minion_Task {
|
||||
protected $_options = array(
|
||||
'site'=>NULL,
|
||||
);
|
||||
}
|
||||
?>
|
194
application/classes/Model/Account.php
Normal file
194
application/classes/Model/Account.php
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This Model manages both the accounts that users use to login to the system, as well as the account where services are owned.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Account extends Model_Auth_UserDefault {
|
||||
// Relationships
|
||||
protected $_has_many = array(
|
||||
'user_tokens' => array('model' => 'user_token'),
|
||||
'email_log' => array('far_key'=>'id'),
|
||||
'group' => array('through' => 'account_group'),
|
||||
'invoice' => array('far_key'=>'id'),
|
||||
'payment'=>array('far_key'=>'id'),
|
||||
'service' => array('far_key'=>'id'),
|
||||
);
|
||||
|
||||
protected $_has_one = array(
|
||||
'country'=>array('foreign_key'=>'id'),
|
||||
'currency'=>array('foreign_key'=>'id'),
|
||||
'language'=>array('foreign_key'=>'id'),
|
||||
'RTM'=>array('far_key'=>'id'),
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'date_orig'=>array(
|
||||
array('Config::date',array(':value')),
|
||||
),
|
||||
'date_last'=>array(
|
||||
array('Config::date',array(':value')),
|
||||
),
|
||||
'status'=>array(
|
||||
array('StaticList_YesNo::display',array(':value')),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Our account number format
|
||||
*/
|
||||
public function accnum() {
|
||||
return sprintf('%s-%04s',Company::instance()->site(TRUE),$this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the groups that an account belongs to
|
||||
*/
|
||||
public function groups() {
|
||||
return $this->group->where_active()->find_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all invoices for this account
|
||||
*/
|
||||
public function invoices($processed=FALSE) {
|
||||
$o = $this->invoice;
|
||||
|
||||
return $processed ? $o->find_all() : $o->where_unprocessed()->find_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of due invoices for this account
|
||||
*
|
||||
* @param int Date (in secs) to only retrieve invoices prior to this date
|
||||
*/
|
||||
public function invoices_due($date=NULL) {
|
||||
$result = array();
|
||||
|
||||
foreach ($this->invoices() as $io)
|
||||
if ((is_null($date) OR $io->date_orig < $date) AND $io->due())
|
||||
$result[$io->id] = $io;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the total of invoices due for this account
|
||||
*/
|
||||
public function invoices_due_total($date=NULL,$format=FALSE) {
|
||||
$result = 0;
|
||||
|
||||
foreach ($this->invoices_due($date) as $io)
|
||||
$result += $io->due();
|
||||
|
||||
return $format ? Currency::display($result) : $result;
|
||||
}
|
||||
|
||||
public function log($message) {
|
||||
// Log the logout
|
||||
$alo = ORM::factory('Account_Log');
|
||||
$alo->account_id = $this->id;
|
||||
$alo->ip = Request::$client_ip;
|
||||
$alo->details = $message;
|
||||
$alo->save();
|
||||
|
||||
return $alo->saved();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an account name
|
||||
*/
|
||||
public function name($withcompany=FALSE) {
|
||||
if ($withcompany)
|
||||
return sprintf('%s %s%s',$this->first_name,$this->last_name,$this->company ? sprintf(' (%s)',$this->company) : '');
|
||||
else
|
||||
return sprintf('%s %s',$this->first_name,$this->last_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all the services for this account
|
||||
*/
|
||||
public function services($active=TRUE) {
|
||||
$o = $this->service;
|
||||
|
||||
return $active ? $o->where_active()->find_all() : $o->find_all();
|
||||
}
|
||||
|
||||
public function services_count($active=TRUE,$afid=NULL) {
|
||||
return $this->services($active)->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* The key we use to sort entries of this model type
|
||||
*/
|
||||
public function sortkey($withcompany=FALSE) {
|
||||
$sk = '';
|
||||
|
||||
if ($withcompany AND $this->company)
|
||||
$sk .= $this->company.' ';
|
||||
|
||||
return $sk.sprintf('%s %s',$this->last_name,$this->first_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for accounts matching a term
|
||||
*/
|
||||
public function list_autocomplete($term,$index='id',array $limit=array()) {
|
||||
$result = array();
|
||||
$ao = Auth::instance()->get_user();
|
||||
|
||||
$this->clear();
|
||||
$this->where_active();
|
||||
$value = 'name(TRUE)';
|
||||
|
||||
// Build our where clause
|
||||
// First Name, Last name
|
||||
if (preg_match('/\ /',$term)) {
|
||||
list($fn,$ln) = explode(' ',$term,2);
|
||||
|
||||
$this->where_open()
|
||||
->where('first_name','like','%'.$fn.'%')
|
||||
->and_where('last_name','like','%'.$ln.'%')
|
||||
->where_close()
|
||||
->or_where('company','like','%'.$term.'%');
|
||||
|
||||
} elseif (is_numeric($term)) {
|
||||
$this->where('id','like','%'.$term.'%');
|
||||
|
||||
} elseif (preg_match('/\@/',$term)) {
|
||||
$this->where('email','like','%'.$term.'%');
|
||||
$value = 'email';
|
||||
|
||||
} else {
|
||||
$this->where_open()
|
||||
->where('company','like','%'.$term.'%')
|
||||
->or_where('first_name','like','%'.$term.'%')
|
||||
->or_where('last_name','like','%'.$term.'%')
|
||||
->or_where('email','like','%'.$term.'%')
|
||||
->where_close();
|
||||
}
|
||||
|
||||
foreach ($limit as $w) {
|
||||
list($k,$s,$v) = $w;
|
||||
|
||||
$this->and_where($k,$s,$v);
|
||||
}
|
||||
|
||||
// Restrict results to authorised accounts
|
||||
$this->and_where('id','IN',$ao->RTM->customers($ao->RTM));
|
||||
|
||||
foreach ($this->find_all() as $o)
|
||||
$result[$o->$index] = array(
|
||||
'value'=>$o->$index,
|
||||
'label'=>sprintf('ACC %s: %s',$o->id,Table::resolve($o,$value)),
|
||||
);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
?>
|
27
application/classes/Model/Account/Log.php
Normal file
27
application/classes/Model/Account/Log.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class supports Account Login Logging
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Account_Log extends ORM_OSB {
|
||||
protected $_belongs_to = array(
|
||||
'account'=>array(),
|
||||
);
|
||||
|
||||
protected $_sorting = array(
|
||||
'id'=>'DESC',
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'date_orig'=>array(
|
||||
array('Config::datetime',array(':value')),
|
||||
),
|
||||
);
|
||||
}
|
||||
?>
|
14
application/classes/Model/Affiliate.php
Normal file
14
application/classes/Model/Affiliate.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Affiliate
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Affiliate extends ORM_OSB {
|
||||
}
|
||||
?>
|
13
application/classes/Model/Auth/RoleDefault.php
Normal file
13
application/classes/Model/Auth/RoleDefault.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Auth_RoleDefault extends Model_Auth_Role {
|
||||
}
|
||||
?>
|
76
application/classes/Model/Auth/UserDefault.php
Normal file
76
application/classes/Model/Auth/UserDefault.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Auth_UserDefault extends Model_Auth_User {
|
||||
// Validation rules
|
||||
public function rules() {
|
||||
return array(
|
||||
'username' => array(
|
||||
array('not_empty'),
|
||||
array('min_length', array(':value', 4)),
|
||||
array('max_length', array(':value', 32)),
|
||||
),
|
||||
'password' => array(
|
||||
array('not_empty'),
|
||||
array('min_length', array(':value', 5)),
|
||||
array('max_length', array(':value', 32)),
|
||||
),
|
||||
'email' => array(
|
||||
array('not_empty'),
|
||||
array('min_length', array(':value', 4)),
|
||||
array('max_length', array(':value', 127)),
|
||||
array('email'),
|
||||
),
|
||||
// @todo To test
|
||||
'password_confirm' => array(
|
||||
array('matches_ifset', array(':validation', 'password', 'password_confirm')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Validation callbacks
|
||||
// @todo _callbacks no longer used
|
||||
protected $_callbacks = array(
|
||||
'username' => array('username_available'),
|
||||
'email' => array('email_available'),
|
||||
);
|
||||
|
||||
// Columns to ignore
|
||||
protected $_ignored_columns = array('password_confirm');
|
||||
|
||||
/*
|
||||
* Complete our login
|
||||
*
|
||||
* For some database logins, we may not want to record the user last login
|
||||
* details in the repository, so we just override that parent function
|
||||
* here.
|
||||
*
|
||||
* We can also do some other post-login actions here.
|
||||
* @todo Maybe we can do our session update here.
|
||||
*/
|
||||
public function complete_login() {
|
||||
return $this->log('Logged In');
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug function to see that has() finds
|
||||
* @todo This function could be removed
|
||||
*/
|
||||
public function has_list($alias, $model) {
|
||||
// Return list of matches
|
||||
return DB::select()
|
||||
->from($this->_has_many[$alias]['through'])
|
||||
->where($this->_has_many[$alias]['foreign_key'], '=', $this->pk())
|
||||
->where($this->_has_many[$alias]['far_key'], '=', $model->pk())
|
||||
->execute($this->_db)
|
||||
->as_array();
|
||||
}
|
||||
}
|
||||
?>
|
17
application/classes/Model/Country.php
Normal file
17
application/classes/Model/Country.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Country Model
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Country extends ORM_OSB {
|
||||
public function currency() {
|
||||
return ORM::factory('Currency')->where('country_id','=',$this->id)->find();
|
||||
}
|
||||
}
|
||||
?>
|
14
application/classes/Model/Currency.php
Normal file
14
application/classes/Model/Currency.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Currency Model
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Currency extends ORM_OSB {
|
||||
}
|
||||
?>
|
84
application/classes/Model/Group.php
Normal file
84
application/classes/Model/Group.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Group extends Model_Auth_RoleDefault {
|
||||
// Relationships
|
||||
protected $_has_many = array(
|
||||
'account'=>array('through'=>'account_group'),
|
||||
'module_method'=>array('through'=>'group_method','far_key'=>'method_id'),
|
||||
);
|
||||
|
||||
protected $_sorting = array(
|
||||
'name'=>'ASC',
|
||||
);
|
||||
|
||||
// Validation rules
|
||||
protected $_rules = array(
|
||||
'name' => array(
|
||||
'not_empty' => NULL,
|
||||
'min_length' => array(4),
|
||||
'max_length' => array(32),
|
||||
),
|
||||
'description' => array(
|
||||
'max_length' => array(255),
|
||||
),
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'status'=>array(
|
||||
array('StaticList_YesNo::display',array(':value')),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* This function will, given a group, list all of the children that
|
||||
* are also related to this group, in the group heirarchy.
|
||||
*/
|
||||
public function list_childgrps($incParent=FALSE) {
|
||||
$result = array();
|
||||
|
||||
if (! $this->loaded())
|
||||
return $result;
|
||||
|
||||
foreach (ORM::factory('Group')->where_active()->and_where('parent_id','=',$this)->find_all() as $go) {
|
||||
array_push($result,$go);
|
||||
|
||||
$result = array_merge($result,$go->list_childgrps());
|
||||
}
|
||||
|
||||
if ($incParent)
|
||||
array_push($result,$this);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will, given a group, list all of the parent that
|
||||
* are also related to this group, in the group heirarchy.
|
||||
*/
|
||||
public function list_parentgrps($incParent=FALSE) {
|
||||
$result = array();
|
||||
|
||||
if (! $this->loaded())
|
||||
return $result;
|
||||
|
||||
foreach (ORM::factory('Group')->where_active()->and_where('id','=',$this->parent_id)->find_all() as $go) {
|
||||
array_push($result,$go);
|
||||
|
||||
$result = array_merge($result,$go->list_parentgrps());
|
||||
}
|
||||
|
||||
if ($incParent)
|
||||
array_push($result,$this);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
?>
|
25
application/classes/Model/Group/Method.php
Normal file
25
application/classes/Model/Group/Method.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Application Module Method Model
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Group_Method extends ORM_OSB {
|
||||
// Relationships
|
||||
protected $_has_one = array(
|
||||
'record_id'=>array(),
|
||||
);
|
||||
protected $_belongs_to = array(
|
||||
'group'=>array(),
|
||||
);
|
||||
|
||||
// This module doesnt keep track of column updates automatically
|
||||
protected $_created_column = FALSE;
|
||||
protected $_updated_column = FALSE;
|
||||
}
|
||||
?>
|
15
application/classes/Model/Language.php
Normal file
15
application/classes/Model/Language.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Language Model
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Language extends ORM_OSB {
|
||||
protected $_form = array('id'=>'id','value'=>'name');
|
||||
}
|
||||
?>
|
14
application/classes/Model/Log/Error.php
Normal file
14
application/classes/Model/Log/Error.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* Log errors in the database.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Log_Error extends ORM_OSB {
|
||||
}
|
||||
?>
|
51
application/classes/Model/Module.php
Normal file
51
application/classes/Model/Module.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?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
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Module extends ORM_OSB {
|
||||
// Relationships
|
||||
protected $_has_many = array(
|
||||
'module_method'=>array('far_key'=>'id'),
|
||||
);
|
||||
protected $_has_one = array(
|
||||
'record_id'=>array('model'=>'Record_ID','far_key'=>'id'),
|
||||
);
|
||||
|
||||
protected $_sorting = array(
|
||||
'status'=>'DESC',
|
||||
'name'=>'ASC',
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'name'=>array(
|
||||
array('strtoupper',array(':value')),
|
||||
),
|
||||
'status'=>array(
|
||||
array('StaticList_YesNo::display',array(':value')),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Return an instance of this Module's Model
|
||||
*
|
||||
* @param $id PK of Model
|
||||
*/
|
||||
public function instance($id=NULL) {
|
||||
return ORM::factory(ucwords($this->name),$id);
|
||||
}
|
||||
|
||||
public function list_external() {
|
||||
return $this->_where_active()->where('external','=',TRUE)->find_all();
|
||||
}
|
||||
}
|
||||
?>
|
43
application/classes/Model/Module/Method.php
Normal file
43
application/classes/Model/Module/Method.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Application Module Method Model
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Module_Method extends ORM_OSB {
|
||||
// Relationships
|
||||
protected $_belongs_to = array(
|
||||
'module'=>array(),
|
||||
);
|
||||
protected $_has_one = array(
|
||||
'record_id'=>array(),
|
||||
);
|
||||
protected $_has_many = array(
|
||||
'group'=>array('through'=>'group_method','foreign_key'=>'method_id')
|
||||
);
|
||||
|
||||
protected $_sorting = array(
|
||||
'name'=>'ASC',
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'menu_display'=>array(
|
||||
array('StaticList_YesNo::display',array(':value')),
|
||||
),
|
||||
);
|
||||
|
||||
// This module doesnt keep track of column updates automatically
|
||||
protected $_created_column = FALSE;
|
||||
protected $_updated_column = FALSE;
|
||||
|
||||
// Return the method name.
|
||||
public function name() {
|
||||
return sprintf('%s::%s',$this->module->name,$this->name);
|
||||
}
|
||||
}
|
||||
?>
|
112
application/classes/Model/Module/Method/Token.php
Normal file
112
application/classes/Model/Module/Method/Token.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Application Module Method Token Model
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Module_Method_Token extends ORM_OSB {
|
||||
// Relationships
|
||||
protected $_belongs_to = array(
|
||||
'account'=>array(),
|
||||
'module_method'=>array('foreign_key'=>'method_id'),
|
||||
);
|
||||
protected $_has_one = array(
|
||||
'record_id'=>array(),
|
||||
);
|
||||
|
||||
// This module doesnt keep track of column updates automatically
|
||||
protected $_update_column = FALSE;
|
||||
|
||||
public function method(array $modmeth) {
|
||||
list($module,$method) = $modmeth;
|
||||
|
||||
if (! $method instanceof Model_Module_Method) {
|
||||
if (is_numeric($module))
|
||||
$mo = ORM::factory('Module',$module);
|
||||
elseif (is_string($module))
|
||||
$mo = ORM::factory('Module',array('name'=>$module));
|
||||
elseif (! $module instanceof Model_Module)
|
||||
throw new Kohana_Exception('Unknown module :module',array(':module'=>serialize($module)));
|
||||
else
|
||||
$mo = $module;
|
||||
|
||||
if (! $mo->loaded())
|
||||
throw new Kohana_Exception('Unknown module :module - not loaded?',array(':module'=>$mo->id));
|
||||
|
||||
if (is_numeric($method))
|
||||
$mmo = ORM::factory('Module_Method',$method);
|
||||
elseif (is_string($method))
|
||||
$mmo = ORM::factory('Module_Method',array('name'=>$method,'module_id'=>$mo->id));
|
||||
else
|
||||
throw new Kohana_Exception('Unknown method :method',array(':method'=>serialize($method)));
|
||||
} else
|
||||
$mmo = $method;
|
||||
|
||||
if (! $mmo->loaded())
|
||||
throw new Kohana_Exception('Unknown method :method - not loaded?',array(':method'=>$mmo->id));
|
||||
|
||||
$this->method_id = $mmo->id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function account($account) {
|
||||
if (! $account instanceof Model_Account) {
|
||||
if (is_numeric($account))
|
||||
$ao = ORM::factory('Account',$account);
|
||||
else
|
||||
throw new Kohana_Exception('Unknown account :account',array(':account'=>serialize($account)));
|
||||
} else
|
||||
$ao = $account;
|
||||
|
||||
$this->account_id = $ao->id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function uses($uses) {
|
||||
$this->uses = $uses;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function expire($expire) {
|
||||
$this->date_expire = $expire;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// @todo Login Reset: When called within a timelimit (so existing token already exists), is returning true but password reset emails have blanks where the tokens are
|
||||
public function generate() {
|
||||
if (! $this->account_id OR ! $this->method_id OR ! ($this->date_expire OR $this->uses))
|
||||
return NULL;
|
||||
|
||||
// Check we dont already have a valid token
|
||||
$mmto = ORM::factory('Module_Method_Token')
|
||||
->where('account_id','=',$this->account_id)
|
||||
->where('method_id','=',$this->method_id)
|
||||
->find();
|
||||
|
||||
if ($mmto->loaded()) {
|
||||
// Check that the token is still good
|
||||
if ((is_null($mmto->date_expire) OR $mmto->date_expire > time()) AND (is_null($mmto->uses) OR $mmto->uses > 0)) {
|
||||
$this->token = $mmto->token;
|
||||
return $this->token;
|
||||
|
||||
// Token expired
|
||||
} else
|
||||
$mmto->delete();
|
||||
}
|
||||
|
||||
$this->token = md5(sprintf('%s:%s:%s',$this->account_id,$this->method_id,time()));
|
||||
$this->save();
|
||||
|
||||
return $this->saved() ? $this->token : NULL;
|
||||
}
|
||||
}
|
||||
?>
|
42
application/classes/Model/RTM.php
Normal file
42
application/classes/Model/RTM.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Route to Market
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_RTM extends ORM_OSB {
|
||||
protected $_belongs_to = array(
|
||||
'account' => array(),
|
||||
);
|
||||
|
||||
protected $_has_many = array(
|
||||
'customer' => array('model'=>'account','far_key'=>'id','foreign_key'=>'rtm_id'),
|
||||
'agent' => array('model'=>'rtm','far_key'=>'id','foreign_key'=>'parent_id'),
|
||||
);
|
||||
|
||||
public function customers(Model_RTM $rtmo) {
|
||||
$result = array();
|
||||
|
||||
foreach ($rtmo->agents_direct() as $artmo)
|
||||
$result = $result+$rtmo->customers($artmo);
|
||||
|
||||
foreach ($rtmo->customers_direct() as $ao)
|
||||
array_push($result,$ao);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function agents_direct() {
|
||||
return $this->agent->find_all();
|
||||
}
|
||||
|
||||
public function customers_direct() {
|
||||
return $this->customer->find_all();
|
||||
}
|
||||
}
|
||||
?>
|
42
application/classes/Model/Record/ID.php
Normal file
42
application/classes/Model/Record/ID.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
* @todo Rename to Record/ID.php
|
||||
*/
|
||||
class Model_Record_ID extends ORM_OSB {
|
||||
protected $_primary_key = 'module_id';
|
||||
|
||||
// This module doesnt keep track of column updates automatically
|
||||
protected $_created_column = FALSE;
|
||||
protected $_updated_column = FALSE;
|
||||
|
||||
// @todo we need $mid here, since if there is no record, we cant figure out the module that called us.
|
||||
public function next_id($mid) {
|
||||
if (is_null($this->id)) {
|
||||
$this->module_id = $mid;
|
||||
|
||||
// We'll get the next ID as the MAX(id) of the table
|
||||
$mo = ORM::factory('Module',$mid);
|
||||
|
||||
$max = DB::select(array('MAX(id)','id'))
|
||||
->from($mo->name)
|
||||
->where('site_id','=',Company::instance()->site());
|
||||
|
||||
$this->id = $max->execute()->get('id');
|
||||
}
|
||||
|
||||
$this->id++;
|
||||
|
||||
if (! $this->save())
|
||||
throw new Koahan_Exception(_('Unable to increase ID for :table'),array(':table'=>$mid));
|
||||
|
||||
return $this->id;
|
||||
}
|
||||
}
|
||||
?>
|
83
application/classes/Model/Setup.php
Normal file
83
application/classes/Model/Setup.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Setup Model
|
||||
*
|
||||
* This module must remain in applications/ as it is used very early in the
|
||||
* OSB initialisation.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Setup extends ORM_OSB {
|
||||
// Setup doesnt use the update column
|
||||
protected $_updated_column = FALSE;
|
||||
|
||||
protected $_has_one = array(
|
||||
'account'=>array('foreign_key'=>'id','far_key'=>'admin_id'),
|
||||
'country'=>array('foreign_key'=>'id','far_key'=>'country_id'),
|
||||
'language'=>array('foreign_key'=>'id','far_key'=>'language_id'),
|
||||
);
|
||||
|
||||
public function rules() {
|
||||
$r = parent::rules();
|
||||
|
||||
// This module doesnt use site_id.
|
||||
unset($r['site_id']);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/Set Module Configuration
|
||||
*
|
||||
* @param $key Module name.
|
||||
* @param $value Values to store. If NULL, retrieves the value stored, otherwise stores value.
|
||||
*/
|
||||
public function module_config($key,array $value=NULL) {
|
||||
// If we are not loaded, we dont have any config.
|
||||
if (! $this->loaded() OR (is_null($value) AND ! $this->module_config))
|
||||
return array();
|
||||
|
||||
$mo = ORM::factory('Module')->where('name','=',$key)->find();
|
||||
|
||||
if (! $mo->loaded())
|
||||
throw new Kohana_Exception('Unknown module :name',array(':name'=>$key));
|
||||
|
||||
$mc = $this->module_config ? $this->module_config : array();
|
||||
|
||||
// If $value is NULL, we are a getter
|
||||
if ($value === NULL)
|
||||
return empty($mc[$mo->id]) ? array() : $mc[$mo->id];
|
||||
|
||||
// Store new value
|
||||
$mc[$mo->id] = $value;
|
||||
$this->module_config = $mc;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/Set our Site Configuration from the DB
|
||||
*
|
||||
* @param $key Key
|
||||
* @param $value Values to store. If NULL, retrieves the value stored, otherwise stores value.
|
||||
*/
|
||||
public function site_details($key,array $value=NULL) {
|
||||
if (! in_array($key,array('name','address1','address2','city','state','pcode','phone','fax','email')))
|
||||
throw new Kohana_Exception('Unknown Site Configuration Key :key',array(':key'=>$key));
|
||||
|
||||
// If $value is NULL, we are a getter
|
||||
if ($value === NULL)
|
||||
return empty($this->site_details[$key]) ? '' : $this->site_details[$key];
|
||||
|
||||
// Store new value
|
||||
$sc[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
?>
|
125
application/classes/ORM.php
Normal file
125
application/classes/ORM.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's ORM
|
||||
*
|
||||
* This file contains enhancements for Kohana, that should be considered upstream and maybe havent been yet.
|
||||
* It also contains some functionality for OSB, which cannot be covered in ORM_OSB.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class ORM extends Kohana_ORM {
|
||||
protected $_table_names_plural = FALSE;
|
||||
protected $_model_names_plural = FALSE;
|
||||
private $_object_formated = array();
|
||||
private $_formated = FALSE;
|
||||
// Our filters used to display values in a friendly format
|
||||
protected $_display_filters = array();
|
||||
|
||||
/**
|
||||
* Format fields for display purposes
|
||||
*
|
||||
* @param string column name
|
||||
* @return mixed
|
||||
*/
|
||||
private function _format() {
|
||||
foreach ($this->_display_filters as $column => $formats)
|
||||
$this->_object_formated[$column] = $this->run_filter($column,$this->__get($column),array($column=>$formats));
|
||||
|
||||
$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->_formated AND $this->_display_filters)
|
||||
$this->_format();
|
||||
|
||||
if (isset($this->_object_formated[$column]))
|
||||
return $this->_object_formated[$column];
|
||||
else
|
||||
return HTML::nbsp($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override KH's ORM count_relations() function, to include our site_id in the query.
|
||||
*
|
||||
* This is a copy of KH's ORM count_relations() function, with the addition of a where
|
||||
* clause to include the site id.
|
||||
*/
|
||||
public function count_relations($alias, $far_keys = NULL)
|
||||
{
|
||||
if ($far_keys === NULL)
|
||||
{
|
||||
return (int) DB::select(array(DB::expr('COUNT(*)'), 'records_found'))
|
||||
->from($this->_has_many[$alias]['through'])
|
||||
->where($this->_has_many[$alias]['foreign_key'], '=', $this->pk())
|
||||
->where('site_id', '=', Company::instance()->site())
|
||||
->execute($this->_db)->get('records_found');
|
||||
}
|
||||
|
||||
$far_keys = ($far_keys instanceof ORM) ? $far_keys->pk() : $far_keys;
|
||||
|
||||
// We need an array to simplify the logic
|
||||
$far_keys = (array) $far_keys;
|
||||
|
||||
// Nothing to check if the model isn't loaded or we don't have any far_keys
|
||||
if ( ! $far_keys OR ! $this->_loaded)
|
||||
return 0;
|
||||
|
||||
$count = (int) DB::select(array(DB::expr('COUNT(*)'), 'records_found'))
|
||||
->from($this->_has_many[$alias]['through'])
|
||||
->where($this->_has_many[$alias]['foreign_key'], '=', $this->pk())
|
||||
->where($this->_has_many[$alias]['far_key'], 'IN', $far_keys)
|
||||
->where('site_id', '=', Company::instance()->site())
|
||||
->execute($this->_db)->get('records_found');
|
||||
|
||||
// Rows found need to match the rows searched
|
||||
return (int) $count;
|
||||
}
|
||||
|
||||
/** OSB SPECIFIC ENHANCEMENTS **/
|
||||
|
||||
// Tables that do not have a site_id column
|
||||
public static $no_site_id_tables = array('setup','country','currency','language','tax');
|
||||
|
||||
/**
|
||||
* Add our OSB site_id to each SELECT query
|
||||
* @see parent::__build()
|
||||
*/
|
||||
final protected function _build($type) {
|
||||
// Exclude tables without site ID's
|
||||
if (! in_array($this->_table_name,ORM::$no_site_id_tables))
|
||||
$this->where($this->_object_name.'.site_id','=',Company::instance()->site());
|
||||
|
||||
return parent::_build($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function help to find records that are active
|
||||
*/
|
||||
public function list_active() {
|
||||
return $this->_where_active()->find_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function help to find records that are active
|
||||
*/
|
||||
protected function _where_active() {
|
||||
return $this->where('status','=',TRUE);
|
||||
}
|
||||
|
||||
public function where_active() {
|
||||
return $this->_where_active();
|
||||
}
|
||||
}
|
||||
?>
|
228
application/classes/ORM/OSB.php
Normal file
228
application/classes/ORM/OSB.php
Normal file
@@ -0,0 +1,228 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends Kohana's [ORM] class to create defaults for OSB.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class ORM_OSB extends ORM {
|
||||
/**
|
||||
* @var string Database to connect to
|
||||
*/
|
||||
protected $_db = 'default';
|
||||
|
||||
protected $_created_column = array('column'=>'date_orig','format'=>TRUE);
|
||||
protected $_updated_column = array('column'=>'date_last','format'=>TRUE);
|
||||
|
||||
// Our attribute values that need to be stored as serialized
|
||||
protected $_serialize_column = array();
|
||||
|
||||
// Our attributes used in forms.
|
||||
protected $_form = array();
|
||||
|
||||
// Rules to assist with site ID and getting next record ID for inserts.
|
||||
public function rules() {
|
||||
return array(
|
||||
'id'=>array(
|
||||
array('ORM_OSB::get_next_id',array(':model',':field')),
|
||||
),
|
||||
'site_id'=>array(
|
||||
array('ORM_OSB::set_site_id',array(':model',':field')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto process some data as it comes from the database
|
||||
* @see parent::__get()
|
||||
*/
|
||||
public function __get($column) {
|
||||
if (array_key_exists($column,$this->_table_columns)) {
|
||||
// If the column is a blob, we'll decode it automatically
|
||||
if (
|
||||
$this->_table_columns[$column]['data_type'] == 'blob'
|
||||
AND ! is_null($this->_object[$column])
|
||||
AND ! isset($this->_changed[$column])
|
||||
AND (! isset($this->_table_columns[$column]['auto_convert']) OR ! $this->_table_columns[$column]['auto_convert'])
|
||||
) {
|
||||
|
||||
// In case our blob hasnt been saved as one.
|
||||
try {
|
||||
$this->_object[$column] = $this->blob($this->_object[$column]);
|
||||
}
|
||||
catch(Exception $e) {
|
||||
// @todo Log this exception
|
||||
echo Kohana_Exception::text($e), "\n";
|
||||
echo debug_print_backtrace();
|
||||
}
|
||||
|
||||
$this->_table_columns[$column]['auto_convert'] = TRUE;
|
||||
}
|
||||
|
||||
// If the column is a serialized object, we'll unserialize it.
|
||||
if (
|
||||
in_array($column,$this->_serialize_column)
|
||||
AND is_string($this->_object[$column])
|
||||
AND ! is_null($this->_object[$column])
|
||||
AND ! isset($this->_changed[$column])
|
||||
AND (! isset($this->_table_columns[$column]['unserialized']) OR ! $this->_table_columns[$column]['unserialized'])
|
||||
) {
|
||||
|
||||
// In case our object hasnt been saved as serialized.
|
||||
try {
|
||||
$this->_object[$column] = unserialize($this->_object[$column]);
|
||||
}
|
||||
catch(Exception $e) {
|
||||
// @todo Log this exception
|
||||
echo Kohana_Exception::text($e), "\n";
|
||||
echo debug_print_backtrace();
|
||||
}
|
||||
|
||||
$this->_table_columns[$column]['unserialized'] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return parent::__get($column);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @todo This has probably changed in KH 3.1
|
||||
*/
|
||||
final public static function x_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));
|
||||
}
|
||||
}
|
||||
|
||||
final public static function xform($table,$blank=FALSE) {
|
||||
return ORM::factory($table)->formselect($blank);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve and Store DB BLOB data.
|
||||
*/
|
||||
private function blob($data,$set=FALSE) {
|
||||
try {
|
||||
return $set ? gzcompress(serialize($data)) : unserialize(gzuncompress($data));
|
||||
|
||||
// Maybe the data isnt compressed?
|
||||
} catch (Exception $e) {
|
||||
return $set ? serialize($data) : unserialize($data);
|
||||
}
|
||||
}
|
||||
|
||||
public function config($key) {
|
||||
$mc = Config::instance()->module_config($this->_object_name);
|
||||
|
||||
return empty($mc[$key]) ? '' : $mc[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Next record id
|
||||
*
|
||||
* @param array Validate object
|
||||
* @param string Primary Key
|
||||
*/
|
||||
final public static function get_next_id($model,$field) {
|
||||
if (! is_null($model->$field))
|
||||
return TRUE;
|
||||
|
||||
$model->_changed[$field] = $field;
|
||||
|
||||
$ido = ORM::factory('Module')
|
||||
->where('name','=',$model->_table_name)
|
||||
->find();
|
||||
|
||||
if (! $ido->loaded())
|
||||
throw new Kohana_Exception('Problem getting record_id for :table',array(':table'=>$model->_table_name));
|
||||
|
||||
$model->$field = $ido->record_id->next_id($ido->id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the site ID attribute for each row update
|
||||
*/
|
||||
final public static function set_site_id($model,$field) {
|
||||
if (! is_null($model->$field))
|
||||
return TRUE;
|
||||
|
||||
$model->_changed[$field] = $field;
|
||||
$model->$field = Company::instance()->site();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function xformselect($blank) {
|
||||
$result = array();
|
||||
|
||||
if ($blank)
|
||||
$result[] = '';
|
||||
|
||||
foreach ($this->find_all() as $o)
|
||||
$result[$o->{$this->_form['id']}] = $o->{$this->_form['value']};
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function keyget($column,$key=NULL) {
|
||||
if (is_null($key) OR ! is_array($this->$column))
|
||||
return $this->$column;
|
||||
else
|
||||
return array_key_exists($key,$this->$column) ? $this->{$column}[$key] : NULL;
|
||||
}
|
||||
|
||||
final public function mid() {
|
||||
return ORM::factory('Module',array('name'=>$this->_table_name));
|
||||
}
|
||||
|
||||
public function save(Validation $validation = NULL) {
|
||||
// Find any fields that have changed, and process them.
|
||||
if ($this->_changed)
|
||||
foreach ($this->_changed as $c)
|
||||
// Any fields that are blobs, and encode them.
|
||||
if ($this->_table_columns[$c]['data_type'] == 'blob') {
|
||||
$this->_object[$c] = $this->blob($this->_object[$c],TRUE);
|
||||
|
||||
// We need to reset our auto_convert flag
|
||||
if (isset($this->_table_columns[$c]['auto_convert']))
|
||||
$this->_table_columns[$c]['auto_convert'] = FALSE;
|
||||
|
||||
// Any fields that should be seriailzed, we'll do that.
|
||||
} elseif (is_array($this->_object[$c]) AND in_array($c,$this->_serialize_column)) {
|
||||
$this->_object[$c] = serialize($this->_object[$c]);
|
||||
}
|
||||
|
||||
return parent::save($validation);
|
||||
}
|
||||
|
||||
public function list_count($active=TRUE) {
|
||||
$x=($active ? $this->_where_active() : $this);
|
||||
|
||||
return $x->find_all()->count();
|
||||
}
|
||||
}
|
||||
?>
|
129
application/classes/Period.php
Normal file
129
application/classes/Period.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class is for calculating date periods.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.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,$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));
|
||||
|
||||
$inc_months = $used_months = 0;
|
||||
|
||||
switch ($type) {
|
||||
// Weekly
|
||||
case 0:
|
||||
if ($strict)
|
||||
throw new Kohana_Exception('Strict doesnt work here');
|
||||
|
||||
$period_start = is_null($weekday) ? $start : $start+86400*($weekday-date('w',$start));
|
||||
$period_end = $period_start+(86400*7);
|
||||
|
||||
break;
|
||||
|
||||
// Monthly
|
||||
case 1:
|
||||
// NOTE: Strict doesnt do anything here.
|
||||
$inc_months = 1;
|
||||
break;
|
||||
|
||||
// Quarterly
|
||||
case 2:
|
||||
$inc_months = 3;
|
||||
break;
|
||||
|
||||
// Half Yearly
|
||||
case 3:
|
||||
$inc_months = 6;
|
||||
break;
|
||||
|
||||
// Yearly
|
||||
case 4:
|
||||
$inc_months = 12;
|
||||
break;
|
||||
|
||||
// Biennial
|
||||
case 5:
|
||||
$inc_months = 24;
|
||||
break;
|
||||
|
||||
// Triennial
|
||||
case 6:
|
||||
if ($strict)
|
||||
throw new Kohana_Exception('Strict not implemented here');
|
||||
|
||||
$inc_months = 36;
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Workout the period start day
|
||||
if (is_null($weekday))
|
||||
$weekday = $strict ? 1 : date('d',$start);
|
||||
|
||||
// We only work our used_months for periods monthly or more.
|
||||
if ($inc_months) {
|
||||
if ($strict)
|
||||
$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));
|
||||
|
||||
// Workout the period end
|
||||
$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;
|
||||
|
||||
$result = array(
|
||||
'start'=>$period_start,
|
||||
'start_time'=>$start,
|
||||
'date'=>$start,
|
||||
'end'=>$period_end,
|
||||
'end_time'=>$period_end,
|
||||
'weekday'=>$weekday,
|
||||
'prorata'=>round($remain_time/$total_time,4),
|
||||
'total_time'=>sprintf('%3.1f',$total_time/86400),
|
||||
'remain_time'=>sprintf('%3.1f',$remain_time/86400),
|
||||
'used_time'=>sprintf('%3.1f',$used_time/86400),
|
||||
);
|
||||
|
||||
if ($df)
|
||||
foreach (array('start','date','end') as $key)
|
||||
$result[$key] = Config::date($result[$key]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
?>
|
31
application/classes/Request.php
Normal file
31
application/classes/Request.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* Request. Uses the [Route] class to determine what
|
||||
* [Controller] to send the request to.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Request extends Kohana_Request {
|
||||
/**
|
||||
* Sets and gets the directory for the controller.
|
||||
*
|
||||
* We override the Kohana version, so that we can have short directory URLs.
|
||||
* eg: admin=>a,reseller=>r.
|
||||
*
|
||||
* @param string $directory Directory to execute the controller from
|
||||
* @return mixed
|
||||
*/
|
||||
public function directory($directory = NULL) {
|
||||
// If $directory is NULL, we are a getter and see if we need to expand the directory
|
||||
if ($directory === NULL AND $this->_directory)
|
||||
$this->_directory = URL::dir($this->_directory);
|
||||
|
||||
return parent::directory($directory);
|
||||
}
|
||||
}
|
||||
?>
|
18
application/classes/Response.php
Normal file
18
application/classes/Response.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's Response
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Response extends Kohana_Response {
|
||||
// Append to the body.
|
||||
public function bodyadd($content) {
|
||||
$this->_body .= (string) $content;
|
||||
}
|
||||
}
|
||||
?>
|
71
application/classes/StaticList.php
Normal file
71
application/classes/StaticList.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders standard lists and their values
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.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)
|
||||
return 'No Table';
|
||||
elseif (empty($table[$id]))
|
||||
return sprintf('No Value (%s)',$id);
|
||||
else
|
||||
return $table[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists our available keys
|
||||
*/
|
||||
public static function keys() {
|
||||
return array_keys(static::factory()->table());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
?>
|
93
application/classes/StaticList/Module.php
Normal file
93
application/classes/StaticList/Module.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?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
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class StaticList_Module 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,$addblank,$attributes) = func_get_args();
|
||||
|
||||
$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();
|
||||
if ($addblank)
|
||||
$x[] = '';
|
||||
|
||||
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,$attributes);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
?>
|
29
application/classes/StaticList/PriceType.php
Normal file
29
application/classes/StaticList/PriceType.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Price Type responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.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);
|
||||
}
|
||||
}
|
||||
?>
|
55
application/classes/StaticList/RecurSchedule.php
Normal file
55
application/classes/StaticList/RecurSchedule.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Recurring Schedule Times on responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.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='',$default='',$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(Tax::add($price['price_base'])),$table[$term]);
|
||||
|
||||
if ($price['price_setup'] > 0)
|
||||
$x[$term] .= sprintf(' + %s %s',Currency::display(Tax::add($price['price_setup'])),_('Setup'));
|
||||
}
|
||||
|
||||
return Form::select($name,$x,$default);
|
||||
}
|
||||
}
|
||||
?>
|
28
application/classes/StaticList/RecurType.php
Normal file
28
application/classes/StaticList/RecurType.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Recurring Schedule Types on responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class StaticList_RecurType extends StaticList {
|
||||
protected function table() {
|
||||
return array(
|
||||
0=>_('Bill on Aniversary Date of Subscription'),
|
||||
1=>_('Bill on Fixed Schedule'),
|
||||
);
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_RecurType;
|
||||
}
|
||||
|
||||
public static function display($value) {
|
||||
return static::_display($value);
|
||||
}
|
||||
}
|
||||
?>
|
33
application/classes/StaticList/SweepType.php
Normal file
33
application/classes/StaticList/SweepType.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Charge Sweep Types on responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class StaticList_SweepType extends StaticList {
|
||||
protected function table() {
|
||||
return array(
|
||||
0=>_('Daily'),
|
||||
1=>_('Weekly'),
|
||||
2=>_('Monthly'),
|
||||
3=>_('Quarterly'),
|
||||
4=>_('Semi-Annually'),
|
||||
5=>_('Annually'),
|
||||
6=>_('Service Rebill'),
|
||||
);
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_SweepType;
|
||||
}
|
||||
|
||||
public static function display($value) {
|
||||
return static::_display($value);
|
||||
}
|
||||
}
|
||||
?>
|
28
application/classes/StaticList/Title.php
Normal file
28
application/classes/StaticList/Title.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Person Title responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.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;
|
||||
}
|
||||
}
|
||||
?>
|
28
application/classes/StaticList/YesNo.php
Normal file
28
application/classes/StaticList/YesNo.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Yes/No responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.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);
|
||||
}
|
||||
}
|
||||
?>
|
20
application/classes/Task.php
Normal file
20
application/classes/Task.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends Minions Tasks to require the site option
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class Task extends Minion_Task {
|
||||
protected $_options = array(
|
||||
'site'=>NULL,
|
||||
'id'=>NULL,
|
||||
'force'=>FALSE,
|
||||
'verbose'=>FALSE,
|
||||
);
|
||||
}
|
||||
?>
|
33
application/classes/Task/Account/Complete.php
Normal file
33
application/classes/Task/Account/Complete.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* Mark all accounts that have no outstanding invoices and active services as disabled.
|
||||
*
|
||||
* @package Account
|
||||
* @category Tasks
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Task_Account_Complete extends Task {
|
||||
protected function _execute(array $params) {
|
||||
$c = 0;
|
||||
|
||||
$o = ORM::factory('Account')
|
||||
->where_active();
|
||||
|
||||
foreach ($o->find_all() as $ao) {
|
||||
if (count($ao->invoice->where_unprocessed()->find_all()) == 0 AND count($ao->service->where_active()->find_all()) == 0)
|
||||
// @todo Cant update status=0, problem with sessions in CLI
|
||||
echo $ao->id.',';
|
||||
|
||||
$ao->save();
|
||||
|
||||
if ($ao->saved())
|
||||
$c++;
|
||||
}
|
||||
|
||||
printf('%s services updated',$c);
|
||||
}
|
||||
}
|
||||
?>
|
54
application/classes/URL.php
Normal file
54
application/classes/URL.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's URL
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class URL extends Kohana_URL {
|
||||
// Our method paths for different functions
|
||||
public static $method_directory = array(
|
||||
'admin'=>'a',
|
||||
'affiliate'=>'affiliate', // @todo To retire
|
||||
'reseller'=>'r',
|
||||
'task'=>'task',
|
||||
'user'=>'u',
|
||||
);
|
||||
|
||||
/**
|
||||
* Wrapper to provide a URL::site() link based on function
|
||||
*/
|
||||
public static function link($dir,$src,$site=FALSE) {
|
||||
if (! $dir)
|
||||
return $src;
|
||||
|
||||
if (! array_key_exists($dir,URL::$method_directory))
|
||||
throw new Kohana_Exception('Unknown directory :dir for :src',array(':dir'=>$dir,':src'=>$src));
|
||||
|
||||
$x = URL::$method_directory[$dir].'/'.$src;
|
||||
|
||||
return $site ? URL::site($x) : $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to reveal the real directory for a URL
|
||||
*/
|
||||
public static function dir($dir) {
|
||||
// Quick check if we can do something here
|
||||
if (! in_array(strtolower($dir),URL::$method_directory))
|
||||
return $dir;
|
||||
|
||||
// OK, we can, find it.
|
||||
foreach (URL::$method_directory as $k=>$v)
|
||||
if (strtolower($dir) == $v)
|
||||
return ucfirst($k);
|
||||
|
||||
// If we get here, we didnt have anything.
|
||||
return $dir;
|
||||
}
|
||||
}
|
||||
?>
|
27
application/classes/Valid.php
Normal file
27
application/classes/Valid.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* Array and variable validation.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class Valid extends Kohana_Valid {
|
||||
/**
|
||||
* Checks if a field matches the value of another field, if it is set.
|
||||
* Field is ignored if it is blank.
|
||||
*
|
||||
* @param array array of values
|
||||
* @param string field name
|
||||
* @param string field name to match
|
||||
* @return boolean
|
||||
*/
|
||||
public static function matches_ifset($array, $field, $match)
|
||||
{
|
||||
return isset($array[$match]) ? ($array[$field] === $array[$match]) : TRUE;
|
||||
}
|
||||
}
|
||||
?>
|
44
application/classes/XML.php
Normal file
44
application/classes/XML.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends the Kohana XML
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class XML extends XML_Core {
|
||||
/**
|
||||
* Collapse an XML object into a simple array
|
||||
*/
|
||||
public function collapse(XML $xml=NULL) {
|
||||
if (is_null($xml))
|
||||
$xml = $this;
|
||||
$result = array();
|
||||
|
||||
foreach ($xml->as_array() as $j=>$k) {
|
||||
$v = $xml->$j->value();
|
||||
|
||||
if (count($k) > 1) {
|
||||
foreach ($xml->get($j,1) as $k)
|
||||
if (isset($k['name'][0]))
|
||||
$result[$j][$k['name'][0]] = (isset($k['value'][0]) ? $k['value'][0] : '');
|
||||
else
|
||||
$result[$j][] = $k;
|
||||
|
||||
} elseif (! is_null($v))
|
||||
$result[$j] = $v;
|
||||
else {
|
||||
$result[$j] = $this->collapse($xml->$j);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('name',$result) AND array_key_exists('value',$result))
|
||||
$result = array($result['name']=>$result['value']);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
?>
|
Reference in New Issue
Block a user