2013-10-10 02:44:53 +00:00
|
|
|
<?php defined('SYSPATH') or die('No direct access allowed.');
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This class overrides Kohana's ORM
|
|
|
|
*
|
|
|
|
* This file contains enhancements for Kohana, that should be considered upstream and maybe havent been yet.
|
|
|
|
* It also contains some functionality for OSB, which cannot be covered in ORM_OSB.
|
|
|
|
*
|
|
|
|
* @package OSB
|
|
|
|
* @category Modifications
|
|
|
|
* @author Deon George
|
|
|
|
* @copyright (c) 2009-2013 Open Source Billing
|
|
|
|
* @license http://dev.osbill.net/license.html
|
|
|
|
*/
|
|
|
|
abstract class ORM extends Kohana_ORM {
|
|
|
|
protected $_table_names_plural = FALSE;
|
|
|
|
protected $_model_names_plural = FALSE;
|
|
|
|
private $_object_formated = array();
|
|
|
|
private $_formated = FALSE;
|
|
|
|
// Our filters used to display values in a friendly format
|
|
|
|
protected $_display_filters = array();
|
2013-05-10 10:48:10 +00:00
|
|
|
// Tables that do not have a site_id column
|
|
|
|
public static $no_site_id_tables = array('setup','country','currency','language','tax');
|
|
|
|
|
2013-11-22 04:36:50 +00:00
|
|
|
// Whether to show a SystemMessage when a record is saved.
|
|
|
|
protected $_save_message = FALSE;
|
|
|
|
|
2013-05-10 10:48:10 +00:00
|
|
|
/**
|
|
|
|
* 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());
|
|
|
|
|
2013-06-19 09:26:07 +00:00
|
|
|
// 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));
|
|
|
|
|
2013-05-10 10:48:10 +00:00
|
|
|
return parent::_build($type);
|
|
|
|
}
|
2013-10-10 02:44:53 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Format fields for display purposes
|
|
|
|
*
|
2013-10-09 05:43:41 +00:00
|
|
|
* @param string column name
|
|
|
|
* @return mixed
|
2013-10-10 02:44:53 +00:00
|
|
|
*/
|
|
|
|
private function _format() {
|
|
|
|
foreach ($this->_display_filters as $column => $formats)
|
|
|
|
$this->_object_formated[$column] = $this->run_filter($column,$this->__get($column),array($column=>$formats));
|
|
|
|
|
|
|
|
$this->_formated = TRUE;
|
|
|
|
}
|
|
|
|
|
2013-05-10 10:48:10 +00:00
|
|
|
/**
|
|
|
|
* Function help to find records that are active
|
|
|
|
*/
|
|
|
|
protected function _where_active() {
|
|
|
|
return $this->where('status','=',TRUE);
|
|
|
|
}
|
|
|
|
|
2013-11-08 11:02:32 +00:00
|
|
|
/**
|
|
|
|
* 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));
|
|
|
|
}
|
|
|
|
|
2013-07-05 06:11:37 +00:00
|
|
|
/**
|
|
|
|
* Overrides Kohana cache so that it can be globally disabled.
|
|
|
|
*/
|
|
|
|
public function cached($lifetime=NULL) {
|
2014-01-23 13:20:48 +00:00
|
|
|
return $this->_db->caching($this->_table_name) ? parent::cached($lifetime) : $this;
|
2013-07-05 06:11:37 +00:00
|
|
|
}
|
|
|
|
|
2013-05-08 09:00:47 +00:00
|
|
|
public function clear() {
|
|
|
|
$this->_formated = FALSE;
|
|
|
|
$this->_object_formated = array();
|
|
|
|
|
|
|
|
return parent::clear();
|
|
|
|
}
|
|
|
|
|
2013-10-10 02:44:53 +00:00
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-05-10 10:48:10 +00:00
|
|
|
* Return a formated columns, as per the model definition
|
2013-10-10 02:44:53 +00:00
|
|
|
*/
|
2013-05-10 10:48:10 +00:00
|
|
|
public function display($column) {
|
|
|
|
// Trigger a load of the record.
|
|
|
|
$value = $this->__get($column);
|
2013-10-10 02:44:53 +00:00
|
|
|
|
2013-05-10 10:48:10 +00:00
|
|
|
// If some of our fields need to be formated for display purposes.
|
|
|
|
if (! $this->_formated AND $this->_display_filters)
|
|
|
|
$this->_format();
|
|
|
|
|
|
|
|
if (isset($this->_object_formated[$column]))
|
|
|
|
return $this->_object_formated[$column];
|
|
|
|
else
|
|
|
|
return $value;
|
2013-10-10 02:44:53 +00:00
|
|
|
}
|
|
|
|
|
2013-05-14 13:53:04 +00:00
|
|
|
public function display_filters(array $filters) {
|
|
|
|
$this->_display_filters = Arr::merge($this->_display_filters,$filters);
|
|
|
|
}
|
|
|
|
|
2013-10-10 02:44:53 +00:00
|
|
|
/**
|
|
|
|
* Function help to find records that are active
|
|
|
|
*/
|
|
|
|
public function list_active() {
|
|
|
|
return $this->_where_active()->find_all();
|
|
|
|
}
|
|
|
|
|
2013-05-10 10:48:10 +00:00
|
|
|
/**
|
|
|
|
* This function is our AJAX helper, used by module list_autocomplete()
|
|
|
|
*/
|
2013-05-08 09:00:47 +00:00
|
|
|
public function list_autocomplete($term,$index,$value,array $label,array $limit=array(),array $options=NULL) {
|
|
|
|
$result = array();
|
|
|
|
|
|
|
|
$query = empty($options['object']) ? $this : $options['object'];
|
|
|
|
|
|
|
|
foreach ($limit as $w) {
|
|
|
|
list($k,$s,$v) = $w;
|
|
|
|
|
|
|
|
$query->and_where($k,$s,$v);
|
|
|
|
}
|
|
|
|
|
2013-07-05 06:11:37 +00:00
|
|
|
$c = 0;
|
2013-05-08 09:00:47 +00:00
|
|
|
foreach ((empty($options['object']) ? $query->find_all() : $query->execute()) as $o) {
|
|
|
|
// If we got here via a DB query, we need to reload our ORM object from the result.
|
|
|
|
if (! is_object($o)) {
|
|
|
|
if (empty($options['key']))
|
|
|
|
throw new Kohana_Exception('Missing key for non object');
|
|
|
|
|
|
|
|
$o = $this->clear()->where($options['key'],'=',$o[$options['key']])->find();
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ($index) {
|
|
|
|
case 'url':
|
|
|
|
if (empty($options['urlprefix']))
|
|
|
|
throw new Kohana_Exception('Missing URL Prefix');
|
|
|
|
|
|
|
|
$v = $options['urlprefix'].$o->resolve($value);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: $v = $o->resolve($value);
|
|
|
|
}
|
|
|
|
|
|
|
|
$k = '';
|
2013-07-05 06:11:37 +00:00
|
|
|
foreach ($label as $k => $details)
|
2013-05-08 09:00:47 +00:00
|
|
|
foreach ($details as $lvalue)
|
|
|
|
$k = preg_replace('/%s/',$o->resolve($lvalue),$k,1);
|
|
|
|
|
|
|
|
$result[$c++] = array(
|
|
|
|
'value'=>$v,
|
|
|
|
'label'=>$k,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
2014-02-06 00:03:25 +00:00
|
|
|
/**
|
|
|
|
* Return an array of data that can be used in a SELECT statement.
|
|
|
|
* The ID and VALUE is defined in the model for the select.
|
|
|
|
*/
|
|
|
|
public function list_select($blank=FALSE) {
|
|
|
|
$result = array();
|
|
|
|
|
|
|
|
if ($blank)
|
|
|
|
$result[] = '';
|
|
|
|
|
|
|
|
if ($this->_form AND array_intersect(array('id','value'),$this->_form))
|
|
|
|
foreach ($this->find_all() as $o)
|
|
|
|
$result[$o->{$this->_form['id']}] = $o->resolve($this->_form['value']);
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
2013-05-08 09:00:47 +00:00
|
|
|
/**
|
|
|
|
* This function is used so that methods can be called via variables
|
|
|
|
*/
|
|
|
|
public function resolve($key) {
|
|
|
|
eval("\$x = \$this->$key;");
|
|
|
|
|
|
|
|
return $x;
|
|
|
|
}
|
|
|
|
|
2013-11-22 04:36:50 +00:00
|
|
|
public function save(Validation $validation=NULL) {
|
|
|
|
parent::save();
|
|
|
|
|
2013-12-02 04:16:28 +00:00
|
|
|
if ($this->saved() AND $this->_save_message AND (PHP_SAPI !== 'cli'))
|
2013-11-22 04:36:50 +00:00
|
|
|
SystemMessage::factory()
|
|
|
|
->title('Record Updated')
|
|
|
|
->type('success')
|
|
|
|
->body(sprintf('Record %s:%s Updated',$this->_table_name,$this->id));
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2013-10-10 02:44:53 +00:00
|
|
|
public function where_active() {
|
|
|
|
return $this->_where_active();
|
|
|
|
}
|
2013-10-09 05:43:41 +00:00
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
2013-10-10 02:44:53 +00:00
|
|
|
}
|
|
|
|
?>
|