573 lines
15 KiB
PHP
573 lines
15 KiB
PHP
<?php
|
|
/**
|
|
* osBilling - Open Billing Software
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Originally authored by Deon George
|
|
*
|
|
* @author Deon George <deonATleenooksDOTnet>
|
|
* @copyright 2009 Deon George
|
|
* @link http://osb.leenooks.net
|
|
* @license http://www.gnu.org/licenses/
|
|
* @package AgileBill
|
|
* @subpackage Modules
|
|
*/
|
|
|
|
require_once(PATH_CORE.'xml.inc.php');
|
|
|
|
/**
|
|
* Module Abstract Class
|
|
* This abstract class provides the basic variables and methods for all modules.
|
|
*
|
|
* @package AgileBill
|
|
* @subpackage Modules
|
|
*/
|
|
abstract class OSB_module {
|
|
# Validation error array
|
|
public $val_error = array();
|
|
# Debug output to STDOUT
|
|
protected $debug = false;
|
|
# Inbound VAR value
|
|
protected $VAR = array();
|
|
# Object database ID & Record
|
|
private $record = array();
|
|
# Last Record ID read from DB
|
|
private $record_id = null;
|
|
|
|
/**
|
|
* Initialise the module
|
|
*/
|
|
public function __construct($id=null) {
|
|
global $VAR;
|
|
|
|
$this->VAR = $VAR;
|
|
|
|
if (isset($this->VAR['debug']) && $this->VAR['debug'])
|
|
$this->debug = true;
|
|
|
|
$f = sprintf('%s%s/%s_construct.xml',PATH_MODULES,get_class($this),get_class($this));
|
|
|
|
if (is_file($f)) {
|
|
# Open the construct file for parsing
|
|
$C_xml = new CORE_xml;
|
|
$construct = $C_xml->xml_to_array($f);
|
|
|
|
# Required attributes of the construct file.
|
|
foreach (array('module','table','field') as $index) {
|
|
if (! isset($construct['construct'][$index]))
|
|
printf('ERROR: Missing [%s] for [%s]',$index,$f);
|
|
else
|
|
$this->{$index} = $construct['construct'][$index];
|
|
}
|
|
|
|
# Optional attributes of the construct file.
|
|
foreach (array('method','trigger','cache','order_by','limit','title','tpl') as $index)
|
|
if (isset($construct['construct'][$index]))
|
|
$this->{$index} = $construct['construct'][$index];
|
|
|
|
# Bind our language translation path
|
|
bindtextdomain($this->module,PATH_LANGUAGE);
|
|
bind_textdomain_codeset($this->module,'UTF-8');
|
|
}
|
|
|
|
$this->sql_LoadRecord($id);
|
|
}
|
|
|
|
/**
|
|
* Return this record from the database
|
|
*/
|
|
protected function getRecord() {
|
|
return isset($this->record) ? $this->record : null;
|
|
}
|
|
|
|
protected function clearRecord() {
|
|
$this->record = array();
|
|
}
|
|
|
|
protected function delRecordAttr($attr) {
|
|
if (isset($this->record[$attr]))
|
|
unset($this->record[$attr]);
|
|
}
|
|
|
|
/**
|
|
* Return a field from the database record
|
|
*/
|
|
protected function getRecordAttr($attr) {
|
|
return isset($this->record[$attr]) ? $this->record[$attr] : null;
|
|
}
|
|
|
|
protected function setRecordAttr($attr,$value) {
|
|
$this->record[$attr] = $value;
|
|
return $value;
|
|
}
|
|
|
|
public function getlist() {
|
|
# Open the construct file for parsing
|
|
$C_xml = new CORE_xml;
|
|
|
|
$dh = opendir(PATH_MODULES);
|
|
$modules = array();
|
|
|
|
while ($module=readdir($dh))
|
|
if (! in_array($module,array('.','..')) && is_dir(PATH_MODULES.$module) && is_file($f=sprintf('%s/%s/%s_install.xml',PATH_MODULES,$module,$module))) {
|
|
|
|
$install = $C_xml->xml_to_array($f);
|
|
|
|
# Determine the type
|
|
if (! isset($install['install']['module_properties']['type']))
|
|
$type = 'plugin';
|
|
else
|
|
$type = $install['install']['module_properties']['type'];
|
|
|
|
# Store the data
|
|
foreach (array('parent','name','notes','sub_modules','dependancy','type','table-only','method-only') as $index)
|
|
if (isset($install['install']['module_properties'][$index]))
|
|
$modules[$type][$module][$index] = $install['install']['module_properties'][$index];
|
|
|
|
}
|
|
|
|
return $modules;
|
|
}
|
|
|
|
/**
|
|
* Basic module helper when interacting with the database.
|
|
*/
|
|
private function database($type,$VAR,$method=null) {
|
|
if ($type && ! is_array($this->method[$type]))
|
|
$this->method[$type] = explode(',',$this->method[$type]);
|
|
|
|
if (is_null($method) && $type)
|
|
$method = $type;
|
|
|
|
$db = new CORE_database;
|
|
|
|
if (method_exists($db,$method))
|
|
return $db->$method($VAR,$this,$type);
|
|
|
|
else {
|
|
global $C_debug;
|
|
|
|
$C_debug->error(__FILE__,__METHOD__,sprintf('Method doesnt exist'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Export module helper
|
|
*/
|
|
private function export($type,$VAR,$method=null) {
|
|
# Require the export class
|
|
require_once(PATH_CORE.'export.inc.php');
|
|
|
|
$this->method[$type] = explode(',',$this->method[$type]);
|
|
|
|
if (is_null($method) && $type)
|
|
$method = $type;
|
|
|
|
$export = new CORE_export;
|
|
|
|
if (method_exists($export,$method))
|
|
$export->$method($VAR,$this,$type);
|
|
|
|
else {
|
|
global $C_debug;
|
|
$C_debug->error(__FILE__,__METHOD__,sprintf('Method doesnt exist'));
|
|
}
|
|
}
|
|
|
|
/** ADMIN INTERFACE METHODS **/
|
|
|
|
/**
|
|
* Add Records to the database
|
|
*/
|
|
public function add($VAR) {
|
|
if ($id = $this->database('add',$VAR))
|
|
return $id;
|
|
|
|
global $VAR;
|
|
|
|
# If update fails, return to the add page.
|
|
if (isset($VAR['_page']) && $VAR['_page'] == sprintf('%s:%s',$this->module,'view'))
|
|
$VAR['_page'] = sprintf('%s:%s',$this->module,'add');
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Delete Records in the database
|
|
*/
|
|
public function delete($VAR) {
|
|
return $this->database('',$VAR,'mass_delete');
|
|
}
|
|
|
|
/**
|
|
* Search for Records in the database
|
|
*/
|
|
public function search($VAR) {
|
|
$this->database('search',$VAR);
|
|
}
|
|
|
|
/**
|
|
* Export Records from the database
|
|
*/
|
|
public function search_export($VAR) {
|
|
switch ($VAR['format']) {
|
|
case 'csv':
|
|
$this->export('export_csv',$VAR,'search_csv');
|
|
break;
|
|
|
|
case 'excel':
|
|
$this->export('export_excel',$VAR,'search_excel');
|
|
break;
|
|
|
|
case 'pdf':
|
|
$this->export('export_pdf',$VAR,'pdf_invoice');
|
|
break;
|
|
|
|
case 'tab':
|
|
$this->export('export_tab',$VAR,'search_tab');
|
|
break;
|
|
|
|
case 'xml':
|
|
$this->export('export_xml',$VAR,'search_xml');
|
|
break;
|
|
|
|
default:
|
|
global $C_debug;
|
|
$C_debug->error(__FILE__,__METHOD__,sprintf('Export method doesnt exist'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Search for Records in the database
|
|
*/
|
|
public function search_form($VAR) {
|
|
$this->database('search',$VAR,'search_form');
|
|
}
|
|
|
|
/**
|
|
* Show the Records from a Search in the database
|
|
*/
|
|
public function search_show($VAR) {
|
|
return $this->database('search',$VAR,'search_show');
|
|
}
|
|
|
|
/**
|
|
* Update Records in the database
|
|
*/
|
|
public function update($VAR) {
|
|
return $this->database('update',$VAR);
|
|
}
|
|
|
|
/**
|
|
* View a Record in the database
|
|
*/
|
|
public function view($VAR) {
|
|
#@todo implement showing the modified attributes if a update fails.
|
|
return $this->database('view',$VAR);
|
|
}
|
|
|
|
/** USER INTERFACE METHODS **/
|
|
|
|
/**
|
|
* Add Records to the database
|
|
*/
|
|
public function user_add($VAR) {
|
|
return $this->database('user_add',$VAR,'add');
|
|
}
|
|
|
|
/**
|
|
* Search for Records in the database
|
|
*/
|
|
public function user_search($VAR) {
|
|
if (! SESS_LOGGED) return false;
|
|
|
|
if (get_class($this) == 'discount')
|
|
$VAR[$this->module.'_avail_account_id'] = SESS_ACCOUNT;
|
|
else
|
|
$VAR[$this->module.'_account_id'] = SESS_ACCOUNT;
|
|
|
|
$this->database('search',$VAR);
|
|
}
|
|
|
|
/**
|
|
* Show the Records from a Search in the database
|
|
*/
|
|
public function user_search_show($VAR) {
|
|
if (! SESS_LOGGED) return false;
|
|
|
|
return $this->database('search',$VAR,'search_show');
|
|
}
|
|
|
|
/**
|
|
* Static Vars
|
|
*/
|
|
public function static_var($VAR) {
|
|
global $smarty;
|
|
|
|
require_once(PATH_CORE.'static_var.inc.php');
|
|
$static_var = new CORE_static_var;
|
|
|
|
if (preg_match('/search/',$VAR['_page']))
|
|
$arr = $static_var->generate_form($this->module,'add','search');
|
|
else
|
|
$arr = $static_var->generate_form($this->module,'add','update');
|
|
|
|
if (gettype($arr) == 'array') {
|
|
# Set everything as a smarty array, and return
|
|
$smarty->assign('show_static_var',true);
|
|
$smarty->assign('static_var',$arr);
|
|
return true;
|
|
|
|
} else {
|
|
# Or if no results
|
|
$smarty->assign('show_static_var',false);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Render the results of a search
|
|
*
|
|
* This function can also be used to only render the headers, and the tpl file can be responsible for rendering the data
|
|
*
|
|
* If $args is null, we only render the header
|
|
*/
|
|
public function tpl_search_show($VAR,$object,$args) {
|
|
global $C_list;
|
|
|
|
require_once(PATH_CORE.'translate.inc.php');
|
|
$C_translate = new CORE_translate;
|
|
|
|
list($class,$method) = explode(':',$VAR['_page']);
|
|
|
|
$method = strtolower($method);
|
|
|
|
if (! isset($this->tpl[$method]))
|
|
return;
|
|
|
|
# If we are only rendering the headers, then skip the table definitions
|
|
if (! is_null($args)) {
|
|
echo '<table width="100%" border="0" cellspacing="0" cellpadding="0" class="table_background"><tr><td>';
|
|
echo '<table width="100%" border="0" cellspacing="1" cellpadding="3">';
|
|
}
|
|
|
|
# Display the search heading
|
|
echo '<tr valign="middle" align="center" class="table_heading">';
|
|
|
|
foreach ($this->tpl[$method] as $index => $details) {
|
|
switch ($index) {
|
|
case 'blank':
|
|
case 'checkbox':
|
|
case 'icon':
|
|
case 'last':
|
|
printf('<td class="table_heading"%s> </td>',isset($details['width']) ? sprintf(' style="width: %s;"',$details['width']) : '');
|
|
break;
|
|
|
|
default:
|
|
printf('<td class="table_heading"%s>',isset($details['width']) ? sprintf(' style="width: %s;"',$details['width']) : '');
|
|
printf('<script type="text/javascript">document.write(search_heading(\'%s\',\'%s\'));</script>',
|
|
isset($details['translate'])
|
|
? $C_translate->translate($details['translate'],$this->module)
|
|
: $C_translate->tf(array('module'=>$this->module,'field'=>$details['field']),null),
|
|
$details['field']);
|
|
echo '</td>';
|
|
}
|
|
}
|
|
|
|
echo '</tr>';
|
|
|
|
# Loop through each record
|
|
if (is_array($args) && count($args[0])) {
|
|
foreach ($args[0] as $key => $values) {
|
|
printf('<tr id="row%s" onclick="row_sel(\'%s\',1);" ondblclick="window.location=\'?_page=%s:view&id=%s\';" onmouseover="row_mouseover(\'%s\',\'row_mouse_over_select\',\'row_mouse_over\');" onmouseout="row_mouseout(\'%s\',\'%s\',\'row_select\');" class="%s">',
|
|
$values['id'],$values['id'],$this->module,$values['id'],$values['id'],$values['id'],$values['_C'],$values['_C']);
|
|
|
|
foreach ($this->tpl[$method] as $index => $details) {
|
|
switch ($details['type']) {
|
|
case 'bool':
|
|
printf('<td>%s</td>',$values[$details['field']] ? $C_translate->translate('true') : $C_translate->translate('false'));
|
|
|
|
break;
|
|
|
|
case 'bool_icon':
|
|
echo '<td>';
|
|
|
|
if ($values[$details['field']])
|
|
printf('<img src="themes/%s/images/icons/%s" alt="True" width="16" height="16" style="border: 0px;"/>',DEFAULT_THEME,isset($details['true']) ? $details['true'] : 'go_16.gif');
|
|
else
|
|
printf('<img src="themes/%s/images/icons/%s" alt="False" width="16" height="16" style="border: 0px;"/>',DEFAULT_THEME,isset($details['false']) ? $details['false'] : 'stop_16.gif');
|
|
|
|
echo '</td>';
|
|
|
|
break;
|
|
|
|
case 'checkbox':
|
|
echo '<td style="text-align: center">';
|
|
printf('<input type="checkbox" id="record%s" name="record%s" value="%s" onclick="row_sel(\'%s\',1,\'%s\');"/>',
|
|
$values['id'],$values['id'],$values['id'],$values['id'],$values['_C']);
|
|
printf('<script type="text/javascript">row_sel(\'%s\',0,\'%s\'); record_arr[i] = \'%s\'; i++;</script>',$values['id'],$values['_C'],$values['id']);
|
|
echo '</td>';
|
|
|
|
break;
|
|
|
|
case 'currency':
|
|
printf('<td>%s</td>',$C_list->format_currency($values[$details['field']],DEFAULT_CURRENCY));
|
|
|
|
break;
|
|
|
|
case 'date':
|
|
printf('<td>%s %s</td>',date(UNIX_DATE_FORMAT,$values[$details['field']]),date(DEFAULT_TIME_FORMAT,$values[$details['field']]));
|
|
|
|
break;
|
|
|
|
case 'literal':
|
|
printf('<td>%s</td>',str_replace('%%id%%',$values['id'],$details['data']));
|
|
|
|
break;
|
|
|
|
default:
|
|
printf('<td> %s</td>',$values[$details['field']]);
|
|
}
|
|
}
|
|
|
|
echo '</tr>';
|
|
}
|
|
}
|
|
|
|
if (! is_null($args)) {
|
|
echo '</table>';
|
|
echo '</td></tr></table>';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a record from the table by ID
|
|
*/
|
|
protected function getID($id) {
|
|
$db = &DB();
|
|
$record = $db->Execute(sqlSelect($db,$this->table,'*',array('id'=>$id)));
|
|
|
|
if ($record && $record->RecordCount() == 1)
|
|
return $record->fields;
|
|
else
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Get a record from the table by Name
|
|
*/
|
|
protected function getName($name) {
|
|
$db = &DB();
|
|
$record = $db->Execute(sqlSelect($db,$this->table,'*',array('name'=>$name)));
|
|
|
|
if ($record && $record->RecordCount() == 1)
|
|
return $record->fields;
|
|
else
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Graph Statistics
|
|
*/
|
|
public function graph($start,$end,$constraint,$default) {
|
|
global $C_translate;
|
|
|
|
$db = &DB();
|
|
$result = $db->Execute(sqlSelect($db,$this->table,sprintf('date_orig>=%s AND date_orig<=',$start,$end)));
|
|
|
|
if ($result->RecordCount() == 0) {
|
|
$arr['title'] = $C_translate->translate('search_no_results','','');
|
|
$arr['results'] = $default;
|
|
|
|
return $arr;
|
|
}
|
|
|
|
while (! $result->EOF) {
|
|
$d = $result->fields['date_orig'];
|
|
|
|
for ($i=0; $i<count($constraint); $i++) {
|
|
if ($d >= $constraint[$i]['start'] && $d < $constraint[$i]['end'])
|
|
$default[$i]++;
|
|
}
|
|
|
|
$result->MoveNext();
|
|
}
|
|
|
|
$C_translate->value[$this->table]['count'] = $result->RecordCount();
|
|
$title = $C_translate->translate('statistics',$this->table,'');
|
|
$arr['title'] = $title;
|
|
$arr['results'] = $default;
|
|
|
|
return $arr;
|
|
}
|
|
|
|
protected function sql_SaveRecord($noconvert=false,$ignoreval=false) {
|
|
global $VAR;
|
|
|
|
$lVAR = array();
|
|
if (is_array($VAR))
|
|
$lVAR = array_merge($VAR);
|
|
|
|
foreach ($this->record as $k => $v)
|
|
$lVAR[sprintf('%s_%s',$this->table,$k)] = $v;
|
|
$lVAR['_noredirect'] = true;
|
|
|
|
if ($noconvert)
|
|
$lVAR['_noconvert'] = true;
|
|
if ($ignoreval)
|
|
$lVAR['_ignoreval'] = true;
|
|
|
|
# Adding record
|
|
if (! isset($this->record['id']) || $this->record['id'] != $this->record_id)
|
|
return $this->add($lVAR);
|
|
else
|
|
return $this->update($lVAR);
|
|
}
|
|
|
|
protected function sql_LoadRecord($id) {
|
|
$record = $this->sql_GetRecords(array('where'=>array('id'=>$id)));
|
|
|
|
if (count($record) == 1) {
|
|
$this->record = array_pop($record);
|
|
$this->record_id = $id;
|
|
|
|
} else {
|
|
$this->record = null;
|
|
$this->record_id = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Data out of the tables for the module
|
|
*
|
|
* @return array Table records
|
|
*/
|
|
protected function sql_GetRecords($opt=array()) {
|
|
$db = &DB();
|
|
|
|
$data = array();
|
|
$result = $db->Execute(sqlSelect($this->table,'*',$opt));
|
|
|
|
if ($result && $result->RecordCount())
|
|
while (! $result->EOF) {
|
|
array_push($data,$result->fields);
|
|
$result->MoveNext();
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
}
|
|
?>
|