From febaad9ea6562d5c32133a0aaa9593bce0d227df Mon Sep 17 00:00:00 2001 From: Deon George Date: Wed, 9 Jul 2014 13:04:56 +1000 Subject: [PATCH] Initial Membership Database Work --- .gitmodules | 4 +- .htaccess | 9 +- application/bootstrap.php | 29 +- application/classes/Auth/MDB.php | 229 ++++++++++++++ application/classes/Auth/ORM.php | 22 ++ application/classes/Company.php | 122 ++++++++ application/classes/Config.php | 118 ++++--- application/classes/Controller/Translate.php | 218 ------------- application/classes/Controller/Welcome.php | 18 +- application/classes/Cookie.php | 4 +- application/classes/DB.php | 35 +++ application/classes/Database.php | 18 ++ application/classes/Database/MySQL.php | 20 ++ application/classes/Kohana.php | 72 +++++ application/classes/Model/Account.php | 144 +++++++++ .../Model/{Original.php => Account/Log.php} | 19 +- .../classes/Model/Auth/UserDefault.php | 42 +++ application/classes/Model/Group.php | 71 +++++ application/classes/Model/Language.php | 30 -- application/classes/Model/Module.php | 55 ++++ application/classes/Model/Record/ID.php | 40 +++ application/classes/Model/Setup.php | 115 +++++++ application/classes/Model/Translate.php | 30 -- application/classes/ORM.php | 179 +++++++++++ application/classes/ORM/OSB.php | 287 ------------------ application/classes/Site.php | 39 +++ application/classes/URL.php | 40 +++ application/config/auth.php | 17 ++ application/config/config.php | 10 + application/config/database.php | 10 +- application/config/mainnav.php | 16 + application/views/pages/navbar.php | 0 application/views/theme/baseadmin/page.php | 130 -------- application/views/translate.php | 33 -- includes/kohana | 2 +- modules/lnApp | 1 - modules/lnapp | 1 + 37 files changed, 1395 insertions(+), 834 deletions(-) create mode 100644 application/classes/Auth/MDB.php create mode 100644 application/classes/Auth/ORM.php create mode 100644 application/classes/Company.php delete mode 100644 application/classes/Controller/Translate.php create mode 100644 application/classes/DB.php create mode 100644 application/classes/Database.php create mode 100644 application/classes/Database/MySQL.php create mode 100644 application/classes/Kohana.php create mode 100644 application/classes/Model/Account.php rename application/classes/Model/{Original.php => Account/Log.php} (53%) create mode 100644 application/classes/Model/Auth/UserDefault.php create mode 100644 application/classes/Model/Group.php delete mode 100644 application/classes/Model/Language.php create mode 100644 application/classes/Model/Module.php create mode 100644 application/classes/Model/Record/ID.php create mode 100644 application/classes/Model/Setup.php delete mode 100644 application/classes/Model/Translate.php create mode 100644 application/classes/ORM.php delete mode 100644 application/classes/ORM/OSB.php create mode 100644 application/classes/Site.php create mode 100644 application/classes/URL.php create mode 100644 application/config/auth.php create mode 100644 application/config/config.php create mode 100644 application/config/mainnav.php delete mode 100644 application/views/pages/navbar.php delete mode 100644 application/views/theme/baseadmin/page.php delete mode 100644 application/views/translate.php delete mode 160000 modules/lnApp create mode 160000 modules/lnapp diff --git a/.gitmodules b/.gitmodules index f37ce1e..f53f5f4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "includes/kohana"] path = includes/kohana url = ssh://deon@l.dlcm.co:222/afs/local/git/lnkohana -[submodule "modules/lnApp"] - path = modules/lnApp +[submodule "modules/lnapp"] + path = modules/lnapp url = ssh://deon@l.dlcm.co:222/afs/local/git/lnapp diff --git a/.htaccess b/.htaccess index aa2b575..7a13b73 100644 --- a/.htaccess +++ b/.htaccess @@ -2,7 +2,7 @@ RewriteEngine On # Installation directory -RewriteBase /aer +RewriteBase /ebccc # Protect hidden files from being viewed @@ -19,10 +19,3 @@ RewriteCond %{REQUEST_FILENAME} !-d # Rewrite all other URLs to index.php/URL RewriteRule .* index.php/$0 [PT] - -AuthType Basic -AuthName "Restricted !" -# (Following line optional) -AuthBasicProvider file -AuthUserFile /local/WEB/sites/net.leenooks.dev/aer/.htuser -Require valid-user diff --git a/application/bootstrap.php b/application/bootstrap.php index 1874298..a39044a 100644 --- a/application/bootstrap.php +++ b/application/bootstrap.php @@ -1,6 +1,9 @@ " */ + +/** + * Set the environment status by the domain. + */ +Kohana::$environment = (! isset($_SERVER['SERVER_NAME']) OR in_array($_SERVER['SERVER_NAME'],$SERVER_NAMES)) ? Kohana::PRODUCTION : Kohana::DEVELOPMENT; + if (isset($_SERVER['KOHANA_ENV'])) { Kohana::$environment = constant('Kohana::'.strtoupper($_SERVER['KOHANA_ENV'])); @@ -90,9 +99,10 @@ if (isset($_SERVER['KOHANA_ENV'])) * - boolean expose set the X-Powered-By header FALSE */ Kohana::init(array( - 'base_url' => '/aer', - 'caching' => TRUE, - 'index_file' => '', + 'base_url' => Kohana::$environment === Kohana::PRODUCTION ? '/ebccc' : '/ebccc', + 'caching' => Kohana::$environment === Kohana::PRODUCTION, + 'profile' => Kohana::$environment !== Kohana::PRODUCTION, + 'index_file' => FALSE, )); /** @@ -109,10 +119,10 @@ Kohana::$config->attach(new Config_File); * Enable modules. Modules are referenced by a relative or absolute path. */ Kohana::modules(array( - 'lnapp' => MODPATH.'lnApp', // lnApp Base Application Tools + 'lnapp' => MODPATH.'lnapp', // lnApp Base Application Tools // 'oauth' => MODPATH.'oauth', // OAuth Module for External Authentication 'auth' => SMDPATH.'auth', // Basic authentication - 'cache' => SMDPATH.'cache', // Caching with multiple backends + // 'cache' => SMDPATH.'cache', // Caching with multiple backends // 'cron' => SMDPATH.'cron', // Kohana Cron Module // 'codebench' => SMDPATH.'codebench', // Benchmarking tool 'database' => SMDPATH.'database', // Database access @@ -122,12 +132,17 @@ Kohana::modules(array( // 'khemail' => SMDPATH.'khemail', // Email module for Kohana 3 PHP Framework // 'minion' => SMDPATH.'minion', // CLI Tasks 'orm' => SMDPATH.'orm', // Object Relationship Mapping - 'pagination' => SMDPATH.'pagination', // Kohana Pagination module for Kohana 3 PHP Framework + // 'pagination' => SMDPATH.'pagination', // Kohana Pagination module for Kohana 3 PHP Framework // 'unittest' => SMDPATH.'unittest', // Unit testing // 'userguide' => SMDPATH.'userguide', // User guide and API documentation - 'xml' => SMDPATH.'xml', // XML module for Kohana 3 PHP Framework + // 'xml' => SMDPATH.'xml', // XML module for Kohana 3 PHP Framework )); +/** + * Load our modules defined in the DB + */ +Kohana::modules(array_merge(Kohana::modules(),Config::modules())); + /** * Enable specalised interfaces */ diff --git a/application/classes/Auth/MDB.php b/application/classes/Auth/MDB.php new file mode 100644 index 0000000..4b95447 --- /dev/null +++ b/application/classes/Auth/MDB.php @@ -0,0 +1,229 @@ +_config = $config; + + if (PHP_SAPI !== 'cli') + parent::__construct($config); + } + + /** + * 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 = $mo->module_method + ->where('name','=',strtolower(Request::current()->directory() ? sprintf('%s:%s',Request::current()->directory(),Request::current()->action()) : Request::current()->action())) + ->find(); + + // 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'))); + + 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'))); + + 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->id,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->active 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)))); + } + + /** + * 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) { + // If we are a CLI, we are not logged in + if (PHP_SAPI === 'cli') + throw new Kohana_Exception('Calling :method from the CLI is not allowed!',array(':method'=>__METHOD__)); + + // 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; + } + + public function get_groups() { + return is_null($x=$this->get_user()) ? ORM::factory('Group')->where('id','=',0)->find_all() : $x->groups(); + } + + /** + * 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; + + // If we are a CLI, we are not logged in + if (PHP_SAPI === 'cli') + return $status; + + // 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 (! empty($role)) { + if (($x = Request::current()->mmo()) instanceof Model) + // If the role has the authorisation to run the method + foreach ($x->group->find_all() as $go) + if ($go->id == 0 OR $uo->has_any('group',$go->list_childgrps(TRUE))) { + $status = TRUE; + break; + } + + // There is no role, so the method should be allowed to run as anonymous + } else + $status = TRUE; + + return $status; + } +} +?> diff --git a/application/classes/Auth/ORM.php b/application/classes/Auth/ORM.php new file mode 100644 index 0000000..4c8da84 --- /dev/null +++ b/application/classes/Auth/ORM.php @@ -0,0 +1,22 @@ +_config['hash_method']) { + case '' : return $str; + case 'md5': return md5($str); + default: return hash_hmac($this->_config['hash_method'], $str, $this->_config['hash_key']); + } + } +} +?> diff --git a/application/classes/Company.php b/application/classes/Company.php new file mode 100644 index 0000000..04cd214 --- /dev/null +++ b/application/classes/Company.php @@ -0,0 +1,122 @@ +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() { + $x = URL::base('http'); + + if (! isset(Company::$instance[$x])) + Company::$instance[$x] = new Company(ORM::factory('Setup',array('url'=>$x))); + + return Company::$instance[$x]; + } + + public function admin() { + return $this->so->account->name(); + } + + public function address($ln='
') { + 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 faq() { + return $this->so->site_details('faqurl'); + } + + public function language() { + return $this->so->language; + } + + 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,array $value=NULL) { + return $this->so->module_config($item,$value); + } + + 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='
') { + 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 time_format() { + return $this->so->time_format; + } +} +?> diff --git a/application/classes/Config.php b/application/classes/Config.php index abab2cb..7e8fcae 100644 --- a/application/classes/Config.php +++ b/application/classes/Config.php @@ -4,16 +4,13 @@ * This class extends the core Kohana class by adding some core application * specific functions, and configuration. * - * @package WWZ + * @package Membership Database * @category Helpers * @author Deon George * @copyright (c) 2014 Deon George * @license http://dev.leenooks.net/license.html */ class Config extends Kohana_Config { - // Our default logo, if there is no site logo - public static $logo = 'img/logo-small.png'; - /** * Some early initialisation * @@ -41,73 +38,64 @@ class Config extends Kohana_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() { + public static function Copywrite() { return '(c) 2014 Deon George'; } - public static function country() { - return NULL; - } - - /** - * Show a date using a site configured format - */ - public static function date($date) { - return (is_null($date) OR ! $date) ? '' : date('d-M-Y',$date); - } - - public static function language() { - // @todo To implement - return 'auto'; - } - - /** - * 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)) ? $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); - } - - public static function siteid($format=FALSE) { - return ''; - } - - /** - * Work out our site mode (dev,test,prod) - */ - public static function sitemode() { - return Kohana::$config->load('config.site')->mode; - } - - public static function sitename() { - return 'AER Translate'; - } - - public static function theme() { - return 'theme/'.Kohana::$config->load('config')->theme; - } - public static function version() { // @todo Work out our versioning return 'TBA'; } + + /** + * 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'))) { + echo _('Cant figure out the site, use --site= for CLI')."\n"; + die(); + + } 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,array $value=NULL) { + return Company::instance()->module_config($item,$value); + } + + public static function module_exist($module) { + return array_key_exists(strtolower($module),self::modules()) ? TRUE : FALSE; + } + + /** + * 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('debug')->email_admin_only; + + if (is_null($config) OR ! is_array($config) OR empty($config[$template])) + return FALSE; + else + return $config[$template]; + } } ?> diff --git a/application/classes/Controller/Translate.php b/application/classes/Controller/Translate.php deleted file mode 100644 index 34c6be3..0000000 --- a/application/classes/Controller/Translate.php +++ /dev/null @@ -1,218 +0,0 @@ -/','',$data); - - return $data; - } - - public function action_index() { - HTTP::redirect(URL::link('','translate/render')); - $output = ''; - - Block::factory() - ->title('Hello') - ->title_icon('icon-cog') - ->body($output); - } - - public function action_import() { - $html = new simple_html_dom(); - $html->load($this->aer()); - - $this->store($html->find('head',0)->find('title',0)); - - foreach ($this->_tags as $z) - foreach ($html->find($z) as $x) - $this->store($x); - - HTTP::redirect(URL::link('','translate/index')); - } - - public function action_render() { - $output = ''; - - if ($this->request->post('language_id')) { - $html = new simple_html_dom(); - $html->load($this->aer()); - - $x = $html->find('head',0); - $x->innertext .= ''; - $lo = ORM::factory('Language',$this->request->post('language_id')); - - foreach ($this->_tags as $z) - foreach ($html->find($z) as $x) - $x->innertext = $this->translate($x,$lo); - - // Convert order the img tags - foreach ($html->find('img') as $z) { - $z->src = sprintf('%s/%s',URL::site('media/aer'),$z->src); - } - - $this->response->body($html); - $this->auto_render = FALSE; - - // We dont know what sort of payment type yet - } else { - $x = $this->lang(); - $output .= Form::open(); - $output .= Form::select('language_id',ORM::factory('Language')->list_select(),$x->id); - $output .= Form::button('submit','Submit',array('class'=>'btn btn-primary')); - $output .= Form::close(); - } - - Block::factory() - ->title('Render in...') - ->title_icon('icon-share') - ->body($output); - } - - public function action_save() { - foreach ($this->request->post('x') as $id => $value) { - if (! $value) - continue; - - $to = ORM::factory('Translate',array('language_id'=>$this->request->post('language_id'),'original_id'=>$id)); - - $to->translation = $value; - $to->language_id = $this->request->post('language_id'); - $to->original_id = $id; - $to->save(); - } - - HTTP::redirect(sprintf('%s?language_id=%s&page=%s',URL::link('','translate/text'),$this->request->post('language_id'),$this->request->post('page'))); - } - - private function lang() { - foreach ($this->request->accept_lang() as $k=>$v) { - if (strlen($k) == 2) - $k = sprintf('%s_%s',strtolower($k),strtoupper($k)); - else { - list($k,$v) = preg_split('/[-_]/',$k,2); - $k = sprintf('%s_%s',strtolower($k),strtoupper($v)); - } - - if ($x=ORM::factory('Language',array('iso'=>$k))) - return $x; - } - } - - private function store(simple_html_dom_node $x,$l=0) { - if ($x->children()) { - foreach ($x->children() as $y) { - $this->store($y,$l+1); - $y->innertext = '%s'; - } - } - - // If we have a numeric value, convert it to %d - $x->innertext = preg_replace('/[0-9.]+/','%d',$x->innertext); - - $oo = ORM::factory('Original',array('sentence'=>$x->innertext)); - - if (! trim($x->innertext) or (in_array(trim($x->innertext),array('$',' ')) or preg_match('/%d%?$/',$x->innertext))) { - return $x->innertext; - - } elseif (! $oo->loaded()) { - $oo->sentence = $x->innertext; - $oo->save(); - } - - return $x->innertext; - } - - private function translate(simple_html_dom_node $x,Model_Language $lo,$l=0) { - $nums = NULL; - $matches = array(); - $dom_tmp = str_get_html($x->outertext); - $dom_tmp_node = $dom_tmp->firstChild(); - - $string = $this->store($dom_tmp_node,$l); - $oo = ORM::factory('Original',array('sentence'=>$string)); - - // If we have numbers, we'll need to save them. - if (preg_match('/%d/',$string)) - $nums = preg_match('/[0-9.]+/',$x->innertext,$matches); - - if ($oo->loaded()) { - $to = ORM::factory('Translate',array('original_id'=>$oo->id,'language_id'=>$lo->id)); - - $string = $to->loaded() ? $to->translation : $x->innertext; - } - - if ($nums && $nums == 1) - $string = str_replace('%d',$matches[0],$string); - elseif ($nums > 1) - throw HTTP_Exception::factory('501','Argh, didnt allow for more than 1 match'); - - - if ($x->children()) { - foreach ($x->children() as $y) { - $string = preg_replace('/%s/',$this->translate($y,$lo,$l+1),$string); - } - } - - return $string; - } - - public function action_text() { - $output = ''; - - if ($this->request->query('language_id')) { - - $output .= Form::open(URL::link('','translate/save')); - $output .= Form::hidden('language_id',$this->request->query('language_id')); - - $oo = ORM::factory('Original') - ->select('translate.translation') - ->join('translate','LEFT OUTER') - ->on('original.id','=','translate.original_id') - ->on('translate.language_id','=',$this->request->query('language_id')); - - $output .= View::factory('translate') - ->set('o',$oo->find_all()); - - // We dont know what sort of payment type yet - } else { - $x = $this->lang(); - $output .= Form::open(NULL,array('method'=>'GET')); - $output .= Form::select('language_id',ORM::factory('Language')->list_select(),$x->id); - } - - $output .= Form::button('submit','Submit',array('class'=>'btn btn-primary')); - $output .= Form::close(); - - Block::factory() - ->title('Translate Text') - ->title_icon('icon-share') - ->body($output); - } - -} // End Welcome diff --git a/application/classes/Controller/Welcome.php b/application/classes/Controller/Welcome.php index 6134f85..95f0470 100644 --- a/application/classes/Controller/Welcome.php +++ b/application/classes/Controller/Welcome.php @@ -1,10 +1,18 @@ load('config')->appname) + throw HTTP_Exception::factory(500,'Site not setup!'); + + $output = ''; + + $output = View::factory('pages/welcome'); + Style::factory() + ->type('file') + ->data('media/css/pages/welcome.css'); + + $this->template->content = $output; } - } // End Welcome diff --git a/application/classes/Cookie.php b/application/classes/Cookie.php index 2d210ee..7ca3852 100644 --- a/application/classes/Cookie.php +++ b/application/classes/Cookie.php @@ -3,13 +3,13 @@ /** * This class overrides Kohana's Cookie * - * @package AER + * @package Membership Database * @category Modifications * @author Deon George * @copyright (c) 2014 Deon George * @license http://dev.leenooks.net/license.html */ class Cookie extends Kohana_Cookie { - public static $salt = 'AER'; + public static $salt = 'Photo'; } ?> diff --git a/application/classes/DB.php b/application/classes/DB.php new file mode 100644 index 0000000..cbce646 --- /dev/null +++ b/application/classes/DB.php @@ -0,0 +1,35 @@ +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; + } +} +?> diff --git a/application/classes/Database.php b/application/classes/Database.php new file mode 100644 index 0000000..d5e697f --- /dev/null +++ b/application/classes/Database.php @@ -0,0 +1,18 @@ +_config['caching']) ? $this->_config['caching'] : FALSE; + } +} +?> diff --git a/application/classes/Database/MySQL.php b/application/classes/Database/MySQL.php new file mode 100644 index 0000000..6d53cd0 --- /dev/null +++ b/application/classes/Database/MySQL.php @@ -0,0 +1,20 @@ + diff --git a/application/classes/Kohana.php b/application/classes/Kohana.php new file mode 100644 index 0000000..9bdd9b6 --- /dev/null +++ b/application/classes/Kohana.php @@ -0,0 +1,72 @@ + diff --git a/application/classes/Model/Account.php b/application/classes/Model/Account.php new file mode 100644 index 0000000..2bcbf6b --- /dev/null +++ b/application/classes/Model/Account.php @@ -0,0 +1,144 @@ +array('model'=>'user_token'), + 'email_log'=>array('far_key'=>'id'), + 'group'=>array('through'=>'account_group'), + ); + + protected $_has_one = array( + 'country'=>array('foreign_key'=>'id'), + 'currency'=>array('foreign_key'=>'id'), + 'language'=>array('foreign_key'=>'id'), + ); + + protected $_display_filters = array( + 'date_orig'=>array( + array('Site::Date',array(':value')), + ), + 'date_last'=>array( + array('Site::Date',array(':value')), + ), + 'active'=>array( + array('StaticList_YesNo::get',array(':value',TRUE)), + ), + ); + + protected $_form = array('id'=>'id','value'=>'name(TRUE)'); + + protected $_save_message = TRUE; + + /** + * 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() { + $result = array(); + + foreach ($this->group->where_active()->find_all() as $go) + foreach ($go->list_parentgrps(TRUE) as $cgo) + if (empty($result[$cgo->id])) + $result[$cgo->id] = $cgo; + + return $result; + } + + public function log($message) { + // Log a message for this account + $alo = ORM::factory('Account_Log'); + $alo->account_id = $this->id; + $alo->ip = Request::$client_ip; + $alo->details = $message; + $alo->save(); + + return $alo->saved(); + } + + /** + * This function will extract the available methods for this account + * This is used both for menu options and method security + */ + public function methods() { + static $result = array(); + + // @todo We may want to optimise this with some session caching. + if ($result) + return $result; + + foreach ($this->groups() as $go) + foreach ($go->module_method->find_all() as $mmo) + if (empty($result[$mmo->id])) + $result[$mmo->id] = $mmo; + + Sort::MAsort($result,'module->name,menu_display'); + + return $result; + } + + /** + * Return an account name + */ + public function name() { + return trim(sprintf('%s %s',$this->first_name,$this->last_name)); + } + + /** + * Search for accounts matching a term + */ + public function list_autocomplete($term,$index,$value,array $label,array $limit=array(),array $options=NULL) { + $ao = Auth::instance()->get_user(); + + $this->clear(); + $this->where_active(); + + // Build our where clause + // First Name, Last name + if (preg_match('/\ /',$term)) { + list($fn,$ln) = explode(' ',$term,2); + + $this->where_open() + ->where_open() + ->where('first_name','like','%'.$fn.'%') + ->and_where('last_name','like','%'.$ln.'%') + ->where_close() + ->or_where('company','like','%'.$term.'%') + ->where_close(); + + } elseif (is_numeric($term)) { + $this->where('id','like','%'.$term.'%'); + + } elseif (preg_match('/\@/',$term)) { + $this->where('email','like','%'.$term.'%'); + + } else { + $this->where_open() + ->where('company','like','%'.$term.'%') + ->or_where('first_name','like','%'.$term.'%') + ->or_where('last_name','like','%'.$term.'%') + ->where_close(); + } + + // Restrict results to authorised accounts + array_push($limit,array('id','IN',$ao->RTM->customers($ao->RTM))); + + return parent::list_autocomplete($term,$index,$value,$label,$limit,$options); + } +} +?> diff --git a/application/classes/Model/Original.php b/application/classes/Model/Account/Log.php similarity index 53% rename from application/classes/Model/Original.php rename to application/classes/Model/Account/Log.php index 16f601b..851361a 100644 --- a/application/classes/Model/Original.php +++ b/application/classes/Model/Account/Log.php @@ -1,27 +1,26 @@ array(), + ); + + protected $_sorting = array( + 'id'=>'DESC', ); - /** - * Filters used to format the display of values into friendlier values - */ protected $_display_filters = array( 'date_orig'=>array( - array('Config::datetime',array(':value')), + array('Site::Datetime',array(':value')), ), ); } diff --git a/application/classes/Model/Auth/UserDefault.php b/application/classes/Model/Auth/UserDefault.php new file mode 100644 index 0000000..d3f4d06 --- /dev/null +++ b/application/classes/Model/Auth/UserDefault.php @@ -0,0 +1,42 @@ + array( + array('not_empty'), + array('min_length', array(':value', 4)), + array('max_length', array(':value', 256)), + ), + 'email' => array( + array('not_empty'), + array('min_length', array(':value', 4)), + array('max_length', array(':value', 127)), + array('email'), + ), + ); + } + + /** + * 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. + */ + public function complete_login() { + return $this->log('Logged In'); + } +} +?> diff --git a/application/classes/Model/Group.php b/application/classes/Model/Group.php new file mode 100644 index 0000000..701c08b --- /dev/null +++ b/application/classes/Model/Group.php @@ -0,0 +1,71 @@ +array('through'=>'account_group'), + 'module_method'=>array('through'=>'group_method','far_key'=>'method_id'), + ); + protected $_sorting = array( + 'name'=>'ASC', + ); + + protected $_display_filters = array( + 'active'=>array( + array('StaticList_YesNo::get',array(':value',TRUE)), + ), + ); + + /** + * 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; + } +} +?> diff --git a/application/classes/Model/Language.php b/application/classes/Model/Language.php deleted file mode 100644 index 7897a60..0000000 --- a/application/classes/Model/Language.php +++ /dev/null @@ -1,30 +0,0 @@ -'id','value'=>'name'); - - /** - * Filters used to format the display of values into friendlier values - */ - protected $_display_filters = array( - 'date_orig'=>array( - array('Config::datetime',array(':value')), - ), - ); -} -?> diff --git a/application/classes/Model/Module.php b/application/classes/Model/Module.php new file mode 100644 index 0000000..0405cac --- /dev/null +++ b/application/classes/Model/Module.php @@ -0,0 +1,55 @@ +array('model'=>'Record_ID','far_key'=>'id'), + ); + protected $_has_many = array( + 'module_method'=>array('far_key'=>'id'), + ); + protected $_sorting = array( + 'name'=>'ASC', + ); + + protected $_display_filters = array( + 'external'=>array( + array('StaticList_YesNo::get',array(':value',TRUE)), + ), + 'name'=>array( + array('strtoupper',array(':value')), + ), + 'active'=>array( + array('StaticList_YesNo::get',array(':value',TRUE)), + ), + ); + + /** + * Return an instance of this Module's Model + * + * @param $id PK of Model + */ + public function instance($id=NULL) { + if (! $this->loaded()) + throw new Kohana_Exception('Cant call an instance of a model when it is not loaded'); + + return ORM::factory(Kohana::classname($this->name),$id); + } + + public function list_external() { + return $this->where_active()->where('external','=',TRUE)->find_all(); + } +} +?> diff --git a/application/classes/Model/Record/ID.php b/application/classes/Model/Record/ID.php new file mode 100644 index 0000000..cff704d --- /dev/null +++ b/application/classes/Model/Record/ID.php @@ -0,0 +1,40 @@ +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 HTTP_Exception::factory(501,'Unable to increase ID for :table',array(':table'=>$mid)); + + return $this->id; + } +} +?> diff --git a/application/classes/Model/Setup.php b/application/classes/Model/Setup.php new file mode 100644 index 0000000..bb73eaf --- /dev/null +++ b/application/classes/Model/Setup.php @@ -0,0 +1,115 @@ +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'), + ); + + protected $_compress_column = array( + 'module_config', + 'site_details', + ); + + // Validation rules + public function rules() { + $x = Arr::merge(parent::rules(), array( + 'url' => array( + array('not_empty'), + array('min_length', array(':value', 8)), + array('max_length', array(':value', 127)), + array('url'), + ), + )); + + // This module doesnt use site_id. + unset($x['site_id']); + + return $x; + } + + /** + * 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',array('name'=>$key)); + + 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; + } + + public function module_config_id($key=NULL) { + $result = array(); + + foreach (array_keys($this->module_config) as $mid) { + if (is_null($key) OR $key == $mid) { + $result[$mid] = array( + 'object'=>ORM::factory('Module',$mid), + 'data'=>$this->module_config[$mid], + ); + + // If we are just after our key, we can continue here + if ($key AND $key==$mid) + break; + } + } + + return $result; + } + + /** + * 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','faqurl'))) + 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; + } +} +?> diff --git a/application/classes/Model/Translate.php b/application/classes/Model/Translate.php deleted file mode 100644 index 0c9d602..0000000 --- a/application/classes/Model/Translate.php +++ /dev/null @@ -1,30 +0,0 @@ -'id','value'=>'translation'); - - /** - * Filters used to format the display of values into friendlier values - */ - protected $_display_filters = array( - 'date_orig'=>array( - array('Config::datetime',array(':value')), - ), - ); -} -?> diff --git a/application/classes/ORM.php b/application/classes/ORM.php new file mode 100644 index 0000000..4dc5fc9 --- /dev/null +++ b/application/classes/ORM.php @@ -0,0 +1,179 @@ +array( + array('ORM::get_next_id',array(':model',':field')), + ), + 'site_id'=>array( + array('ORM::set_site_id',array(':model',':field')), + ), + ); + } + + /** + * 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()); + + // Ensure we Cache our queries + $caching = FALSE; + foreach ($this->_db_pending as $method) + if ($method['name'] == 'cached') { + $caching = TRUE; + break; + } + + if (! $caching) + $this->cached(Kohana::$config->load('cache.orm.'.$this->_table_name)); + + return parent::_build($type); + } + + /** + * Determine if the account is authoised by the user + */ + public function authorised(Model $o=NULL,Model_Account $ao=NULL,$aid='account_id') { + if (is_null($o)) + $o = $this; + if (is_null($ao)) + $ao = Auth::instance()->get_user(); + + return in_array($o->{$aid},$ao->RTM->customers($ao->RTM)); + } + + /** + * 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; + } + 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; + } + + final public function mid() { + return ORM::factory('Module',array('name'=>$this->_table_name)); + } + + /** + * 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; + } + + /** + * Function help to find records that are active + */ + public function list_active($active=TRUE) { + $x=($active ? $this->_where_active() : $this); + + return $x->find_all(); + } + + public function list_count($active=TRUE) { + $x=($active ? $this->_where_active() : $this); + + return $x->find_all()->count(); + } + + public function where_active() { + return $this->where('active','=',TRUE); + } + + public function where_authorised(Model_Account $ao=NULL,$aid='account_id') { + if (is_null($ao)) + $ao = Auth::instance()->get_user(); + + return $this->where($aid,'IN',$ao->RTM->customers($ao->RTM)); + } +} +?> diff --git a/application/classes/ORM/OSB.php b/application/classes/ORM/OSB.php deleted file mode 100644 index 1ca09b8..0000000 --- a/application/classes/ORM/OSB.php +++ /dev/null @@ -1,287 +0,0 @@ -'date_orig','format'=>TRUE); - protected $_updated_column = array('column'=>'date_last','format'=>TRUE); - - // Our attributes used in forms. - protected $_form = array(); - - // Our attributes that should be converted to NULL when empty - protected $_nullifempty = array(); - - // Our attribute values that need to be stored as serialized - protected $_serialize_column = array(); - - // If we need to load any sub items on loading this model - protected $_sub_items = array(); - protected $_sub_items_load = array(); - protected $_sub_items_sorted = FALSE; - - // Rules to assist with site ID and getting next record ID for inserts. - public function xrules() { - 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')), - ), - ); - } - - /** - * Retrieve and Store DB BLOB data. - */ - private function _blob($data,$set=FALSE) { - try { - return $set ? gzcompress($this->_serialize($data,$set)) : $this->_serialize(gzuncompress($data)); - - // Maybe the data isnt compressed? - } catch (Exception $e) { - return $this->_serialize($data,$set); - } - } - - /** - * 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) { - HTTP_Exception::factory(501,Kohana_Exception::text($e)); - } - - $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) { - HTTP_Exception::factory(501,Kohana_Exception::text($e)); - } - - $this->_table_columns[$column]['unserialized'] = TRUE; - } - } - - return parent::__get($column); - } - - /** - * Intercept our object load, so that we can load our subitems - */ - protected function _load_values(array $values) { - parent::_load_values($values); - - $sort = FALSE; - if ($this->_loaded AND $this->_sub_items_load AND count($this->_sub_items_load) == 1) - foreach ($this->_sub_items_load as $item => $sort) - $this->_sub_items = $this->$item->find_all()->as_array(); - - if ($sort) { - Sort::MAsort($this->_sub_items,$sort); - $this->_sub_items_sorted = TRUE; - } - - return $this; - } - - /** - * If a column is marked to be nullified if it is empty, this is where it is done. - */ - private function _nullifempty(array $array) { - foreach ($array as $k=>$v) { - if (is_array($v)) { - if (is_null($x=$this->_nullifempty($v))) - unset($array[$k]); - else - $array[$k] = $x; - - } elseif (! $v AND $v !== 0 AND $v !== '0') - unset($array[$k]); - - } - - return count($array) ? $array : NULL; - } - - /** - * Try and (un)serialize our data, and if it fails, just return it. - */ - private function _serialize($data,$set=FALSE) { - try { - return $set ? serialize($data) : unserialize($data); - - // Maybe the data serialized? - } catch (Exception $e) { - return $data; - } - } - - public function config($key) { - $mc = Config::instance()->module_config($this->_object_name); - - return empty($mc[$key]) ? '' : $mc[$key]; - } - - public function dump() { - $result = array(); - - $result['this'] = $this->object(); - - foreach ($this->_sub_items as $o) - $result['sub'][] = $o->dump(); - - return $result; - } - - /** - * 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; - } - - 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 xsave(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 (! is_null($this->_object[$c]) AND $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]); - } - - // Test if the value has still changed - if ($this->_original_values AND $this->_object[$c] == $this->_original_values[$c]) - unset($this->_changed[$c]); - } - - return parent::save($validation); - } - - /** - * 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 subitems() { - return $this->_sub_items; - } - - /** - * Override the Kohana processing so we can null values if required. - */ - public function values(array $values,array $expected=NULL) { - foreach ($values as $k=>$v) { - // Convert to NULL - if (in_array($k,$this->_nullifempty)) { - if (is_array($v)) - $values[$k] = $this->_nullifempty($v); - - elseif (! $v AND $v !== 0 AND $v !== '0') - $values[$k] = NULL; - } - } - - return parent::values($values,$expected); - } - - /** - * Function help to find records that are active - */ - public function list_active($active=TRUE) { - $x=($active ? $this->_where_active() : $this); - - return $x->find_all(); - } - - public function list_count($active=TRUE) { - $x=($active ? $this->_where_active() : $this); - - return $x->find_all()->count(); - } -} -?> diff --git a/application/classes/Site.php b/application/classes/Site.php new file mode 100644 index 0000000..5524c53 --- /dev/null +++ b/application/classes/Site.php @@ -0,0 +1,39 @@ +date_format(),$date); + } + + /** + * Work out our site ID for multihosting + */ + public static function ID($format=FALSE) { + return Company::instance()->site($format); + } + + public static function Theme() { + // If we are using user admin pages (and login), we'll choose the admin theme. + return 'theme/'.(URL::admin_url() ? Kohana::$config->load('config')->theme_admin : Kohana::$config->load('config')->theme); + } + + /** + * Show a date using a site configured format + */ + public static function Time($date) { + return date(Company::instance()->time_format(),($date ? $date : time())); + } +} +?> diff --git a/application/classes/URL.php b/application/classes/URL.php new file mode 100644 index 0000000..4bee911 --- /dev/null +++ b/application/classes/URL.php @@ -0,0 +1,40 @@ +'a', + 'committee'=>'c', + 'user'=>'u', + ); + + public static function navbar() { + $result = array(); + + foreach (array_reverse(self::$method_directory) as $k=>$v) + switch ($k) { + case 'admin': $result[$k] = array('name'=>'Administrator','icon'=>'icon-globe'); + break; + + case 'committe': $result[$k] = array('name'=>'Reseller','icon'=>'icon-th-list'); + break; + + case 'user': $result[$k] = array('name'=>Auth::instance()->get_user()->name(),'icon'=>'icon-user'); + break; + + default: $result[$k] = array('name'=>$k,'icon'=>'icon-question-sign'); + } + + return $result; + } +} +?> diff --git a/application/config/auth.php b/application/config/auth.php new file mode 100644 index 0000000..b8bef81 --- /dev/null +++ b/application/config/auth.php @@ -0,0 +1,17 @@ + 'MDB', + 'hash_method' => 'md5', +); +?> diff --git a/application/config/config.php b/application/config/config.php new file mode 100644 index 0000000..77eb350 --- /dev/null +++ b/application/config/config.php @@ -0,0 +1,10 @@ + 'Membership Database', + 'session_change_trigger'=>array( // Updates to tables to make when our session ID is changed + ), + 'theme' => 'focusbusiness', + 'theme_admin' => 'baseadmin', +); diff --git a/application/config/database.php b/application/config/database.php index db4753c..a781657 100644 --- a/application/config/database.php +++ b/application/config/database.php @@ -18,13 +18,13 @@ return array * * Ports and sockets may be appended to the hostname. */ - 'hostname' => 'localhost', - 'database' => 'weblnaer', - 'username' => 'aer', - 'password' => 'AeR', + 'hostname' => 'mysql.leenooks.vpn', + 'database' => 'weblnebcccmdb', + 'username' => 'ln-ebccc', + 'password' => 'ebccc', 'persistent' => TRUE, ), - 'table_prefix' => '', + 'table_prefix' => 'mdb_', 'charset' => 'utf8', 'caching' => FALSE, ), diff --git a/application/config/mainnav.php b/application/config/mainnav.php new file mode 100644 index 0000000..1a2cfcf --- /dev/null +++ b/application/config/mainnav.php @@ -0,0 +1,16 @@ + array('icon'=>'icon-edit','url'=>URL::site('photo/duplicate')), +); +?> diff --git a/application/views/pages/navbar.php b/application/views/pages/navbar.php deleted file mode 100644 index e69de29..0000000 diff --git a/application/views/theme/baseadmin/page.php b/application/views/theme/baseadmin/page.php deleted file mode 100644 index 4dee9aa..0000000 --- a/application/views/theme/baseadmin/page.php +++ /dev/null @@ -1,130 +0,0 @@ - - - - <?php echo $meta->title; ?> - - - - - - - - - - - - = Kohana::TESTING OR Request::current()->secure()) { - echo HTML::style('media/theme/bootstrap/css/bootstrap.min.css'); - echo HTML::style('media/theme/bootstrap/css/bootstrap-responsive.min.css'); - echo HTML::style('media/vendor/font-awesome/css/font-awesome.min.css'); - } else { - echo HTML::style($meta->secure().'netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap.min.css'); - echo HTML::style($meta->secure().'netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css'); - echo HTML::style($meta->secure().'netdna.bootstrapcdn.com/font-awesome/3.0.2/css/font-awesome.css'); - } - - echo HTML::style($meta->secure().'fonts.googleapis.com/css?family=Open+Sans:400italic,600italic,800italic,400,600,800'); - echo HTML::style('media/css/ui-lightness/jquery-ui-1.10.0.custom.min.css'); - echo HTML::style('media/theme/baseadmin/css/base-admin-2.css'); - echo HTML::style('media/theme/baseadmin/css/base-admin-2-responsive.css'); - echo HTML::style('media/theme/baseadmin/css/custom.css'); - echo Style::factory()->render_all(); - ?> - - - - - - - - - -
-
-
-
- render_all(); ?> -
-
-
-
- -
-
-
- -
-
-
- - = Kohana::TESTING OR Request::current()->secure()) { - echo HTML::script('media/js/jquery/jquery-1.9.1.min.js'); - echo HTML::script('media/theme/bootstrap/js/bootstrap.min.js'); - echo HTML::script('media/js/lodash/lodash-1.2.1.min.js'); - } else { - echo HTML::script($meta->secure().'code.jquery.com/jquery-1.9.1.min.js'); - echo HTML::script($meta->secure().'netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js'); - echo HTML::script($meta->secure().'cdnjs.cloudflare.com/ajax/libs/lodash.js/1.2.1/lodash.min.js'); - } - - echo HTML::script('media/theme/baseadmin/js/backtotop.js'); - echo HTML::script('media/js/search.js'); - echo HTML::script('media/js/custom.js'); - echo Script::factory()->render_all(); - ?> - - diff --git a/application/views/translate.php b/application/views/translate.php deleted file mode 100644 index 433ff1f..0000000 --- a/application/views/translate.php +++ /dev/null @@ -1,33 +0,0 @@ -$o->count(),'items_per_page'=>10)); ?> - - -current_page()); ?> - - - - - - - - - current_first_item()) - continue; - elseif ($i > $pag->current_last_item()) - break; - ?> - - sentence) OR preg_match('/>/',$oo->sentence)) : - $oo->sentence = preg_replace('/sentence); - $oo->sentence = preg_replace('/>/','>',$oo->sentence); - endwhile - ?> - - - - - - - - -
TextTranslationIgnore
sentence; ?>id),$oo->translation,array('style'=>'width: 100%;')); ?>
diff --git a/includes/kohana b/includes/kohana index e2475db..5ffa395 160000 --- a/includes/kohana +++ b/includes/kohana @@ -1 +1 @@ -Subproject commit e2475dba9e6eaeafc6ecc4c71542937638354cd4 +Subproject commit 5ffa395307a3b26f901dde5f3064c48a15979f0d diff --git a/modules/lnApp b/modules/lnApp deleted file mode 160000 index a889d25..0000000 --- a/modules/lnApp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a889d25eda0d6c1b8766b15f2d71f3dd4f0357d9 diff --git a/modules/lnapp b/modules/lnapp new file mode 160000 index 0000000..e6bc2de --- /dev/null +++ b/modules/lnapp @@ -0,0 +1 @@ +Subproject commit e6bc2de66ab85d5fd9e6de01c118e07a911f9921