Updated bootstrap and many other items
This commit is contained in:
parent
85150c655c
commit
9ae0980221
4
classes/Auth.php
Normal file
4
classes/Auth.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||||
|
|
||||||
|
abstract class Auth extends lnApp_Auth {}
|
||||||
|
?>
|
9
classes/Controller/Welcome.php
Normal file
9
classes/Controller/Welcome.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
|
|
||||||
|
class Controller_Welcome extends Controller_TemplateDefault {
|
||||||
|
protected $auth_required = FALSE;
|
||||||
|
|
||||||
|
public function action_index() {
|
||||||
|
throw HTTP_Exception::factory(500,'Site not setup!');
|
||||||
|
}
|
||||||
|
} // End Welcome
|
4
classes/Database/MySQL.php
Normal file
4
classes/Database/MySQL.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||||
|
|
||||||
|
class Database_MySQL extends lnApp_Database_MySQL {}
|
||||||
|
?>
|
4
classes/Email.php
Normal file
4
classes/Email.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||||
|
|
||||||
|
class Email extends lnApp_Email {}
|
||||||
|
?>
|
3
classes/Email/Exception.php
Normal file
3
classes/Email/Exception.php
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?php defined('SYSPATH') OR die('No direct script access.');
|
||||||
|
|
||||||
|
class Email_Exception extends lnApp_Email_Exception {}
|
@ -6,8 +6,8 @@
|
|||||||
* @package lnApp
|
* @package lnApp
|
||||||
* @category Helpers
|
* @category Helpers
|
||||||
* @author Deon George
|
* @author Deon George
|
||||||
* @copyright (c) 2009-2013 Open Source Billing
|
* @copyright (c) 2009-2013 Deon George
|
||||||
* @license http://dev.osbill.net/license.html
|
* @license http://dev.leenooks.net/license.html
|
||||||
*/
|
*/
|
||||||
class Object {
|
class Object {
|
||||||
/**
|
/**
|
||||||
|
22
classes/lnApp/Auth.php
Normal file
22
classes/lnApp/Auth.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class overrides Kohana's Auth
|
||||||
|
*
|
||||||
|
* This file contains enhancements for Kohana, that should be considered upstream and maybe havent been yet.
|
||||||
|
*
|
||||||
|
* @package lnApp
|
||||||
|
* @category Modifications
|
||||||
|
* @author Deon George
|
||||||
|
* @copyright (c) 2014 Deon George
|
||||||
|
* @license http://dev.leenooks.net/license.html
|
||||||
|
*/
|
||||||
|
abstract class lnApp_Auth extends Kohana_Auth {
|
||||||
|
protected $_model = 'Account';
|
||||||
|
|
||||||
|
public function get_user($default=NULL) {
|
||||||
|
$x = parent::get_user($default);
|
||||||
|
|
||||||
|
return (! $x) ? ORM::factory($this->_model) : $x;
|
||||||
|
}
|
||||||
|
}
|
@ -50,11 +50,11 @@ abstract class lnApp_Block extends HTMLRender {
|
|||||||
$record = self::$_data[$this->_x];
|
$record = self::$_data[$this->_x];
|
||||||
|
|
||||||
$output = '';
|
$output = '';
|
||||||
$output .= sprintf('<div class="col-md-%s %s">',empty($record['span']) ? '12' : $record['span'],empty($record['scrollable']) ? '' : 'scrollable');
|
$output .= sprintf('<div class="col-md-%s %s">',Arr::get($record,'span',12),Arr::get($record,'scrollable',''));
|
||||||
$output .= '<div class="widget stacked">';
|
$output .= '<div class="widget stacked">';
|
||||||
|
|
||||||
if (! empty($record['title']))
|
if (! empty($record['title']))
|
||||||
$output .= sprintf('<div class="widget-header">%s<h3>%s</h3></div>',empty($record['title_icon']) ? '' : sprintf(' <i class="fa %s"></i>',$record['title_icon']),$record['title']);
|
$output .= sprintf('<div class="widget-header"><i class="fa %s"></i><h3>%s</h3></div>',Arr::get($record,'title_icon','fa-square'),Arr::get($record,'title','NO Title!'));
|
||||||
|
|
||||||
$output .= '<div class="widget-content">';
|
$output .= '<div class="widget-content">';
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ abstract class lnApp_Block extends HTMLRender {
|
|||||||
$output .= Form::close();
|
$output .= Form::close();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'form-horizontal': $output .= Form::open(NULL,Arr::merge(array('class'=>'form-horizontal','role'=>'form'),(empty($record['id']) ? array() : array('id'=>$record['id']))));
|
case 'form-horizontal': $output .= Form::open(NULL,Arr::merge(array('class'=>'form-horizontal','role'=>'form','data-toggle'=>'validator'),(empty($record['id']) ? array() : array('id'=>$record['id']))));
|
||||||
$output .= (string)$record['body'];
|
$output .= (string)$record['body'];
|
||||||
$output .= Form::close();
|
$output .= Form::close();
|
||||||
break;
|
break;
|
||||||
|
@ -13,6 +13,93 @@
|
|||||||
class lnApp_Controller_Login extends Controller_TemplateDefault {
|
class lnApp_Controller_Login extends Controller_TemplateDefault {
|
||||||
protected $auth_required = FALSE;
|
protected $auth_required = FALSE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activate an account so that it can login and use the site
|
||||||
|
*/
|
||||||
|
public function action_activate() {
|
||||||
|
if ($this->request->post()) {
|
||||||
|
$ao = ORM::factory('Account',array('id'=>$this->request->param('id'),'email'=>$this->request->post('email')));
|
||||||
|
|
||||||
|
if ($ao->loaded()) {
|
||||||
|
if ($ao->activated())
|
||||||
|
HTTP::redirect('login');
|
||||||
|
|
||||||
|
elseif ($ao->activate_code() == $this->request->post('code')) {
|
||||||
|
$go = ORM::factory('Group',array('name'=>'Registered Users'));
|
||||||
|
|
||||||
|
$ago = ORM::factory('Account_Group',array('account_id'=>$ao,'group_id'=>$go));
|
||||||
|
|
||||||
|
if (! $ago->loaded()) {
|
||||||
|
$ago->account_id=$ao;
|
||||||
|
$ago->group_id=$go;
|
||||||
|
}
|
||||||
|
$ago->active = TRUE;
|
||||||
|
$ago->save();
|
||||||
|
|
||||||
|
SystemMessage::factory()
|
||||||
|
->title(_('Account Activated'))
|
||||||
|
->type('info')
|
||||||
|
->body(_('Your account has been activated.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} elseif (! $this->request->param('id'))
|
||||||
|
HTTP::redirect('login/activate_resend');
|
||||||
|
|
||||||
|
Block::factory()
|
||||||
|
->title('Activate account')
|
||||||
|
->title_icon('fa-wrench')
|
||||||
|
->type('form-horizontal')
|
||||||
|
->body(View::factory('login/activate')->set('o',Session::instance()->get_once('activate')));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the account activation code to the email address, validating the email address
|
||||||
|
*/
|
||||||
|
public function action_activate_resend() {
|
||||||
|
if ($this->request->post('email')) {
|
||||||
|
$ao = ORM::factory('Account',array('email'=>$this->request->post('email')));
|
||||||
|
|
||||||
|
if ($ao->loaded()) {
|
||||||
|
if ($ao->activated())
|
||||||
|
HTTP::redirect('login');
|
||||||
|
else {
|
||||||
|
$co = Company::instance();
|
||||||
|
|
||||||
|
// Send our email with the token
|
||||||
|
$email = Email::factory('login_activate')
|
||||||
|
->set('SITE',URL::base(TRUE,TRUE))
|
||||||
|
->set('SITE_ADMIN',$co->admin()->name())
|
||||||
|
->set('CODE',$ao->activate_code())
|
||||||
|
->set('EMAIL',$ao->email)
|
||||||
|
->set('ID',$ao->id)
|
||||||
|
->set('USER_NAME',$ao->name());
|
||||||
|
|
||||||
|
$email->to = array('email'=>array($ao->email=>$ao->name()));
|
||||||
|
$email->from = array('email'=>array($co->admin()->email=>$co->admin()->name()));
|
||||||
|
$email->subject = 'Activation Code for '.$co->name();
|
||||||
|
$email->deliver();
|
||||||
|
|
||||||
|
// Log the password reset
|
||||||
|
$ao->log('Activation code sent');
|
||||||
|
Session::instance()->set('activate',$ao);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTP::redirect('login/activate/'.$ao->id);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Block::factory()
|
||||||
|
->title('Activate account')
|
||||||
|
->title_icon('fa-wrench')
|
||||||
|
->type('form-horizontal')
|
||||||
|
->body(View::factory('login/activate_resend'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login to the site
|
||||||
|
*/
|
||||||
public function action_index() {
|
public function action_index() {
|
||||||
$output = '';
|
$output = '';
|
||||||
|
|
||||||
@ -24,9 +111,9 @@ class lnApp_Controller_Login extends Controller_TemplateDefault {
|
|||||||
HTTP::redirect(URL::link('user','welcome/index'));
|
HTTP::redirect(URL::link('user','welcome/index'));
|
||||||
|
|
||||||
// If there is a post and $_POST is not empty
|
// If there is a post and $_POST is not empty
|
||||||
if ($_POST) {
|
if ($this->request->post()) {
|
||||||
// If the post data validates using the rules setup in the user model
|
// If the post data validates using the rules setup in the user model
|
||||||
if (Auth::instance()->login($_POST['username'],$_POST['password'])) {
|
if (Auth::instance()->login($this->request->post('username'),$this->request->post('password'))) {
|
||||||
// Redirect to the user account
|
// Redirect to the user account
|
||||||
if ($redir = Session::instance()->get('afterlogin')) {
|
if ($redir = Session::instance()->get('afterlogin')) {
|
||||||
Session::instance()->delete('afterlogin');
|
Session::instance()->delete('afterlogin');
|
||||||
@ -48,7 +135,7 @@ class lnApp_Controller_Login extends Controller_TemplateDefault {
|
|||||||
else
|
else
|
||||||
$oauthlogin = FALSE;
|
$oauthlogin = FALSE;
|
||||||
|
|
||||||
$output .= View::factory('pages/login')
|
$output .= View::factory('login')
|
||||||
->set('oauth',$oauthlogin);
|
->set('oauth',$oauthlogin);
|
||||||
|
|
||||||
Style::factory()
|
Style::factory()
|
||||||
@ -63,11 +150,92 @@ class lnApp_Controller_Login extends Controller_TemplateDefault {
|
|||||||
$this->template->shownavbar = FALSE;
|
$this->template->shownavbar = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method redirect when authenticated user doesnt have access to the url
|
||||||
|
*/
|
||||||
public function action_noaccess() {
|
public function action_noaccess() {
|
||||||
SystemMessage::factory()
|
SystemMessage::factory()
|
||||||
->title(_('No access to requested resource'))
|
->title(_('No access to requested resource'))
|
||||||
->type('danger')
|
->type('danger')
|
||||||
->body(_('You do not have access to the requested resource, please contact your administrator.'));
|
->body(_('You do not have access to the requested resource, please contact your administrator.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register for an account on the site
|
||||||
|
*/
|
||||||
|
public function action_register() {
|
||||||
|
$ao = ORM::factory('Account',$this->request->param('id'));
|
||||||
|
|
||||||
|
if ($this->request->post() AND $ao->values($this->request->post())->changed() AND (! $this->save($ao)))
|
||||||
|
$ao->reload()->values($this->request->post());
|
||||||
|
|
||||||
|
if ($ao->loaded())
|
||||||
|
HTTP::redirect('login');
|
||||||
|
|
||||||
|
Block::factory()
|
||||||
|
->type('form-horizontal')
|
||||||
|
->title('Register Account')
|
||||||
|
->title_icon('fa-edit')
|
||||||
|
->body(View::factory('account/user/edit')->set('o',$ao));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable user password reset
|
||||||
|
*/
|
||||||
|
public function action_reset() {
|
||||||
|
// Minutes to keep our token
|
||||||
|
$token_expire = 15;
|
||||||
|
$co = Company::instance();
|
||||||
|
|
||||||
|
// 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 ($this->request->post()) {
|
||||||
|
// If the username is correct, create a method token
|
||||||
|
if ($ao=ORM::factory('Account',array('email'=>$this->request->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
|
||||||
|
$email = Email::factory('login_reset')
|
||||||
|
->set('SITE',URL::base(TRUE,TRUE))
|
||||||
|
->set('SITE_ADMIN',$co->admin()->name())
|
||||||
|
->set('TOKEN',$mmto->token)
|
||||||
|
->set('TOKEN_EXPIRE_MIN',$token_expire)
|
||||||
|
->set('USER_NAME',$mmto->account->name());
|
||||||
|
|
||||||
|
$email->to = array('email'=>array($mmto->account->email=>$mmto->account->name()));
|
||||||
|
$email->from = array('email'=>array($co->admin()->email=>$co->admin()->name()));
|
||||||
|
$email->subject = 'Login Reset Token for '.$co->name();
|
||||||
|
$email->deliver();
|
||||||
|
|
||||||
|
// Log the password reset
|
||||||
|
$ao->log('Password reset token sent');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect to our password reset, the Auth will validate the token.
|
||||||
|
} elseif ($this->request->post('token')) {
|
||||||
|
HTTP::redirect(URL::link('user','account/resetpassword?token='.$this->request->post('token')));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show our token screen even if the email was invalid.
|
||||||
|
if ($this->request->post('username'))
|
||||||
|
$output = View::factory('login/reset_sent');
|
||||||
|
else
|
||||||
|
HTTP::redirect('login');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$output = View::factory('login/reset');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->template->content = $output;
|
||||||
|
$this->template->shownavbar = FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
@ -56,13 +56,7 @@ abstract class lnApp_Controller_TemplateDefault extends Kohana_Controller_Templa
|
|||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
protected function _auth_required() {
|
protected function _auth_required() {
|
||||||
// If our global configurable is disabled, then continue
|
return FALSE;
|
||||||
if (! Kohana::$config->load('config')->method_security)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return (($this->auth_required !== FALSE && Auth::instance()->logged_in(NULL,get_class($this).'|'.__METHOD__) === FALSE) ||
|
|
||||||
(is_array($this->secure_actions) && array_key_exists($this->request->action(),$this->secure_actions) &&
|
|
||||||
! Auth::instance()->logged_in($this->secure_actions[$this->request->action()],get_class($this).'|'.__METHOD__)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,16 +66,6 @@ abstract class lnApp_Controller_TemplateDefault extends Kohana_Controller_Templa
|
|||||||
* @uses meta
|
* @uses meta
|
||||||
*/
|
*/
|
||||||
public function before() {
|
public function before() {
|
||||||
if ($this->auth_required) {
|
|
||||||
if (! count($this->secure_actions) OR (! isset($this->secure_actions[Request::current()->action()])))
|
|
||||||
throw HTTP_Exception::factory(403,'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));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actions that start with ajax, should only be ajax
|
// Actions that start with ajax, should only be ajax
|
||||||
if (! Kohana::$config->load('debug')->ajax AND preg_match('/^ajax/',Request::current()->action()) AND ! Request::current()->is_ajax())
|
if (! Kohana::$config->load('debug')->ajax AND preg_match('/^ajax/',Request::current()->action()) AND ! Request::current()->is_ajax())
|
||||||
throw HTTP_Exception::factory(412,_('Unable to fulfil request.'));
|
throw HTTP_Exception::factory(412,_('Unable to fulfil request.'));
|
||||||
@ -94,6 +78,9 @@ abstract class lnApp_Controller_TemplateDefault extends Kohana_Controller_Templa
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->ao AND $this->ao->loaded() AND ! $this->ao->activated() AND ($this->request->controller() != 'Account' OR $this->request->action() != 'activate'))
|
||||||
|
HTTP::redirect('login/activate');
|
||||||
|
|
||||||
// Check user auth and role
|
// Check user auth and role
|
||||||
if ($this->_auth_required()) {
|
if ($this->_auth_required()) {
|
||||||
if (PHP_SAPI === 'cli')
|
if (PHP_SAPI === 'cli')
|
||||||
@ -187,30 +174,18 @@ abstract class lnApp_Controller_TemplateDefault extends Kohana_Controller_Templa
|
|||||||
$this->check_cache(sha1($this->response->body()));
|
$this->check_cache(sha1($this->response->body()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function save(Model $o) {
|
||||||
* Generate a view path to help View::factory() calls
|
try {
|
||||||
*
|
return $o->save();
|
||||||
* The purpose of this method is to ensure that we have a consistant
|
|
||||||
* layout for our view files, including those that are needed by
|
|
||||||
* plugins
|
|
||||||
*
|
|
||||||
* @param string Plugin Name (optional)
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public function viewpath($plugin='') {
|
|
||||||
$request = Request::current();
|
|
||||||
|
|
||||||
$path = $request->controller();
|
} catch (ORM_Validation_Exception $e) {
|
||||||
|
SystemMessage::factory()
|
||||||
|
->title('Record NOT updated')
|
||||||
|
->type('danger')
|
||||||
|
->body(join('<br/>',array_values($e->errors('models'))));
|
||||||
|
|
||||||
if ($request->directory())
|
return FALSE;
|
||||||
$path .= ($path ? '/' : '').$request->directory();
|
}
|
||||||
|
|
||||||
if ($plugin)
|
|
||||||
$path .= ($path ? '/' : '').$plugin;
|
|
||||||
|
|
||||||
$path .= ($path ? '/' : '').$request->action();
|
|
||||||
|
|
||||||
return strtolower($path);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
20
classes/lnApp/Database/MySQL.php
Normal file
20
classes/lnApp/Database/MySQL.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MySQL database connection.
|
||||||
|
*
|
||||||
|
* Modified for MDB, so that ORM can use enhanced SQL queries. This has been
|
||||||
|
* achieved by simply removing the identifier backtick.
|
||||||
|
* (IE: SELECT function()...)
|
||||||
|
*
|
||||||
|
* @package lnApp
|
||||||
|
* @category Modifications
|
||||||
|
* @author Deon George
|
||||||
|
* @copyright (c) 2014 Deon George
|
||||||
|
* @license http://dev.leenooks.net/license.html
|
||||||
|
*/
|
||||||
|
abstract class lnApp_Database_MySQL extends Kohana_Database_MySQL {
|
||||||
|
// MySQL uses a backtick for identifiers
|
||||||
|
protected $_identifier = '';
|
||||||
|
}
|
||||||
|
?>
|
374
classes/lnApp/Email.php
Normal file
374
classes/lnApp/Email.php
Normal file
@ -0,0 +1,374 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides email template handling in the same manor as views.
|
||||||
|
*
|
||||||
|
* @package lnApp
|
||||||
|
* @category Helpers
|
||||||
|
* @author Deon George
|
||||||
|
* @copyright (c) 2014 Deon George
|
||||||
|
* @license http://dev.leenooks.net/license.html
|
||||||
|
*/
|
||||||
|
abstract class lnApp_Email extends Kohana_Email {
|
||||||
|
// Array of global variables
|
||||||
|
protected static $_global_data = array();
|
||||||
|
|
||||||
|
// View filename
|
||||||
|
protected $_file = array();
|
||||||
|
|
||||||
|
// Array of local variables
|
||||||
|
protected $_data = array();
|
||||||
|
|
||||||
|
// Email Details
|
||||||
|
protected $_email = array();
|
||||||
|
|
||||||
|
// Our email subject key
|
||||||
|
private $_key;
|
||||||
|
|
||||||
|
private $_mime = array(
|
||||||
|
'txt'=>'text/plain',
|
||||||
|
'htm'=>'text/html',
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the initial view filename and local data. Views should almost
|
||||||
|
* always only be created using [Email::factory].
|
||||||
|
*
|
||||||
|
* $email = new Email($file);
|
||||||
|
*
|
||||||
|
* @param string $file view filename
|
||||||
|
* @param array $data array of values
|
||||||
|
* @return void
|
||||||
|
* @uses Email::set_filename
|
||||||
|
*/
|
||||||
|
public function __construct($file=NULL,array $data=NULL) {
|
||||||
|
$this->_key = $file;
|
||||||
|
|
||||||
|
if ($file !== NULL)
|
||||||
|
$this->set_filename($file);
|
||||||
|
|
||||||
|
// Add the values to the current data
|
||||||
|
if ($data !== NULL)
|
||||||
|
$this->_data = $data + $this->_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Magic method, searches for the given variable and returns its value.
|
||||||
|
* Local variables will be returned before global variables.
|
||||||
|
*
|
||||||
|
* $value = $email->foo;
|
||||||
|
*
|
||||||
|
* [!!] If the variable has not yet been set, an exception will be thrown.
|
||||||
|
*
|
||||||
|
* @param string $key variable name
|
||||||
|
* @return mixed
|
||||||
|
* @throws Kohana_Exception
|
||||||
|
*/
|
||||||
|
public function & __get($key) {
|
||||||
|
if (array_key_exists($key,$this->_data))
|
||||||
|
return $this->_data[$key];
|
||||||
|
|
||||||
|
elseif (array_key_exists($key,$this->_email))
|
||||||
|
return $this->_email[$key];
|
||||||
|
|
||||||
|
elseif (array_key_exists($key,Email::$_global_data))
|
||||||
|
return Email::$_global_data[$key];
|
||||||
|
|
||||||
|
else
|
||||||
|
throw new Kohana_Exception('View variable is not set: :var',array(':var'=>$key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Magic method, determines if a variable is set.
|
||||||
|
*
|
||||||
|
* isset($email->foo);
|
||||||
|
*
|
||||||
|
* [!!] `NULL` variables are not considered to be set by [isset](http://php.net/isset).
|
||||||
|
*
|
||||||
|
* @param string $key variable name
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function __isset($key) {
|
||||||
|
return (isset($this->_data[$key]) OR isset($this->_email[$key]) OR isset(Email::$_global_data[$key]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Magic method, calls [Email::set] with the same parameters.
|
||||||
|
*
|
||||||
|
* $email->foo = 'something';
|
||||||
|
*
|
||||||
|
* @param string $key variable name
|
||||||
|
* @param mixed $value value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __set($key,$value) {
|
||||||
|
switch ($key) {
|
||||||
|
case 'from':
|
||||||
|
case 'bcc':
|
||||||
|
case 'to':
|
||||||
|
if (! is_array($value) OR ! array_intersect(array('email','account'),array_keys($value)))
|
||||||
|
throw new Email_Exception('Values for to should be an array of either "mail" or "account", however :value was given',
|
||||||
|
array(':value'=>serialize($value)));
|
||||||
|
|
||||||
|
case 'subject':
|
||||||
|
$this->_email[$key] = $value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$this->set($key,$value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Magic method, returns the output of [Email::render].
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @uses Email::render
|
||||||
|
*/
|
||||||
|
public function __toString() {
|
||||||
|
$e = Email::connect();
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (string)$this->render();
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
/**
|
||||||
|
* Display the exception message.
|
||||||
|
*
|
||||||
|
* We use this method here because it's impossible to throw an
|
||||||
|
* exception from __toString().
|
||||||
|
*/
|
||||||
|
$error_response = Kohana_Exception::_handler($e);
|
||||||
|
|
||||||
|
return $error_response->body();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Magic method, unsets a given variable.
|
||||||
|
*
|
||||||
|
* unset($email->foo);
|
||||||
|
*
|
||||||
|
* @param string $key variable name
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __unset($key) {
|
||||||
|
unset($this->_data[$key],$this->_email[$key],Email::$_global_data[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns a value by reference. The benefit of binding is that values can
|
||||||
|
* be altered without re-setting them. It is also possible to bind variables
|
||||||
|
* before they have values. Assigned values will be available as a
|
||||||
|
* variable within the view file:
|
||||||
|
*
|
||||||
|
* // This reference can be accessed as $ref within the view
|
||||||
|
* $email->bind('ref', $bar);
|
||||||
|
*
|
||||||
|
* @param string $key variable name
|
||||||
|
* @param mixed $value referenced variable
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function bind($key,&$value) {
|
||||||
|
$this->_data[$key] =& $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns a global variable by reference, similar to [Email::bind], except
|
||||||
|
* that the variable will be accessible to all views.
|
||||||
|
*
|
||||||
|
* Email::bind_global($key,$value);
|
||||||
|
*
|
||||||
|
* @param string $key variable name
|
||||||
|
* @param mixed $value referenced variable
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function bind_global($key,&$value) {
|
||||||
|
Email::$_global_data[$key] =& $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Captures the output that is generated when a view is included.
|
||||||
|
* The view data will be extracted to make local variables. This method
|
||||||
|
* is static to prevent object scope resolution.
|
||||||
|
*
|
||||||
|
* $output = Email::capture($file,$data);
|
||||||
|
*
|
||||||
|
* @param string $kohana_view_filename filename
|
||||||
|
* @param array $kohana_view_data variables
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected static function capture($kohana_view_filename,array $kohana_view_data) {
|
||||||
|
return Email::complete(file_get_contents($kohana_view_filename),Arr::merge(Email::$_global_data,$kohana_view_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exchange the variables for values
|
||||||
|
*/
|
||||||
|
private static function complete($output,$data) {
|
||||||
|
foreach (Email::variables($output) as $v)
|
||||||
|
$output = str_replace('$'.$v.'$',$data[$v],$output);
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deliver the email
|
||||||
|
*/
|
||||||
|
public function deliver(array $admin=array()) {
|
||||||
|
// @todo - Setup queue mode
|
||||||
|
return Email::connect()->send($this->render(NULL,$admin));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get email details
|
||||||
|
*/
|
||||||
|
private function email($key) {
|
||||||
|
if (is_array($this->_email[$key]) AND isset($this->_email[$key]['email']))
|
||||||
|
return $this->_email[$key]['email'];
|
||||||
|
else
|
||||||
|
return (is_array($this->_email[$key]) AND isset($this->_email[$key]['account'])) ? $this->_email[$key]['account'] : $this->_email[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Email object. If you do not define the "file" parameter,
|
||||||
|
* you must call [Email::set_filename].
|
||||||
|
*
|
||||||
|
* $email = Email::factory($file);
|
||||||
|
*
|
||||||
|
* @param string $file email filename
|
||||||
|
* @param array $data array of values
|
||||||
|
* @return Email
|
||||||
|
*/
|
||||||
|
public static function factory($file=NULL,array $data=NULL) {
|
||||||
|
return new Email($file,$data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the view object to a string. Global and local data are merged
|
||||||
|
* and extracted to create local variables within the view file.
|
||||||
|
*
|
||||||
|
* $output = $email->render();
|
||||||
|
*
|
||||||
|
* [!!] Global variables with the same key name as local variables will be
|
||||||
|
* overwritten by the local variable.
|
||||||
|
*
|
||||||
|
* @param string $file view filename
|
||||||
|
* @return string
|
||||||
|
* @throws Email_Exception
|
||||||
|
* @uses Email::capture
|
||||||
|
*/
|
||||||
|
public function render($file=NULL,array $admin=array()) {
|
||||||
|
if ($file !== NULL)
|
||||||
|
$this->set_filename($file);
|
||||||
|
|
||||||
|
if (empty($this->_file))
|
||||||
|
throw new Email_Exception('You must set the file to use within your email before rendering');
|
||||||
|
|
||||||
|
if ($x=array_diff(array('to','from','subject'),array_keys($this->_email)))
|
||||||
|
throw new Email_Exception('You are missing :missing from the Email',array(':missing'=>join('|',$x)));
|
||||||
|
|
||||||
|
$sm = Swift_Message::newInstance()
|
||||||
|
->setFrom($this->email('from'))
|
||||||
|
->setSubject($this->email('subject'));
|
||||||
|
|
||||||
|
foreach ($this->_file as $file) {
|
||||||
|
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
|
||||||
|
$sm->addPart(Email::capture($file,$this->_data),array_key_exists($ext,$this->_mime) ? $this->_mime[$ext] : File::mime($file));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Our list of BCC recipients
|
||||||
|
if (Kohana::$config->load('debug')->email_bcc_admin AND $x=Arr::merge($this->email('bcc'),Kohana::$config->load('debug')->email_bcc_admin))
|
||||||
|
$sm->setBcc($x);
|
||||||
|
|
||||||
|
$sm->setTo(($admin OR ($admin = Config::testmail($this->_key))) ? $admin : $this->email('to'));
|
||||||
|
|
||||||
|
return $sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns a variable by name. Assigned values will be available as a
|
||||||
|
* variable within the view file:
|
||||||
|
*
|
||||||
|
* // This value can be accessed as $foo within the view
|
||||||
|
* $email->set('foo','my value');
|
||||||
|
*
|
||||||
|
* You can also use an array to set several values at once:
|
||||||
|
*
|
||||||
|
* // Create the values $food and $beverage in the view
|
||||||
|
* $email->set(array('food' => 'bread', 'beverage' => 'water'));
|
||||||
|
*
|
||||||
|
* @param string $key variable name or an array of variables
|
||||||
|
* @param mixed $value value
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function set($key,$value=NULL) {
|
||||||
|
if (is_array($key))
|
||||||
|
foreach ($key as $name => $value)
|
||||||
|
$this->_data[$name] = $value;
|
||||||
|
|
||||||
|
else
|
||||||
|
$this->_data[$key] = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the view filename.
|
||||||
|
*
|
||||||
|
* $email->set_filename($file);
|
||||||
|
*
|
||||||
|
* @param string $file view filename
|
||||||
|
* @return Email
|
||||||
|
* @throws Email_Exception
|
||||||
|
*/
|
||||||
|
public function set_filename($file) {
|
||||||
|
foreach (array_keys($this->_mime) as $ext)
|
||||||
|
if ($path=Kohana::find_file('email',$file,$ext))
|
||||||
|
// Store the file path locally
|
||||||
|
array_push($this->_file,$path);
|
||||||
|
|
||||||
|
if (! $this->_file)
|
||||||
|
throw new Email_Exception('The requested email :file could not be found',array(':file'=>$file));
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a global variable, similar to [Email::set], except that the
|
||||||
|
* variable will be accessible to all views.
|
||||||
|
*
|
||||||
|
* Email::set_global($name, $value);
|
||||||
|
*
|
||||||
|
* @param string $key variable name or an array of variables
|
||||||
|
* @param mixed $value value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function set_global($key,$value=NULL) {
|
||||||
|
if (is_array($key))
|
||||||
|
foreach ($key as $key2 => $value)
|
||||||
|
Email::$_global_data[$key2] = $value;
|
||||||
|
|
||||||
|
else
|
||||||
|
Email::$_global_data[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the variables in the text
|
||||||
|
*/
|
||||||
|
public static function variables($output) {
|
||||||
|
$results = array();
|
||||||
|
$matches = array();
|
||||||
|
|
||||||
|
preg_match_all('/\$([A-Z0-9_]+)\$/U',$output,$matches,PREG_OFFSET_CAPTURE);
|
||||||
|
|
||||||
|
foreach ($matches[1] as $k => $v)
|
||||||
|
if (! in_array($v[0],$results))
|
||||||
|
array_push($results,$v[0]);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
9
classes/lnApp/Email/Exception.php
Normal file
9
classes/lnApp/Email/Exception.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php defined('SYSPATH') OR die('No direct script access.');
|
||||||
|
/**
|
||||||
|
* @package lnApp
|
||||||
|
* @category Exceptions
|
||||||
|
* @author Deon George
|
||||||
|
* @copyright (c) 2014 Deon George
|
||||||
|
* @license http://dev.leenooks.net/license
|
||||||
|
*/
|
||||||
|
class lnApp_Email_Exception extends Kohana_Exception {}
|
@ -51,6 +51,9 @@ abstract class lnApp_Form extends Kohana_Form {
|
|||||||
|
|
||||||
$output .= '%s';
|
$output .= '%s';
|
||||||
|
|
||||||
|
if (in_array('required',$attributes))
|
||||||
|
$output .= '<div class="help-block with-errors"></div>';
|
||||||
|
|
||||||
if ($classdiv)
|
if ($classdiv)
|
||||||
$output .= '</div>';
|
$output .= '</div>';
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* @package lnApp
|
* @package lnApp
|
||||||
* @category Modifications
|
* @category Modifications
|
||||||
* @author Deon George
|
* @author Deon George
|
||||||
* @copyright (c) 2009-2013 Open Source Billing
|
* @copyright (c) 2009-2013 Deon George
|
||||||
* @license http://dev.leenooks.net/license.html
|
* @license http://dev.leenooks.net/license.html
|
||||||
*/
|
*/
|
||||||
abstract class lnApp_HTTP_Exception extends Kohana_HTTP_Exception {
|
abstract class lnApp_HTTP_Exception extends Kohana_HTTP_Exception {
|
||||||
@ -20,7 +20,7 @@ abstract class lnApp_HTTP_Exception extends Kohana_HTTP_Exception {
|
|||||||
->set('message',$this->getMessage());
|
->set('message',$this->getMessage());
|
||||||
|
|
||||||
$output .= '<div class="error-actions">';
|
$output .= '<div class="error-actions">';
|
||||||
$output .= HTML::anchor((array_key_exists('auth',Kohana::modules()) AND URL::admin_url() ? 'u/' : '').'welcome','<i class="fa fa-chevron-left"></i> Back to Home',array('class'=>'btn btn-large btn-primary'));
|
$output .= HTML::anchor(((array_key_exists('auth',Kohana::modules()) AND URL::admin_url()) ? 'u/' : '').'welcome','<i class="fa fa-chevron-left"></i> Back to Home',array('class'=>'btn btn-large btn-primary'));
|
||||||
$output .= '</div>';
|
$output .= '</div>';
|
||||||
$output .= '</div></div></div>';
|
$output .= '</div></div></div>';
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
* This class overrides Kohana's ORM
|
* This class overrides Kohana's ORM
|
||||||
*
|
*
|
||||||
* This file contains enhancements for Kohana, that should be considered upstream and maybe havent been yet.
|
* 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 lnApp
|
* @package lnApp
|
||||||
* @category Modifications
|
* @category Modifications
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WWZ Configuration - Debug Settings
|
* lnApp Configuration - Debug Settings
|
||||||
*
|
*
|
||||||
* @package lnApp
|
* @package lnApp
|
||||||
* @category Configuration
|
* @category Configuration
|
||||||
@ -14,6 +14,13 @@ return array
|
|||||||
(
|
(
|
||||||
'ajax'=>FALSE, // AJAX actions can only be run by ajax calls if set to FALSE
|
'ajax'=>FALSE, // AJAX actions can only be run by ajax calls if set to FALSE
|
||||||
'etag'=>FALSE, // Force generating ETAGS
|
'etag'=>FALSE, // Force generating ETAGS
|
||||||
|
'method_security'=>FALSE, // Debug Method Security
|
||||||
'site'=>FALSE, // Glogal site debug
|
'site'=>FALSE, // Glogal site debug
|
||||||
|
'email_bcc_admin'=>array(
|
||||||
|
// 'deon@leenooks.vpn' => 'Deon George',
|
||||||
|
), // BCC this person on all emails
|
||||||
|
'email_admin_only'=>array(
|
||||||
|
// 'login_reset'=>array('deon@leenooks.vpn'=>'Deon George'),
|
||||||
|
), // Send emails for this template to just this person
|
||||||
);
|
);
|
||||||
?>
|
?>
|
||||||
|
18
email/login_activate.txt
Normal file
18
email/login_activate.txt
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Dear $USER_NAME$,
|
||||||
|
|
||||||
|
You (or someone who knows your email) has recently submitted a request to activate your account
|
||||||
|
|
||||||
|
If this was you, you can click the link below to activate your account.
|
||||||
|
|
||||||
|
$SITE$u/login/activate?id=$ID$&email=$EMAIL$&code=$CODE$
|
||||||
|
|
||||||
|
If the link above does not display as a link in your browser, you will need to paste it into the address bar of your browser instead.
|
||||||
|
|
||||||
|
If your browser is still on the activation page, and asking for a Code, yours is
|
||||||
|
|
||||||
|
$CODE$
|
||||||
|
|
||||||
|
If you did not request a password retrieval at our site, then you can safetly ignore and delete this email.
|
||||||
|
|
||||||
|
Thank you,
|
||||||
|
$SITE_ADMIN$
|
19
email/login_reset.htm
Normal file
19
email/login_reset.htm
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<p>Dear $USER_NAME$,<br />
|
||||||
|
<br />
|
||||||
|
You (or someone who knows your email) has recently submitted a password retrieval request at our site.<br />
|
||||||
|
<br />
|
||||||
|
If this was you, you can click the link below to change your password. <br />
|
||||||
|
The link expires in $TOKEN_EXPIRE_MIN$ minutes so be sure to do this right away:<br />
|
||||||
|
<br />
|
||||||
|
<a href="$SITE$u/account/resetpassword?token=$TOKEN$">$SITE$u/account/resetpassword?token=$TOKEN$</a><br />
|
||||||
|
<br />
|
||||||
|
If the link above does not display as a link in your browser, you will need to paste it into the address bar of your browser instead.<br />
|
||||||
|
<br />
|
||||||
|
If your browser is still on the password reset page, and asking for a Pass Code, yours is<br />
|
||||||
|
<br />
|
||||||
|
$TOKEN$<br />
|
||||||
|
<br />
|
||||||
|
If you did not request a password retrieval at our site, then you can safetly ignore and delete this email.<br />
|
||||||
|
<br />
|
||||||
|
Thank you,<br />
|
||||||
|
$SITE_ADMIN$</p>
|
19
email/login_reset.txt
Normal file
19
email/login_reset.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Dear $USER_NAME$,
|
||||||
|
|
||||||
|
You (or someone who knows your email) has recently submitted a password retrieval request at our site.
|
||||||
|
|
||||||
|
If this was you, you can click the link below to change your password.
|
||||||
|
The link expires in $TOKEN_EXPIRE_MIN$ minutes so be sure to do this right away:
|
||||||
|
|
||||||
|
$SITE$u/account/resetpassword?token=$TOKEN$
|
||||||
|
|
||||||
|
If the link above does not display as a link in your browser, you will need to paste it into the address bar of your browser instead.
|
||||||
|
|
||||||
|
If your browser is still on the password reset page, and asking for a Pass Code, yours is
|
||||||
|
|
||||||
|
$TOKEN$
|
||||||
|
|
||||||
|
If you did not request a password retrieval at our site, then you can safetly ignore and delete this email.
|
||||||
|
|
||||||
|
Thank you,
|
||||||
|
$SITE_ADMIN$
|
@ -38,11 +38,11 @@ select,
|
|||||||
textarea {
|
textarea {
|
||||||
font-family: 'Open Sans';
|
font-family: 'Open Sans';
|
||||||
}
|
}
|
||||||
[class^="icon-"]:not(.ui-icon),
|
[class^="fa-"]:not(.ui-icon),
|
||||||
[class*="icon-"]:not(.ui-icon) {
|
[class*="fa-"]:not(.ui-icon) {
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
[class^="icon-"] {
|
[class^="fa-"] {
|
||||||
background: none\9;
|
background: none\9;
|
||||||
}
|
}
|
||||||
.dropdown .dropdown-menu {
|
.dropdown .dropdown-menu {
|
||||||
@ -707,8 +707,8 @@ h6 {
|
|||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.5);
|
text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.5);
|
||||||
}
|
}
|
||||||
.widget .widget-header [class^="icon-"],
|
.widget .widget-header [class^="fa-"],
|
||||||
.widget .widget-header [class*=" icon-"] {
|
.widget .widget-header [class*=" fa-"] {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-top: -3px;
|
margin-top: -3px;
|
||||||
margin-left: 13px;
|
margin-left: 13px;
|
||||||
|
260
media/theme/bootstrap/js/bootstrap.validator.js
vendored
Normal file
260
media/theme/bootstrap/js/bootstrap.validator.js
vendored
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* Bootstrap (plugin): validator.js v0.5.0
|
||||||
|
* ========================================================================
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Spiceworks, Inc.
|
||||||
|
* Made by Cina Saffary (@1000hz) in the style of Bootstrap 3 era @fat
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
* ======================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
+function ($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// VALIDATOR CLASS DEFINITION
|
||||||
|
// ==========================
|
||||||
|
|
||||||
|
var Validator = function (element, options) {
|
||||||
|
this.$element = $(element)
|
||||||
|
this.options = options
|
||||||
|
|
||||||
|
this.$element.attr('novalidate', true) // disable automatic native validation
|
||||||
|
this.toggleSubmit()
|
||||||
|
|
||||||
|
this.$element.on('input.bs.validator change.bs.validator focusout.bs.validator', $.proxy(this.validateInput, this))
|
||||||
|
this.$element.on('submit.bs.validator', $.proxy(this.onSubmit, this))
|
||||||
|
|
||||||
|
this.$element.find('[data-match]').each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
var target = $this.data('match')
|
||||||
|
|
||||||
|
$(target).on('input.bs.validator', function (e) {
|
||||||
|
$this.val() && $this.trigger('input')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Validator.DEFAULTS = {
|
||||||
|
delay: 500,
|
||||||
|
html: false,
|
||||||
|
errors: {
|
||||||
|
match: 'Does not match',
|
||||||
|
minlength: 'Not long enough'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Validator.VALIDATORS = {
|
||||||
|
native: function ($el) {
|
||||||
|
var el = $el[0]
|
||||||
|
return el.checkValidity ? el.checkValidity() : true
|
||||||
|
},
|
||||||
|
match: function ($el) {
|
||||||
|
var target = $el.data('match')
|
||||||
|
return !$el.val() || $el.val() === $(target).val()
|
||||||
|
},
|
||||||
|
minlength: function ($el) {
|
||||||
|
var minlength = $el.data('minlength')
|
||||||
|
return !$el.val() || $el.val().length >= minlength
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Validator.prototype.validateInput = function (e) {
|
||||||
|
var $el = $(e.target)
|
||||||
|
var prevErrors = $el.data('bs.validator.errors')
|
||||||
|
var errors
|
||||||
|
|
||||||
|
if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]')
|
||||||
|
|
||||||
|
this.$element.trigger(e = $.Event('validate.bs.validator', {relatedTarget: $el[0]}))
|
||||||
|
|
||||||
|
if (e.isDefaultPrevented()) return
|
||||||
|
|
||||||
|
var self = this
|
||||||
|
|
||||||
|
this.runValidators($el).done(function (errors) {
|
||||||
|
$el.data('bs.validator.errors', errors)
|
||||||
|
|
||||||
|
errors.length ? self.showErrors($el) : self.clearErrors($el)
|
||||||
|
|
||||||
|
if (!prevErrors || errors.toString() !== prevErrors.toString()) {
|
||||||
|
e = errors.length
|
||||||
|
? $.Event('invalid.bs.validator', {relatedTarget: $el[0], detail: errors})
|
||||||
|
: $.Event('valid.bs.validator', {relatedTarget: $el[0], detail: prevErrors})
|
||||||
|
|
||||||
|
self.$element.trigger(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.toggleSubmit()
|
||||||
|
|
||||||
|
self.$element.trigger($.Event('validated.bs.validator', {relatedTarget: $el[0]}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Validator.prototype.runValidators = function ($el) {
|
||||||
|
var errors = []
|
||||||
|
var validators = [Validator.VALIDATORS.native]
|
||||||
|
var deferred = $.Deferred()
|
||||||
|
var options = this.options
|
||||||
|
|
||||||
|
$el.data('bs.validator.deferred') && $el.data('bs.validator.deferred').reject()
|
||||||
|
$el.data('bs.validator.deferred', deferred)
|
||||||
|
|
||||||
|
function getErrorMessage(key) {
|
||||||
|
return $el.data(key + '-error')
|
||||||
|
|| $el.data('error')
|
||||||
|
|| key == 'native' && $el[0].validationMessage
|
||||||
|
|| options.errors[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
$.each(Validator.VALIDATORS, $.proxy(function (key, validator) {
|
||||||
|
if (($el.data(key) || key == 'native') && !validator.call(this, $el)) {
|
||||||
|
var error = getErrorMessage(key)
|
||||||
|
!~errors.indexOf(error) && errors.push(error)
|
||||||
|
}
|
||||||
|
}, this))
|
||||||
|
|
||||||
|
if (!errors.length && $el.val() && $el.data('remote')) {
|
||||||
|
this.defer($el, function () {
|
||||||
|
$.get($el.data('remote'), [$el.attr('name'), $el.val()].join('='))
|
||||||
|
.fail(function (jqXHR, textStatus, error) { errors.push(getErrorMessage('remote') || error) })
|
||||||
|
.always(function () { deferred.resolve(errors)})
|
||||||
|
})
|
||||||
|
} else deferred.resolve(errors)
|
||||||
|
|
||||||
|
return deferred.promise()
|
||||||
|
}
|
||||||
|
|
||||||
|
Validator.prototype.validate = function () {
|
||||||
|
var delay = this.options.delay
|
||||||
|
|
||||||
|
this.options.delay = 0
|
||||||
|
this.$element.find(':input').trigger('input')
|
||||||
|
this.options.delay = delay
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
Validator.prototype.showErrors = function ($el) {
|
||||||
|
var method = this.options.html ? 'html' : 'text'
|
||||||
|
|
||||||
|
this.defer($el, function () {
|
||||||
|
var $group = $el.closest('.form-group')
|
||||||
|
var $block = $group.find('.help-block.with-errors')
|
||||||
|
var errors = $el.data('bs.validator.errors')
|
||||||
|
|
||||||
|
if (!errors.length) return
|
||||||
|
|
||||||
|
errors = $('<ul/>')
|
||||||
|
.addClass('list-unstyled')
|
||||||
|
.append($.map(errors, function (error) { return $('<li/>')[method](error) }))
|
||||||
|
|
||||||
|
$block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
|
||||||
|
$block.empty().append(errors)
|
||||||
|
|
||||||
|
$group.addClass('has-error')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Validator.prototype.clearErrors = function ($el) {
|
||||||
|
var $group = $el.closest('.form-group')
|
||||||
|
var $block = $group.find('.help-block.with-errors')
|
||||||
|
|
||||||
|
$block.html($block.data('bs.validator.originalContent'))
|
||||||
|
$group.removeClass('has-error')
|
||||||
|
}
|
||||||
|
|
||||||
|
Validator.prototype.hasErrors = function () {
|
||||||
|
function fieldErrors() {
|
||||||
|
return !!($(this).data('bs.validator.errors') || []).length
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!this.$element.find(':input:enabled').filter(fieldErrors).length
|
||||||
|
}
|
||||||
|
|
||||||
|
Validator.prototype.isIncomplete = function () {
|
||||||
|
function fieldIncomplete() {
|
||||||
|
return this.type === 'checkbox' ? !this.checked :
|
||||||
|
this.type === 'radio' ? !$('[name="' + this.name + '"]:checked').length :
|
||||||
|
$.trim(this.value) === ''
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!this.$element.find(':input[required]:enabled').filter(fieldIncomplete).length
|
||||||
|
}
|
||||||
|
|
||||||
|
Validator.prototype.onSubmit = function (e) {
|
||||||
|
this.validate()
|
||||||
|
if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
Validator.prototype.toggleSubmit = function () {
|
||||||
|
var $btn = this.$element.find('input[type="submit"], button[type="submit"]')
|
||||||
|
$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
|
||||||
|
.css({'pointer-events': 'all', 'cursor': 'pointer'})
|
||||||
|
}
|
||||||
|
|
||||||
|
Validator.prototype.defer = function ($el, callback) {
|
||||||
|
if (!this.options.delay) return callback()
|
||||||
|
window.clearTimeout($el.data('bs.validator.timeout'))
|
||||||
|
$el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
|
||||||
|
}
|
||||||
|
|
||||||
|
// VALIDATOR PLUGIN DEFINITION
|
||||||
|
// ===========================
|
||||||
|
|
||||||
|
|
||||||
|
function Plugin(option) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||||
|
var data = $this.data('bs.validator')
|
||||||
|
|
||||||
|
if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
|
||||||
|
if (typeof option == 'string') data[option]()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var old = $.fn.validator
|
||||||
|
|
||||||
|
$.fn.validator = Plugin
|
||||||
|
$.fn.validator.Constructor = Validator
|
||||||
|
|
||||||
|
|
||||||
|
// VALIDATOR NO CONFLICT
|
||||||
|
// =====================
|
||||||
|
|
||||||
|
$.fn.validator.noConflict = function () {
|
||||||
|
$.fn.validator = old
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// VALIDATOR DATA-API
|
||||||
|
// ==================
|
||||||
|
|
||||||
|
$(window).on('load', function () {
|
||||||
|
$('form[data-toggle="validator"]').each(function () {
|
||||||
|
var $form = $(this)
|
||||||
|
Plugin.call($form, $form.data())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}(jQuery);
|
@ -29,3 +29,11 @@
|
|||||||
#footer #footer-logo {
|
#footer #footer-logo {
|
||||||
height: 65px;
|
height: 65px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-dialog {
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper {
|
||||||
|
width: 980px;
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<div class="center-block" style="width: 350px;">
|
<div class="center-block" style="width: 350px;">
|
||||||
<div class="content clearfix">
|
<div class="content clearfix">
|
||||||
<form method="post" action="<?php echo URL::site('login'); ?>">
|
<form method="post" action="<?php echo URL::site('login'); ?>">
|
||||||
<br>
|
<br/>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<div class="panel-title">Sign In</div>
|
<div class="panel-title">Sign In</div>
|
||||||
@ -48,7 +48,11 @@
|
|||||||
<div class="login-extra">
|
<div class="login-extra">
|
||||||
<!-- Don't have an account? <a href="./signup.html">Sign Up</a><br/> -->
|
<!-- Don't have an account? <a href="./signup.html">Sign Up</a><br/> -->
|
||||||
</div> <!-- /login-extra -->
|
</div> <!-- /login-extra -->
|
||||||
<div class="modal hide fade" id="modal-reset" role="dialog" aria-hidden="true">
|
<div class="modal fade" id="modal-reset" role="dialog" aria-hidden="true">
|
||||||
<div class="modal-body"></div>
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-body"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="fb-root"></div>
|
<div class="fb-root"></div>
|
@ -136,6 +136,7 @@
|
|||||||
echo HTML::script(Site::Protocol('cdnjs.cloudflare.com/ajax/libs/lodash.js/1.2.1/lodash.min.js'));
|
echo HTML::script(Site::Protocol('cdnjs.cloudflare.com/ajax/libs/lodash.js/1.2.1/lodash.min.js'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
echo HTML::script('media/theme/bootstrap/js/bootstrap.validator.js');
|
||||||
echo HTML::script('media/theme/baseadmin/js/backtotop.js');
|
echo HTML::script('media/theme/baseadmin/js/backtotop.js');
|
||||||
echo HTML::script('media/js/typeahead.bundle.min.js');
|
echo HTML::script('media/js/typeahead.bundle.min.js');
|
||||||
echo HTML::script('media/js/search.js');
|
echo HTML::script('media/js/search.js');
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
<ul id="main-nav">
|
<ul id="main-nav">
|
||||||
<li class="active"><a href="<?php echo URL::site(''); ?>">Home</a></li>
|
<li class="active"><a href="<?php echo URL::site(''); ?>">Home</a></li>
|
||||||
|
|
||||||
<?php if (class_exists('Company') AND $x=Company::instance()->faq()) : ?>
|
<?php if (class_exists('Company') AND $x=Company::instance()->faq()) : ?>
|
||||||
<li><a href="<?php echo $x; ?>">Faq</a></li>
|
<li><a href="<?php echo $x; ?>">Faq</a></li>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<?php if (array_key_exists('auth',Kohana::modules()) AND Auth::instance()->logged_in()) : ?>
|
<?php if (array_key_exists('auth',Kohana::modules()) AND Auth::instance()->logged_in()) : ?>
|
||||||
<li><a href="<?php echo URL::site('login'); ?>">Customer Login</a></li>
|
<li><a href="<?php echo URL::site('login'); ?>">Customer Login</a></li>
|
||||||
<?php else : ?>
|
<?php else : ?>
|
||||||
<li><a href="<?php echo URL::site('login'); ?>" data-toggle="modal" data-target="#modal-login">Customer Login</a></li>
|
<li><a href="<?php echo URL::site('login'); ?>" data-toggle="modal" data-target="#modal-login">Customer Login</a></li>
|
||||||
|
<li><a href="<?php echo URL::site('login/register'); ?>">Register</a></li>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="modal fade" id="modal-login" role="dialog" aria-hidden="true" aria-labelledby="myModalLabel">
|
<div class="modal fade" id="modal-login" role="dialog" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-body"></div>
|
<div class="modal-body"></div>
|
||||||
|
@ -16,12 +16,10 @@
|
|||||||
<?php
|
<?php
|
||||||
if (Kohana::$environment >= Kohana::TESTING OR Request::current()->secure()) {
|
if (Kohana::$environment >= Kohana::TESTING OR Request::current()->secure()) {
|
||||||
echo HTML::style('media/theme/bootstrap/css/bootstrap.min.css');
|
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');
|
echo HTML::style('media/vendor/font-awesome/css/font-awesome.min.css');
|
||||||
} else {
|
} else {
|
||||||
echo HTML::style(Site::Protocol('netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap.min.css'));
|
echo HTML::style(Site::Protocol('maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'));
|
||||||
echo HTML::style(Site::Protocol('netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css'));
|
echo HTML::style(Site::Protocol('maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css'));
|
||||||
echo HTML::style(Site::Protocol('netdna.bootstrapcdn.com/font-awesome/3.0.2/css/font-awesome.css'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
echo HTML::style(Site::Protocol('fonts.googleapis.com/css?family=Open+Sans:400italic,600italic,800italic,400,600,800'));
|
echo HTML::style(Site::Protocol('fonts.googleapis.com/css?family=Open+Sans:400italic,600italic,800italic,400,600,800'));
|
||||||
@ -53,6 +51,7 @@
|
|||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<!--
|
||||||
<div class="grid-4">
|
<div class="grid-4">
|
||||||
<h1 id="footer-logo">Focus Business</h1>
|
<h1 id="footer-logo">Focus Business</h1>
|
||||||
<p></p>
|
<p></p>
|
||||||
@ -74,7 +73,8 @@
|
|||||||
<a href="javascript:;" class="social-icon social-icon-facebook">Facebook</a>
|
<a href="javascript:;" class="social-icon social-icon-facebook">Facebook</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div> <!-- /grid-4 -->
|
</div>
|
||||||
|
-->
|
||||||
|
|
||||||
<div class="grid-4">
|
<div class="grid-4">
|
||||||
<h3><span class="slash">//</span> Contact Us</h3>
|
<h3><span class="slash">//</span> Contact Us</h3>
|
||||||
@ -98,7 +98,7 @@
|
|||||||
echo HTML::script('media/theme/bootstrap/js/bootstrap.min.js');
|
echo HTML::script('media/theme/bootstrap/js/bootstrap.min.js');
|
||||||
} else {
|
} else {
|
||||||
echo HTML::script(Site::Protocol('code.jquery.com/jquery-1.9.1.min.js'));
|
echo HTML::script(Site::Protocol('code.jquery.com/jquery-1.9.1.min.js'));
|
||||||
echo HTML::script(Site::Protocol('netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js'));
|
echo HTML::script(Site::Protocol('maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js'));
|
||||||
}
|
}
|
||||||
|
|
||||||
echo HTML::script('media/theme/focusbusiness/js/focus.js');
|
echo HTML::script('media/theme/focusbusiness/js/focus.js');
|
||||||
|
Reference in New Issue
Block a user