Pseudo merge-in, which is a wholesale copy from the branch directly to trunk. This is fine since trunk has always been empty up to this point.
git-svn-id: file:///svn-source/pmgr/trunk/site@732 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
5
.htaccess
Normal file
5
.htaccess
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
RewriteEngine on
|
||||||
|
RewriteRule ^$ webroot/ [L]
|
||||||
|
RewriteRule (.*) webroot/$1 [L]
|
||||||
|
</IfModule>
|
||||||
881
app_controller.php
Normal file
881
app_controller.php
Normal file
@@ -0,0 +1,881 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: app_controller.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||||
|
/**
|
||||||
|
* Short description for file.
|
||||||
|
*
|
||||||
|
* This file is application-wide controller file. You can put all
|
||||||
|
* application-wide controller-related methods here.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app
|
||||||
|
* @since CakePHP(tm) v 0.2.9
|
||||||
|
* @version $Revision: 7945 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Short description for class.
|
||||||
|
*
|
||||||
|
* Add your application-wide methods in the class below, your controllers
|
||||||
|
* will inherit them.
|
||||||
|
*
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app
|
||||||
|
*/
|
||||||
|
class AppController extends Controller {
|
||||||
|
var $helpers = array('Html', 'Form', 'Javascript', 'Format', 'Time', 'Grid');
|
||||||
|
var $components = array('DebugKit.Toolbar');
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
$this->params['dev'] = false;
|
||||||
|
$this->params['admin'] = false;
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
function sideMenuLinks() {
|
||||||
|
// Stupid Cake... our constructor sets admin/dev,
|
||||||
|
// but cake stomps it somewhere along the way
|
||||||
|
// after constructing the CakeError controller.
|
||||||
|
if ($this->name === 'CakeError') {
|
||||||
|
$this->params['dev'] = false;
|
||||||
|
$this->params['admin'] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$menu = array();
|
||||||
|
$menu[] = array('name' => 'Common', 'header' => true);
|
||||||
|
$menu[] = array('name' => 'Site Map', 'url' => array('controller' => 'maps', 'action' => 'view', 1));
|
||||||
|
$menu[] = array('name' => 'Units', 'url' => array('controller' => 'units', 'action' => 'index'));
|
||||||
|
$menu[] = array('name' => 'Leases', 'url' => array('controller' => 'leases', 'action' => 'index'));
|
||||||
|
$menu[] = array('name' => 'Customers', 'url' => array('controller' => 'customers', 'action' => 'index'));
|
||||||
|
$menu[] = array('name' => 'Deposits', 'url' => array('controller' => 'transactions', 'action' => 'deposit'));
|
||||||
|
|
||||||
|
if ($this->params['admin']) {
|
||||||
|
$menu[] = array('name' => 'Admin', 'header' => true);
|
||||||
|
$menu[] = array('name' => 'Accounts', 'url' => array('controller' => 'accounts', 'action' => 'index'));
|
||||||
|
$menu[] = array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index'));
|
||||||
|
$menu[] = array('name' => 'Ledgers', 'url' => array('controller' => 'ledgers', 'action' => 'index'));
|
||||||
|
$menu[] = array('name' => 'Tenders', 'url' => array('controller' => 'tenders', 'action' => 'index'));
|
||||||
|
$menu[] = array('name' => 'Transactions', 'url' => array('controller' => 'transactions', 'action' => 'index'));
|
||||||
|
$menu[] = array('name' => 'Ldgr Entries', 'url' => array('controller' => 'ledger_entries', 'action' => 'index'));
|
||||||
|
$menu[] = array('name' => 'Stmt Entries', 'url' => array('controller' => 'statement_entries', 'action' => 'index'));
|
||||||
|
$menu[] = array('name' => 'New Ledgers', 'url' => array('controller' => 'accounts', 'action' => 'newledger'));
|
||||||
|
$menu[] = array('name' => 'Assess Charges', 'url' => array('controller' => 'leases', 'action' => 'assess_all'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->params['dev']) {
|
||||||
|
$menu[] = array('name' => 'Development', 'header' => true);
|
||||||
|
$menu[] = array('name' => 'Un-Nuke', 'url' => '#', 'htmlAttributes' =>
|
||||||
|
array('onclick' => '$(".pr-section").show(); return false;'));
|
||||||
|
$menu[] = array('name' => 'New Ledgers', 'url' => array('controller' => 'accounts', 'action' => 'newledger'));
|
||||||
|
//array('name' => 'RESET DATA', 'url' => array('controller' => 'accounts', 'action' => 'reset_data'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
function beforeFilter() {
|
||||||
|
$this->params['dev'] =
|
||||||
|
(!empty($this->params['dev_route']));
|
||||||
|
$this->params['admin'] =
|
||||||
|
(!empty($this->params['admin_route']) || !empty($this->params['dev_route']));
|
||||||
|
|
||||||
|
if (!$this->params['dev'])
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
function beforeRender() {
|
||||||
|
$this->set('sidemenu', $this->sideMenuLinks());
|
||||||
|
}
|
||||||
|
|
||||||
|
function redirect($url, $status = null, $exit = true) {
|
||||||
|
// OK, since the controller will not be able to
|
||||||
|
// utilize our overriden url function in AppHelper,
|
||||||
|
// we'll have to do it manually here.
|
||||||
|
App::import('Helper', 'Html');
|
||||||
|
$url = HtmlHelper::url($url, true);
|
||||||
|
|
||||||
|
if (headers_sent()) {
|
||||||
|
// If we've already sent the headers, it's because
|
||||||
|
// we're debugging, and our debug output has gotten
|
||||||
|
// out before the redirect. That's probably a good
|
||||||
|
// thing, as we don't typically want pages to be
|
||||||
|
// jerked out from under us while trying to read
|
||||||
|
// the debug output. So, since we can't redirect
|
||||||
|
// anyway, we may as well go with the flow and just
|
||||||
|
// render this page instead, using an empty template
|
||||||
|
$this->set('message',
|
||||||
|
("Intended redirect:<P><BR>" .
|
||||||
|
'<A HREF="'.$url.'">'.$url.'</A>'));
|
||||||
|
|
||||||
|
echo $this->render('/empty');
|
||||||
|
if ($exit)
|
||||||
|
$this->_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::redirect($url, $status, $exit);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset_data() {
|
||||||
|
$this->layout = null;
|
||||||
|
$this->autoLayout = false;
|
||||||
|
$this->autoRender = false;
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
$script = $_SERVER['DOCUMENT_ROOT'] . '/pmgr/build.cmd';
|
||||||
|
echo "<P>" . date('r') . "\n";
|
||||||
|
//echo "<P>Script: $script" . "\n";
|
||||||
|
$db = & $this->Account->getDataSource();
|
||||||
|
$script .= ' "' . $db->config['database'] . '"';
|
||||||
|
$script .= ' "' . $db->config['login'] . '"';
|
||||||
|
$script .= ' "' . $db->config['password'] . '"';
|
||||||
|
$handle = popen($script . ' 2>&1', 'r');
|
||||||
|
//echo "<P>Handle: $handle; " . gettype($handle) . "\n";
|
||||||
|
echo "<P><PRE>\n";
|
||||||
|
while (($read = fread($handle, 2096))) {
|
||||||
|
echo $read;
|
||||||
|
}
|
||||||
|
echo "</PRE>\n";
|
||||||
|
pclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* helper: gridView
|
||||||
|
* - called by derived controllers to create an index listing
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridView($title, $action = null, $element = null) {
|
||||||
|
$this->set('title', $title);
|
||||||
|
// The resulting page will contain a grid, which will
|
||||||
|
// use ajax to obtain the actual data for this action
|
||||||
|
$this->set('action', $action ? $action : $this->params['action']);
|
||||||
|
$this->render('/elements/' . ($element ? $element : $this->params['controller']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: gridData
|
||||||
|
* - Fetches the actual data requested by grid as XML
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridData() {
|
||||||
|
// Grab a copy of the parameters that control this request
|
||||||
|
$params = array();
|
||||||
|
if (isset($this->params['url']) && is_array($this->params['url']))
|
||||||
|
$params = $this->params['url'];
|
||||||
|
|
||||||
|
// Do any preliminary setup necessary
|
||||||
|
$this->gridDataSetup($params);
|
||||||
|
|
||||||
|
// Get the top level model for this grid
|
||||||
|
$model = $this->gridDataModel($params);
|
||||||
|
|
||||||
|
// Get the number of records prior to pagination
|
||||||
|
$count = $this->gridDataCount($params, $model);
|
||||||
|
|
||||||
|
// Determine pagination configuration (and save to $params)
|
||||||
|
$pagination = $this->gridDataPagination($params, $model, $count);
|
||||||
|
|
||||||
|
// Retreive the appropriate subset of data
|
||||||
|
$records = $this->gridDataRecords($params, $model, $pagination);
|
||||||
|
|
||||||
|
// Post process the records
|
||||||
|
$this->gridDataPostProcess($params, $model, $records);
|
||||||
|
|
||||||
|
// Output the resulting record set
|
||||||
|
$this->gridDataOutput($params, $model, $records, $pagination);
|
||||||
|
|
||||||
|
// Call out to finalize everything
|
||||||
|
$this->gridDataFinalize($params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtual: gridData* functions
|
||||||
|
* - These set up the context for the grid data, and will
|
||||||
|
* need to be overridden in the derived class for anything
|
||||||
|
* other than the most basic of grids.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* gridData SETUP / CLEANUP
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataModel(&$params) {
|
||||||
|
return $this->{$this->modelClass};
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataSetup(&$params) {
|
||||||
|
// Debug only if requested
|
||||||
|
$params['debug'] = !empty($this->passedArgs['debug']);
|
||||||
|
|
||||||
|
if ($params['debug']) {
|
||||||
|
ob_start();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->layout = null;
|
||||||
|
$this->autoLayout = false;
|
||||||
|
$this->autoRender = false;
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establish some defaults (except for serialized items)
|
||||||
|
$params = array_merge(array('page' => 1,
|
||||||
|
'rows' => 20),
|
||||||
|
$params);
|
||||||
|
|
||||||
|
// Unserialize our complex structure of post data.
|
||||||
|
// This SHOULD always be set, except when debugging
|
||||||
|
if (isset($params['post']))
|
||||||
|
$params['post'] = unserialize($params['post']);
|
||||||
|
else
|
||||||
|
$params['post'] = array();
|
||||||
|
|
||||||
|
// Unserialize our complex structure of dynamic post data
|
||||||
|
if (isset($params['dynamic_post']))
|
||||||
|
$params['dynamic_post'] = unserialize($params['dynamic_post']);
|
||||||
|
else
|
||||||
|
$params['dynamic_post'] = null;
|
||||||
|
|
||||||
|
// Unserialize our complex structure of dynamic post data
|
||||||
|
if (isset($params['dynamic_post_replace']))
|
||||||
|
$params['dynamic_post_replace'] = unserialize($params['dynamic_post_replace']);
|
||||||
|
else
|
||||||
|
$params['dynamic_post_replace'] = null;
|
||||||
|
|
||||||
|
// Merge the static and dynamic post data
|
||||||
|
if (!empty($params['dynamic_post']))
|
||||||
|
$params['post'] = array_merge_recursive($params['post'], $params['dynamic_post']);
|
||||||
|
if (!empty($params['dynamic_post_replace']))
|
||||||
|
$params['post'] = array_merge($params['post'], $params['dynamic_post_replace']);
|
||||||
|
|
||||||
|
// This SHOULD always be set, except when debugging
|
||||||
|
if (!isset($params['post']['fields']))
|
||||||
|
$params['post']['fields'] = array($this->{$this->modelClass}->alias
|
||||||
|
.'.'.
|
||||||
|
$this->{$this->modelClass}->primaryKey);
|
||||||
|
|
||||||
|
// Make sure the action parameter at least exists, and
|
||||||
|
// promote it to the top level (since it drives the operation).
|
||||||
|
if (isset($params['post']['action']))
|
||||||
|
$params['action'] = $params['post']['action'];
|
||||||
|
else
|
||||||
|
$params['action'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFinalize(&$params) {
|
||||||
|
if ($params['debug']) {
|
||||||
|
$xml = ob_get_contents();
|
||||||
|
ob_end_clean();
|
||||||
|
|
||||||
|
$xml = preg_replace("/&/", "&", $xml);
|
||||||
|
$xml = preg_replace("/</", "<", $xml);
|
||||||
|
$xml = preg_replace("/>/", ">", $xml);
|
||||||
|
echo ("\n<PRE>\n$xml\n</PRE>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* gridData COUNTING
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataCount(&$params, &$model) {
|
||||||
|
// Establish the tables and conditions for counting
|
||||||
|
$query = array_intersect_key($this->gridDataCountTableSet($params, $model),
|
||||||
|
array('link'=>1, 'contain'=>1));
|
||||||
|
|
||||||
|
// Conditions for the count
|
||||||
|
$query['conditions'] = $this->gridDataCountConditionSet($params, $model);
|
||||||
|
|
||||||
|
// Grouping (which would not be typical)
|
||||||
|
$query['group'] = $this->gridDataCountGroup($params, $model);
|
||||||
|
|
||||||
|
// DEBUG PURPOSES ONLY!
|
||||||
|
$params['count_query'] = $query;
|
||||||
|
|
||||||
|
// Get the number of records prior to pagination
|
||||||
|
return $this->gridDataCountExecute($params, $model, $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataCountExecute(&$params, &$model, $query) {
|
||||||
|
return $model->find('count', $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataCountTables(&$params, &$model) {
|
||||||
|
// Same tables for counting as for retreiving
|
||||||
|
return $this->gridDataTables($params, $model);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataCountTableSet(&$params, &$model) {
|
||||||
|
// Preliminary set of tables
|
||||||
|
$query = array_intersect_key($this->gridDataCountTables($params, $model),
|
||||||
|
array('link'=>1, 'contain'=>1));
|
||||||
|
|
||||||
|
// Perform filtering based on user request: $params['post']['filter']
|
||||||
|
return array_intersect_key($this->gridDataFilterTables($params, $model, $query),
|
||||||
|
array('link'=>1, 'contain'=>1));
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataCountConditions(&$params, &$model) {
|
||||||
|
// Same conditions for counting as for retreiving
|
||||||
|
return $this->gridDataConditions($params, $model);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataCountConditionSet(&$params, &$model) {
|
||||||
|
// Conditions for the count
|
||||||
|
$conditions = $this->gridDataCountConditions($params, $model);
|
||||||
|
|
||||||
|
// Perform filtering based on user request: $params['post']['filter']
|
||||||
|
return $this->gridDataFilterConditions($params, $model, $conditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataCountGroup(&$params, &$model) {
|
||||||
|
// Grouping will screw up the count, since it
|
||||||
|
// causes the results to be split into chunks
|
||||||
|
// based on the GROUP BY clause. We can't have
|
||||||
|
// more than one row of data in the count query,
|
||||||
|
// just a _single_ row with the actual count.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* gridData FILTERING
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataFilterTables(&$params, &$model, $query) {
|
||||||
|
if (isset($query['contain']))
|
||||||
|
$link = 'contain';
|
||||||
|
else
|
||||||
|
$link = 'link';
|
||||||
|
|
||||||
|
if (empty($params['post']['filter']))
|
||||||
|
return $query;
|
||||||
|
|
||||||
|
foreach ($params['post']['filter'] AS $filter => $filter_value) {
|
||||||
|
$split = $this->gridDataFilterSplit($params, $model, $filter, $filter_value);
|
||||||
|
|
||||||
|
/* pr(array('AppController::gridDataFilterTable' => */
|
||||||
|
/* array('checkpoint' => "Filter split") */
|
||||||
|
/* + compact('split'))); */
|
||||||
|
|
||||||
|
$table = $this->gridDataFilterTablesTable($params, $model, $split['table']);
|
||||||
|
if (!$table)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$config = $this->gridDataFilterTablesConfig($params, $model, $split['table']);
|
||||||
|
|
||||||
|
/* pr(array('AppController::gridDataFilterTable' => */
|
||||||
|
/* array('checkpoint' => "Add filter config to query") */
|
||||||
|
/* + array('query[link]' => $query[$link]) */
|
||||||
|
/* + compact('config'))); */
|
||||||
|
|
||||||
|
// If the table is already part of the query, append to it
|
||||||
|
if ($table == $model->alias) {
|
||||||
|
$query[$link] =
|
||||||
|
array_merge_recursive(array_diff_key($config, array('fields'=>1)),
|
||||||
|
$query[$link]);
|
||||||
|
}
|
||||||
|
elseif (isset($query[$link][$table])) {
|
||||||
|
$query[$link][$table] =
|
||||||
|
array_merge_recursive($config, $query[$link][$table]);
|
||||||
|
}
|
||||||
|
elseif (in_array($table, $query[$link])) {
|
||||||
|
// REVISIT <AP>: 20090727
|
||||||
|
// This presents a dilema. $config may specify fields
|
||||||
|
// as array(), whereas the user has already indicated
|
||||||
|
// they desire ALL fields (by the fact that table is
|
||||||
|
// a member of the query['link'] array without anything
|
||||||
|
// specified). However, $config _could_ specify a
|
||||||
|
// non-standard field in the array, such as using SUM()
|
||||||
|
// or other equation. In that case, we'd have to add
|
||||||
|
// in all the fields of table to the array. That
|
||||||
|
// wouldn't be very hard, but I'll ignore it at the
|
||||||
|
// moment and wait until it's needed.
|
||||||
|
$key = array_search($table, $query[$link]);
|
||||||
|
$query[$link][$table] = array('fields' => null) + $config;
|
||||||
|
unset($query[$link][$key]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Table is NOT already part of the query... set it now
|
||||||
|
$query[$link][$table] = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pr(array('post-filter-table-config' => */
|
||||||
|
/* array('query[link]' => $query[$link]))); */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFilterTablesTable(&$params, &$model, $table) {
|
||||||
|
// By default, don't add anything if the filter
|
||||||
|
// condition occurs on the actual model table
|
||||||
|
if ($table == $model->alias)
|
||||||
|
return null;
|
||||||
|
return $this->gridDataFilterTableName($params, $model, $table);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFilterTablesConfig(&$params, &$model, $table) {
|
||||||
|
return array('fields' => array());
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFilterConditions(&$params, &$model, $conditions) {
|
||||||
|
if (empty($params['post']['filter']))
|
||||||
|
return $conditions;
|
||||||
|
|
||||||
|
foreach ($params['post']['filter'] AS $filter => $filter_value) {
|
||||||
|
$split = $this->gridDataFilterSplit($params, $model, $filter, $filter_value);
|
||||||
|
|
||||||
|
$table = $this->gridDataFilterConditionsTable($params, $model, $split['table']);
|
||||||
|
$key = $this->gridDataFilterConditionsKey($params, $model, $split['table'], $split['field']);
|
||||||
|
if (!$key)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$conditions[]
|
||||||
|
= $this->gridDataFilterConditionsStatement($params, $model, $table, $key,
|
||||||
|
array_intersect_key
|
||||||
|
($split,
|
||||||
|
array('value'=>1,
|
||||||
|
'value_present'=>1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFilterConditionsTable(&$params, &$model, $table) {
|
||||||
|
return $this->gridDataFilterTableName($params, $model, $table);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFilterConditionsKey(&$params, &$model, $table, $id) {
|
||||||
|
// REVISIT <AP>: 20090722
|
||||||
|
// When $id is null, we could instantiate the table,
|
||||||
|
// and use the _actual_ primary key. However, I don't
|
||||||
|
// expect that functionality to be used, and will just
|
||||||
|
// stick with 'id' for now.
|
||||||
|
return $id ? $id : 'id';
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFilterConditionsStatement(&$params, &$model, $table, $key, $value) {
|
||||||
|
$key = (empty($table)?"":"{$table}.") . $key;
|
||||||
|
if (isset($value['value_present']) && $value['value_present'])
|
||||||
|
return array($key => $value['value']);
|
||||||
|
else
|
||||||
|
return array($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFilterSplit(&$params, &$model, $filter, $value) {
|
||||||
|
$value_present = true;
|
||||||
|
if (!is_string($filter)) {
|
||||||
|
// only a filter condition was set, not filter=>value
|
||||||
|
$filter = $value;
|
||||||
|
$value = null;
|
||||||
|
$value_present = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = $field = null;
|
||||||
|
if (preg_match("/^\w+\.\w+(\s*[!<>=]+)?$/", $filter)) {
|
||||||
|
list($table, $field) = explode(".", $filter);
|
||||||
|
}
|
||||||
|
elseif (preg_match('/^[A-Z][A-Za-z]*$/', $filter)) {
|
||||||
|
$table = $filter;
|
||||||
|
$field = null;
|
||||||
|
}
|
||||||
|
elseif (preg_match('/^\w+(\s*[!<>=]+)?$/', $filter)) {
|
||||||
|
$table = $model->alias;
|
||||||
|
$field = $filter;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// $filter must be a function or other complicated condition
|
||||||
|
$table = null;
|
||||||
|
$field = $filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return compact('table', 'field', 'value', 'value_present');
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFilterTableName(&$params, &$model, $table) {
|
||||||
|
return Inflector::camelize($table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* gridData PAGINATION
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataPagination(&$params, &$model, $record_count) {
|
||||||
|
// Retrieve, or calculate, all parameters necesssary for
|
||||||
|
// pagination. Verify the passed in parameters are valid.
|
||||||
|
|
||||||
|
$limit = $params['rows'] > 0 ? $params['rows'] : 10;
|
||||||
|
$total = ($record_count < 0) ? 0 : ceil($record_count/$limit);
|
||||||
|
$page = ($params['page'] <= 1) ? 1 : (($params['page'] > $total) ? $total : $params['page']);
|
||||||
|
$start = $limit * ($page - 1);
|
||||||
|
|
||||||
|
return compact('record_count', 'limit', 'page', 'start', 'total');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* gridData RETREIVAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataRecords(&$params, &$model, $pagination) {
|
||||||
|
// Establish the tables for this query
|
||||||
|
$query = array_intersect_key($this->gridDataTableSet($params, $model),
|
||||||
|
array('link'=>1, 'contain'=>1));
|
||||||
|
|
||||||
|
// Specify the fields for the query
|
||||||
|
$query['fields'] = $this->gridDataFields($params, $model);
|
||||||
|
|
||||||
|
// Conditions of the query
|
||||||
|
$query['conditions'] = $this->gridDataConditionSet($params, $model);
|
||||||
|
|
||||||
|
// Data record grouping
|
||||||
|
$query['group'] = $this->gridDataGroup($params, $model);
|
||||||
|
|
||||||
|
// The subset of data based on pagination
|
||||||
|
$query['limit'] = $this->gridDataLimit($params, $model, $pagination['start'], $pagination['limit']);
|
||||||
|
|
||||||
|
// Ordering based on user request
|
||||||
|
$query['order'] = $this->gridDataOrder($params, $model,
|
||||||
|
isset($params['sidx']) ? $params['sidx'] : null,
|
||||||
|
isset($params['sord']) ? $params['sord'] : null);
|
||||||
|
|
||||||
|
// DEBUG PURPOSES ONLY!
|
||||||
|
$params['query'] = $query;
|
||||||
|
|
||||||
|
return $this->gridDataRecordsExecute($params, $model, $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataRecordsExecute(&$params, &$model, $query) {
|
||||||
|
return $model->find('all', $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
return array('link' => array());
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataTableSet(&$params, &$model) {
|
||||||
|
// Preliminary set of tables
|
||||||
|
$query = array_intersect_key($this->gridDataTables($params, $model),
|
||||||
|
array('link'=>1, 'contain'=>1));
|
||||||
|
|
||||||
|
// Perform filtering based on user request: $params['post']['filter']
|
||||||
|
$query = array_intersect_key($this->gridDataFilterTables($params, $model, $query),
|
||||||
|
array('link'=>1, 'contain'=>1));
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function gridDataConditions(&$params, &$model) {
|
||||||
|
$searches = array();
|
||||||
|
|
||||||
|
if (isset($params['_search']) && $params['_search'] === 'true') {
|
||||||
|
if (isset($params['searchOper'])) {
|
||||||
|
$searches[] = array('op' => $params['searchOper'],
|
||||||
|
'field' => $params['searchField'],
|
||||||
|
'value' => $params['searchString']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// DOH! Crappy mechanism puts toolbar search terms
|
||||||
|
// directly into params as name/value pairs. No
|
||||||
|
// way to know which elements of params are search
|
||||||
|
// terms, so skipping this at the moment.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif (isset($params['filt']) && $params['filt']) {
|
||||||
|
$searches[] = array('op' => 'bw',
|
||||||
|
'field' => $params['filtField'],
|
||||||
|
'value' => $params['filtValue']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ops = array('eq' => array('op' => null, 'pre' => '', 'post' => ''),
|
||||||
|
'ne' => array('op' => '<>', 'pre' => '', 'post' => ''),
|
||||||
|
'lt' => array('op' => '<', 'pre' => '', 'post' => ''),
|
||||||
|
'le' => array('op' => '<=', 'pre' => '', 'post' => ''),
|
||||||
|
'gt' => array('op' => '>', 'pre' => '', 'post' => ''),
|
||||||
|
'ge' => array('op' => '>=', 'pre' => '', 'post' => ''),
|
||||||
|
'bw' => array('op' => 'LIKE', 'pre' => '', 'post' => '%'),
|
||||||
|
'ew' => array('op' => 'LIKE', 'pre' => '%', 'post' => ''),
|
||||||
|
'cn' => array('op' => 'LIKE', 'pre' => '%', 'post' => '%'),
|
||||||
|
);
|
||||||
|
|
||||||
|
$conditions = array();
|
||||||
|
foreach ($searches AS $search) {
|
||||||
|
$op = $ops[$search['op']];
|
||||||
|
$field = $search['field'] . ($op['op'] ? ' '.$op['op'] : '');
|
||||||
|
$value = $op['pre'] . $search['value']. $op['post'];
|
||||||
|
$conditions[] = array($field => $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($params['action']) && $params['action'] === 'idlist') {
|
||||||
|
if (count($params['post']['idlist']))
|
||||||
|
$conditions[] = array($model->alias.'.'.$model->primaryKey => $params['post']['idlist']);
|
||||||
|
else
|
||||||
|
$conditions[] = '0=1';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataConditionSet(&$params, &$model) {
|
||||||
|
// Conditions for record retrieval
|
||||||
|
$conditions = $this->gridDataConditions($params, $model);
|
||||||
|
|
||||||
|
// Perform filtering based on user request: $params['post']['filter']
|
||||||
|
return $this->gridDataFilterConditions($params, $model, $conditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFields(&$params, &$model) {
|
||||||
|
$db = &$model->getDataSource();
|
||||||
|
$fields = $db->fields($model, $model->alias);
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataGroup(&$params, &$model) {
|
||||||
|
return $model->alias.'.'.$model->primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
return $index ? array($index .' '. $direction) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataLimit(&$params, &$model, $start, $limit) {
|
||||||
|
return $start . ', ' . $limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* gridData POST PROCESSING
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataPostProcess(&$params, &$model, &$records) {
|
||||||
|
// Add grid IDs to each record
|
||||||
|
$this->gridDataPostProcessGridIDs($params, $model, $records);
|
||||||
|
|
||||||
|
// Add the calculated fields (if any), to the model fields
|
||||||
|
$this->gridDataPostProcessCalculatedFields($params, $model, $records);
|
||||||
|
|
||||||
|
// Perform any requested subtotaling of fields
|
||||||
|
$this->gridDataPostProcessSubtotal($params, $model, $records);
|
||||||
|
|
||||||
|
// Add in any needed hyperlinks
|
||||||
|
$this->gridDataPostProcessLinks($params, $model, $records, array());
|
||||||
|
|
||||||
|
// DEBUG PURPOSES ONLY!
|
||||||
|
//$params['records'] = $records;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessGridIDs(&$params, &$model, &$records) {
|
||||||
|
$model_alias = $model->alias;
|
||||||
|
$id = $model->primaryKey;
|
||||||
|
|
||||||
|
foreach ($records AS &$record) {
|
||||||
|
$record['grid_id'] = $record[$model_alias][$id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessCalculatedFields(&$params, &$model, &$records) {
|
||||||
|
$model_alias = $model->alias;
|
||||||
|
|
||||||
|
foreach ($records AS &$record) {
|
||||||
|
// Add the calculated fields (if any), to the model fields
|
||||||
|
if (isset($record[0])) {
|
||||||
|
$record[$model_alias] = $record[0] + $record[$model_alias];
|
||||||
|
unset($record[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessSubtotal(&$params, &$model, &$records) {
|
||||||
|
$model_alias = $model->alias;
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090722
|
||||||
|
// Horrible solution to something that should be done
|
||||||
|
// in SQL. But, it works for now, so what the heck...
|
||||||
|
|
||||||
|
$subtotals = array();
|
||||||
|
foreach ($params['post']['fields'] AS $field) {
|
||||||
|
if (preg_match('/subtotal-(.*)$/', $field, $matches))
|
||||||
|
$subtotals[] = array('field' => $matches[1],
|
||||||
|
'name' => $field,
|
||||||
|
'amount' => 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($records AS &$record) {
|
||||||
|
foreach ($subtotals AS &$subtotal) {
|
||||||
|
$field = $subtotal['field'];
|
||||||
|
if (preg_match("/\./", $field)) {
|
||||||
|
list($tbl, $col) = explode(".", $field);
|
||||||
|
$record['subtotal-'.$tbl][$col] =
|
||||||
|
($subtotal['amount'] += $record[$tbl][$col]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$record[$model->alias]['subtotal-'.$field] =
|
||||||
|
($subtotal['amount'] += $record[$model->alias][$field]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
// Don't create any links if ordered not to.
|
||||||
|
if (isset($params['post']['nolinks']))
|
||||||
|
return;
|
||||||
|
|
||||||
|
App::import('Helper', 'Html');
|
||||||
|
|
||||||
|
foreach ($links AS $table => $fields) {
|
||||||
|
$special = array('controller', 'action', 'id');
|
||||||
|
$controller = Inflector::pluralize(Inflector::underscore($table));
|
||||||
|
$action = 'view';
|
||||||
|
$id = 'id';
|
||||||
|
extract(array_intersect_key($fields, array_flip($special)));
|
||||||
|
foreach ($records AS &$record) {
|
||||||
|
if (!isset($record[$table]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach (array_diff_key($fields, array_flip($special)) AS $field) {
|
||||||
|
if (!isset($record[$table][$id]) || !isset($record[$table][$field]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// DEBUG PURPOSES ONLY!
|
||||||
|
//$params['linkrecord'][] = compact('table', 'field', 'id', 'controller', 'record');
|
||||||
|
$record[$table][$field] =
|
||||||
|
'<A HREF="' .
|
||||||
|
HtmlHelper::url(array('controller' => $controller,
|
||||||
|
'action' => $action,
|
||||||
|
$record[$table][$id])) .
|
||||||
|
'">' .
|
||||||
|
$record[$table][$field] .
|
||||||
|
'</A>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* gridData OUTPUT
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataOutput(&$params, &$model, &$records, $pagination) {
|
||||||
|
$this->gridDataOutputHeader($params, $model);
|
||||||
|
$this->gridDataOutputXMLHeader($params, $model);
|
||||||
|
$this->gridDataOutputRootNodeBegin($params, $model);
|
||||||
|
$this->gridDataOutputSummary($params, $model, $pagination);
|
||||||
|
$this->gridDataOutputRecords($params, $model, $records);
|
||||||
|
$this->gridDataOutputRootNodeEnd($params, $model);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOutputHeader(&$params, &$model) {
|
||||||
|
if (!$params['debug']) {
|
||||||
|
header("Content-type: text/xml;charset=utf-8");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOutputXMLHeader(&$params, &$model) {
|
||||||
|
echo "<?xml version='1.0' encoding='utf-8'?>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOutputRootNodeBegin(&$params, &$model) {
|
||||||
|
echo "<rows>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOutputRootNodeEnd(&$params, &$model) {
|
||||||
|
echo "</rows>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOutputSummary(&$params, &$model, $pagination) {
|
||||||
|
echo " <params><![CDATA[\n" . print_r($params, true) . "\n]]></params>\n";
|
||||||
|
echo " <page>{$pagination['page']}</page>\n";
|
||||||
|
echo " <total>{$pagination['total']}</total>\n";
|
||||||
|
echo " <records>{$pagination['record_count']}</records>\n";
|
||||||
|
|
||||||
|
if (isset($params['userdata'])) {
|
||||||
|
foreach ($params['userdata'] AS $field => $value)
|
||||||
|
echo ' <userdata name="'.$field.'">' . "{$value}</userdata>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOutputRecords(&$params, &$model, &$records) {
|
||||||
|
$id_field = 'grid_id';
|
||||||
|
foreach ($records AS $record) {
|
||||||
|
$this->gridDataOutputRecord($params, $model, $record,
|
||||||
|
$record[$id_field], $params['post']['fields']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOutputRecord(&$params, &$model, &$record, $id, $fields) {
|
||||||
|
echo " <row id='$id'>\n";
|
||||||
|
foreach ($fields AS $field) {
|
||||||
|
$this->gridDataOutputRecordField($params, $model, $record, $field);
|
||||||
|
}
|
||||||
|
echo " </row>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOutputRecordField(&$params, &$model, &$record, $field) {
|
||||||
|
if (preg_match("/\./", $field)) {
|
||||||
|
list($tbl, $col) = explode(".", $field);
|
||||||
|
//pr(compact('record', 'field', 'tbl', 'col'));
|
||||||
|
$data = $record[$tbl][$col];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$data = $record[$model->alias][$field];
|
||||||
|
}
|
||||||
|
$this->gridDataOutputRecordCell($params, $model, $record, $field, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOutputRecordCell(&$params, &$model, &$record, $field, $data) {
|
||||||
|
// be sure to put text data in CDATA
|
||||||
|
if (preg_match("/^\d*$/", $data))
|
||||||
|
echo " <cell>$data</cell>\n";
|
||||||
|
else
|
||||||
|
echo " <cell><![CDATA[$data]]></cell>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function INTERNAL_ERROR($msg, $depth = 0) {
|
||||||
|
INTERNAL_ERROR($msg, false, $depth+1);
|
||||||
|
$this->render_empty();
|
||||||
|
$this->_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_empty() {
|
||||||
|
$this->render('/empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
50
app_helper.php
Normal file
50
app_helper.php
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: app_helper.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||||
|
/**
|
||||||
|
* Short description for file.
|
||||||
|
*
|
||||||
|
* This file is application-wide helper file. You can put all
|
||||||
|
* application-wide helper-related methods here.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake
|
||||||
|
* @since CakePHP(tm) v 0.2.9
|
||||||
|
* @version $Revision: 7945 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
App::import('Core', 'Helper');
|
||||||
|
/**
|
||||||
|
* This is a placeholder class.
|
||||||
|
* Create the same file in app/app_helper.php
|
||||||
|
*
|
||||||
|
* Add your application-wide methods in the class below, your helpers
|
||||||
|
* will inherit them.
|
||||||
|
*
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake
|
||||||
|
*/
|
||||||
|
class AppHelper extends Helper {
|
||||||
|
|
||||||
|
function url($url = null, $full = false) {
|
||||||
|
foreach(array('admin_route', 'dev_route') AS $mod) {
|
||||||
|
if (isset($this->params[$mod]) && is_array($url) && !isset($url[$mod]))
|
||||||
|
$url[$mod] = $this->params[$mod];
|
||||||
|
}
|
||||||
|
return parent::url($url, $full);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
491
app_model.php
Normal file
491
app_model.php
Normal file
@@ -0,0 +1,491 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: app_model.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application model for Cake.
|
||||||
|
*
|
||||||
|
* This file is application-wide model file. You can put all
|
||||||
|
* application-wide model-related methods here.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app
|
||||||
|
* @since CakePHP(tm) v 0.2.9
|
||||||
|
* @version $Revision: 7945 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application model for Cake.
|
||||||
|
*
|
||||||
|
* Add your application-wide methods in the class below, your models
|
||||||
|
* will inherit them.
|
||||||
|
*
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app
|
||||||
|
*/
|
||||||
|
class AppModel extends Model {
|
||||||
|
|
||||||
|
var $actsAs = array('Containable', 'Linkable');
|
||||||
|
var $useNullForEmpty = true;
|
||||||
|
var $formatDateFields = true;
|
||||||
|
|
||||||
|
// Default Log Level, if not specified at the function level
|
||||||
|
var $default_log_level = 5;
|
||||||
|
|
||||||
|
// Class specific log levels
|
||||||
|
var $class_log_level = array('Model' => 5);
|
||||||
|
|
||||||
|
// Function specific log levels
|
||||||
|
var $function_log_level = array();
|
||||||
|
|
||||||
|
// Force the module to log at LEAST at this level
|
||||||
|
var $min_log_level;
|
||||||
|
|
||||||
|
// Force logging of nothing higher than this level
|
||||||
|
var $max_log_level;
|
||||||
|
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090730
|
||||||
|
// Why is this constructor crashing?
|
||||||
|
// Clearly it's in some sort of infinite
|
||||||
|
// loop, but it seems the correct way
|
||||||
|
// to have a constructor call the parent...
|
||||||
|
|
||||||
|
/* function __construct() { */
|
||||||
|
/* parent::__construct(); */
|
||||||
|
/* $this->prClassLevel(5, 'Model'); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: pr
|
||||||
|
* - Prints out debug information, if the log level allows
|
||||||
|
*/
|
||||||
|
|
||||||
|
function prClassLevel($level, $class = null) {
|
||||||
|
$trace = debug_backtrace(false);
|
||||||
|
$caller = array_shift($trace);
|
||||||
|
$caller = array_shift($trace);
|
||||||
|
if (empty($class))
|
||||||
|
$class = $caller['class'];
|
||||||
|
$this->class_log_level[$class] = $level;
|
||||||
|
}
|
||||||
|
|
||||||
|
function prFunctionLevel($level, $function = null, $class = null) {
|
||||||
|
$trace = debug_backtrace(false);
|
||||||
|
$caller = array_shift($trace);
|
||||||
|
$caller = array_shift($trace);
|
||||||
|
if (empty($class))
|
||||||
|
$class = $caller['class'];
|
||||||
|
if (empty($function))
|
||||||
|
$function = $caller['function'];
|
||||||
|
$this->function_log_level["{$class}-{$function}"] = $level;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _pr($level, $mixed, $checkpoint = null) {
|
||||||
|
if (Configure::read() <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
$log_level = $this->default_log_level;
|
||||||
|
|
||||||
|
$trace = debug_backtrace(false);
|
||||||
|
|
||||||
|
// Get rid of pr/prEnter/prReturn
|
||||||
|
$caller = array_shift($trace);
|
||||||
|
|
||||||
|
// The next entry shows where pr was called from, but it
|
||||||
|
// shows _what_ was called, which is pr/prEntry/prReturn.
|
||||||
|
$caller = array_shift($trace);
|
||||||
|
$file = $caller['file'];
|
||||||
|
$line = $caller['line'];
|
||||||
|
|
||||||
|
// So, this caller holds the calling function name
|
||||||
|
$caller = $trace[0];
|
||||||
|
$function = $caller['function'];
|
||||||
|
$class = $caller['class'];
|
||||||
|
//$class = $this->name;
|
||||||
|
|
||||||
|
// Use class or function specific log level if available
|
||||||
|
if (isset($this->class_log_level[$class]))
|
||||||
|
$log_level = $this->class_log_level[$class];
|
||||||
|
if (isset($this->function_log_level["{$class}-{$function}"]))
|
||||||
|
$log_level = $this->function_log_level["{$class}-{$function}"];
|
||||||
|
|
||||||
|
// Establish log level minimums
|
||||||
|
$min_log_level = $this->min_log_level;
|
||||||
|
if (is_array($this->min_log_level)) {
|
||||||
|
$min_show_level = $min_log_level['show'];
|
||||||
|
$min_log_level = $min_log_level['log'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establish log level maximums
|
||||||
|
$max_log_level = $this->max_log_level;
|
||||||
|
if (is_array($this->max_log_level)) {
|
||||||
|
$max_show_level = $max_log_level['show'];
|
||||||
|
$max_log_level = $max_log_level['log'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the applicable log and show levels
|
||||||
|
if (is_array($log_level)) {
|
||||||
|
$show_level = $log_level['show'];
|
||||||
|
$log_level = $log_level['log'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust log level up/down to min/max
|
||||||
|
if (isset($min_log_level))
|
||||||
|
$log_level = max($log_level, $min_log_level);
|
||||||
|
if (isset($max_log_level))
|
||||||
|
$log_level = min($log_level, $max_log_level);
|
||||||
|
|
||||||
|
// Adjust show level up/down to min/max
|
||||||
|
if (isset($min_show_level))
|
||||||
|
$show_level = max($show_level, $min_show_level);
|
||||||
|
if (isset($max_show_level))
|
||||||
|
$show_level = min($show_level, $max_show_level);
|
||||||
|
|
||||||
|
// If the level is insufficient, bail out
|
||||||
|
if ($level > $log_level)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!empty($checkpoint)) {
|
||||||
|
$chk = array("checkpoint" => $checkpoint);
|
||||||
|
if (is_array($mixed))
|
||||||
|
$mixed = $chk + $mixed;
|
||||||
|
else
|
||||||
|
$mixed = $chk + array($mixed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static $pr_unique_number = 0;
|
||||||
|
$pr_id = 'pr-section-class-' . $class . '-print-' . (++$pr_unique_number);
|
||||||
|
$pr_trace_id = $pr_id . '-trace';
|
||||||
|
$pr_output_id = $pr_id . '-output';
|
||||||
|
|
||||||
|
$pr_entire_base_class = "pr-section";
|
||||||
|
$pr_entire_class_class = $pr_entire_base_class . '-class-' . $class;
|
||||||
|
$pr_entire_function_class = $pr_entire_class_class . '-function-' . $function;
|
||||||
|
$pr_entire_class = "$pr_entire_base_class $pr_entire_class_class $pr_entire_function_class";
|
||||||
|
$pr_header_class = "pr-caller";
|
||||||
|
$pr_trace_class = "pr-trace";
|
||||||
|
$pr_output_base_class = 'pr-output';
|
||||||
|
$pr_output_class_class = $pr_output_base_class . '-class-' . $class;
|
||||||
|
$pr_output_function_class = $pr_output_class_class . '-function-' . $function;
|
||||||
|
$pr_output_class = "$pr_output_base_class $pr_output_class_class $pr_output_function_class";
|
||||||
|
|
||||||
|
echo '<DIV class="'.$pr_entire_class.'" id="'.$pr_id.'">'."\n";
|
||||||
|
echo '<DIV class="'.$pr_header_class.'">'."\n";
|
||||||
|
echo '<DIV class="'.$pr_trace_class.'" id="'.$pr_trace_id.'" style="display:none;">'."\n";
|
||||||
|
echo '<HR />' . "\n";
|
||||||
|
|
||||||
|
// Flip trace around so the sequence flows from top to bottom
|
||||||
|
// Then print out the entire stack trace (in hidden div)
|
||||||
|
$trace = array_reverse($trace);
|
||||||
|
for ($i = 0; $i < count($trace); ++$i) {
|
||||||
|
$bline = $trace[$i]['line'];
|
||||||
|
$bfile = $trace[$i]['file'];
|
||||||
|
$bfile = str_replace(ROOT.DS, '', $bfile);
|
||||||
|
$bfile = str_replace(CAKE_CORE_INCLUDE_PATH.DS, '', $bfile);
|
||||||
|
|
||||||
|
if ($i > 0) {
|
||||||
|
$bfunc = $trace[$i-1]['function'];
|
||||||
|
$bclas = $trace[$i-1]['class'];
|
||||||
|
} else {
|
||||||
|
$bfunc = null;
|
||||||
|
$bclas = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo("$bfile:$bline (" . ($bclas ? "$bclas::$bfunc" : "entry point") . ")<BR>\n");
|
||||||
|
//echo(($bclas ? "$bclas::$bfunc" : "entry point") . "; $bfile : $bline<BR>\n");
|
||||||
|
}
|
||||||
|
echo '</DIV>' . "\n"; // End pr_trace_class
|
||||||
|
$file = str_replace(ROOT.DS, '', $file);
|
||||||
|
$file = str_replace(CAKE_CORE_INCLUDE_PATH.DS, '', $file);
|
||||||
|
|
||||||
|
echo "<strong>$file:$line ($class::$function)</strong>" . ";\n";
|
||||||
|
/* $log_show_level = isset($show_level) ? $show_level : '?'; */
|
||||||
|
/* echo ' L' . $level . "({$log_level}/{$log_show_level})" . ";\n"; */
|
||||||
|
echo ' L' . $level . ";\n";
|
||||||
|
echo ' <A HREF="#" onclick="$' . "('#{$pr_trace_id}').slideToggle(); return false;" . '">stack</A>'.";\n";
|
||||||
|
|
||||||
|
echo " this ";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('#{$pr_output_id}').slideToggle(); return false;" . '">t</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('#{$pr_id}').hide(); return false;" . '">n</A>'.";\n";
|
||||||
|
|
||||||
|
echo " $class ";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_output_class_class}').slideDown(); return false;" . '">s</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_output_class_class}').slideUp(); return false;" . '">h</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_entire_class_class}').hide(); return false;" . '">n</A>'.";\n";
|
||||||
|
|
||||||
|
echo " $function ";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_output_function_class}').slideDown(); return false;" . '">s</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_output_function_class}').slideUp(); return false;" . '">h</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_entire_function_class}').hide(); return false;" . '">n</A>'.";\n";
|
||||||
|
|
||||||
|
echo " all ";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_output_base_class}').show(); return false;" . '">s</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_output_base_class}').hide(); return false;" . '">h</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_entire_base_class}').hide(); return false;" . '">n</A>'."\n";
|
||||||
|
|
||||||
|
echo '</DIV>' . "\n"; // End pr_header_class
|
||||||
|
|
||||||
|
if (isset($show_level) && $level > $show_level)
|
||||||
|
$display = 'none';
|
||||||
|
else
|
||||||
|
$display = 'block';
|
||||||
|
|
||||||
|
echo '<DIV class="'.$pr_output_class.'" id="'.$pr_output_id.'" style="display:'.$display.';">'."\n";
|
||||||
|
pr($mixed, false, false);
|
||||||
|
echo '</DIV>' . "\n"; // End pr_output_class
|
||||||
|
echo '</DIV>' . "\n"; // End pr_entire_class
|
||||||
|
}
|
||||||
|
|
||||||
|
function pr($level, $mixed, $checkpoint = null) {
|
||||||
|
$this->_pr($level, $mixed, $checkpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
function prEnter($args, $level = 15) {
|
||||||
|
$this->_pr($level, $args, 'Function Entry');
|
||||||
|
}
|
||||||
|
|
||||||
|
function prReturn($retval, $level = 16) {
|
||||||
|
$this->_pr($level, $retval, 'Function Return');
|
||||||
|
return $retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: queryInit
|
||||||
|
* - Initializes the query fields
|
||||||
|
*/
|
||||||
|
function prDump($all = false) {
|
||||||
|
$vars = get_object_vars($this);
|
||||||
|
foreach (array_keys($vars) AS $name) {
|
||||||
|
if (preg_match("/^[A-Z]/", $name))
|
||||||
|
unset($vars[$name]);
|
||||||
|
if (preg_match("/^_/", $name) && !$all)
|
||||||
|
unset($vars[$name]);
|
||||||
|
}
|
||||||
|
pr($vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Enum Values
|
||||||
|
* Snippet v0.1.3
|
||||||
|
* http://cakeforge.org/snippet/detail.php?type=snippet&id=112
|
||||||
|
*
|
||||||
|
* Gets the enum values for MySQL 4 and 5 to use in selectTag()
|
||||||
|
*/
|
||||||
|
function getEnumValues($columnName=null, $tableName=null)
|
||||||
|
{
|
||||||
|
if ($columnName==null) { return array(); } //no field specified
|
||||||
|
|
||||||
|
if (!isset($tableName)) {
|
||||||
|
//Get the name of the table
|
||||||
|
$db =& ConnectionManager::getDataSource($this->useDbConfig);
|
||||||
|
$tableName = $db->fullTableName($this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the values for the specified column (database and version specific, needs testing)
|
||||||
|
$result = $this->query("SHOW COLUMNS FROM {$tableName} LIKE '{$columnName}'");
|
||||||
|
|
||||||
|
//figure out where in the result our Types are (this varies between mysql versions)
|
||||||
|
$types = null;
|
||||||
|
if ( isset( $result[0]['COLUMNS']['Type'] ) ) { //MySQL 5
|
||||||
|
$types = $result[0]['COLUMNS']['Type']; $default = $result[0]['COLUMNS']['Default'];
|
||||||
|
}
|
||||||
|
elseif ( isset( $result[0][0]['Type'] ) ) { //MySQL 4
|
||||||
|
$types = $result[0][0]['Type']; $default = $result[0][0]['Default'];
|
||||||
|
}
|
||||||
|
else { //types return not accounted for
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the values
|
||||||
|
return array_flip(array_merge(array(''), // MySQL sets 0 to be the empty string
|
||||||
|
explode("','", strtoupper(preg_replace("/(enum)\('(.+?)'\)/","\\2", $types)))
|
||||||
|
));
|
||||||
|
} //end getEnumValues
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: queryInit
|
||||||
|
* - Initializes the query fields
|
||||||
|
*/
|
||||||
|
function queryInit(&$query, $link = true) {
|
||||||
|
if (!isset($query))
|
||||||
|
$query = array();
|
||||||
|
if (!isset($query['conditions']))
|
||||||
|
$query['conditions'] = array();
|
||||||
|
if (!isset($query['group']))
|
||||||
|
$query['group'] = null;
|
||||||
|
if (!isset($query['fields']))
|
||||||
|
$query['fields'] = null;
|
||||||
|
if ($link && !isset($query['link']))
|
||||||
|
$query['link'] = array();
|
||||||
|
if (!$link && !isset($query['contain']))
|
||||||
|
$query['contain'] = array();
|
||||||
|
|
||||||
|
// In case caller expects query to come back
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: nameToID
|
||||||
|
* - Returns the ID of the named item
|
||||||
|
*/
|
||||||
|
function nameToID($name) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$item = $this->find('first', array
|
||||||
|
('recursive' => -1,
|
||||||
|
'conditions' => compact('name'),
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
if ($item) {
|
||||||
|
$item = current($item);
|
||||||
|
return $item['id'];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: statMerge
|
||||||
|
* - Merges summary data from $b into $a
|
||||||
|
*/
|
||||||
|
|
||||||
|
function statsMerge (&$a, $b) {
|
||||||
|
if (!isset($b))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!isset($a)) {
|
||||||
|
$a = $b;
|
||||||
|
}
|
||||||
|
elseif (!is_array($a) && !is_array($b)) {
|
||||||
|
$a += $b;
|
||||||
|
}
|
||||||
|
elseif (is_array($a) && is_array($b)) {
|
||||||
|
foreach (array_intersect_key($a, $b) AS $k => $v)
|
||||||
|
{
|
||||||
|
if (preg_match("/^sp\./", $k))
|
||||||
|
$a[$k] .= '; ' . $b[$k];
|
||||||
|
else
|
||||||
|
$this->statsMerge($a[$k], $b[$k]);
|
||||||
|
}
|
||||||
|
$a = array_merge($a, array_diff_key($b, $a));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die ("Can't yet merge array and non-array stats");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function filter_null($array) {
|
||||||
|
return array_diff_key($array, array_filter($array, 'is_null'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function recursive_array_replace($find, $replace, &$data) {
|
||||||
|
if (!isset($data))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (is_array($data)) {
|
||||||
|
foreach ($data as $key => &$value) {
|
||||||
|
$this->recursive_array_replace($find, $replace, $value);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($replace))
|
||||||
|
$data = preg_replace($find, $replace, $data);
|
||||||
|
elseif (preg_match($find, $data))
|
||||||
|
$data = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function beforeSave() {
|
||||||
|
/* pr(array('class' => $this->name, */
|
||||||
|
/* 'alias' => $this->alias, */
|
||||||
|
/* 'function' => 'AppModel::beforeSave')); */
|
||||||
|
|
||||||
|
// Replace all empty strings with NULL.
|
||||||
|
// If a particular model doesn't like this, they'll have to
|
||||||
|
// override the behavior, or set useNullForEmpty to false.
|
||||||
|
if ($this->useNullForEmpty)
|
||||||
|
$this->recursive_array_replace("/^\s*$/", null, $this->data);
|
||||||
|
|
||||||
|
if ($this->formatDateFields) {
|
||||||
|
$alias = $this->alias;
|
||||||
|
|
||||||
|
foreach ($this->_schema AS $field => $info) {
|
||||||
|
if ($info['type'] == 'date' || $info['type'] == 'timestamp') {
|
||||||
|
if (isset($this->data[$alias][$field])) {
|
||||||
|
/* pr("Fix Date for '$alias'.'$field'; current value = " . */
|
||||||
|
/* "'{$this->data[$alias][$field]}'"); */
|
||||||
|
if ($this->data[$alias][$field] === 'CURRENT_TIMESTAMP')
|
||||||
|
// Seems CakePHP is broken for the default timestamp.
|
||||||
|
// It tries to automagically set the value to CURRENT_TIMESTAMP
|
||||||
|
// which is wholly rejected by MySQL. Just put it back to NULL
|
||||||
|
// and let the SQL engine deal with the defaults... it's not
|
||||||
|
// Cake's place to do this anyway :-/
|
||||||
|
$this->data[$alias][$field] = null;
|
||||||
|
else
|
||||||
|
$this->data[$alias][$field] =
|
||||||
|
$this->dateFormatBeforeSave($this->data[$alias][$field]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: dateFormatBeforeSave
|
||||||
|
* - convert dates to database format
|
||||||
|
*/
|
||||||
|
|
||||||
|
function dateFormatBeforeSave($dateString) {
|
||||||
|
/* $time = ''; */
|
||||||
|
/* if (preg_match('/(\d+(:\d+))/', $dateString, $match)) */
|
||||||
|
/* $time = ' '.$match[1]; */
|
||||||
|
/* $dateString = preg_replace('/(\d+(:\d+))/', '', $dateString); */
|
||||||
|
/* return date('Y-m-d', strtotime($dateString)) . $time; */
|
||||||
|
|
||||||
|
if (preg_match('/:/', $dateString))
|
||||||
|
return date('Y-m-d H:i:s', strtotime($dateString));
|
||||||
|
else
|
||||||
|
return date('Y-m-d', strtotime($dateString));
|
||||||
|
}
|
||||||
|
|
||||||
|
function INTERNAL_ERROR($msg, $depth = 0) {
|
||||||
|
INTERNAL_ERROR($msg, false, $depth+1);
|
||||||
|
echo $this->requestAction(array('controller' => 'accounts',
|
||||||
|
'action' => 'render_empty'),
|
||||||
|
array('return', 'bare' => false)
|
||||||
|
);
|
||||||
|
$this->_stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
74
config/acl.ini.php
Normal file
74
config/acl.ini.php
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
;<?php die() ?>
|
||||||
|
; SVN FILE: $Id: acl.ini.php 7945 2008-12-19 02:16:01Z gwoo $
|
||||||
|
;/**
|
||||||
|
; * Short description for file.
|
||||||
|
; *
|
||||||
|
; *
|
||||||
|
; * PHP versions 4 and 5
|
||||||
|
; *
|
||||||
|
; * CakePHP(tm) : Rapid Development Framework http://www.cakephp.org/
|
||||||
|
; * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
; *
|
||||||
|
; * Licensed under The MIT License
|
||||||
|
; * Redistributions of files must retain the above copyright notice.
|
||||||
|
; *
|
||||||
|
; * @filesource
|
||||||
|
; * @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
; * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
; * @package cake
|
||||||
|
; * @subpackage cake.app.config
|
||||||
|
; * @since CakePHP(tm) v 0.10.0.1076
|
||||||
|
; * @version $Revision: 7945 $
|
||||||
|
; * @modifiedby $LastChangedBy: gwoo $
|
||||||
|
; * @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
; * @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
; */
|
||||||
|
|
||||||
|
; acl.ini.php - Cake ACL Configuration
|
||||||
|
; ---------------------------------------------------------------------
|
||||||
|
; Use this file to specify user permissions.
|
||||||
|
; aco = access control object (something in your application)
|
||||||
|
; aro = access request object (something requesting access)
|
||||||
|
;
|
||||||
|
; User records are added as follows:
|
||||||
|
;
|
||||||
|
; [uid]
|
||||||
|
; groups = group1, group2, group3
|
||||||
|
; allow = aco1, aco2, aco3
|
||||||
|
; deny = aco4, aco5, aco6
|
||||||
|
;
|
||||||
|
; Group records are added in a similar manner:
|
||||||
|
;
|
||||||
|
; [gid]
|
||||||
|
; allow = aco1, aco2, aco3
|
||||||
|
; deny = aco4, aco5, aco6
|
||||||
|
;
|
||||||
|
; The allow, deny, and groups sections are all optional.
|
||||||
|
; NOTE: groups names *cannot* ever be the same as usernames!
|
||||||
|
;
|
||||||
|
; ACL permissions are checked in the following order:
|
||||||
|
; 1. Check for user denies (and DENY if specified)
|
||||||
|
; 2. Check for user allows (and ALLOW if specified)
|
||||||
|
; 3. Gather user's groups
|
||||||
|
; 4. Check group denies (and DENY if specified)
|
||||||
|
; 5. Check group allows (and ALLOW if specified)
|
||||||
|
; 6. If no aro, aco, or group information is found, DENY
|
||||||
|
;
|
||||||
|
; ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
;-------------------------------------
|
||||||
|
;Users
|
||||||
|
;-------------------------------------
|
||||||
|
|
||||||
|
[username-goes-here]
|
||||||
|
groups = group1, group2
|
||||||
|
deny = aco1, aco2
|
||||||
|
allow = aco3, aco4
|
||||||
|
|
||||||
|
;-------------------------------------
|
||||||
|
;Groups
|
||||||
|
;-------------------------------------
|
||||||
|
|
||||||
|
[groupname-goes-here]
|
||||||
|
deny = aco5, aco6
|
||||||
|
allow = aco7, aco8
|
||||||
84
config/bootstrap.php
Normal file
84
config/bootstrap.php
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: bootstrap.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||||
|
/**
|
||||||
|
* Short description for file.
|
||||||
|
*
|
||||||
|
* Long description for file
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app.config
|
||||||
|
* @since CakePHP(tm) v 0.10.8.2117
|
||||||
|
* @version $Revision: 7945 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This file is loaded automatically by the app/webroot/index.php file after the core bootstrap.php is loaded
|
||||||
|
* This is an application wide file to load any function that is not used within a class define.
|
||||||
|
* You can also use this to include or require any files in your application.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
function INTERNAL_ERROR($message, $exit = true, $drop = 0) {
|
||||||
|
echo '<DIV class="internal-error" style="color:#000; background:#c22; padding:0.5em 1.5em 0.5em 1.5em;">' . "\n";
|
||||||
|
echo '<H1 style="color:#000; margin-bottom:0.2em; font-size:2em;">INTERNAL ERROR:</H1>' . "\n";
|
||||||
|
echo '<H2 style="color:#000; margin-top:0; margin-left:1.5em; font-size:1.5em">' . $message . '</H2>' . "\n";
|
||||||
|
echo '<H4 style="color:#000;">This error was not caused by anything that you did wrong.' . "\n";
|
||||||
|
echo '<BR>It is a problem within the application itself and should be reported to the administrator.</H4>' . "\n";
|
||||||
|
|
||||||
|
// Print out the entire stack trace
|
||||||
|
echo '<HR style="margin-top:1.0em; margin-bottom:0.5em;">' . "\nStack Trace:\n";
|
||||||
|
echo '<OL style="margin-left:1.5em";>' . "\n";
|
||||||
|
$trace = array_slice(debug_backtrace(false), $drop);
|
||||||
|
for ($i = 0; $i < count($trace); ++$i) {
|
||||||
|
$bline = $trace[$i]['line'];
|
||||||
|
$bfile = $trace[$i]['file'];
|
||||||
|
$bfile = str_replace(ROOT.DS, '', $bfile);
|
||||||
|
$bfile = str_replace(CAKE_CORE_INCLUDE_PATH.DS, '', $bfile);
|
||||||
|
|
||||||
|
if ($i < count($trace)-1) {
|
||||||
|
$bfunc = $trace[$i+1]['function'];
|
||||||
|
$bclas = $trace[$i+1]['class'];
|
||||||
|
} else {
|
||||||
|
$bfunc = null;
|
||||||
|
$bclas = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo("<LI>$bfile:$bline (" . ($bclas ? "$bclas::$bfunc" : "entry point") . ")</LI>\n");
|
||||||
|
}
|
||||||
|
echo "</OL>\n";
|
||||||
|
|
||||||
|
echo '<HR style="margin-top:1.0em; margin-bottom:0.5em;">' . "\nHTTP Request:\n";
|
||||||
|
echo '<P><PRE style="color:#000; background:#c22;">' . "\n";
|
||||||
|
print_r($_REQUEST);
|
||||||
|
echo "\n</PRE>\n";
|
||||||
|
|
||||||
|
echo '</DIV>';
|
||||||
|
if ($exit)
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The settings below can be used to set additional paths to models, views and controllers.
|
||||||
|
* This is related to Ticket #470 (https://trac.cakephp.org/ticket/470)
|
||||||
|
*
|
||||||
|
* $modelPaths = array('full path to models', 'second full path to models', 'etc...');
|
||||||
|
* $viewPaths = array('this path to views', 'second full path to views', 'etc...');
|
||||||
|
* $controllerPaths = array('this path to controllers', 'second full path to controllers', 'etc...');
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//EOF
|
||||||
|
?>
|
||||||
227
config/core.php
Normal file
227
config/core.php
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: core.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||||
|
/**
|
||||||
|
* This is core configuration file.
|
||||||
|
*
|
||||||
|
* Use it to configure core behavior of Cake.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app.config
|
||||||
|
* @since CakePHP(tm) v 0.2.9
|
||||||
|
* @version $Revision: 7945 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* CakePHP Debug Level:
|
||||||
|
*
|
||||||
|
* Production Mode:
|
||||||
|
* 0: No error messages, errors, or warnings shown. Flash messages redirect.
|
||||||
|
*
|
||||||
|
* Development Mode:
|
||||||
|
* 1: Errors and warnings shown, model caches refreshed, flash messages halted.
|
||||||
|
* 2: As in 1, but also with full debug messages and SQL output.
|
||||||
|
* 3: As in 2, but also with full controller dump.
|
||||||
|
*
|
||||||
|
* In production mode, flash messages redirect after a time interval.
|
||||||
|
* In development mode, you need to click the flash message to continue.
|
||||||
|
*/
|
||||||
|
Configure::write('debug', 2);
|
||||||
|
/**
|
||||||
|
* Application wide charset encoding
|
||||||
|
*/
|
||||||
|
Configure::write('App.encoding', 'UTF-8');
|
||||||
|
/**
|
||||||
|
* To configure CakePHP *not* to use mod_rewrite and to
|
||||||
|
* use CakePHP pretty URLs, remove these .htaccess
|
||||||
|
* files:
|
||||||
|
*
|
||||||
|
* /.htaccess
|
||||||
|
* /app/.htaccess
|
||||||
|
* /app/webroot/.htaccess
|
||||||
|
*
|
||||||
|
* And uncomment the App.baseUrl below:
|
||||||
|
*/
|
||||||
|
//Configure::write('App.baseUrl', env('SCRIPT_NAME'));
|
||||||
|
/**
|
||||||
|
* Uncomment the define below to use CakePHP admin routes.
|
||||||
|
*
|
||||||
|
* The value of the define determines the name of the route
|
||||||
|
* and its associated controller actions:
|
||||||
|
*
|
||||||
|
* 'admin' -> admin_index() and /admin/controller/index
|
||||||
|
* 'superuser' -> superuser_index() and /superuser/controller/index
|
||||||
|
*/
|
||||||
|
//Configure::write('Routing.admin', 'admin');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn off all caching application-wide.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//Configure::write('Cache.disable', true);
|
||||||
|
/**
|
||||||
|
* Enable cache checking.
|
||||||
|
*
|
||||||
|
* If set to true, for view caching you must still use the controller
|
||||||
|
* var $cacheAction inside your controllers to define caching settings.
|
||||||
|
* You can either set it controller-wide by setting var $cacheAction = true,
|
||||||
|
* or in each action using $this->cacheAction = true.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//Configure::write('Cache.check', true);
|
||||||
|
/**
|
||||||
|
* Defines the default error type when using the log() function. Used for
|
||||||
|
* differentiating error logging and debugging. Currently PHP supports LOG_DEBUG.
|
||||||
|
*/
|
||||||
|
define('LOG_ERROR', 2);
|
||||||
|
/**
|
||||||
|
* The preferred session handling method. Valid values:
|
||||||
|
*
|
||||||
|
* 'php' Uses settings defined in your php.ini.
|
||||||
|
* 'cake' Saves session files in CakePHP's /tmp directory.
|
||||||
|
* 'database' Uses CakePHP's database sessions.
|
||||||
|
*
|
||||||
|
* To define a custom session handler, save it at /app/config/<name>.php.
|
||||||
|
* Set the value of 'Session.save' to <name> to utilize it in CakePHP.
|
||||||
|
*
|
||||||
|
* To use database sessions, execute the SQL file found at /app/config/sql/sessions.sql.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Configure::write('Session.save', 'php');
|
||||||
|
/**
|
||||||
|
* The name of the table used to store CakePHP database sessions.
|
||||||
|
*
|
||||||
|
* 'Session.save' must be set to 'database' in order to utilize this constant.
|
||||||
|
*
|
||||||
|
* The table name set here should *not* include any table prefix defined elsewhere.
|
||||||
|
*/
|
||||||
|
//Configure::write('Session.table', 'cake_sessions');
|
||||||
|
/**
|
||||||
|
* The DATABASE_CONFIG::$var to use for database session handling.
|
||||||
|
*
|
||||||
|
* 'Session.save' must be set to 'database' in order to utilize this constant.
|
||||||
|
*/
|
||||||
|
//Configure::write('Session.database', 'default');
|
||||||
|
/**
|
||||||
|
* The name of CakePHP's session cookie.
|
||||||
|
*/
|
||||||
|
Configure::write('Session.cookie', 'CAKEPHP');
|
||||||
|
/**
|
||||||
|
* Session time out time (in seconds).
|
||||||
|
* Actual value depends on 'Security.level' setting.
|
||||||
|
*/
|
||||||
|
Configure::write('Session.timeout', '120');
|
||||||
|
/**
|
||||||
|
* If set to false, sessions are not automatically started.
|
||||||
|
*/
|
||||||
|
Configure::write('Session.start', true);
|
||||||
|
/**
|
||||||
|
* When set to false, HTTP_USER_AGENT will not be checked
|
||||||
|
* in the session
|
||||||
|
*/
|
||||||
|
Configure::write('Session.checkAgent', true);
|
||||||
|
/**
|
||||||
|
* The level of CakePHP security. The session timeout time defined
|
||||||
|
* in 'Session.timeout' is multiplied according to the settings here.
|
||||||
|
* Valid values:
|
||||||
|
*
|
||||||
|
* 'high' Session timeout in 'Session.timeout' x 10
|
||||||
|
* 'medium' Session timeout in 'Session.timeout' x 100
|
||||||
|
* 'low' Session timeout in 'Session.timeout' x 300
|
||||||
|
*
|
||||||
|
* CakePHP session IDs are also regenerated between requests if
|
||||||
|
* 'Security.level' is set to 'high'.
|
||||||
|
*/
|
||||||
|
Configure::write('Security.level', 'high');
|
||||||
|
/**
|
||||||
|
* A random string used in security hashing methods.
|
||||||
|
*/
|
||||||
|
Configure::write('Security.salt', 'fbd497077ac32a7ab159333cd7e3eeb85db5c2a5');
|
||||||
|
/**
|
||||||
|
* Compress CSS output by removing comments, whitespace, repeating tags, etc.
|
||||||
|
* This requires a/var/cache directory to be writable by the web server for caching.
|
||||||
|
* and /vendors/csspp/csspp.php
|
||||||
|
*
|
||||||
|
* To use, prefix the CSS link URL with '/ccss/' instead of '/css/' or use HtmlHelper::css().
|
||||||
|
*/
|
||||||
|
//Configure::write('Asset.filter.css', 'css.php');
|
||||||
|
/**
|
||||||
|
* Plug in your own custom JavaScript compressor by dropping a script in your webroot to handle the
|
||||||
|
* output, and setting the config below to the name of the script.
|
||||||
|
*
|
||||||
|
* To use, prefix your JavaScript link URLs with '/cjs/' instead of '/js/' or use JavaScriptHelper::link().
|
||||||
|
*/
|
||||||
|
//Configure::write('Asset.filter.js', 'custom_javascript_output_filter.php');
|
||||||
|
/**
|
||||||
|
* The classname and database used in CakePHP's
|
||||||
|
* access control lists.
|
||||||
|
*/
|
||||||
|
Configure::write('Acl.classname', 'DbAcl');
|
||||||
|
Configure::write('Acl.database', 'default');
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Cache Engine Configuration
|
||||||
|
* Default settings provided below
|
||||||
|
*
|
||||||
|
* File storage engine.
|
||||||
|
*
|
||||||
|
* Cache::config('default', array(
|
||||||
|
* 'engine' => 'File', //[required]
|
||||||
|
* 'duration'=> 3600, //[optional]
|
||||||
|
* 'probability'=> 100, //[optional]
|
||||||
|
* 'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path
|
||||||
|
* 'prefix' => 'cake_', //[optional] prefix every cache file with this string
|
||||||
|
* 'lock' => false, //[optional] use file locking
|
||||||
|
* 'serialize' => true, [optional]
|
||||||
|
* ));
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* APC (http://pecl.php.net/package/APC)
|
||||||
|
*
|
||||||
|
* Cache::config('default', array(
|
||||||
|
* 'engine' => 'Apc', //[required]
|
||||||
|
* 'duration'=> 3600, //[optional]
|
||||||
|
* 'probability'=> 100, //[optional]
|
||||||
|
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
|
||||||
|
* ));
|
||||||
|
*
|
||||||
|
* Xcache (http://xcache.lighttpd.net/)
|
||||||
|
*
|
||||||
|
* Cache::config('default', array(
|
||||||
|
* 'engine' => 'Xcache', //[required]
|
||||||
|
* 'duration'=> 3600, //[optional]
|
||||||
|
* 'probability'=> 100, //[optional]
|
||||||
|
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
|
||||||
|
* 'user' => 'user', //user from xcache.admin.user settings
|
||||||
|
* 'password' => 'password', //plaintext password (xcache.admin.pass)
|
||||||
|
* ));
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Memcache (http://www.danga.com/memcached/)
|
||||||
|
*
|
||||||
|
* Cache::config('default', array(
|
||||||
|
* 'engine' => 'Memcache', //[required]
|
||||||
|
* 'duration'=> 3600, //[optional]
|
||||||
|
* 'probability'=> 100, //[optional]
|
||||||
|
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
|
||||||
|
* 'servers' => array(
|
||||||
|
* '127.0.0.1:11211' // localhost, default port 11211
|
||||||
|
* ), //[optional]
|
||||||
|
* 'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory)
|
||||||
|
* ));
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Cache::config('default', array('engine' => 'File'));
|
||||||
|
?>
|
||||||
14
config/database.php
Normal file
14
config/database.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
class DATABASE_CONFIG {
|
||||||
|
|
||||||
|
var $default = array(
|
||||||
|
'driver' => 'mysql',
|
||||||
|
'persistent' => false,
|
||||||
|
'host' => 'localhost',
|
||||||
|
'login' => 'pmgr',
|
||||||
|
'password' => 'pmgruser',
|
||||||
|
'database' => 'property_manager',
|
||||||
|
'prefix' => 'pmgr_',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
?>
|
||||||
101
config/database.php.default
Normal file
101
config/database.php.default
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: database.php.default 8004 2009-01-16 20:15:21Z gwoo $ */
|
||||||
|
/**
|
||||||
|
* This is core configuration file.
|
||||||
|
*
|
||||||
|
* Use it to configure core behaviour ofCake.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app.config
|
||||||
|
* @since CakePHP(tm) v 0.2.9
|
||||||
|
* @version $Revision: 8004 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2009-01-16 12:15:21 -0800 (Fri, 16 Jan 2009) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* In this file you set up your database connection details.
|
||||||
|
*
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.config
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Database configuration class.
|
||||||
|
* You can specify multiple configurations for production, development and testing.
|
||||||
|
*
|
||||||
|
* driver => The name of a supported driver; valid options are as follows:
|
||||||
|
* mysql - MySQL 4 & 5,
|
||||||
|
* mysqli - MySQL 4 & 5 Improved Interface (PHP5 only),
|
||||||
|
* sqlite - SQLite (PHP5 only),
|
||||||
|
* postgres - PostgreSQL 7 and higher,
|
||||||
|
* mssql - Microsoft SQL Server 2000 and higher,
|
||||||
|
* db2 - IBM DB2, Cloudscape, and Apache Derby (http://php.net/ibm-db2)
|
||||||
|
* oracle - Oracle 8 and higher
|
||||||
|
* firebird - Firebird/Interbase
|
||||||
|
* sybase - Sybase ASE
|
||||||
|
* adodb-[drivername] - ADOdb interface wrapper (see below),
|
||||||
|
* odbc - ODBC DBO driver
|
||||||
|
*
|
||||||
|
* You can add custom database drivers (or override existing drivers) by adding the
|
||||||
|
* appropriate file to app/models/datasources/dbo. Drivers should be named 'dbo_x.php',
|
||||||
|
* where 'x' is the name of the database.
|
||||||
|
*
|
||||||
|
* persistent => true / false
|
||||||
|
* Determines whether or not the database should use a persistent connection
|
||||||
|
*
|
||||||
|
* connect =>
|
||||||
|
* ADOdb set the connect to one of these
|
||||||
|
* (http://phplens.com/adodb/supported.databases.html) and
|
||||||
|
* append it '|p' for persistent connection. (mssql|p for example, or just mssql for not persistent)
|
||||||
|
* For all other databases, this setting is deprecated.
|
||||||
|
*
|
||||||
|
* host =>
|
||||||
|
* the host you connect to the database. To add a socket or port number, use 'port' => #
|
||||||
|
*
|
||||||
|
* prefix =>
|
||||||
|
* Uses the given prefix for all the tables in this database. This setting can be overridden
|
||||||
|
* on a per-table basis with the Model::$tablePrefix property.
|
||||||
|
*
|
||||||
|
* schema =>
|
||||||
|
* For Postgres and DB2, specifies which schema you would like to use the tables in. Postgres defaults to
|
||||||
|
* 'public', DB2 defaults to empty.
|
||||||
|
*
|
||||||
|
* encoding =>
|
||||||
|
* For MySQL, MySQLi, Postgres and DB2, specifies the character encoding to use when connecting to the
|
||||||
|
* database. Uses database default.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class DATABASE_CONFIG {
|
||||||
|
|
||||||
|
var $default = array(
|
||||||
|
'driver' => 'mysql',
|
||||||
|
'persistent' => false,
|
||||||
|
'host' => 'localhost',
|
||||||
|
'login' => 'user',
|
||||||
|
'password' => 'password',
|
||||||
|
'database' => 'database_name',
|
||||||
|
'prefix' => '',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $test = array(
|
||||||
|
'driver' => 'mysql',
|
||||||
|
'persistent' => false,
|
||||||
|
'host' => 'localhost',
|
||||||
|
'login' => 'user',
|
||||||
|
'password' => 'password',
|
||||||
|
'database' => 'test_database_name',
|
||||||
|
'prefix' => '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
?>
|
||||||
70
config/inflections.php
Normal file
70
config/inflections.php
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: inflections.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||||
|
/**
|
||||||
|
* Custom Inflected Words.
|
||||||
|
*
|
||||||
|
* This file is used to hold words that are not matched in the normail Inflector::pluralize() and
|
||||||
|
* Inflector::singularize()
|
||||||
|
*
|
||||||
|
* PHP versions 4 and %
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app.config
|
||||||
|
* @since CakePHP(tm) v 1.0.0.2312
|
||||||
|
* @version $Revision: 7945 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* This is a key => value array of regex used to match words.
|
||||||
|
* If key matches then the value is returned.
|
||||||
|
*
|
||||||
|
* $pluralRules = array('/(s)tatus$/i' => '\1\2tatuses', '/^(ox)$/i' => '\1\2en', '/([m|l])ouse$/i' => '\1ice');
|
||||||
|
*/
|
||||||
|
$pluralRules = array();
|
||||||
|
/**
|
||||||
|
* This is a key only array of plural words that should not be inflected.
|
||||||
|
* Notice the last comma
|
||||||
|
*
|
||||||
|
* $uninflectedPlural = array('.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox');
|
||||||
|
*/
|
||||||
|
$uninflectedPlural = array('.*cash');
|
||||||
|
/**
|
||||||
|
* This is a key => value array of plural irregular words.
|
||||||
|
* If key matches then the value is returned.
|
||||||
|
*
|
||||||
|
* $irregularPlural = array('atlas' => 'atlases', 'beef' => 'beefs', 'brother' => 'brothers')
|
||||||
|
*/
|
||||||
|
$irregularPlural = array();
|
||||||
|
/**
|
||||||
|
* This is a key => value array of regex used to match words.
|
||||||
|
* If key matches then the value is returned.
|
||||||
|
*
|
||||||
|
* $singularRules = array('/(s)tatuses$/i' => '\1\2tatus', '/(matr)ices$/i' =>'\1ix','/(vert|ind)ices$/i')
|
||||||
|
*/
|
||||||
|
$singularRules = array();
|
||||||
|
/**
|
||||||
|
* This is a key only array of singular words that should not be inflected.
|
||||||
|
* You should not have to change this value below if you do change it use same format
|
||||||
|
* as the $uninflectedPlural above.
|
||||||
|
*/
|
||||||
|
$uninflectedSingular = $uninflectedPlural;
|
||||||
|
/**
|
||||||
|
* This is a key => value array of singular irregular words.
|
||||||
|
* Most of the time this will be a reverse of the above $irregularPlural array
|
||||||
|
* You should not have to change this value below if you do change it use same format
|
||||||
|
*
|
||||||
|
* $irregularSingular = array('atlases' => 'atlas', 'beefs' => 'beef', 'brothers' => 'brother')
|
||||||
|
*/
|
||||||
|
$irregularSingular = array_flip($irregularPlural);
|
||||||
|
?>
|
||||||
55
config/routes.php
Normal file
55
config/routes.php
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: routes.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||||
|
/**
|
||||||
|
* Short description for file.
|
||||||
|
*
|
||||||
|
* In this file, you set up routes to your controllers and their actions.
|
||||||
|
* Routes are very important mechanism that allows you to freely connect
|
||||||
|
* different urls to chosen controllers and their actions (functions).
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app.config
|
||||||
|
* @since CakePHP(tm) v 0.2.9
|
||||||
|
* @version $Revision: 7945 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
$default_path = array('controller' => 'maps', 'action' => 'view', '1');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Here, we are connecting '/' (base path) to our site map.
|
||||||
|
* It's hardcoded to map #1, but at some point we'll implement
|
||||||
|
* a login mechanism and the default path will be to log on instead.
|
||||||
|
*/
|
||||||
|
Router::connect('/', $default_path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Route for admin functionality
|
||||||
|
*/
|
||||||
|
Router::connect('/admin',
|
||||||
|
array('admin_route' => true) + $default_path);
|
||||||
|
Router::connect('/admin/:controller/:action/*',
|
||||||
|
array('admin_route' => true, 'action' => null));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Route for development functionality
|
||||||
|
*/
|
||||||
|
Router::connect('/dev',
|
||||||
|
array('dev_route' => true) + $default_path);
|
||||||
|
Router::connect('/dev/:controller/:action/*',
|
||||||
|
array('dev_route' => true, 'action' => null));
|
||||||
|
|
||||||
|
?>
|
||||||
79
config/sql/db_acl.php
Normal file
79
config/sql/db_acl.php
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: db_acl.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||||
|
/*DbAcl schema generated on: 2007-11-24 15:11:13 : 1195945453*/
|
||||||
|
/**
|
||||||
|
* This is Acl Schema file
|
||||||
|
*
|
||||||
|
* Use it to configure database for ACL
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app.config.sql
|
||||||
|
* @since CakePHP(tm) v 0.2.9
|
||||||
|
* @version $Revision: 7945 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Using the Schema command line utility
|
||||||
|
* cake schema run create DbAcl
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class DbAclSchema extends CakeSchema {
|
||||||
|
|
||||||
|
var $name = 'DbAcl';
|
||||||
|
|
||||||
|
function before($event = array()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function after($event = array()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
var $acos = array(
|
||||||
|
'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 10, 'key' => 'primary'),
|
||||||
|
'parent_id' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||||
|
'model' => array('type'=>'string', 'null' => true),
|
||||||
|
'foreign_key' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||||
|
'alias' => array('type'=>'string', 'null' => true),
|
||||||
|
'lft' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||||
|
'rght' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||||
|
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1))
|
||||||
|
);
|
||||||
|
|
||||||
|
var $aros = array(
|
||||||
|
'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 10, 'key' => 'primary'),
|
||||||
|
'parent_id' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||||
|
'model' => array('type'=>'string', 'null' => true),
|
||||||
|
'foreign_key' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||||
|
'alias' => array('type'=>'string', 'null' => true),
|
||||||
|
'lft' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||||
|
'rght' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||||
|
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1))
|
||||||
|
);
|
||||||
|
|
||||||
|
var $aros_acos = array(
|
||||||
|
'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 10, 'key' => 'primary'),
|
||||||
|
'aro_id' => array('type'=>'integer', 'null' => false, 'length' => 10, 'key' => 'index'),
|
||||||
|
'aco_id' => array('type'=>'integer', 'null' => false, 'length' => 10),
|
||||||
|
'_create' => array('type'=>'string', 'null' => false, 'default' => '0', 'length' => 2),
|
||||||
|
'_read' => array('type'=>'string', 'null' => false, 'default' => '0', 'length' => 2),
|
||||||
|
'_update' => array('type'=>'string', 'null' => false, 'default' => '0', 'length' => 2),
|
||||||
|
'_delete' => array('type'=>'string', 'null' => false, 'default' => '0', 'length' => 2),
|
||||||
|
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'ARO_ACO_KEY' => array('column' => array('aro_id', 'aco_id'), 'unique' => 1))
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
40
config/sql/db_acl.sql
Normal file
40
config/sql/db_acl.sql
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# $Id: db_acl.sql 7945 2008-12-19 02:16:01Z gwoo $
|
||||||
|
#
|
||||||
|
# Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under The MIT License
|
||||||
|
# Redistributions of files must retain the above copyright notice.
|
||||||
|
# http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
|
||||||
|
CREATE TABLE acos (
|
||||||
|
id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
parent_id INTEGER(10) DEFAULT NULL,
|
||||||
|
model VARCHAR(255) DEFAULT '',
|
||||||
|
foreign_key INTEGER(10) UNSIGNED DEFAULT NULL,
|
||||||
|
alias VARCHAR(255) DEFAULT '',
|
||||||
|
lft INTEGER(10) DEFAULT NULL,
|
||||||
|
rght INTEGER(10) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE aros_acos (
|
||||||
|
id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
aro_id INTEGER(10) UNSIGNED NOT NULL,
|
||||||
|
aco_id INTEGER(10) UNSIGNED NOT NULL,
|
||||||
|
_create CHAR(2) NOT NULL DEFAULT 0,
|
||||||
|
_read CHAR(2) NOT NULL DEFAULT 0,
|
||||||
|
_update CHAR(2) NOT NULL DEFAULT 0,
|
||||||
|
_delete CHAR(2) NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE aros (
|
||||||
|
id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
parent_id INTEGER(10) DEFAULT NULL,
|
||||||
|
model VARCHAR(255) DEFAULT '',
|
||||||
|
foreign_key INTEGER(10) UNSIGNED DEFAULT NULL,
|
||||||
|
alias VARCHAR(255) DEFAULT '',
|
||||||
|
lft INTEGER(10) DEFAULT NULL,
|
||||||
|
rght INTEGER(10) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
56
config/sql/i18n.php
Normal file
56
config/sql/i18n.php
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: i18n.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||||
|
/*i18n schema generated on: 2007-11-25 07:11:25 : 1196004805*/
|
||||||
|
/**
|
||||||
|
* This is i18n Schema file
|
||||||
|
*
|
||||||
|
* Use it to configure database for i18n
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app.config.sql
|
||||||
|
* @since CakePHP(tm) v 0.2.9
|
||||||
|
* @version $Revision: 7945 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Using the Schema command line utility
|
||||||
|
* cake schema run create i18n
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class i18nSchema extends CakeSchema {
|
||||||
|
|
||||||
|
var $name = 'i18n';
|
||||||
|
|
||||||
|
function before($event = array()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function after($event = array()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
var $i18n = array(
|
||||||
|
'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 10, 'key' => 'primary'),
|
||||||
|
'locale' => array('type'=>'string', 'null' => false, 'length' => 6, 'key' => 'index'),
|
||||||
|
'model' => array('type'=>'string', 'null' => false, 'key' => 'index'),
|
||||||
|
'foreign_key' => array('type'=>'integer', 'null' => false, 'length' => 10, 'key' => 'index'),
|
||||||
|
'field' => array('type'=>'string', 'null' => false, 'key' => 'index'),
|
||||||
|
'content' => array('type'=>'text', 'null' => true, 'default' => NULL),
|
||||||
|
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'locale' => array('column' => 'locale', 'unique' => 0), 'model' => array('column' => 'model', 'unique' => 0), 'row_id' => array('column' => 'foreign_key', 'unique' => 0), 'field' => array('column' => 'field', 'unique' => 0))
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
26
config/sql/i18n.sql
Normal file
26
config/sql/i18n.sql
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# $Id: i18n.sql 7945 2008-12-19 02:16:01Z gwoo $
|
||||||
|
#
|
||||||
|
# Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under The MIT License
|
||||||
|
# Redistributions of files must retain the above copyright notice.
|
||||||
|
# http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
|
||||||
|
CREATE TABLE i18n (
|
||||||
|
id int(10) NOT NULL auto_increment,
|
||||||
|
locale varchar(6) NOT NULL,
|
||||||
|
model varchar(255) NOT NULL,
|
||||||
|
foreign_key int(10) NOT NULL,
|
||||||
|
field varchar(255) NOT NULL,
|
||||||
|
content mediumtext,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
# UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field),
|
||||||
|
# INDEX I18N_LOCALE_ROW(locale, model, foreign_key),
|
||||||
|
# INDEX I18N_LOCALE_MODEL(locale, model),
|
||||||
|
# INDEX I18N_FIELD(model, foreign_key, field),
|
||||||
|
# INDEX I18N_ROW(model, foreign_key),
|
||||||
|
INDEX locale (locale),
|
||||||
|
INDEX model (model),
|
||||||
|
INDEX row_id (foreign_key),
|
||||||
|
INDEX field (field)
|
||||||
|
);
|
||||||
53
config/sql/sessions.php
Normal file
53
config/sql/sessions.php
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: sessions.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||||
|
/*Sessions schema generated on: 2007-11-25 07:11:54 : 1196004714*/
|
||||||
|
/**
|
||||||
|
* This is Sessions Schema file
|
||||||
|
*
|
||||||
|
* Use it to configure database for Sessions
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app.config.sql
|
||||||
|
* @since CakePHP(tm) v 0.2.9
|
||||||
|
* @version $Revision: 7945 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Using the Schema command line utility
|
||||||
|
* cake schema run create Sessions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class SessionsSchema extends CakeSchema {
|
||||||
|
|
||||||
|
var $name = 'Sessions';
|
||||||
|
|
||||||
|
function before($event = array()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function after($event = array()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
var $cake_sessions = array(
|
||||||
|
'id' => array('type'=>'string', 'null' => false, 'key' => 'primary'),
|
||||||
|
'data' => array('type'=>'text', 'null' => true, 'default' => NULL),
|
||||||
|
'expires' => array('type'=>'integer', 'null' => true, 'default' => NULL),
|
||||||
|
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1))
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
16
config/sql/sessions.sql
Normal file
16
config/sql/sessions.sql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# $Id: sessions.sql 7118 2008-06-04 20:49:29Z gwoo $
|
||||||
|
#
|
||||||
|
# Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||||
|
# 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
# Las Vegas, Nevada 89104
|
||||||
|
#
|
||||||
|
# Licensed under The MIT License
|
||||||
|
# Redistributions of files must retain the above copyright notice.
|
||||||
|
# http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
|
||||||
|
CREATE TABLE cake_sessions (
|
||||||
|
id varchar(255) NOT NULL default '',
|
||||||
|
data text,
|
||||||
|
expires int(11) default NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
204
controllers/accounts_controller.php
Normal file
204
controllers/accounts_controller.php
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class AccountsController extends AppController {
|
||||||
|
|
||||||
|
var $uses = array('Account', 'LedgerEntry');
|
||||||
|
|
||||||
|
var $sidemenu_links =
|
||||||
|
array(array('name' => 'Accounts', 'header' => true),
|
||||||
|
array('name' => 'All', 'url' => array('controller' => 'accounts', 'action' => 'all')),
|
||||||
|
array('name' => 'Asset', 'url' => array('controller' => 'accounts', 'action' => 'asset')),
|
||||||
|
array('name' => 'Liability', 'url' => array('controller' => 'accounts', 'action' => 'liability')),
|
||||||
|
array('name' => 'Equity', 'url' => array('controller' => 'accounts', 'action' => 'equity')),
|
||||||
|
array('name' => 'Income', 'url' => array('controller' => 'accounts', 'action' => 'income')),
|
||||||
|
array('name' => 'Expense', 'url' => array('controller' => 'accounts', 'action' => 'expense')),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / asset / liability / equity / income / expense / all
|
||||||
|
* - Generate a chart of accounts
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function asset() { $this->gridView('Asset Accounts'); }
|
||||||
|
function liability() { $this->gridView('Liability Accounts'); }
|
||||||
|
function equity() { $this->gridView('Equity Accounts'); }
|
||||||
|
function income() { $this->gridView('Income Accounts'); }
|
||||||
|
function expense() { $this->gridView('Expense Accounts'); }
|
||||||
|
function all() { $this->gridView('All Accounts', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataSetup(&$params) {
|
||||||
|
parent::gridDataSetup($params);
|
||||||
|
if (!isset($params['action']))
|
||||||
|
$params['action'] = 'all';
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataCountTables(&$params, &$model) {
|
||||||
|
// Our count should NOT include anything extra,
|
||||||
|
// so we need the virtual function to prevent
|
||||||
|
// the base class from just calling our
|
||||||
|
// gridDataTables function
|
||||||
|
return parent::gridDataTables($params, $model);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
return array
|
||||||
|
('link' =>
|
||||||
|
array(// Models
|
||||||
|
'CurrentLedger' => array
|
||||||
|
(// Models
|
||||||
|
'LedgerEntry'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFields(&$params, &$model) {
|
||||||
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
return array_merge($fields,
|
||||||
|
$this->Account->Ledger->LedgerEntry->debitCreditFields(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataConditions(&$params, &$model) {
|
||||||
|
$conditions = parent::gridDataConditions($params, $model);
|
||||||
|
|
||||||
|
if (in_array($params['action'], array('asset', 'liability', 'equity', 'income', 'expense'))) {
|
||||||
|
$conditions[] = array('Account.type' => strtoupper($params['action']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090811
|
||||||
|
// No security issues have been worked out yet
|
||||||
|
$conditions[] = array('Account.level >=' => 10);
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Account'] = array('name');
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: newledger
|
||||||
|
* - Close the current account ledger and create a new one,
|
||||||
|
* carrying forward any balance if necessary.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function newledger($id = null) {
|
||||||
|
$result = $this->Account->closeCurrentLedgers($id);
|
||||||
|
|
||||||
|
if ($result['error']) {
|
||||||
|
pr(compact('result'));
|
||||||
|
die("Unable to create new ledger.");
|
||||||
|
$this->Session->setFlash(__('Unable to create new Ledger.', true));
|
||||||
|
}
|
||||||
|
if ($id)
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
else
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: collected
|
||||||
|
* - Displays the items actually collected for the period
|
||||||
|
* e.g. How much was collected in rent from 4/1/09 - 5/1/09
|
||||||
|
*/
|
||||||
|
function collected($id = null) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->Account->recursive = -1;
|
||||||
|
$account = $this->Account->read(null, $id);
|
||||||
|
$account = $account['Account'];
|
||||||
|
|
||||||
|
$accounts = $this->Account->collectableAccounts();
|
||||||
|
$payment_accounts = $accounts['all'];
|
||||||
|
$default_accounts = $accounts['default'];
|
||||||
|
$this->set(compact('payment_accounts', 'default_accounts'));
|
||||||
|
|
||||||
|
$title = ($account['name'] . ': Collected Report');
|
||||||
|
$this->set(compact('account', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific account
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
$account = $this->Account->find
|
||||||
|
('first',
|
||||||
|
array('contain' =>
|
||||||
|
array(// Models
|
||||||
|
'CurrentLedger' =>
|
||||||
|
array('fields' => array('id', 'sequence', 'name')),
|
||||||
|
|
||||||
|
'Ledger' =>
|
||||||
|
array('CloseTransaction' => array
|
||||||
|
('order' => array('CloseTransaction.stamp' => 'DESC'))),
|
||||||
|
),
|
||||||
|
'conditions' => array(array('Account.id' => $id),
|
||||||
|
// REVISIT <AP>: 20090811
|
||||||
|
// No security issues have been worked out yet
|
||||||
|
array('Account.level >=' => 10),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (empty($account)) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtain stats across ALL ledgers for the summary infobox
|
||||||
|
$stats = $this->Account->stats($id, true);
|
||||||
|
$stats = $stats['Ledger'];
|
||||||
|
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Operations', 'header' => true);
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'New Ledger', 'url' => array('action' => 'newledger', $id));
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Collected', 'url' => array('action' => 'collected', $id));
|
||||||
|
|
||||||
|
// Prepare to render
|
||||||
|
$title = 'Account: ' . $account['Account']['name'];
|
||||||
|
$this->set(compact('account', 'title', 'stats'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
202
controllers/contacts_controller.php
Normal file
202
controllers/contacts_controller.php
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class ContactsController extends AppController {
|
||||||
|
|
||||||
|
var $sidemenu_links = array();
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / all
|
||||||
|
* - Generate a listing of contacts
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function all() { $this->gridView('All Contacts', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
||||||
|
if ($index === 'Contact.last_name') {
|
||||||
|
$order[] = 'Contact.first_name ' . $direction;
|
||||||
|
}
|
||||||
|
if ($index === 'Contact.first_name') {
|
||||||
|
$order[] = 'Contact.last_name ' . $direction;
|
||||||
|
}
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Contact'] = array('id');
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific contact
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$contact = $this->Contact->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'ContactPhone',
|
||||||
|
'ContactEmail',
|
||||||
|
'ContactAddress',
|
||||||
|
'Customer'),
|
||||||
|
|
||||||
|
'conditions' => array('Contact.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Set up dynamic menu items
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Operations', 'header' => true);
|
||||||
|
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Edit',
|
||||||
|
'url' => array('action' => 'edit',
|
||||||
|
$id));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = 'Contact: ' . $contact['Contact']['display_name'];
|
||||||
|
$this->set(compact('contact', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: edit
|
||||||
|
*/
|
||||||
|
|
||||||
|
function edit($id = null, $customer_id = null) {
|
||||||
|
if (isset($this->data)) {
|
||||||
|
|
||||||
|
if (isset($this->params['form']['cancel'])) {
|
||||||
|
if (isset($this->data['Contact']['id']))
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Contact']['id']));
|
||||||
|
/* else */
|
||||||
|
/* $this->redirect(array('controller' => 'customers', */
|
||||||
|
/* 'action'=>'add', $this->data['Customer']['id'])); */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through each contact method and strip the bogus ID if new
|
||||||
|
foreach (array_intersect_key($this->data,
|
||||||
|
array('ContactPhone'=>1,
|
||||||
|
'ContactAddress'=>1,
|
||||||
|
'ContactEmail'=>1)) AS $type => $arr) {
|
||||||
|
foreach ($arr AS $idx => $item) {
|
||||||
|
if (isset($item['source']) && $item['source'] === 'new')
|
||||||
|
unset($this->data[$type][$idx]['id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the contact and all associated data
|
||||||
|
$this->Contact->saveContact($this->data['Contact']['id'], $this->data);
|
||||||
|
|
||||||
|
// Now that the work is done, let the user view the updated contact
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Contact']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($id) {
|
||||||
|
$this->data = $this->Contact->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'ContactPhone',
|
||||||
|
'ContactEmail',
|
||||||
|
'ContactAddress',
|
||||||
|
'Customer'),
|
||||||
|
|
||||||
|
'conditions' => array('Contact.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
$title = 'Contact: ' . $this->data['Contact']['display_name'] . " : Edit";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$title = "Enter New Contact";
|
||||||
|
$this->data = array('ContactPhone' => array(),
|
||||||
|
'ContactAddress' => array(),
|
||||||
|
'ContactEmail' => array());
|
||||||
|
}
|
||||||
|
|
||||||
|
$phone_types = array_flip($this->Contact->ContactPhone->getEnumValues('type'));
|
||||||
|
unset($phone_types[0]);
|
||||||
|
// REVISIT <AP> 20090705
|
||||||
|
// Use this to have a mixed case enum
|
||||||
|
// array_map('ucfirst', array_map('strtolower', $phone_types))
|
||||||
|
$phone_types = array_combine($phone_types, $phone_types);
|
||||||
|
$this->set(compact('phone_types'));
|
||||||
|
|
||||||
|
$method_types = array_flip($this->Contact->getEnumValues
|
||||||
|
('type',
|
||||||
|
$this->Contact->tablePrefix . 'contacts_methods'));
|
||||||
|
unset($method_types[0]);
|
||||||
|
$method_types = array_combine($method_types, $method_types);
|
||||||
|
$this->set(compact('method_types'));
|
||||||
|
|
||||||
|
$method_preferences = array_flip($this->Contact->getEnumValues
|
||||||
|
('preference',
|
||||||
|
$this->Contact->tablePrefix . 'contacts_methods'));
|
||||||
|
unset($method_preferences[0]);
|
||||||
|
$method_preferences = array_combine($method_preferences, $method_preferences);
|
||||||
|
$this->set(compact('method_preferences'));
|
||||||
|
|
||||||
|
$contact_phones = $this->Contact->ContactPhone->phoneList();
|
||||||
|
$this->set(compact('contact_phones'));
|
||||||
|
|
||||||
|
$contact_addresses = $this->Contact->ContactAddress->addressList();
|
||||||
|
$this->set(compact('contact_addresses'));
|
||||||
|
|
||||||
|
$contact_emails = $this->Contact->ContactEmail->emailList();
|
||||||
|
$this->set(compact('contact_emails'));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
//pr($this->data);
|
||||||
|
$this->set(compact('title'));
|
||||||
|
$this->render('edit');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: add
|
||||||
|
* - Adds a new contact
|
||||||
|
*/
|
||||||
|
|
||||||
|
function add($customer_id = null) {
|
||||||
|
$this->edit(null, $customer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
486
controllers/customers_controller.php
Normal file
486
controllers/customers_controller.php
Normal file
@@ -0,0 +1,486 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class CustomersController extends AppController {
|
||||||
|
var $sidemenu_links =
|
||||||
|
array(array('name' => 'Customers', 'header' => true),
|
||||||
|
array('name' => 'Current', 'url' => array('controller' => 'customers', 'action' => 'current')),
|
||||||
|
array('name' => 'Past', 'url' => array('controller' => 'customers', 'action' => 'past')),
|
||||||
|
array('name' => 'All', 'url' => array('controller' => 'customers', 'action' => 'all')),
|
||||||
|
array('name' => 'Add Customer', 'url' => array('controller' => 'customers', 'action' => 'add')),
|
||||||
|
);
|
||||||
|
|
||||||
|
//var $components = array('RequestHandler');
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / current / past / all
|
||||||
|
* - Creates a list of customers
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->current(); }
|
||||||
|
function current() { $this->gridView('Current Tenants', 'current'); }
|
||||||
|
function past() { $this->gridView('Past Tenants'); }
|
||||||
|
function all() { $this->gridView('All Customers'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataCountTables(&$params, &$model) {
|
||||||
|
return array
|
||||||
|
('link' =>
|
||||||
|
array(// Models
|
||||||
|
'PrimaryContact',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
$link = $this->gridDataCountTables($params, $model);
|
||||||
|
// StatementEntry is needed to determine customer balance
|
||||||
|
$link['link']['StatementEntry'] = array('fields' => array());
|
||||||
|
return $link;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFields(&$params, &$model) {
|
||||||
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
return array_merge($fields,
|
||||||
|
$this->Customer->StatementEntry->chargeDisbursementFields(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataConditions(&$params, &$model) {
|
||||||
|
$conditions = parent::gridDataConditions($params, $model);
|
||||||
|
|
||||||
|
if ($params['action'] === 'current') {
|
||||||
|
$conditions[] = array('Customer.current_lease_count >' => 0);
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'past') {
|
||||||
|
$conditions[] = array('Customer.current_lease_count' => 0);
|
||||||
|
$conditions[] = array('Customer.past_lease_count >' => 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
$order = array();
|
||||||
|
$order[] = parent::gridDataOrder($params, $model, $index, $direction);
|
||||||
|
|
||||||
|
if ($index !== 'PrimaryContact.last_name')
|
||||||
|
$order[] = parent::gridDataOrder($params, $model,
|
||||||
|
'PrimaryContact.last_name', $direction);
|
||||||
|
if ($index !== 'PrimaryContact.first_name')
|
||||||
|
$order[] = parent::gridDataOrder($params, $model,
|
||||||
|
'PrimaryContact.first_name', $direction);
|
||||||
|
if ($index !== 'Customer.id')
|
||||||
|
$order[] = parent::gridDataOrder($params, $model,
|
||||||
|
'Customer.id', $direction);
|
||||||
|
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Customer'] = array('name');
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: move_in
|
||||||
|
* - Sets up the move-in page for the given customer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function move_in($id = null) {
|
||||||
|
$customer = array();
|
||||||
|
$unit = array();
|
||||||
|
|
||||||
|
if (isset($id)) {
|
||||||
|
$this->Customer->recursive = -1;
|
||||||
|
$customer = current($this->Customer->read(null, $id));
|
||||||
|
}
|
||||||
|
$this->set(compact('customer', 'unit'));
|
||||||
|
|
||||||
|
$title = 'Customer Move-In';
|
||||||
|
$this->set(compact('title'));
|
||||||
|
$this->render('/leases/move');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: move_out
|
||||||
|
* - prepare to move a customer out of one of their units
|
||||||
|
*/
|
||||||
|
|
||||||
|
function move_out($id) {
|
||||||
|
|
||||||
|
$customer = $this->Customer->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'Lease' =>
|
||||||
|
array('conditions' => array('Lease.moveout_date' => null),
|
||||||
|
// Models
|
||||||
|
'Unit' =>
|
||||||
|
array('order' => array('sort_order'),
|
||||||
|
'fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
'conditions' => array('Customer.id' => $id),
|
||||||
|
));
|
||||||
|
$this->set('customer', $lease['Customer']);
|
||||||
|
$this->set('unit', array());
|
||||||
|
|
||||||
|
$redirect = array('controller' => 'customers',
|
||||||
|
'action' => 'view',
|
||||||
|
$id);
|
||||||
|
|
||||||
|
$title = $customer['Customer']['name'] . ': Prepare Move-Out';
|
||||||
|
$this->set(compact('title', 'customer', 'redirect'));
|
||||||
|
$this->render('/leases/move');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific customer
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get details on this customer, its contacts and leases
|
||||||
|
$customer = $this->Customer->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'Contact' =>
|
||||||
|
array('order' => array('Contact.display_name'),
|
||||||
|
// Models
|
||||||
|
'ContactPhone',
|
||||||
|
'ContactEmail',
|
||||||
|
'ContactAddress',
|
||||||
|
),
|
||||||
|
'Lease' =>
|
||||||
|
array('Unit' =>
|
||||||
|
array('order' => array('sort_order'),
|
||||||
|
'fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
'conditions' => array('Customer.id' => $id),
|
||||||
|
));
|
||||||
|
//pr($customer);
|
||||||
|
|
||||||
|
// Determine how long this customer has been with us.
|
||||||
|
$leaseinfo = $this->Customer->find
|
||||||
|
('first', array
|
||||||
|
('link' => array('Lease' => array('fields' => array())),
|
||||||
|
'fields' => array('MIN(Lease.movein_date) AS since',
|
||||||
|
'IF(Customer.current_lease_count = 0, MAX(Lease.moveout_date), NULL) AS until'),
|
||||||
|
'conditions' => array('Customer.id' => $id),
|
||||||
|
'group' => 'Customer.id',
|
||||||
|
));
|
||||||
|
$this->set($leaseinfo[0]);
|
||||||
|
|
||||||
|
// Figure out the outstanding balances for this customer
|
||||||
|
//$this->set('stats', $this->Customer->stats($id));
|
||||||
|
$outstanding_balance = $this->Customer->balance($id);
|
||||||
|
$outstanding_deposit = $this->Customer->securityDepositBalance($id);
|
||||||
|
|
||||||
|
// Figure out if this customer has any non-closed leases
|
||||||
|
$show_moveout = false;
|
||||||
|
$show_payment = false;
|
||||||
|
foreach ($customer['Lease'] AS $lease) {
|
||||||
|
if (!isset($lease['close_date']))
|
||||||
|
$show_payment = true;
|
||||||
|
if (!isset($lease['moveout_date']))
|
||||||
|
$show_moveout = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up dynamic menu items
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Operations', 'header' => true);
|
||||||
|
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Edit',
|
||||||
|
'url' => array('action' => 'edit',
|
||||||
|
$id));
|
||||||
|
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Move-In',
|
||||||
|
'url' => array('action' => 'move_in',
|
||||||
|
$id));
|
||||||
|
|
||||||
|
/* if ($show_moveout) { */
|
||||||
|
/* $this->sidemenu_links[] = */
|
||||||
|
/* array('name' => 'Move-Out', */
|
||||||
|
/* 'url' => array('action' => 'move_out', */
|
||||||
|
/* $id)); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
if ($show_payment || $outstanding_balance > 0)
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'New Receipt',
|
||||||
|
'url' => array('action' => 'receipt',
|
||||||
|
$id));
|
||||||
|
|
||||||
|
if (!$show_moveout && $outstanding_balance > 0)
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Write-Off',
|
||||||
|
'url' => array('action' => 'bad_debt',
|
||||||
|
$id));
|
||||||
|
|
||||||
|
if ($outstanding_balance < 0)
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Issue Refund',
|
||||||
|
'url' => array('action' => 'refund', $id));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = 'Customer: ' . $customer['Customer']['name'];
|
||||||
|
$this->set(compact('customer', 'title',
|
||||||
|
'outstanding_balance',
|
||||||
|
'outstanding_deposit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: edit
|
||||||
|
* - Edit customer information
|
||||||
|
*/
|
||||||
|
|
||||||
|
function edit($id = null) {
|
||||||
|
if (isset($this->data)) {
|
||||||
|
// Check to see if the operation was cancelled.
|
||||||
|
if (isset($this->params['form']['cancel'])) {
|
||||||
|
if (isset($this->data['Customer']['id']))
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Customer']['id']));
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have at least one contact
|
||||||
|
if (!isset($this->data['Contact']) || count($this->data['Contact']) == 0) {
|
||||||
|
$this->Session->setFlash("MUST SPECIFY AT LEAST ONE CONTACT", true);
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Customer']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure there is a primary contact
|
||||||
|
if (!isset($this->data['Customer']['primary_contact_entry'])) {
|
||||||
|
$this->Session->setFlash("MUST SPECIFY A PRIMARY CONTACT", true);
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Customer']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through each customer and strip the bogus ID if new
|
||||||
|
foreach ($this->data['Contact'] AS &$contact) {
|
||||||
|
if (isset($contact['source']) && $contact['source'] === 'new')
|
||||||
|
unset($contact['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the customer and all associated data
|
||||||
|
if (!$this->Customer->saveCustomer($this->data['Customer']['id'],
|
||||||
|
$this->data,
|
||||||
|
$this->data['Customer']['primary_contact_entry'])) {
|
||||||
|
$this->Session->setFlash("CUSTOMER SAVE FAILED", true);
|
||||||
|
pr("CUSTOMER SAVE FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If existing customer, then view it.
|
||||||
|
if ($this->data['Customer']['id'])
|
||||||
|
$this->redirect(array('action'=>'view', $this->Customer->id));
|
||||||
|
|
||||||
|
// Since this is a new customer, go to the move in screen.
|
||||||
|
$this->redirect(array('action'=>'move_in', $this->Customer->id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($id) {
|
||||||
|
// REVISIT <AP>: 20090816
|
||||||
|
// This should never need to be done by a controller.
|
||||||
|
// However, until things stabilize, this gives the
|
||||||
|
// user a way to update any cached items on the
|
||||||
|
// customer, by just clicking Edit then Cancel.
|
||||||
|
$this->Customer->update($id);
|
||||||
|
|
||||||
|
// Get details on this customer, its contacts and leases
|
||||||
|
$customer = $this->Customer->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'Contact' =>
|
||||||
|
array('order' => array('Contact.display_name'),
|
||||||
|
// Models
|
||||||
|
'ContactPhone',
|
||||||
|
'ContactEmail',
|
||||||
|
'ContactAddress',
|
||||||
|
),
|
||||||
|
'Lease' =>
|
||||||
|
array('Unit' =>
|
||||||
|
array('order' => array('sort_order'),
|
||||||
|
'fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
'conditions' => array('Customer.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->data = $customer;
|
||||||
|
$title = 'Customer: ' . $this->data['Customer']['name'] . " : Edit";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$title = "Enter New Customer";
|
||||||
|
$this->data = array('Contact' => array(), 'PrimaryContact' => null);
|
||||||
|
}
|
||||||
|
|
||||||
|
$contact_types = array_flip($this->Customer->ContactsCustomer->getEnumValues('type'));
|
||||||
|
unset($contact_types[0]);
|
||||||
|
$contact_types = array_combine($contact_types, $contact_types);
|
||||||
|
$this->set(compact('contact_types'));
|
||||||
|
|
||||||
|
$contacts = $this->Customer->Contact->contactList();
|
||||||
|
$this->set(compact('contacts'));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
//pr($this->data);
|
||||||
|
$this->set(compact('title'));
|
||||||
|
$this->render('edit');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: add
|
||||||
|
* - Add a new customer
|
||||||
|
*/
|
||||||
|
|
||||||
|
function add() {
|
||||||
|
$this->edit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: receipt
|
||||||
|
* - Sets up the receipt entry page for the given customer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function receipt($id = null) {
|
||||||
|
if (isset($id)) {
|
||||||
|
$this->Customer->recursive = -1;
|
||||||
|
$customer = $this->Customer->read(null, $id);
|
||||||
|
$customer = $customer['Customer'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$customer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$TT = new TenderType();
|
||||||
|
$payment_types = $TT->paymentTypes();
|
||||||
|
$default_type = $TT->defaultPaymentType();
|
||||||
|
$this->set(compact('payment_types', 'default_type'));
|
||||||
|
|
||||||
|
$title = ($customer['name'] . ': Receipt Entry');
|
||||||
|
$this->set(compact('customer', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: refund
|
||||||
|
* - Refunds customer charges
|
||||||
|
*/
|
||||||
|
|
||||||
|
function refund($id) {
|
||||||
|
$customer = $this->Customer->find
|
||||||
|
('first', array
|
||||||
|
('contain' => false,
|
||||||
|
'conditions' => array(array('Customer.id' => $id),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
if (empty($customer)) {
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the customer balance, bailing if the customer owes money
|
||||||
|
$balance = $this->Customer->balance($id);
|
||||||
|
if ($balance >= 0) {
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The refund will be for a positive amount
|
||||||
|
$balance *= -1;
|
||||||
|
|
||||||
|
// Get the accounts capable of paying the refund
|
||||||
|
$refundAccounts = $this->Customer->StatementEntry->Account->refundAccounts();
|
||||||
|
$defaultAccount = current($refundAccounts);
|
||||||
|
$this->set(compact('refundAccounts', 'defaultAccount'));
|
||||||
|
|
||||||
|
// Prepare to render
|
||||||
|
$title = ($customer['Customer']['name'] . ': Refund');
|
||||||
|
$this->set(compact('title', 'customer', 'balance'));
|
||||||
|
$this->render('/transactions/refund');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: bad_debt
|
||||||
|
* - Sets up the write-off entry page, so that the
|
||||||
|
* user can write off remaining charges of a customer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function bad_debt($id) {
|
||||||
|
$this->Customer->id = $id;
|
||||||
|
$customer = $this->Customer->find
|
||||||
|
('first', array
|
||||||
|
('contain' => false,
|
||||||
|
));
|
||||||
|
|
||||||
|
// Make sure we have a valid customer to write off
|
||||||
|
if (empty($customer))
|
||||||
|
$this->redirect(array('action' => 'index'));
|
||||||
|
|
||||||
|
// Get the customer balance
|
||||||
|
$balance = $this->Customer->balance($id);
|
||||||
|
|
||||||
|
// Prepare to render
|
||||||
|
$title = ($customer['Customer']['name'] . ': Write Off Bad Debt');
|
||||||
|
$this->set(compact('title', 'customer', 'balance'));
|
||||||
|
$this->render('/transactions/bad_debt');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
66
controllers/double_entries_controller.php
Normal file
66
controllers/double_entries_controller.php
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class DoubleEntriesController extends AppController {
|
||||||
|
|
||||||
|
var $sidemenu_links = array();
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific entry
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('controller' => 'accounts', 'action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the Entry and related fields
|
||||||
|
$entry = $this->DoubleEntry->find
|
||||||
|
('first',
|
||||||
|
array('contain' => array('DebitEntry', 'CreditEntry'),
|
||||||
|
'conditions' => array('DoubleEntry.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
$entry += $this->DoubleEntry->DebitEntry->Transaction->find
|
||||||
|
('first',
|
||||||
|
array('contain' => false,
|
||||||
|
'conditions' => array('id' => $entry['DebitEntry']['transaction_id']),
|
||||||
|
));
|
||||||
|
|
||||||
|
$entry += $this->DoubleEntry->DebitEntry->find
|
||||||
|
('first',
|
||||||
|
array('contain' => array('Ledger' => array('Account')),
|
||||||
|
'conditions' => array('DebitEntry.id' => $entry['DebitEntry']['id']),
|
||||||
|
));
|
||||||
|
$entry['DebitLedger'] = $entry['Ledger'];
|
||||||
|
unset($entry['Ledger']);
|
||||||
|
|
||||||
|
$entry += $this->DoubleEntry->CreditEntry->find
|
||||||
|
('first',
|
||||||
|
array('contain' => array('Ledger' => array('Account')),
|
||||||
|
'conditions' => array('CreditEntry.id' => $entry['CreditEntry']['id']),
|
||||||
|
));
|
||||||
|
$entry['CreditLedger'] = $entry['Ledger'];
|
||||||
|
unset($entry['Ledger']);
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = "Double Ledger Entry #{$entry['DoubleEntry']['id']}";
|
||||||
|
$this->set(compact('entry', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
524
controllers/leases_controller.php
Normal file
524
controllers/leases_controller.php
Normal file
@@ -0,0 +1,524 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class LeasesController extends AppController {
|
||||||
|
|
||||||
|
var $sidemenu_links =
|
||||||
|
array(array('name' => 'Leases', 'header' => true),
|
||||||
|
array('name' => 'Active', 'url' => array('controller' => 'leases', 'action' => 'active')),
|
||||||
|
array('name' => 'Closed', 'url' => array('controller' => 'leases', 'action' => 'closed')),
|
||||||
|
array('name' => 'Delinquent', 'url' => array('controller' => 'leases', 'action' => 'delinquent')),
|
||||||
|
array('name' => 'All', 'url' => array('controller' => 'leases', 'action' => 'all')),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / active / closed / all
|
||||||
|
* - Generate a listing of leases
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function active() { $this->gridView('Active Leases'); }
|
||||||
|
function delinquent() { $this->gridView('Delinquent Leases'); }
|
||||||
|
function closed() { $this->gridView('Closed Leases'); }
|
||||||
|
function all() { $this->gridView('All Leases', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataSetup(&$params) {
|
||||||
|
parent::gridDataSetup($params);
|
||||||
|
if (!isset($params['action']))
|
||||||
|
$params['action'] = 'all';
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataCountTables(&$params, &$model) {
|
||||||
|
return array
|
||||||
|
('link' => array('Unit' => array('fields' => array('id', 'name')),
|
||||||
|
'Customer' => array('fields' => array('id', 'name'))));
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
$link = $this->gridDataCountTables($params, $model);
|
||||||
|
$link['link']['StatementEntry'] = array('fields' => array());
|
||||||
|
return $link;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFields(&$params, &$model) {
|
||||||
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
$fields[] = ("IF(" . $this->Lease->conditionDelinquent() . "," .
|
||||||
|
" 'DELINQUENT', 'CURRENT') AS 'status'");
|
||||||
|
return array_merge($fields,
|
||||||
|
$this->Lease->StatementEntry->chargeDisbursementFields(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataConditions(&$params, &$model) {
|
||||||
|
$conditions = parent::gridDataConditions($params, $model);
|
||||||
|
|
||||||
|
if ($params['action'] === 'active') {
|
||||||
|
$conditions[] = 'Lease.close_date IS NULL';
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'delinquent') {
|
||||||
|
$conditions[] = $this->Lease->conditionDelinquent();
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'closed') {
|
||||||
|
$conditions[] = 'Lease.close_date IS NOT NULL';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($customer_id))
|
||||||
|
$conditions[] = array('Lease.customer_id' => $customer_id);
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
// Do not sort by number, which is type varchar and
|
||||||
|
// sorts on an ascii basis. Sort by ID instead.
|
||||||
|
if ($index === 'Lease.number')
|
||||||
|
$index = 'Lease.id';
|
||||||
|
|
||||||
|
// Instead of sorting by name, sort by defined order
|
||||||
|
if ($index === 'Unit.name')
|
||||||
|
$index = 'Unit.sort_order';
|
||||||
|
|
||||||
|
$order = array();
|
||||||
|
$order[] = parent::gridDataOrder($params, $model, $index, $direction);
|
||||||
|
|
||||||
|
// If sorting by anything other than id/number
|
||||||
|
// add sorting by id as a secondary condition.
|
||||||
|
if ($index !== 'Lease.id' && $index !== 'Lease.number')
|
||||||
|
$order[] = parent::gridDataOrder($params, $model,
|
||||||
|
'Lease.id', $direction);
|
||||||
|
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* function gridDataPostProcess(&$params, &$model, &$records) { */
|
||||||
|
/* foreach ($records AS &$record) { */
|
||||||
|
/* $record['Lease']['through_date'] */
|
||||||
|
/* = $this->Lease->rentChargeThrough($record['Lease']['id']); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
/* parent::gridDataPostProcess($params, $model, $records); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Lease'] = array('number');
|
||||||
|
$links['Unit'] = array('name');
|
||||||
|
$links['Customer'] = array('name');
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: move_in
|
||||||
|
* - execute a move in on a new lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function move_in() {
|
||||||
|
if (!$this->data)
|
||||||
|
die("Should have some data");
|
||||||
|
|
||||||
|
// Handle the move in based on the data given
|
||||||
|
//pr(array('Move-in data', $this->data));
|
||||||
|
foreach (array('deposit', 'rent') AS $currency) {
|
||||||
|
$this->data['Lease'][$currency]
|
||||||
|
= str_replace('$', '', $this->data['Lease'][$currency]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$lid = $this->Lease->moveIn($this->data['Lease']['customer_id'],
|
||||||
|
$this->data['Lease']['unit_id'],
|
||||||
|
$this->data['Lease']['deposit'],
|
||||||
|
$this->data['Lease']['rent'],
|
||||||
|
$this->data['Lease']['movein_date'],
|
||||||
|
$this->data['Lease']['comment']
|
||||||
|
);
|
||||||
|
|
||||||
|
// Since this is a new lease, go to the invoice
|
||||||
|
// screen so we can start assessing charges.
|
||||||
|
$this->redirect(array('action'=>'invoice', $lid, 'move-in'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: move_out
|
||||||
|
* - prepare or execute a move out on a specific lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function move_out($id = null) {
|
||||||
|
if ($this->data) {
|
||||||
|
// Handle the move out based on the data given
|
||||||
|
//pr($this->data);
|
||||||
|
|
||||||
|
$this->Lease->moveOut($this->data['Lease']['id'],
|
||||||
|
'VACANT',
|
||||||
|
$this->data['Lease']['moveout_date']
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->redirect($this->data['redirect']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($id))
|
||||||
|
die("Oh Nooooo!!");
|
||||||
|
|
||||||
|
$lease = $this->Lease->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'Unit' =>
|
||||||
|
array('order' => array('sort_order'),
|
||||||
|
'fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
|
||||||
|
'Customer' =>
|
||||||
|
array('fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
'conditions' => array(array('Lease.id' => $id),
|
||||||
|
array('Lease.close_date' => null),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
$this->set('customer', $lease['Customer']);
|
||||||
|
$this->set('unit', $lease['Unit']);
|
||||||
|
$this->set('lease', $lease['Lease']);
|
||||||
|
|
||||||
|
$redirect = array('controller' => 'leases',
|
||||||
|
'action' => 'view',
|
||||||
|
$id);
|
||||||
|
|
||||||
|
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
||||||
|
$lease['Unit']['name'] . ': ' .
|
||||||
|
$lease['Customer']['name'] . ': Prepare Move-Out');
|
||||||
|
$this->set(compact('title', 'redirect'));
|
||||||
|
$this->render('/leases/move');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* /\************************************************************************** */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* * action: promote_credit */
|
||||||
|
/* * - Moves any lease credit up to the customer level, so that */
|
||||||
|
/* * it may be used for charges other than those on this lease. */
|
||||||
|
/* *\/ */
|
||||||
|
|
||||||
|
/* function promote_surplus($id) { */
|
||||||
|
/* $this->Lease->promoteSurplus($id); */
|
||||||
|
/* $this->redirect(array('controller' => 'leases', */
|
||||||
|
/* 'action' => 'view', */
|
||||||
|
/* $id)); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: refund
|
||||||
|
* - Provides lease customer with a refund
|
||||||
|
*/
|
||||||
|
|
||||||
|
function refund($id) {
|
||||||
|
$lease = $this->Lease->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'Unit' => array('fields' => array('id', 'name')),
|
||||||
|
'Customer' => array('fields' => array('id', 'name')),
|
||||||
|
),
|
||||||
|
|
||||||
|
'conditions' => array(array('Lease.id' => $id),
|
||||||
|
// Make sure lease is not closed...
|
||||||
|
array('Lease.close_date' => null),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
if (empty($lease)) {
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the lease balance, bailing if the customer owes money
|
||||||
|
$balance = $this->Lease->balance($id);
|
||||||
|
if ($balance >= 0) {
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The refund will be for a positive amount
|
||||||
|
$balance *= -1;
|
||||||
|
|
||||||
|
// Get the accounts capable of paying the refund
|
||||||
|
$refundAccounts = $this->Lease->StatementEntry->Account->refundAccounts();
|
||||||
|
$defaultAccount = current($refundAccounts);
|
||||||
|
$this->set(compact('refundAccounts', 'defaultAccount'));
|
||||||
|
|
||||||
|
// Prepare to render
|
||||||
|
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
||||||
|
$lease['Unit']['name'] . ': ' .
|
||||||
|
$lease['Customer']['name'] . ': Refund');
|
||||||
|
$this->set(compact('title', 'lease', 'balance'));
|
||||||
|
$this->render('/transactions/refund');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: bad_debt
|
||||||
|
* - Sets up the write-off entry page, so that the
|
||||||
|
* user can write off remaining charges on a lease.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function bad_debt($id) {
|
||||||
|
$this->Lease->id = $id;
|
||||||
|
$lease = $this->Lease->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'Unit' => array('fields' => array('id', 'name')),
|
||||||
|
'Customer' => array('fields' => array('id', 'name')),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Make sure we have a valid lease to write off
|
||||||
|
if (empty($lease))
|
||||||
|
$this->redirect(array('action' => 'view', $id));
|
||||||
|
|
||||||
|
// Get the lease balance
|
||||||
|
$balance = $this->Lease->balance($id);
|
||||||
|
|
||||||
|
// Prepare to render
|
||||||
|
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
||||||
|
$lease['Unit']['name'] . ': ' .
|
||||||
|
$lease['Customer']['name'] . ': Write Off Bad Debt');
|
||||||
|
$this->set(compact('title', 'lease', 'balance'));
|
||||||
|
$this->render('/transactions/bad_debt');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: close
|
||||||
|
* - Closes a lease to any further action
|
||||||
|
*/
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090809
|
||||||
|
// While cleaning up the sitelink data, then delete reldep()
|
||||||
|
function reldep($id) {
|
||||||
|
$this->Lease->id = $id;
|
||||||
|
$stamp = $this->Lease->field('moveout_date');
|
||||||
|
$this->Lease->releaseSecurityDeposits($id, $stamp);
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
function close($id) {
|
||||||
|
// REVISIT <AP>: 20090708
|
||||||
|
// We should probably seek confirmation first...
|
||||||
|
if (!$this->Lease->closeable($id)) {
|
||||||
|
$this->INTERNAL_ERROR("This lease is not ready to close");
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->Lease->close($id);
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: invoice
|
||||||
|
* - Sets up the invoice entry page for the given customer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function invoice($id = null, $type = null) {
|
||||||
|
|
||||||
|
$lease = $this->Lease->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'Unit' =>
|
||||||
|
array('order' => array('sort_order'),
|
||||||
|
'fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
|
||||||
|
'Customer' =>
|
||||||
|
array('fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
'conditions' => array(array('Lease.id' => $id),
|
||||||
|
array('Lease.close_date' => null),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$A = new Account();
|
||||||
|
$charge_accounts = $A->invoiceAccounts();
|
||||||
|
$default_account = $A->rentAccountID();
|
||||||
|
$rent_account = $A->rentAccountID();
|
||||||
|
$security_deposit_account = $A->securityDepositAccountID();
|
||||||
|
$this->set(compact('charge_accounts', 'default_account',
|
||||||
|
'rent_account', 'security_deposit_account'));
|
||||||
|
|
||||||
|
// REVISIT <AP> 20090705:
|
||||||
|
// Of course, the late charge should come from the late_schedule
|
||||||
|
$default_late = 10;
|
||||||
|
$this->set(compact('default_late'));
|
||||||
|
|
||||||
|
if ($type === 'move-in') {
|
||||||
|
$movein = array();
|
||||||
|
$movein['time'] = strtotime($lease['Lease']['movein_date']);
|
||||||
|
$movein['effective_time'] = strtotime($lease['Lease']['movein_date']);
|
||||||
|
$movein_date = getdate($movein['effective_time']);
|
||||||
|
$movein['through_time'] = mktime(0, 0, 0, $movein_date['mon'] + 1, 0, $movein_date['year']);
|
||||||
|
$days_in_month = idate('d', $movein['through_time']);
|
||||||
|
$movein['prorated_days'] = $days_in_month - $movein_date['mday'] + 1;
|
||||||
|
$movein['prorated_rent'] = $lease['Lease']['rent'] * $movein['prorated_days'] / $days_in_month;
|
||||||
|
$movein['prorated'] = $movein['prorated_days'] != $days_in_month;
|
||||||
|
$movein['deposit'] = $lease['Lease']['deposit'];
|
||||||
|
$this->set(compact('movein'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
||||||
|
$lease['Unit']['name'] . ': ' .
|
||||||
|
$lease['Customer']['name'] . ': Charge Entry');
|
||||||
|
$this->set(compact('title', 'lease', 'charge'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: assess_rent/late
|
||||||
|
* - Assesses the new monthly rent/late charge, if need be
|
||||||
|
*/
|
||||||
|
|
||||||
|
function assess_rent($date = null) {
|
||||||
|
$this->Lease->assessMonthlyRentAll($date);
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
function assess_late($date = null) {
|
||||||
|
$this->Lease->assessMonthlyLateAll($date);
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
function assess_all($date = null) {
|
||||||
|
$this->Lease->assessMonthlyRentAll($date);
|
||||||
|
$this->Lease->assessMonthlyLateAll($date);
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get details about the lease and its ledgers (no ledger entries yet)
|
||||||
|
$lease = $this->Lease->find
|
||||||
|
('first',
|
||||||
|
array('contain' =>
|
||||||
|
array(// Models
|
||||||
|
'LeaseType(id,name)',
|
||||||
|
'Unit(id,name)',
|
||||||
|
'Customer(id,name)',
|
||||||
|
),
|
||||||
|
'fields' => array('Lease.*', $this->Lease->delinquentField()),
|
||||||
|
'conditions' => array(array('Lease.id' => $id)),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$lease['Lease'] += $lease[0];
|
||||||
|
unset($lease[0]);
|
||||||
|
|
||||||
|
// Figure out the outstanding balances for this lease
|
||||||
|
$outstanding_balance = $this->Lease->balance($id);
|
||||||
|
$outstanding_deposit = $this->Lease->securityDepositBalance($id);
|
||||||
|
|
||||||
|
// Set up dynamic menu items. Normally, these will only be present
|
||||||
|
// on an open lease, but it's possible for a lease to be closed, and
|
||||||
|
// yet still have an outstanding balance. This can happen if someone
|
||||||
|
// were to reverse charges, or if a payment should come back NSF.
|
||||||
|
if (!isset($lease['Lease']['close_date']) || $outstanding_balance > 0) {
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Operations', 'header' => true);
|
||||||
|
|
||||||
|
if (!isset($lease['Lease']['moveout_date']))
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Move-Out', 'url' => array('action' => 'move_out',
|
||||||
|
$id));
|
||||||
|
|
||||||
|
if (!isset($lease['Lease']['close_date']))
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'New Invoice', 'url' => array('action' => 'invoice',
|
||||||
|
$id));
|
||||||
|
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'New Receipt', 'url' => array('controller' => 'customers',
|
||||||
|
'action' => 'receipt',
|
||||||
|
$lease['Customer']['id']));
|
||||||
|
|
||||||
|
/* if ($outstanding_balance < 0) */
|
||||||
|
/* $this->sidemenu_links[] = */
|
||||||
|
/* array('name' => 'Transfer Credit to Customer', */
|
||||||
|
/* 'url' => array('action' => 'promote_surplus', $id)); */
|
||||||
|
|
||||||
|
// REVISIT <AP>:
|
||||||
|
// Not allowing refund to be issued from the lease, as
|
||||||
|
// in fact, we should never have a positive lease balance.
|
||||||
|
// I'll flag this at the moment, since we might get one
|
||||||
|
// when a charge is reimbursed; a bug that we'll either
|
||||||
|
// need to fix, or we'll have to revisit this assumption.
|
||||||
|
if ($outstanding_balance < 0)
|
||||||
|
$this->INTERNAL_ERROR("Should not have a customer lease credit.");
|
||||||
|
|
||||||
|
/* if ($outstanding_balance < 0) */
|
||||||
|
/* $this->sidemenu_links[] = */
|
||||||
|
/* array('name' => 'Issue Refund', */
|
||||||
|
/* 'url' => array('action' => 'refund', $id)); */
|
||||||
|
|
||||||
|
if (isset($lease['Lease']['moveout_date']) && $outstanding_balance > 0)
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Write-Off', 'url' => array('action' => 'bad_debt',
|
||||||
|
$id));
|
||||||
|
|
||||||
|
if ($this->Lease->closeable($id))
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Close', 'url' => array('action' => 'close',
|
||||||
|
$id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare to render
|
||||||
|
$title = 'Lease: #' . $lease['Lease']['id'];
|
||||||
|
$this->set(compact('lease', 'title',
|
||||||
|
'outstanding_deposit',
|
||||||
|
'outstanding_balance'));
|
||||||
|
}
|
||||||
|
}
|
||||||
217
controllers/ledger_entries_controller.php
Normal file
217
controllers/ledger_entries_controller.php
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class LedgerEntriesController extends AppController {
|
||||||
|
|
||||||
|
var $sidemenu_links = array();
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / current / past / all
|
||||||
|
* - Creates a list of ledger entries
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->gridView('All Ledger Entries'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
$link =
|
||||||
|
array(// Models
|
||||||
|
'Transaction' =>
|
||||||
|
array('fields' => array('id', 'stamp'),
|
||||||
|
),
|
||||||
|
|
||||||
|
'Ledger' =>
|
||||||
|
array('fields' => array('id', 'sequence'),
|
||||||
|
'Account' =>
|
||||||
|
array('fields' => array('id', 'name', 'type'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
'Tender' =>
|
||||||
|
array('fields' => array('id', 'name', 'nsf_transaction_id'),
|
||||||
|
),
|
||||||
|
|
||||||
|
/* 'DebitEntry', */
|
||||||
|
/* 'CreditEntry', */
|
||||||
|
);
|
||||||
|
|
||||||
|
return array('link' => $link);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFields(&$params, &$model) {
|
||||||
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
return array_merge($fields,
|
||||||
|
$this->LedgerEntry->debitCreditFields());
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFilterTablesTable(&$params, &$model, $table) {
|
||||||
|
$table = $this->gridDataFilterTableName($params, $model, $table);
|
||||||
|
// Account is already part of our standard table set.
|
||||||
|
// Ensure we don't add it in again as part of filtering.
|
||||||
|
if ($table == 'Account')
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Customer needs to be added beneath Transaction
|
||||||
|
if ($table == 'Customer')
|
||||||
|
return 'Transaction';
|
||||||
|
|
||||||
|
return $table;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFilterTablesConfig(&$params, &$model, $table) {
|
||||||
|
$config = parent::gridDataFilterTablesConfig($params, $model, $table);
|
||||||
|
|
||||||
|
// Customer is special in that its linked in by Transaction
|
||||||
|
// Therefore, the actual table used for the join is 'Transaction',
|
||||||
|
// not 'Customer', and so we need to specify Customer here.
|
||||||
|
if ($table == 'Customer')
|
||||||
|
$config = array('Customer' => $config);
|
||||||
|
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFilterConditionsStatement(&$params, &$model, $table, $key, $value) {
|
||||||
|
//pr(compact('table', 'key', 'value'));
|
||||||
|
if ($table == 'Account' && $value['value_present'] && $value['value'] === '-AR-')
|
||||||
|
$value = $this->LedgerEntry->Ledger->Account->accountReceivableAccountID();
|
||||||
|
return parent::gridDataFilterConditionsStatement($params, $model, $table, $key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
/* if ($index === 'balance') */
|
||||||
|
/* return ($index .' '. $direction); */
|
||||||
|
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
||||||
|
|
||||||
|
if ($index === 'Transaction.stamp') {
|
||||||
|
$order[] = 'LedgerEntry.id ' . $direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessCalculatedFields(&$params, &$model, &$records) {
|
||||||
|
parent::gridDataPostProcessCalculatedFields($params, $model, $records);
|
||||||
|
foreach ($records AS &$record) {
|
||||||
|
// REVISIT <AP>: 20090730
|
||||||
|
// We really need the grid to handle this. We probably need to
|
||||||
|
// either create a hidden column with the nsf id, or pass back
|
||||||
|
// a list of nsf items as user data. We can then add an onload
|
||||||
|
// function to sweep through the nsf items and format them.
|
||||||
|
// For now... this works.
|
||||||
|
if (!empty($record['Tender']['nsf_transaction_id']))
|
||||||
|
$record['Tender']['name'] =
|
||||||
|
'<SPAN class="nsf-tender">' . $record['Tender']['name'] . '</SPAN>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['LedgerEntry'] = array('id');
|
||||||
|
$links['Transaction'] = array('id');
|
||||||
|
$links['Ledger'] = array('id');
|
||||||
|
$links['Account'] = array('controller' => 'accounts', 'name');
|
||||||
|
$links['Tender'] = array('name');
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific entry
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
$entry = $this->LedgerEntry->find
|
||||||
|
('first',
|
||||||
|
array('contain' => array
|
||||||
|
(
|
||||||
|
'Transaction' =>
|
||||||
|
array('fields' => array('id', 'stamp'),
|
||||||
|
),
|
||||||
|
|
||||||
|
'Ledger' =>
|
||||||
|
array('fields' => array('id', 'sequence', 'name'),
|
||||||
|
'Account' =>
|
||||||
|
array('fields' => array('id', 'name', 'type'),
|
||||||
|
'conditions' =>
|
||||||
|
// REVISIT <AP>: 20090811
|
||||||
|
// No security issues have been worked out yet
|
||||||
|
array('Account.level >=' => 5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
'Tender' =>
|
||||||
|
array('fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
|
||||||
|
'DebitDoubleEntry' => array('id'),
|
||||||
|
'CreditDoubleEntry' => array('id'),
|
||||||
|
|
||||||
|
'DebitEntry' => array('fields' => array('id', 'crdr')),
|
||||||
|
'CreditEntry' => array('fields' => array('id', 'crdr')),
|
||||||
|
),
|
||||||
|
|
||||||
|
'conditions' => array('LedgerEntry.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
if (empty($entry) || empty($entry['Ledger']['Account'])) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('controller' => 'accounts', 'action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($entry['DebitEntry']) && !empty($entry['CreditEntry']))
|
||||||
|
die("LedgerEntry has both a matching DebitEntry and CreditEntry");
|
||||||
|
if (empty($entry['DebitEntry']) && empty($entry['CreditEntry']))
|
||||||
|
die("LedgerEntry has neither a matching DebitEntry nor a CreditEntry");
|
||||||
|
if (empty($entry['DebitEntry']) && count($entry['CreditEntry']) != 1)
|
||||||
|
die("LedgerEntry has more than one CreditEntry");
|
||||||
|
if (empty($entry['CreditEntry']) && count($entry['DebitEntry']) != 1)
|
||||||
|
die("LedgerEntry has more than one DebitEntry");
|
||||||
|
|
||||||
|
if (empty($entry['DebitEntry']))
|
||||||
|
$entry['MatchingEntry'] = $entry['CreditEntry'][0];
|
||||||
|
else
|
||||||
|
$entry['MatchingEntry'] = $entry['DebitEntry'][0];
|
||||||
|
|
||||||
|
if (empty($entry['DebitDoubleEntry']['id']))
|
||||||
|
$entry['DoubleEntry'] = $entry['CreditDoubleEntry'];
|
||||||
|
else
|
||||||
|
$entry['DoubleEntry'] = $entry['DebitDoubleEntry'];
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090816
|
||||||
|
// This page doesn't seem very useful, let's just keep it
|
||||||
|
// all to the double entry view.
|
||||||
|
$this->redirect(array('controller' => 'double_entries',
|
||||||
|
'action' => 'view',
|
||||||
|
$entry['DoubleEntry']['id']));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = "Ledger Entry #{$entry['LedgerEntry']['id']}";
|
||||||
|
$this->set(compact('entry', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
149
controllers/ledgers_controller.php
Normal file
149
controllers/ledgers_controller.php
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class LedgersController extends AppController {
|
||||||
|
|
||||||
|
var $sidemenu_links =
|
||||||
|
array(array('name' => 'Ledgers', 'header' => true),
|
||||||
|
array('name' => 'Current', 'url' => array('controller' => 'ledgers', 'action' => 'current')),
|
||||||
|
array('name' => 'Closed', 'url' => array('controller' => 'ledgers', 'action' => 'closed')),
|
||||||
|
array('name' => 'All', 'url' => array('controller' => 'ledgers', 'action' => 'all')),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / current / closed / all
|
||||||
|
* - Generate a list of ledgers
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function current() { $this->gridView('Current Ledgers'); }
|
||||||
|
function closed() { $this->gridView('Closed Ledgers'); }
|
||||||
|
function all() { $this->gridView('All Ledgers', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataSetup(&$params) {
|
||||||
|
parent::gridDataSetup($params);
|
||||||
|
if (!isset($params['action']))
|
||||||
|
$params['action'] = 'all';
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataCountTables(&$params, &$model) {
|
||||||
|
return array
|
||||||
|
('link' =>
|
||||||
|
array(// Models
|
||||||
|
'Account',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
$tables = $this->gridDataCountTables($params, $model);
|
||||||
|
$tables['link'][] = 'LedgerEntry';
|
||||||
|
$tables['link'][] = 'CloseTransaction';
|
||||||
|
return $tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFields(&$params, &$model) {
|
||||||
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
$fields[] = 'CONCAT(Account.id, "-", Ledger.sequence) AS id_sequence';
|
||||||
|
return array_merge($fields,
|
||||||
|
$this->Ledger->LedgerEntry->debitCreditFields(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataConditions(&$params, &$model) {
|
||||||
|
$conditions = parent::gridDataConditions($params, $model);
|
||||||
|
|
||||||
|
if ($params['action'] === 'current') {
|
||||||
|
$conditions[] = array('Ledger.close_transaction_id' => null);
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'closed') {
|
||||||
|
$conditions[] = array('Ledger.close_transaction_id !=' => null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090811
|
||||||
|
// No security issues have been worked out yet
|
||||||
|
$conditions[] = array('Account.level >=' => 10);
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
$id_sequence = false;
|
||||||
|
if ($index === 'id_sequence') {
|
||||||
|
$id_sequence = true;
|
||||||
|
$index = 'Ledger.account_id';
|
||||||
|
}
|
||||||
|
|
||||||
|
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
||||||
|
|
||||||
|
if ($id_sequence) {
|
||||||
|
$order[] = 'Ledger.sequence ' . $direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Ledger'] = array('id_sequence');
|
||||||
|
$links['Account'] = array('name');
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific ledger
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
$ledger = $this->Ledger->find
|
||||||
|
('first',
|
||||||
|
array('contain' =>
|
||||||
|
array(// Models
|
||||||
|
'Account',
|
||||||
|
),
|
||||||
|
'conditions' => array(array('Ledger.id' => $id),
|
||||||
|
// REVISIT <AP>: 20090811
|
||||||
|
// No security issues have been worked out yet
|
||||||
|
array('Account.level >=' => 10),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (empty($ledger)) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get ledger stats for our summary box
|
||||||
|
$stats = $this->Ledger->stats($id);
|
||||||
|
|
||||||
|
// OK, set our view variables and render!
|
||||||
|
$title = 'Ledger: #' . $ledger['Account']['id'] .'-'. $ledger['Ledger']['sequence'];
|
||||||
|
$this->set(compact('ledger', 'title', 'stats'));
|
||||||
|
}
|
||||||
|
}
|
||||||
306
controllers/maps_controller.php
Normal file
306
controllers/maps_controller.php
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class MapsController extends AppController {
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / all
|
||||||
|
* - Generate a listing of maps
|
||||||
|
*
|
||||||
|
* REVISIT <AP> 20090528:
|
||||||
|
* We'll need to present only those site area maps that correspond
|
||||||
|
* to the users particular site.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function all() { $this->gridView('All Maps', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
return array
|
||||||
|
('link' => array('SiteArea' => array('fields' => array('SiteArea.id', 'SiteArea.name')),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Map'] = array('id');
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Generates a site map page
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null, $requested_width = 800) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
$this->set('info', $this->mapInfo($id, $requested_width));
|
||||||
|
$this->set('title', "Site Map");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: map
|
||||||
|
* - Produces a PNG site map image
|
||||||
|
*/
|
||||||
|
|
||||||
|
function map($id = null, $requested_width = 800) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
$this->image($this->mapInfo($id, $requested_width));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* mapInfo
|
||||||
|
*/
|
||||||
|
|
||||||
|
function mapInfo($id, $requested_width) {
|
||||||
|
// Set up array to hold the map information
|
||||||
|
$info = array('map_id' => $id,
|
||||||
|
'border' => true,
|
||||||
|
'units' => array());
|
||||||
|
|
||||||
|
// Find all of the map/unit information from this SiteArea
|
||||||
|
$map = $this->Map->find('first', array('contain' => false,
|
||||||
|
'conditions' => array('id' => $id)));
|
||||||
|
|
||||||
|
$units = $this->Map->Unit->find
|
||||||
|
('all',
|
||||||
|
array('link' =>
|
||||||
|
array('Map' =>
|
||||||
|
array('fields' => array()),
|
||||||
|
|
||||||
|
'CurrentLease' =>
|
||||||
|
array('fields' => array('id', 'paid_through_date',
|
||||||
|
$this->Map->Unit->CurrentLease->
|
||||||
|
delinquentField('CurrentLease')),
|
||||||
|
'Customer'),
|
||||||
|
|
||||||
|
'UnitSize' =>
|
||||||
|
array('fields' => array('id', 'depth', 'width',
|
||||||
|
'MapsUnit.pt_top',
|
||||||
|
'MapsUnit.pt_left',
|
||||||
|
'MapsUnit.transpose')),
|
||||||
|
),
|
||||||
|
'fields' => array('id', 'name', 'status'),
|
||||||
|
'conditions' => array('Map.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
/* pr(compact('map', 'units')); */
|
||||||
|
/* $this->render('/empty'); */
|
||||||
|
/* return; */
|
||||||
|
|
||||||
|
/*****
|
||||||
|
* The preference would be to leave all things "screen" related
|
||||||
|
* to reside in the view. However, two separate views need this
|
||||||
|
* information. The 'view' needs it to include a clickable map
|
||||||
|
* that corresponds to the map image, and of course, the 'map'
|
||||||
|
* (or 'image') view needs it to render the image. So, in the
|
||||||
|
* controller for now, unless I come up with a better idea.
|
||||||
|
*****/
|
||||||
|
|
||||||
|
// Get the overall site limits, and then compute the
|
||||||
|
// actual boundary extents, adjusting for a border
|
||||||
|
$boundary_adjustment = 12;
|
||||||
|
$bottom = 2*$boundary_adjustment + $map['Map']['depth'];
|
||||||
|
$right = 2*$boundary_adjustment + $map['Map']['width'];
|
||||||
|
|
||||||
|
// Scale things according to desired display width
|
||||||
|
$screen_adjustment_factor = $requested_width / $right;
|
||||||
|
|
||||||
|
// Define the overall canvas size
|
||||||
|
$info['width'] = $right * $screen_adjustment_factor;
|
||||||
|
$info['depth'] = $bottom * $screen_adjustment_factor;
|
||||||
|
|
||||||
|
// Go through each unit in the map, calculating the map location
|
||||||
|
foreach ($units AS $unit) {
|
||||||
|
$lft = $unit['MapsUnit']['pt_left'] + $boundary_adjustment;
|
||||||
|
$top = $unit['MapsUnit']['pt_top'] + $boundary_adjustment;
|
||||||
|
|
||||||
|
$width =
|
||||||
|
$unit['MapsUnit']['transpose']
|
||||||
|
? $unit['UnitSize']['depth']
|
||||||
|
: $unit['UnitSize']['width'];
|
||||||
|
|
||||||
|
$depth =
|
||||||
|
$unit['MapsUnit']['transpose']
|
||||||
|
? $unit['UnitSize']['width']
|
||||||
|
: $unit['UnitSize']['depth'];
|
||||||
|
|
||||||
|
$lft *= $screen_adjustment_factor;
|
||||||
|
$top *= $screen_adjustment_factor;
|
||||||
|
$width *= $screen_adjustment_factor;
|
||||||
|
$depth *= $screen_adjustment_factor;
|
||||||
|
|
||||||
|
$info['units'][] =
|
||||||
|
array( 'id' => $unit['Unit']['id'],
|
||||||
|
'name' => $unit['Unit']['name'],
|
||||||
|
'left' => $lft,
|
||||||
|
'right' => $lft + $width,
|
||||||
|
'top' => $top,
|
||||||
|
'bottom' => $top + $depth,
|
||||||
|
'width' => $width,
|
||||||
|
'depth' => $depth,
|
||||||
|
'n-s' => $unit['MapsUnit']['transpose'] ? 0 : 1,
|
||||||
|
'status' => (($unit['Unit']['status'] === 'OCCUPIED' &&
|
||||||
|
!empty($unit[0]['delinquent']))
|
||||||
|
? 'LATE' : $unit['Unit']['status']),
|
||||||
|
'data' => $unit,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pr($info); */
|
||||||
|
/* $this->render('/empty'); exit(); */
|
||||||
|
return $info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: legend
|
||||||
|
* - Produces a PNG color legend image
|
||||||
|
*/
|
||||||
|
|
||||||
|
function legend($id = null, $requested_width = 400) {
|
||||||
|
$status = array_keys($this->Map->Unit->activeStatusEnums());
|
||||||
|
$occupied_key = array_search('OCCUPIED', $status);
|
||||||
|
array_splice($status, $occupied_key+1, 0, array('LATE'));
|
||||||
|
|
||||||
|
$rows = 2;
|
||||||
|
$cols = (int)((count($status) + $rows - 1) / $rows);
|
||||||
|
|
||||||
|
$info = array('units' => array());
|
||||||
|
|
||||||
|
// Get the overall site limits, and then compute the
|
||||||
|
// actual boundary extents, adjusting for a border
|
||||||
|
$boundary_adjustment = 1;
|
||||||
|
$item_width = 40; // Absolute values are irrelevant, as they
|
||||||
|
$item_depth = 10; // will be scaled in the end anyway.
|
||||||
|
$bottom = 2*$boundary_adjustment + $rows*$item_depth;
|
||||||
|
$right = 2*$boundary_adjustment + $cols*$item_width;
|
||||||
|
|
||||||
|
// Scale things according to desired display width
|
||||||
|
$screen_adjustment_factor = $requested_width / $right;
|
||||||
|
|
||||||
|
// Define the overall canvas size
|
||||||
|
$info['width'] = $right * $screen_adjustment_factor;
|
||||||
|
$info['depth'] = $bottom * $screen_adjustment_factor;
|
||||||
|
|
||||||
|
// Get a starting point for our top left position.
|
||||||
|
$top = $lft = $boundary_adjustment;
|
||||||
|
|
||||||
|
// Scale it appropriately.
|
||||||
|
$top *= $screen_adjustment_factor;
|
||||||
|
$lft *= $screen_adjustment_factor;
|
||||||
|
$item_width *= $screen_adjustment_factor;
|
||||||
|
$item_depth *= $screen_adjustment_factor;
|
||||||
|
|
||||||
|
foreach ($status AS $code) {
|
||||||
|
$info['units'][] = array('name' => $code,
|
||||||
|
'status' => $code,
|
||||||
|
'width' => $item_width,
|
||||||
|
'depth' => $item_depth,
|
||||||
|
'left' => $lft,
|
||||||
|
'right' => $lft + $item_width,
|
||||||
|
'top' => $top,
|
||||||
|
'bottom' => $top + $item_depth);
|
||||||
|
$top += $item_depth;
|
||||||
|
if ($top >= $item_depth * $rows) {
|
||||||
|
$top = $boundary_adjustment * $screen_adjustment_factor;
|
||||||
|
$lft += $item_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->image($info, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* helper: image
|
||||||
|
* - used by actions map & legend to set up unit information and
|
||||||
|
* color palates before rendering the PNG image.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function image($info, $legend = false) {
|
||||||
|
$debug = false;
|
||||||
|
|
||||||
|
if (!$debug) {
|
||||||
|
$this->layout = null;
|
||||||
|
$this->autoLayout = false;
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define our color palate
|
||||||
|
// REVISIT <AP>: 20090513
|
||||||
|
// Get colors from DB option tables
|
||||||
|
$info['palate']['main']['layout']['bg'] = array('red' => 255, 'green' => 255, 'blue' => 255);
|
||||||
|
$info['palate']['main']['layout']['border'] = array('red' => 192, 'green' => 192, 'blue' => 192);
|
||||||
|
$info['palate']['main']['layout']['wall'] = array('red' => 0, 'green' => 0, 'blue' => 0);
|
||||||
|
$info['palate']['unit']['DELETED']['bg'] = array('red' => 0, 'green' => 0, 'blue' => 0);
|
||||||
|
$info['palate']['unit']['DAMAGED']['bg'] = array('red' => 192, 'green' => 128, 'blue' => 128);
|
||||||
|
$info['palate']['unit']['COMPANY']['bg'] = array('red' => 128, 'green' => 192, 'blue' => 128);
|
||||||
|
$info['palate']['unit']['UNAVAILABLE']['bg'] = array('red' => 128, 'green' => 128, 'blue' => 192);
|
||||||
|
$info['palate']['unit']['RESERVED']['bg'] = array('red' => 192, 'green' => 192, 'blue' => 128);
|
||||||
|
$info['palate']['unit']['DIRTY']['bg'] = array('red' => 128, 'green' => 192, 'blue' => 192);
|
||||||
|
$info['palate']['unit']['VACANT']['bg'] = array('red' => 0, 'green' => 255, 'blue' => 128);
|
||||||
|
$info['palate']['unit']['OCCUPIED']['bg'] = array('red' => 0, 'green' => 128, 'blue' => 255);
|
||||||
|
$info['palate']['unit']['LATE']['bg'] = array('red' => 255, 'green' => 192, 'blue' => 192);
|
||||||
|
$info['palate']['unit']['LOCKED']['bg'] = array('red' => 255, 'green' => 64, 'blue' => 64);
|
||||||
|
$info['palate']['unit']['LIENED']['bg'] = array('red' => 255, 'green' => 0, 'blue' => 128);
|
||||||
|
|
||||||
|
// Determine text color to go with each background
|
||||||
|
foreach ($info['palate']['unit'] AS &$code) {
|
||||||
|
$component = $code['bg'];
|
||||||
|
$method = 3;
|
||||||
|
if ($method == 1) {
|
||||||
|
foreach (array('red', 'green', 'blue') AS $prim)
|
||||||
|
$component[$prim] = 255 - $component[$prim];
|
||||||
|
} elseif ($method == 2) {
|
||||||
|
foreach (array('red', 'green', 'blue') AS $prim)
|
||||||
|
$component[$prim] = ($component[$prim]) >= 128 ? 0 : 255;
|
||||||
|
} elseif ($method == 3) {
|
||||||
|
$val = (sqrt(pow($component['red'], 2) +
|
||||||
|
pow($component['green'], 2) +
|
||||||
|
pow($component['blue'], 2)) >= sqrt(3) * 128) ? 0 : 255;
|
||||||
|
foreach (array('red', 'green', 'blue') AS $prim)
|
||||||
|
$component[$prim] = $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
$code['fg'] = $component;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->set(compact('info', 'debug'));
|
||||||
|
$this->render('image');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
321
controllers/statement_entries_controller.php
Normal file
321
controllers/statement_entries_controller.php
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class StatementEntriesController extends AppController {
|
||||||
|
|
||||||
|
var $sidemenu_links = array();
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / current / past / all
|
||||||
|
* - Creates a list of statement entries
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->gridView('All Statement Entries'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataCountTables(&$params, &$model) {
|
||||||
|
$link =
|
||||||
|
array(// Models
|
||||||
|
'Transaction' =>
|
||||||
|
array('fields' => array('id', 'stamp'),
|
||||||
|
),
|
||||||
|
|
||||||
|
'Customer' =>
|
||||||
|
array('fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
|
||||||
|
'Lease' =>
|
||||||
|
array('fields' => array('id', 'number'),
|
||||||
|
'Unit' =>
|
||||||
|
array('fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
'Account' =>
|
||||||
|
array('fields' => array('id', 'name', 'type'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!empty($params['post']['custom']['statement_entry_id'])) {
|
||||||
|
$link['ChargeEntry'] = array();
|
||||||
|
$link['DisbursementEntry'] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
return array('link' => $link);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
$tables = $this->gridDataCountTables($params, $model);
|
||||||
|
|
||||||
|
if (in_array('applied', $params['post']['fields'])) {
|
||||||
|
$tables['link'] +=
|
||||||
|
array('ChargeEntry' => array(),
|
||||||
|
'DisbursementEntry' => array());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFields(&$params, &$model) {
|
||||||
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
|
||||||
|
if (in_array('applied', $params['post']['fields'])) {
|
||||||
|
$fields[] = ("IF(StatementEntry.type = 'CHARGE'," .
|
||||||
|
" SUM(COALESCE(DisbursementEntry.amount,0))," .
|
||||||
|
" SUM(COALESCE(ChargeEntry.amount,0)))" .
|
||||||
|
" AS 'applied'");
|
||||||
|
}
|
||||||
|
if (in_array('unapplied', $params['post']['fields'])) {
|
||||||
|
$fields[] = ("StatementEntry.amount - (" .
|
||||||
|
"IF(StatementEntry.type = 'CHARGE'," .
|
||||||
|
" SUM(COALESCE(DisbursementEntry.amount,0))," .
|
||||||
|
" SUM(COALESCE(ChargeEntry.amount,0)))" .
|
||||||
|
") AS 'unapplied'");
|
||||||
|
}
|
||||||
|
|
||||||
|
$fields = array_merge($fields,
|
||||||
|
$this->StatementEntry->chargeDisbursementFields());
|
||||||
|
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataConditions(&$params, &$model) {
|
||||||
|
$conditions = parent::gridDataConditions($params, $model);
|
||||||
|
extract($params['post']['custom']);
|
||||||
|
|
||||||
|
if (!empty($from_date))
|
||||||
|
$conditions[]
|
||||||
|
= array('Transaction.stamp >=' =>
|
||||||
|
$this->StatementEntry->Transaction->dateFormatBeforeSave($from_date));
|
||||||
|
|
||||||
|
if (!empty($through_date))
|
||||||
|
$conditions[]
|
||||||
|
= array('Transaction.stamp <=' =>
|
||||||
|
$this->StatementEntry->Transaction->dateFormatBeforeSave($through_date . ' 23:59:59'));
|
||||||
|
|
||||||
|
if (isset($account_id))
|
||||||
|
$conditions[] = array('StatementEntry.account_id' => $account_id);
|
||||||
|
|
||||||
|
if (isset($customer_id))
|
||||||
|
$conditions[] = array('StatementEntry.customer_id' => $customer_id);
|
||||||
|
|
||||||
|
if (isset($statement_entry_id)) {
|
||||||
|
$conditions[] = array('OR' =>
|
||||||
|
array(array('ChargeEntry.id' => $statement_entry_id),
|
||||||
|
array('DisbursementEntry.id' => $statement_entry_id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($params['action'] === 'unreconciled') {
|
||||||
|
$query = array('conditions' => $conditions);
|
||||||
|
$set = $this->StatementEntry->reconciledSet('CHARGE', $query, true);
|
||||||
|
|
||||||
|
$entries = array();
|
||||||
|
foreach ($set['entries'] AS $entry)
|
||||||
|
$entries[] = $entry['StatementEntry']['id'];
|
||||||
|
|
||||||
|
$conditions[] = array('StatementEntry.id' => $entries);
|
||||||
|
$params['userdata']['balance'] = $set['summary']['balance'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['StatementEntry'] = array('id');
|
||||||
|
$links['Transaction'] = array('id');
|
||||||
|
$links['Account'] = array('name');
|
||||||
|
$links['Customer'] = array('name');
|
||||||
|
$links['Lease'] = array('number');
|
||||||
|
$links['Unit'] = array('name');
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
||||||
|
|
||||||
|
// After sorting by whatever the user wants, add these
|
||||||
|
// defaults into the sort mechanism. If we're already
|
||||||
|
// sorting by one of them, it will only be redundant,
|
||||||
|
// and should cause no harm (possible a longer query?)
|
||||||
|
$order[] = 'Transaction.stamp ' . $direction;
|
||||||
|
$order[] = 'StatementEntry.effective_date ' . $direction;
|
||||||
|
$order[] = 'StatementEntry.id ' . $direction;
|
||||||
|
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataRecordsExecute(&$params, &$model, $query) {
|
||||||
|
/* if ($params['action'] === '???') { */
|
||||||
|
/* $tquery = array_diff_key($query, array('fields'=>1,'group'=>1,'limit'=>1,'order'=>1)); */
|
||||||
|
/* $tquery['fields'] = array("IF(StatementEntry.type = 'CHARGE'," . */
|
||||||
|
/* " SUM(COALESCE(DisbursementEntry.amount,0))," . */
|
||||||
|
/* " SUM(COALESCE(ChargeEntry.amount,0)))" . */
|
||||||
|
/* " AS 'applied'", */
|
||||||
|
|
||||||
|
/* "StatementEntry.amount - (" . */
|
||||||
|
/* "IF(StatementEntry.type = 'CHARGE'," . */
|
||||||
|
/* " SUM(COALESCE(DisbursementEntry.amount,0))," . */
|
||||||
|
/* " SUM(COALESCE(ChargeEntry.amount,0)))" . */
|
||||||
|
/* ") AS 'balance'", */
|
||||||
|
/* ); */
|
||||||
|
|
||||||
|
/* //pr(compact('tquery')); */
|
||||||
|
/* $total = $model->find('first', $tquery); */
|
||||||
|
/* $params['userdata']['total'] = $total[0]['applied']; */
|
||||||
|
/* $params['userdata']['balance'] = $total[0]['balance']; */
|
||||||
|
/* } */
|
||||||
|
if ($params['action'] === 'collected') {
|
||||||
|
$tquery = array_diff_key($query, array('fields'=>1,'group'=>1,'limit'=>1,'order'=>1));
|
||||||
|
$tquery['fields'] = array("SUM(COALESCE(StatementEntry.amount,0)) AS 'total'");
|
||||||
|
$total = $model->find('first', $tquery);
|
||||||
|
$params['userdata']['total'] = $total[0]['total'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::gridDataRecordsExecute($params, $model, $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: reverse the ledger entry
|
||||||
|
*/
|
||||||
|
|
||||||
|
function reverse($id = null) {
|
||||||
|
if ($this->data) {
|
||||||
|
//pr($this->data); die();
|
||||||
|
|
||||||
|
$this->StatementEntry->reverse
|
||||||
|
($this->data['StatementEntry']['id'],
|
||||||
|
$this->data['Transaction']['stamp'],
|
||||||
|
$this->data['Transaction']['comment']);
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'view',
|
||||||
|
$this->data['StatementEntry']['id']));
|
||||||
|
$this->INTERNAL_ERROR('SHOULD HAVE REDIRECTED');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->StatementEntry->id = $id;
|
||||||
|
$entry = $this->StatementEntry->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array('Customer', 'Transaction', 'Account'),
|
||||||
|
));
|
||||||
|
|
||||||
|
if (empty($entry)) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('controller' => 'customers',
|
||||||
|
'action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->StatementEntry->reversable($id)) {
|
||||||
|
$this->Session->setFlash(__('Item not reversable.', true));
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = ("Charge #{$entry['StatementEntry']['id']}" .
|
||||||
|
" : {$entry['StatementEntry']['amount']}" .
|
||||||
|
" : Reverse");
|
||||||
|
$this->set(compact('entry', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: waive the ledger entry
|
||||||
|
*/
|
||||||
|
|
||||||
|
function waive($id) {
|
||||||
|
$this->StatementEntry->waive($id);
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific entry
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
$entry = $this->StatementEntry->find
|
||||||
|
('first',
|
||||||
|
array('contain' => array
|
||||||
|
('Transaction' => array('fields' => array('id', 'type', 'stamp')),
|
||||||
|
'Account' => array('id', 'name', 'type'),
|
||||||
|
'Customer' => array('fields' => array('id', 'name')),
|
||||||
|
'Lease' => array('fields' => array('id')),
|
||||||
|
),
|
||||||
|
|
||||||
|
'conditions' => array(array('StatementEntry.id' => $id),
|
||||||
|
// REVISIT <AP>: 20090811
|
||||||
|
// No security issues have been worked out yet
|
||||||
|
array('Account.level >=' => 5)
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
if (empty($entry)) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('controller' => 'accounts', 'action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$stats = $this->StatementEntry->stats($id);
|
||||||
|
|
||||||
|
if (in_array(strtoupper($entry['StatementEntry']['type']), $this->StatementEntry->debitTypes()))
|
||||||
|
$stats = $stats['Charge'];
|
||||||
|
else
|
||||||
|
$stats = $stats['Disbursement'];
|
||||||
|
|
||||||
|
|
||||||
|
if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE') {
|
||||||
|
|
||||||
|
$reversable = $this->StatementEntry->reversable($id);
|
||||||
|
|
||||||
|
// Set up dynamic menu items
|
||||||
|
if ($reversable || $stats['balance'] > 0)
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Operations', 'header' => true);
|
||||||
|
|
||||||
|
if ($reversable)
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Reverse',
|
||||||
|
'url' => array('action' => 'reverse',
|
||||||
|
$id));
|
||||||
|
|
||||||
|
if ($stats['balance'] > 0)
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Waive Balance',
|
||||||
|
'url' => array('action' => 'waive',
|
||||||
|
$id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = "Statement Entry #{$entry['StatementEntry']['id']}";
|
||||||
|
$this->set(compact('entry', 'title', 'stats'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
258
controllers/tenders_controller.php
Normal file
258
controllers/tenders_controller.php
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class TendersController extends AppController {
|
||||||
|
|
||||||
|
var $sidemenu_links = array();
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / all
|
||||||
|
* - Generate a listing of Tenders
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function all() { $this->gridView('All Legal Tender', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
return array
|
||||||
|
('link' =>
|
||||||
|
array('TenderType',
|
||||||
|
'Customer',
|
||||||
|
'LedgerEntry' =>
|
||||||
|
array('Transaction',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataRecordsExecute(&$params, &$model, $query) {
|
||||||
|
$tquery = array_diff_key($query, array('fields'=>1,'group'=>1,'limit'=>1,'order'=>1));
|
||||||
|
$tquery['fields'] = array("SUM(COALESCE(LedgerEntry.amount,0)) AS 'total'");
|
||||||
|
$total = $model->find('first', $tquery);
|
||||||
|
$params['userdata']['total'] = $total[0]['total'];
|
||||||
|
|
||||||
|
return parent::gridDataRecordsExecute($params, $model, $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessCalculatedFields(&$params, &$model, &$records) {
|
||||||
|
parent::gridDataPostProcessCalculatedFields($params, $model, $records);
|
||||||
|
foreach ($records AS &$record) {
|
||||||
|
// REVISIT <AP>: 20090730
|
||||||
|
// We really need the grid to handle this. We probably need to
|
||||||
|
// either create a hidden column with the nsf id, or pass back
|
||||||
|
// a list of nsf items as user data. We can then add an onload
|
||||||
|
// function to sweep through the nsf items and format them.
|
||||||
|
// For now... this works.
|
||||||
|
if (!empty($record['Tender']['nsf_transaction_id']))
|
||||||
|
$record['Tender']['name'] =
|
||||||
|
'<SPAN class="nsf-tender">' . $record['Tender']['name'] . '</SPAN>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Tender'] = array('name', 'id');
|
||||||
|
$links['Customer'] = array('name');
|
||||||
|
$links['TenderType'] = array('name');
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: deposit
|
||||||
|
* - Prepares the books for a bank deposit
|
||||||
|
*/
|
||||||
|
|
||||||
|
function deposit() {
|
||||||
|
// Prepare a close page...
|
||||||
|
$deposit_types = $this->Tender->TenderType->depositTypes(
|
||||||
|
// Testing... limit to only one type
|
||||||
|
//array('limit' => 1)
|
||||||
|
);
|
||||||
|
$deposit_accounts = $this->Tender->TenderType->Account->depositAccounts();
|
||||||
|
|
||||||
|
foreach ($deposit_types AS $type_id => &$type)
|
||||||
|
$type = array('id' => $type_id,
|
||||||
|
'name' => $type,
|
||||||
|
'stats' => $this->Tender->TenderType->stats($type_id));
|
||||||
|
|
||||||
|
//pr(compact('deposit_types', 'deposit_accounts'));
|
||||||
|
|
||||||
|
$title = 'Prepare Deposit';
|
||||||
|
$this->set(compact('title', 'deposit_types', 'deposit_accounts'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: nsf
|
||||||
|
* - Marks a tender as having insufficient funds.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function nsf($id = null) {
|
||||||
|
if ($this->data) {
|
||||||
|
$result = $this->Tender->nsf
|
||||||
|
($this->data['Tender']['id'],
|
||||||
|
$this->data['Transaction']['stamp'],
|
||||||
|
$this->data['Transaction']['comment']);
|
||||||
|
$this->redirect(array('controller' => 'tenders',
|
||||||
|
'action' => 'view',
|
||||||
|
$this->data['Tender']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->Tender->id = $id;
|
||||||
|
$tender = $this->Tender->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array('Customer', 'LedgerEntry' => array('Transaction')),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = "Tender #{$tender['Tender']['id']} : {$tender['Tender']['name']} : NSF";
|
||||||
|
$this->set(compact('tender', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific entry
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('controller' => 'accounts', 'action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the Tender and related fields
|
||||||
|
$this->Tender->id = $id;
|
||||||
|
$tender = $this->Tender->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array('TenderType', 'Customer', 'LedgerEntry' => array('Transaction')),
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
|
// Set up dynamic menu items
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Operations', 'header' => true);
|
||||||
|
|
||||||
|
// Watch out for the special "Closing" entries
|
||||||
|
if (!empty($tender['TenderType']['id']))
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Edit',
|
||||||
|
'url' => array('action' => 'edit',
|
||||||
|
$id));
|
||||||
|
|
||||||
|
if (!empty($tender['Tender']['deposit_transaction_id'])
|
||||||
|
&& empty($tender['Tender']['nsf_transaction_id'])
|
||||||
|
// Hard to tell what types of items can come back as NSF.
|
||||||
|
// For now, assume iff it is a named item, it can be NSF.
|
||||||
|
// (or if we're in development mode)
|
||||||
|
&& (!empty($tender['TenderType']['data1_name']) || !empty($this->params['dev']))
|
||||||
|
) {
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'NSF',
|
||||||
|
'url' => array('action' => 'nsf',
|
||||||
|
$id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = "Tender #{$tender['Tender']['id']} : {$tender['Tender']['name']}";
|
||||||
|
$this->set(compact('tender', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: edit
|
||||||
|
* - Edit tender information
|
||||||
|
*/
|
||||||
|
|
||||||
|
function edit($id = null) {
|
||||||
|
if (isset($this->data)) {
|
||||||
|
// Check to see if the operation was cancelled.
|
||||||
|
if (isset($this->params['form']['cancel'])) {
|
||||||
|
if (empty($this->data['Tender']['id']))
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Tender']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have tender data
|
||||||
|
if (empty($this->data['Tender']) || empty($this->data['Tender']['id']))
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
|
||||||
|
// Figure out which tender type was chosen
|
||||||
|
// REVISIT <AP>: 20090810; Not ready to change tender type
|
||||||
|
// $tender_type_id = $this->data['Tender']['tender_type_id'];
|
||||||
|
$tender_type_id = $this->Tender->field('tender_type_id');
|
||||||
|
if (empty($tender_type_id))
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Tender']['id']));
|
||||||
|
|
||||||
|
// Get data fields from the selected tender type
|
||||||
|
$this->data['Tender'] += $this->data['type'][$tender_type_id];
|
||||||
|
unset($this->data['type']);
|
||||||
|
|
||||||
|
// Save the tender and all associated data
|
||||||
|
$this->Tender->create();
|
||||||
|
$this->Tender->id = $this->data['Tender']['id'];
|
||||||
|
if (!$this->Tender->save($this->data, false)) {
|
||||||
|
$this->Session->setFlash("TENDER SAVE FAILED", true);
|
||||||
|
pr("TENDER SAVE FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'view', $this->Tender->id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($id) {
|
||||||
|
$this->data = $this->Tender->findById($id);
|
||||||
|
} else {
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$tender_types = $this->Tender->TenderType->find
|
||||||
|
('list', array('order' => array('name')));
|
||||||
|
$this->set(compact('tender_types'));
|
||||||
|
|
||||||
|
$types = $this->Tender->TenderType->find('all', array('contain' => false));
|
||||||
|
$this->set(compact('types'));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = ('Tender #' . $this->data['Tender']['id'] .
|
||||||
|
' : ' . $this->data['Tender']['name'] .
|
||||||
|
" : Edit");
|
||||||
|
$this->set(compact('title'));
|
||||||
|
}
|
||||||
|
}
|
||||||
496
controllers/transactions_controller.php
Normal file
496
controllers/transactions_controller.php
Normal file
@@ -0,0 +1,496 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class TransactionsController extends AppController {
|
||||||
|
|
||||||
|
var $components = array('RequestHandler');
|
||||||
|
|
||||||
|
var $sidemenu_links =
|
||||||
|
array(array('name' => 'Transactions', 'header' => true),
|
||||||
|
array('name' => 'All', 'url' => array('controller' => 'transactions', 'action' => 'all')),
|
||||||
|
array('name' => 'Invoices', 'url' => array('controller' => 'transactions', 'action' => 'invoice')),
|
||||||
|
array('name' => 'Receipts', 'url' => array('controller' => 'transactions', 'action' => 'receipt')),
|
||||||
|
array('name' => 'Deposits', 'url' => array('controller' => 'transactions', 'action' => 'deposit')),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / all
|
||||||
|
* - Generate a listing of transactions
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function all() { $this->gridView('All Transactions', 'all'); }
|
||||||
|
function invoice() { $this->gridView('Invoices'); }
|
||||||
|
function receipt() { $this->gridView('Receipts'); }
|
||||||
|
function deposit() {
|
||||||
|
$this->sidemenu_links = array
|
||||||
|
(array('name' => 'Operations', 'header' => true),
|
||||||
|
array('name' => 'New Deposit', 'url' => array('controller' => 'tenders',
|
||||||
|
'action' => 'deposit')));
|
||||||
|
$this->gridView('Deposits');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataCountTables(&$params, &$model) {
|
||||||
|
return array
|
||||||
|
('link' =>
|
||||||
|
array(// Models
|
||||||
|
'Account' => array('fields' => array()),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
$link = $this->gridDataCountTables($params, $model);
|
||||||
|
$link['link']['StatementEntry'] = array('fields' => array());
|
||||||
|
$link['link']['DepositTender'] = array('fields' => array());
|
||||||
|
return $link;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFields(&$params, &$model) {
|
||||||
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
//$fields[] = 'COUNT(StatementEntry.id) AS entries';
|
||||||
|
$fields[] = ("IF(Transaction.type = 'DEPOSIT'," .
|
||||||
|
" COUNT(DepositTender.id)," .
|
||||||
|
" COUNT(StatementEntry.id)) AS entries");
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataConditions(&$params, &$model) {
|
||||||
|
$conditions = parent::gridDataConditions($params, $model);
|
||||||
|
|
||||||
|
if (in_array($params['action'], array('invoice', 'receipt', 'deposit')))
|
||||||
|
$conditions[] = array('Transaction.type' => strtoupper($params['action']));
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090811
|
||||||
|
// No security issues have been worked out yet
|
||||||
|
$conditions[] = array('Account.level >=' => 5);
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Transaction'] = array('id', 'action' => ($params['action'] == 'deposit'
|
||||||
|
? 'deposit_slip' : 'view'));
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: postInvoice
|
||||||
|
* - handles the creation of a charge invoice
|
||||||
|
*/
|
||||||
|
|
||||||
|
function postInvoice() {
|
||||||
|
if (!$this->RequestHandler->isPost()) {
|
||||||
|
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->Transaction->addInvoice($this->data, null,
|
||||||
|
$this->data['Lease']['id'])) {
|
||||||
|
$this->Session->setFlash("INVOICE FAILED", true);
|
||||||
|
// REVISIT <AP> 20090706:
|
||||||
|
// Until we can work out the session problems,
|
||||||
|
// just die.
|
||||||
|
die("<H1>INVOICE FAILED</H1>");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->layout = null;
|
||||||
|
$this->autoLayout = false;
|
||||||
|
$this->autoRender = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: postReceipt
|
||||||
|
* - handles the creation of a receipt
|
||||||
|
*/
|
||||||
|
|
||||||
|
function postReceipt() {
|
||||||
|
if (!$this->RequestHandler->isPost()) {
|
||||||
|
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($this->data['Entry'] AS &$entry) {
|
||||||
|
$entry['Tender'] = $entry['type'][$entry['tender_type_id']];
|
||||||
|
unset($entry['type']);
|
||||||
|
unset($entry['tender_type_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->Transaction->addReceipt($this->data,
|
||||||
|
$this->data['Customer']['id'],
|
||||||
|
(isset($this->data['Lease']['id'])
|
||||||
|
? $this->data['Lease']['id']
|
||||||
|
: null ))) {
|
||||||
|
$this->Session->setFlash("RECEIPT FAILED", true);
|
||||||
|
// REVISIT <AP> 20090706:
|
||||||
|
// Until we can work out the session problems,
|
||||||
|
// just die.
|
||||||
|
die("<H1>RECEIPT FAILED</H1>");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->layout = null;
|
||||||
|
$this->autoLayout = false;
|
||||||
|
$this->autoRender = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: postDeposit
|
||||||
|
* - handles the creation of a deposit transaction
|
||||||
|
*/
|
||||||
|
|
||||||
|
function postDeposit() {
|
||||||
|
if (!$this->RequestHandler->isPost()) {
|
||||||
|
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//pr($this->data);
|
||||||
|
|
||||||
|
// Go through each type of tender presented to the user
|
||||||
|
// Determine which are to be deposited, and which are to
|
||||||
|
// have their corresponding account ledgers closed.
|
||||||
|
$deposit_tender_ids = array();
|
||||||
|
$deposit_type_ids = array();
|
||||||
|
$close_type_ids = array();
|
||||||
|
foreach ($this->data['TenderType'] AS $type_id => $type) {
|
||||||
|
$type['items'] = unserialize($type['items']);
|
||||||
|
if (empty($type['selection']) ||
|
||||||
|
$type['selection'] === 'none' ||
|
||||||
|
($type['selection'] === 'subset' && count($type['items']) == 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// The deposit includes either the whole type, or just certain tenders
|
||||||
|
if ($type['selection'] === 'all')
|
||||||
|
$deposit_type_ids[] = $type_id;
|
||||||
|
else
|
||||||
|
$deposit_tender_ids = array_merge($deposit_tender_ids, $type['items']);
|
||||||
|
|
||||||
|
// Should we close the ledger for this tender type?
|
||||||
|
// First, the user would have to request that we do so,
|
||||||
|
// but additionally, we shouldn't close a ledger unless
|
||||||
|
// all the tenders are included in this deposit. That
|
||||||
|
// doesn't guarantee that the ledger has a zero balance,
|
||||||
|
// but it does carry the balance forward, and a total
|
||||||
|
// deposit would imply a fresh start, so go for it.
|
||||||
|
if (!empty($type['close']) && $type['selection'] === 'all')
|
||||||
|
$close_type_ids[] = $type_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we actually have something to deposit
|
||||||
|
if (empty($deposit_type_ids) && empty($deposit_tender_ids)) {
|
||||||
|
$this->Session->setFlash(__('Nothing to Deposit', true));
|
||||||
|
$this->redirect(array('controller' => 'tenders', 'action'=>'deposit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build up a set of conditions based on user selection
|
||||||
|
$deposit_conditions = array();
|
||||||
|
if (!empty($deposit_type_ids))
|
||||||
|
$deposit_conditions[] = array('TenderType.id' => $deposit_type_ids);
|
||||||
|
if (!empty($deposit_tender_ids))
|
||||||
|
$deposit_conditions[] = array('DepositTender.id' => $deposit_tender_ids);
|
||||||
|
|
||||||
|
// Add in confirmation that items have not already been deposited
|
||||||
|
$deposit_conditions =
|
||||||
|
array(array('DepositTender.deposit_transaction_id' => null),
|
||||||
|
array('OR' => $deposit_conditions));
|
||||||
|
|
||||||
|
// Lookup the items to be deposited
|
||||||
|
$tenders = $this->Transaction->DepositTender->find
|
||||||
|
('all',
|
||||||
|
array('contain' => array('TenderType', 'LedgerEntry'),
|
||||||
|
'conditions' => $deposit_conditions,
|
||||||
|
));
|
||||||
|
|
||||||
|
// Build the deposit transaction
|
||||||
|
$deposit = array('Transaction' => array(), 'Entry' => array());
|
||||||
|
foreach ($tenders AS $tender) {
|
||||||
|
$deposit['Entry'][] =
|
||||||
|
array('tender_id' => $tender['DepositTender']['id'],
|
||||||
|
'account_id' => $tender['LedgerEntry']['account_id'],
|
||||||
|
'amount' => $tender['LedgerEntry']['amount'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//pr(compact('deposit_type_ids', 'deposit_tender_ids', 'close_type_ids', 'deposit_conditions', 'deposit'));
|
||||||
|
|
||||||
|
// OK, perform the deposit and associated accounting
|
||||||
|
$result = $this->Transaction->addDeposit
|
||||||
|
($deposit, $this->data['Deposit']['Account']['id']);
|
||||||
|
//pr(compact('deposit', 'result'));
|
||||||
|
|
||||||
|
// Close any ledgers necessary
|
||||||
|
if (!empty($close_type_ids)) {
|
||||||
|
// Find the accounts associated with the types to close ...
|
||||||
|
$accounts = $this->Transaction->DepositTender->find
|
||||||
|
('all',
|
||||||
|
array('contain' => array('TenderType.account_id'),
|
||||||
|
'conditions' => array(array('TenderType.id' => $close_type_ids)),
|
||||||
|
));
|
||||||
|
|
||||||
|
// ... and close them
|
||||||
|
$this->Transaction->Account->closeCurrentLedgers
|
||||||
|
(array_map(create_function('$item', 'return $item["TenderType"]["account_id"];'), $accounts));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look out for errors
|
||||||
|
if ($result['error']) {
|
||||||
|
$this->Session->setFlash(__('Unable to Create Deposit', true));
|
||||||
|
$this->redirect(array('controller' => 'tenders', 'action'=>'deposit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Present the deposit slip to the user
|
||||||
|
$this->redirect(array('controller' => 'transactions',
|
||||||
|
'action' => 'deposit_slip',
|
||||||
|
$result['transaction_id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: postWriteOff
|
||||||
|
* - handles the write off of bad debt
|
||||||
|
*/
|
||||||
|
|
||||||
|
function postWriteOff() {
|
||||||
|
if (!$this->RequestHandler->isPost()) {
|
||||||
|
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $this->data;
|
||||||
|
if (empty($data['Customer']['id']))
|
||||||
|
$data['Customer']['id'] = null;
|
||||||
|
if (empty($data['Lease']['id']))
|
||||||
|
$data['Lease']['id'] = null;
|
||||||
|
|
||||||
|
pr(compact('data'));
|
||||||
|
|
||||||
|
if (!$this->Transaction->addWriteOff($data,
|
||||||
|
$data['Customer']['id'],
|
||||||
|
$data['Lease']['id'])) {
|
||||||
|
$this->Session->setFlash("WRITE OFF FAILED", true);
|
||||||
|
// REVISIT <AP> 20090706:
|
||||||
|
// Until we can work out the session problems,
|
||||||
|
// just die.
|
||||||
|
die("<H1>WRITE-OFF FAILED</H1>");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return to viewing the lease/customer
|
||||||
|
if (empty($data['Lease']['id']))
|
||||||
|
$this->redirect(array('controller' => 'customers',
|
||||||
|
'action' => 'view',
|
||||||
|
$data['Customer']['id']));
|
||||||
|
else
|
||||||
|
$this->redirect(array('controller' => 'leases',
|
||||||
|
'action' => 'view',
|
||||||
|
$data['Lease']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: postRefund
|
||||||
|
* - handles issuing a customer refund
|
||||||
|
*/
|
||||||
|
|
||||||
|
function postRefund() {
|
||||||
|
if (!$this->RequestHandler->isPost()) {
|
||||||
|
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $this->data;
|
||||||
|
if (empty($data['Customer']['id']))
|
||||||
|
$data['Customer']['id'] = null;
|
||||||
|
if (empty($data['Lease']['id']))
|
||||||
|
$data['Lease']['id'] = null;
|
||||||
|
|
||||||
|
if (!$this->Transaction->addRefund($data,
|
||||||
|
$data['Customer']['id'],
|
||||||
|
$data['Lease']['id'])) {
|
||||||
|
$this->Session->setFlash("REFUND FAILED", true);
|
||||||
|
// REVISIT <AP> 20090706:
|
||||||
|
// Until we can work out the session problems,
|
||||||
|
// just die.
|
||||||
|
die("<H1>REFUND FAILED</H1>");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return to viewing the lease/customer
|
||||||
|
if (empty($data['Lease']['id']))
|
||||||
|
$this->redirect(array('controller' => 'customers',
|
||||||
|
'action' => 'view',
|
||||||
|
$data['Customer']['id']));
|
||||||
|
else
|
||||||
|
$this->redirect(array('controller' => 'leases',
|
||||||
|
'action' => 'view',
|
||||||
|
$data['Lease']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: destroy
|
||||||
|
* - Deletes a transaction and associated entries
|
||||||
|
* - !!WARNING!! This should be used with EXTREME caution, as it
|
||||||
|
* irreversibly destroys the data. It is not for normal use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function destroy($id = null) {
|
||||||
|
$this->Transaction->destroy($id);
|
||||||
|
//$this->redirect(array('action' => 'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific transaction
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
$transaction = $this->Transaction->find
|
||||||
|
('first',
|
||||||
|
array('contain' =>
|
||||||
|
array(// Models
|
||||||
|
'Account(id,name)',
|
||||||
|
'Ledger(id,name)',
|
||||||
|
'NsfTender(id,name)',
|
||||||
|
),
|
||||||
|
'conditions' => array(array('Transaction.id' => $id),
|
||||||
|
// REVISIT <AP>: 20090811
|
||||||
|
// No security issues have been worked out yet
|
||||||
|
array('OR' =>
|
||||||
|
array(array('Account.level >=' => 5),
|
||||||
|
array('Account.id' => null))),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090815
|
||||||
|
// for debug purposes only (pr output)
|
||||||
|
$this->Transaction->stats($id);
|
||||||
|
|
||||||
|
if (empty($transaction)) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($transaction['Transaction']['type'] === 'DEPOSIT' || $this->params['dev']) {
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Operations', 'header' => true);
|
||||||
|
|
||||||
|
if ($transaction['Transaction']['type'] === 'DEPOSIT')
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'View Slip', 'url' => array('action' => 'deposit_slip', $id));
|
||||||
|
if ($this->params['dev'])
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Destroy', 'url' => array('action' => 'destroy', $id),
|
||||||
|
'confirmMessage' => ("This may leave the database in an unstable state." .
|
||||||
|
" Do NOT do this unless you know what you're doing." .
|
||||||
|
" Proceed anyway?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// OK, prepare to render.
|
||||||
|
$title = 'Transaction #' . $transaction['Transaction']['id'];
|
||||||
|
$this->set(compact('transaction', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: deposit_slip
|
||||||
|
* - Special presentation
|
||||||
|
* Processes the user input and updates the database
|
||||||
|
*/
|
||||||
|
|
||||||
|
function deposit_slip($id) {
|
||||||
|
// Build a container for the deposit slip data
|
||||||
|
$deposit = array('types' => array());
|
||||||
|
|
||||||
|
$this->id = $id;
|
||||||
|
$deposit +=
|
||||||
|
$this->Transaction->find('first', array('contain' => false));
|
||||||
|
|
||||||
|
// Get a summary of all forms of tender in the deposit
|
||||||
|
$result = $this->Transaction->find
|
||||||
|
('all',
|
||||||
|
array('link' => array('DepositTender' =>
|
||||||
|
array('fields' => array(),
|
||||||
|
'TenderType',
|
||||||
|
'LedgerEntry' =>
|
||||||
|
array('fields' => array()))),
|
||||||
|
'fields' => array(//'TenderType.id', 'TenderType.name',
|
||||||
|
"COUNT(DepositTender.id) AS 'count'",
|
||||||
|
"SUM(LedgerEntry.amount) AS 'total'"),
|
||||||
|
//'conditions' => array(array('DepositTender.deposit_transaction_id' => $id)),
|
||||||
|
'conditions' => array(array('Transaction.id' => $id)),
|
||||||
|
'group' => 'TenderType.id',
|
||||||
|
));
|
||||||
|
|
||||||
|
if (empty($result)) {
|
||||||
|
die();
|
||||||
|
$this->Session->setFlash(__('Invalid Deposit.', true));
|
||||||
|
$this->redirect(array('action'=>'deposit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the summary to our deposit slip data container
|
||||||
|
foreach ($result AS $type) {
|
||||||
|
$deposit['types'][$type['TenderType']['id']] =
|
||||||
|
$type['TenderType'] + $type[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$deposit_total = 0;
|
||||||
|
foreach ($deposit['types'] AS $type)
|
||||||
|
$deposit_total += $type['total'];
|
||||||
|
|
||||||
|
if ($deposit['Transaction']['amount'] != $deposit_total)
|
||||||
|
$this->INTERNAL_ERROR("Deposit items do not add up to deposit slip total");
|
||||||
|
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Operations', 'header' => true);
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'View Transaction', 'url' => array('action' => 'view', $id));
|
||||||
|
|
||||||
|
$title = 'Deposit Slip';
|
||||||
|
$this->set(compact('title', 'deposit'));
|
||||||
|
$this->render('deposit_slip');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
336
controllers/units_controller.php
Normal file
336
controllers/units_controller.php
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class UnitsController extends AppController {
|
||||||
|
|
||||||
|
var $sidemenu_links =
|
||||||
|
array(array('name' => 'Units', 'header' => true),
|
||||||
|
array('name' => 'Occupied', 'url' => array('controller' => 'units', 'action' => 'occupied')),
|
||||||
|
array('name' => 'Vacant', 'url' => array('controller' => 'units', 'action' => 'vacant')),
|
||||||
|
array('name' => 'Unavailable', 'url' => array('controller' => 'units', 'action' => 'unavailable')),
|
||||||
|
array('name' => 'All', 'url' => array('controller' => 'units', 'action' => 'all')),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / unavailable / vacant / occupied / all
|
||||||
|
* - Generate a listing of units
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function unavailable() { $this->gridView('Unavailable Units'); }
|
||||||
|
function vacant() { $this->gridView('Vacant Units'); }
|
||||||
|
function occupied() { $this->gridView('Occupied Units'); }
|
||||||
|
function all() { $this->gridView('All Units', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataSetup(&$params) {
|
||||||
|
parent::gridDataSetup($params);
|
||||||
|
if (!isset($params['action']))
|
||||||
|
$params['action'] = 'all';
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataCountTables(&$params, &$model) {
|
||||||
|
return array
|
||||||
|
('link' => array('UnitSize' => array('fields' => array('id', 'name')),
|
||||||
|
'CurrentLease' => array('fields' => array('id'))));
|
||||||
|
|
||||||
|
/* if ($params['action'] === 'occupied') */
|
||||||
|
/* $link['Lease'] = array('fields' => array(), */
|
||||||
|
/* // Models */
|
||||||
|
/* 'Contact' => array('fields' => array('display_name'), */
|
||||||
|
/* //'type' => 'LEFT', */
|
||||||
|
/* ), */
|
||||||
|
/* ); */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
$link = $this->gridDataCountTables($params, $model);
|
||||||
|
$link['link']['CurrentLease']['StatementEntry'] = array('fields' => array());
|
||||||
|
return $link;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* function gridDataTables(&$params, &$model) { */
|
||||||
|
/* return array */
|
||||||
|
/* ('link' => array('Unit' => array('fields' => array('Unit.id', 'Unit.name')), */
|
||||||
|
/* 'Customer' => array('fields' => array('Customer.id', 'Customer.name')))); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
function gridDataFields(&$params, &$model) {
|
||||||
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
|
||||||
|
return array_merge($fields,
|
||||||
|
$this->Unit->Lease->StatementEntry->chargeDisbursementFields(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataConditions(&$params, &$model) {
|
||||||
|
$conditions = parent::gridDataConditions($params, $model);
|
||||||
|
|
||||||
|
if ($params['action'] === 'unavailable') {
|
||||||
|
$conditions[] = $this->Unit->conditionUnavailable();
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'vacant') {
|
||||||
|
$conditions[] = $this->Unit->conditionVacant();
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'occupied') {
|
||||||
|
$conditions[] = $this->Unit->conditionOccupied();
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'unoccupied') {
|
||||||
|
$conditions[] = array('NOT' => array($this->Unit->conditionOccupied()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
// Instead of sorting by name, sort by defined order
|
||||||
|
if ($index === 'Unit.name')
|
||||||
|
$index = 'Unit.sort_order';
|
||||||
|
|
||||||
|
$order = array();
|
||||||
|
$order[] = parent::gridDataOrder($params, $model, $index, $direction);
|
||||||
|
|
||||||
|
// If sorting by anything other than name (defined order)
|
||||||
|
// add the sort-order as a secondary condition
|
||||||
|
if ($index !== 'Unit.name')
|
||||||
|
$order[] = parent::gridDataOrder($params, $model,
|
||||||
|
'Unit.sort_order', $direction);
|
||||||
|
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Unit'] = array('name');
|
||||||
|
$links['UnitSize'] = array('name');
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: move_in
|
||||||
|
* - Sets up the move-in page for the given unit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function move_in($id = null) {
|
||||||
|
$customer = array();
|
||||||
|
$unit = array();
|
||||||
|
|
||||||
|
if (isset($id)) {
|
||||||
|
$this->Unit->recursive = -1;
|
||||||
|
$unit = current($this->Unit->read(null, $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
$title = 'Unit Move-In';
|
||||||
|
$this->set(compact('customer', 'unit', 'title'));
|
||||||
|
$this->render('/leases/move');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: move_out
|
||||||
|
* - prepare or execute a move out on a specific lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function move_out($id) {
|
||||||
|
|
||||||
|
$unit = $this->Unit->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'CurrentLease' =>
|
||||||
|
array(//'conditions' => array('Lease.moveout_date' => null),
|
||||||
|
// Models
|
||||||
|
'Customer' =>
|
||||||
|
array('fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'conditions' => array('Unit.id' => $id),
|
||||||
|
));
|
||||||
|
$this->set('customer', $unit['CurrentLease']['Customer']);
|
||||||
|
$this->set('unit', $unit['Unit']);
|
||||||
|
$this->set('lease', $unit['CurrentLease']);
|
||||||
|
|
||||||
|
$redirect = array('controller' => 'units',
|
||||||
|
'action' => 'view',
|
||||||
|
$id);
|
||||||
|
|
||||||
|
$title = ('Lease #' . $unit['CurrentLease']['number'] . ': ' .
|
||||||
|
$unit['Unit']['name'] . ': ' .
|
||||||
|
$unit['CurrentLease']['Customer']['name'] . ': Prepare Move-Out');
|
||||||
|
$this->set(compact('title', 'redirect'));
|
||||||
|
$this->render('/leases/move');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific unit
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>''));
|
||||||
|
}
|
||||||
|
|
||||||
|
$unit = $this->Unit->find
|
||||||
|
('first',
|
||||||
|
array('contain' =>
|
||||||
|
array(// Models
|
||||||
|
'UnitSize',
|
||||||
|
'Lease' => array('Customer'),
|
||||||
|
'CurrentLease' => array('Customer')
|
||||||
|
),
|
||||||
|
'conditions' => array('Unit.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Get the balance on each lease.
|
||||||
|
foreach ($unit['Lease'] AS &$lease) {
|
||||||
|
$stats = $this->Unit->Lease->stats($lease['id']);
|
||||||
|
$lease['balance'] = $stats['balance'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$outstanding_balance = 0;
|
||||||
|
$outstanding_deposit = 0;
|
||||||
|
if (isset($unit['CurrentLease']['id'])) {
|
||||||
|
// Figure out the outstanding balance of the current lease.
|
||||||
|
$stats = $this->Unit->stats($id);
|
||||||
|
$outstanding_balance =
|
||||||
|
$stats['CurrentLease']['balance'];
|
||||||
|
|
||||||
|
// Figure out the total security deposit for the current lease.
|
||||||
|
$deposits = $this->Unit->Lease->securityDeposits($unit['CurrentLease']['id']);
|
||||||
|
$outstanding_deposit = $this->Unit->Lease->securityDepositBalance($unit['CurrentLease']['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up dynamic menu items
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Operations', 'header' => true);
|
||||||
|
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Edit', 'url' => array('action' => 'edit',
|
||||||
|
$id));
|
||||||
|
|
||||||
|
if (isset($unit['CurrentLease']['id']) &&
|
||||||
|
!isset($unit['CurrentLease']['moveout_date'])) {
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Move-Out', 'url' => array('action' => 'move_out',
|
||||||
|
$id));
|
||||||
|
} elseif ($this->Unit->available($unit['Unit']['status'])) {
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Move-In', 'url' => array('action' => 'move_in',
|
||||||
|
$id));
|
||||||
|
} else {
|
||||||
|
// Unit is unavailable (dirty, damaged, reserved, business-use, etc)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($unit['CurrentLease']['id']) &&
|
||||||
|
!isset($unit['CurrentLease']['close_date'])) {
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'New Invoice', 'url' => array('controller' => 'leases',
|
||||||
|
'action' => 'invoice',
|
||||||
|
$unit['CurrentLease']['id']));
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'New Receipt', 'url' => array('controller' => 'customers',
|
||||||
|
'action' => 'receipt',
|
||||||
|
$unit['CurrentLease']['customer_id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = 'Unit ' . $unit['Unit']['name'];
|
||||||
|
$this->set(compact('unit', 'title',
|
||||||
|
'outstanding_balance',
|
||||||
|
'outstanding_deposit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: edit
|
||||||
|
* - Edit unit information
|
||||||
|
*/
|
||||||
|
|
||||||
|
function edit($id = null) {
|
||||||
|
if (isset($this->data)) {
|
||||||
|
// Check to see if the operation was cancelled.
|
||||||
|
if (isset($this->params['form']['cancel'])) {
|
||||||
|
if (empty($this->data['Unit']['id']))
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Unit']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have unit data
|
||||||
|
if (empty($this->data['Unit']))
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
|
||||||
|
// Make sure we have a rental rate
|
||||||
|
if (empty($this->data['Unit']['rent']))
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Unit']['id']));
|
||||||
|
|
||||||
|
// Save the unit and all associated data
|
||||||
|
$this->Unit->create();
|
||||||
|
$this->Unit->id = $this->data['Unit']['id'];
|
||||||
|
if (!$this->Unit->save($this->data, false)) {
|
||||||
|
$this->Session->setFlash("UNIT SAVE FAILED", true);
|
||||||
|
pr("UNIT SAVE FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'view', $this->Unit->id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($id) {
|
||||||
|
$this->data = $this->Unit->findById($id);
|
||||||
|
$title = 'Unit ' . $this->data['Unit']['name'] . " : Edit";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$title = "Enter New Unit";
|
||||||
|
$this->data = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$statusEnums = $this->Unit->allowedStatusSet($id);
|
||||||
|
$statusEnums = array_combine(array_keys($statusEnums),
|
||||||
|
array_keys($statusEnums));
|
||||||
|
$this->set(compact('statusEnums'));
|
||||||
|
|
||||||
|
$unit_sizes = $this->Unit->UnitSize->find
|
||||||
|
('list', array('order' => array('unit_type_id', 'width', 'depth', 'id')));
|
||||||
|
$this->set(compact('unit_sizes'));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
pr($this->data);
|
||||||
|
$this->set(compact('title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
24
index.php
Normal file
24
index.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: index.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||||
|
/**
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.app
|
||||||
|
* @since CakePHP(tm) v 0.10.0.1076
|
||||||
|
* @version $Revision: 7945 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
require 'webroot' . DIRECTORY_SEPARATOR . 'index.php';
|
||||||
|
?>
|
||||||
389
models/account.php
Normal file
389
models/account.php
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
<?php
|
||||||
|
class Account extends AppModel {
|
||||||
|
|
||||||
|
var $hasOne = array(
|
||||||
|
'CurrentLedger' => array(
|
||||||
|
'className' => 'Ledger',
|
||||||
|
// REVISIT <AP> 20090702:
|
||||||
|
// I would prefer this statement, which has no
|
||||||
|
// engine specific code. However, it doesn't
|
||||||
|
// work with the Linkable behavior. I need to
|
||||||
|
// look into that, just not right now.
|
||||||
|
//'conditions' => array(array('CurrentLedger.close_transaction_id' => null)),
|
||||||
|
'conditions' => array('CurrentLedger.close_transaction_id IS NULL'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'Ledger',
|
||||||
|
'LedgerEntry',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: type
|
||||||
|
* - Returns the type of this account
|
||||||
|
*/
|
||||||
|
function type($id) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$account = $this->find('first', array
|
||||||
|
('recursive' => -1,
|
||||||
|
'fields' => array('type'),
|
||||||
|
'conditions' => array(array('Account.id' => $id)),
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
return $account['Account']['type'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: fundamentalType
|
||||||
|
* - Returns the fundmental type of the account, credit or debit
|
||||||
|
*/
|
||||||
|
function fundamentalType($id_or_type) {
|
||||||
|
if (is_numeric($id_or_type))
|
||||||
|
$type = $this->type($id_or_type);
|
||||||
|
else
|
||||||
|
$type = $id_or_type;
|
||||||
|
|
||||||
|
// Asset and Expense accounts are debit accounts
|
||||||
|
if (in_array(strtoupper($type), array('ASSET', 'EXPENSE')))
|
||||||
|
return 'debit';
|
||||||
|
|
||||||
|
// Otherwise, it's a credit account
|
||||||
|
return 'credit';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: fundamentalOpposite
|
||||||
|
* - Returns the opposite fundmental type of the account, credit or debit
|
||||||
|
*/
|
||||||
|
function fundamentalOpposite($id_or_type) {
|
||||||
|
if (in_array(strtolower($id_or_type), array('credit', 'debit')))
|
||||||
|
$fund = $id_or_type;
|
||||||
|
else
|
||||||
|
$fund = $this->fundamentalType($id_or_type);
|
||||||
|
|
||||||
|
if (strtolower($fund) == 'debit')
|
||||||
|
return 'credit';
|
||||||
|
|
||||||
|
return 'debit';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: name
|
||||||
|
* - Returns the name of this account
|
||||||
|
*/
|
||||||
|
function name($id) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$account = $this->find('first', array
|
||||||
|
('recursive' => -1,
|
||||||
|
'fields' => array('name'),
|
||||||
|
'conditions' => array(array('Account.id' => $id)),
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
return $account['Account']['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: debitCreditFields
|
||||||
|
* - Returns the fields necessary to determine whether the queried
|
||||||
|
* entries are a debit, or a credit, and also the effect each have
|
||||||
|
* on the overall balance of the account.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function debitCreditFields($sum = false, $balance = true,
|
||||||
|
$entry_name = 'LedgerEntry', $account_name = 'Account') {
|
||||||
|
return $this->LedgerEntry->debitCreditFields
|
||||||
|
($sum, $balance, $entry_name, $account_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: Account IDs
|
||||||
|
* - Returns the ID of the desired account
|
||||||
|
*/
|
||||||
|
|
||||||
|
function lookup($name, $check = true) {
|
||||||
|
$id = $this->nameToID($name);
|
||||||
|
if (empty($id) && $check)
|
||||||
|
$this->INTERNAL_ERROR("Missing Account '$name'");
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function securityDepositAccountID() { return $this->lookup('Security Deposit'); }
|
||||||
|
function rentAccountID() { return $this->lookup('Rent'); }
|
||||||
|
function lateChargeAccountID() { return $this->lookup('Late Charge'); }
|
||||||
|
function nsfAccountID() { return $this->lookup('NSF'); }
|
||||||
|
function nsfChargeAccountID() { return $this->lookup('NSF Charge'); }
|
||||||
|
function taxAccountID() { return $this->lookup('Tax'); }
|
||||||
|
function accountReceivableAccountID() { return $this->lookup('A/R'); }
|
||||||
|
function accountPayableAccountID() { return $this->lookup('A/P'); }
|
||||||
|
function cashAccountID() { return $this->lookup('Cash'); }
|
||||||
|
function checkAccountID() { return $this->lookup('Check'); }
|
||||||
|
function moneyOrderAccountID() { return $this->lookup('Money Order'); }
|
||||||
|
function achAccountID() { return $this->lookup('ACH'); }
|
||||||
|
function concessionAccountID() { return $this->lookup('Concession'); }
|
||||||
|
function waiverAccountID() { return $this->lookup('Waiver'); }
|
||||||
|
function pettyCashAccountID() { return $this->lookup('Petty Cash'); }
|
||||||
|
function invoiceAccountID() { return $this->lookup('Invoice'); }
|
||||||
|
function receiptAccountID() { return $this->lookup('Receipt'); }
|
||||||
|
function badDebtAccountID() { return $this->lookup('Bad Debt'); }
|
||||||
|
function customerCreditAccountID() { return $this->lookup(
|
||||||
|
// REVISIT <AP>: 20090816
|
||||||
|
// Use of A/R works, and saves an excess of accounts.
|
||||||
|
// However, a dedicated account is nice, since it can
|
||||||
|
// quickly be spotted how much is _really_ due, vs
|
||||||
|
// how much has been pre-paid. Customer credits in
|
||||||
|
// A/R is not as clear, although a report is an
|
||||||
|
// obvious solution.
|
||||||
|
//'A/R'
|
||||||
|
'Credit'
|
||||||
|
); }
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: fundamentalAccounts
|
||||||
|
* - Returns an array of accounts by their fundamental type
|
||||||
|
*/
|
||||||
|
|
||||||
|
function fundamentalAccounts($ftype) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$account = $this->find('all', array
|
||||||
|
('contain' => array('CurrentLedger'),
|
||||||
|
'fields' => array('Account.id', 'Account.type', 'Account.name', 'CurrentLedger.id'),
|
||||||
|
'conditions' => array('Account.type' => strtoupper($ftype))
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
return $account;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: relatedAccounts
|
||||||
|
* - Returns an array of accounts related by similar attributes
|
||||||
|
*/
|
||||||
|
|
||||||
|
function relatedAccounts($attribute, $extra = null) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$accounts = $this->find('all', array
|
||||||
|
('contain' => array('CurrentLedger'),
|
||||||
|
'fields' => array('Account.id', 'Account.type', 'Account.name', 'CurrentLedger.id'),
|
||||||
|
'conditions' => array('Account.'.$attribute => true),
|
||||||
|
'order' => array('Account.name'),
|
||||||
|
) + (isset($extra) ? $extra : array())
|
||||||
|
);
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
// Rearrange to be of the form (id => name)
|
||||||
|
$rel_accounts = array();
|
||||||
|
foreach ($accounts AS $acct) {
|
||||||
|
$rel_accounts[$acct['Account']['id']] = $acct['Account']['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rel_accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: xxxAccounts
|
||||||
|
* - Returns an array of accounts suitable for activity xxx
|
||||||
|
*/
|
||||||
|
|
||||||
|
function invoiceAccounts() {
|
||||||
|
return $this->relatedAccounts('invoices', array('order' => 'name'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function receiptAccounts() {
|
||||||
|
return $this->relatedAccounts('receipts', array('order' => 'name'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function depositAccounts() {
|
||||||
|
return $this->relatedAccounts('deposits', array('order' => 'name'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function refundAccounts() {
|
||||||
|
return $this->relatedAccounts('refunds', array('order' => 'name'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: collectableAccounts
|
||||||
|
* - Returns an array of accounts suitable to show income collection
|
||||||
|
*/
|
||||||
|
|
||||||
|
function collectableAccounts() {
|
||||||
|
$accounts = $this->receiptAccounts();
|
||||||
|
|
||||||
|
foreach(array($this->customerCreditAccountID(),
|
||||||
|
$this->securityDepositAccountID(),
|
||||||
|
$this->nsfAccountID(),
|
||||||
|
$this->waiverAccountID(),
|
||||||
|
$this->badDebtAccountID(),
|
||||||
|
//$this->lookup('Closing'),
|
||||||
|
//$this->lookup('Equity'),
|
||||||
|
)
|
||||||
|
AS $account_id) {
|
||||||
|
$accounts[$account_id] = $this->name($account_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$accounts['all'] = $accounts['default'] = $accounts;
|
||||||
|
|
||||||
|
foreach(array($this->concessionAccountID(),
|
||||||
|
$this->waiverAccountID(),
|
||||||
|
$this->badDebtAccountID(),
|
||||||
|
)
|
||||||
|
AS $account_id) {
|
||||||
|
unset($accounts['default'][$account_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: currentLedgerID
|
||||||
|
* - Returns the current ledger ID of the account
|
||||||
|
*/
|
||||||
|
function currentLedgerID($id) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$item = $this->find('first', array
|
||||||
|
('contain' => 'CurrentLedger',
|
||||||
|
'conditions' => array('Account.id' => $id),
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
return $item['CurrentLedger']['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: ledgers
|
||||||
|
* - Returns an array of ledger ids from the given account
|
||||||
|
*/
|
||||||
|
function ledgers($id, $all = false) {
|
||||||
|
if ($all) {
|
||||||
|
$contain = array('Ledger' => array('fields' => array('Ledger.id')));
|
||||||
|
} else {
|
||||||
|
$contain = array('CurrentLedger' => array('fields' => array('CurrentLedger.id')));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$account = $this->find('first', array
|
||||||
|
('contain' => $contain,
|
||||||
|
'fields' => array(),
|
||||||
|
'conditions' => array(array('Account.id' => $id)),
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
if ($all) {
|
||||||
|
$ledger_ids = array();
|
||||||
|
foreach ($account['Ledger'] AS $ledger)
|
||||||
|
array_push($ledger_ids, $ledger['id']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$ledger_ids = array($account['CurrentLedger']['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pr(array('function' => 'Account::ledgers', */
|
||||||
|
/* 'args' => compact('id', 'all'), */
|
||||||
|
/* 'return' => $ledger_ids)); */
|
||||||
|
|
||||||
|
return $ledger_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: closeCurrentLedger
|
||||||
|
* - Closes the current account ledger, and opens a new one
|
||||||
|
* with the old balance carried forward.
|
||||||
|
*/
|
||||||
|
function closeCurrentLedgers($ids = null) {
|
||||||
|
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$account = $this->find('all', array
|
||||||
|
('contain' => array('CurrentLedger.id'),
|
||||||
|
'fields' => array(),
|
||||||
|
'conditions' => (empty($ids)
|
||||||
|
? array()
|
||||||
|
: array(array('Account.id' => $ids)))
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
//pr(compact('id', 'account'));
|
||||||
|
|
||||||
|
$ledger_ids = array();
|
||||||
|
foreach ($account AS $acct)
|
||||||
|
$ledger_ids[] = $acct['CurrentLedger']['id'];
|
||||||
|
|
||||||
|
return $this->Ledger->closeLedgers($ledger_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: ledgerEntries
|
||||||
|
* - Returns an array of ledger entries that belong to the given
|
||||||
|
* account, either just from the current ledger, or from all ledgers.
|
||||||
|
*/
|
||||||
|
function ledgerEntries($id, $all = false, $cond = null, $link = null) {
|
||||||
|
$ledgers = $this->ledgers($id, $all);
|
||||||
|
return $this->Ledger->ledgerEntries($ledgers, $cond, $link);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns summary data from the requested account.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function stats($id = null, $all = false, $query = null) {
|
||||||
|
if (!$id)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
$this->queryInit($query);
|
||||||
|
$query['link'] = array('Account' => $query['link']);
|
||||||
|
|
||||||
|
$stats = array();
|
||||||
|
foreach ($this->ledgers($id, $all) AS $ledger)
|
||||||
|
$this->statsMerge($stats['Ledger'],
|
||||||
|
$this->Ledger->stats($ledger, $query));
|
||||||
|
|
||||||
|
return $stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
486
models/behaviors/linkable.php
Normal file
486
models/behaviors/linkable.php
Normal file
@@ -0,0 +1,486 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* LinkableBehavior
|
||||||
|
* Light-weight approach for data mining on deep relations between models.
|
||||||
|
* Join tables based on model relations to easily enable right to left find operations.
|
||||||
|
*
|
||||||
|
* Can be used as a alternative to the ContainableBehavior:
|
||||||
|
* - On data fetching only in right to left operations,
|
||||||
|
* wich means that in "one to many" relations (hasMany, hasAndBelongsToMany)
|
||||||
|
* should only be used from the "many to one" tables. i.e:
|
||||||
|
* To fetch all Users assigneds to a Project with ProjectAssignment,
|
||||||
|
* $Project->find('all', array('link' => 'User', 'conditions' => 'project_id = 1'))
|
||||||
|
* - Won't produce the desired result as data came from users table will be lost.
|
||||||
|
* $User->find('all', array('link' => 'Project', 'conditions' => 'project_id = 1'))
|
||||||
|
* - Will fetch all users related to the specified project in one query
|
||||||
|
*
|
||||||
|
* - On data mining as a much lighter approach - can reduce 300+ query find operations
|
||||||
|
* in one single query with joins; "or your money back!" ;-)
|
||||||
|
*
|
||||||
|
* - Has the 'fields' param enabled to make it easy to replace Containable usage,
|
||||||
|
* only change the 'contain' param to 'link'.
|
||||||
|
*
|
||||||
|
* Linkable Behavior. Taking it easy in your DB.
|
||||||
|
* RafaelBandeira <rafaelbandeira3(at)gmail(dot)com>
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @version 1.0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* NOTE TO <AP> 20090615:
|
||||||
|
* This structure should be linkable (it was my test case).
|
||||||
|
|
||||||
|
$entry = $this->LedgerEntry->find
|
||||||
|
('first',
|
||||||
|
array('link' => array('DebitLedger' =>
|
||||||
|
array(
|
||||||
|
'fields' => array('id'),
|
||||||
|
'alias' => 'MyDebitLedger',
|
||||||
|
'Account' =>
|
||||||
|
array(
|
||||||
|
'fields' => array('id'),
|
||||||
|
'alias' => 'MyDebitAccount'),
|
||||||
|
),
|
||||||
|
|
||||||
|
'MyCreditLedger' =>
|
||||||
|
array(
|
||||||
|
'fields' => array('id'),
|
||||||
|
'class' => 'CreditLedger',
|
||||||
|
'MyCreditAccount' =>
|
||||||
|
array(
|
||||||
|
'fields' => array('id'),
|
||||||
|
'class' => 'Account'),
|
||||||
|
),
|
||||||
|
|
||||||
|
'MyOtherLedger' =>
|
||||||
|
array(
|
||||||
|
'fields' => array('id'),
|
||||||
|
'class' => 'Ledger',
|
||||||
|
'alias' => 'AliasToMyOtherLedger',
|
||||||
|
'Account' =>
|
||||||
|
array(
|
||||||
|
'fields' => array('id'),
|
||||||
|
'alias' => 'AliasToMyOtherAccount'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
'conditions' => array('LedgerEntry.id' => $id),
|
||||||
|
));
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
class LinkableBehavior extends ModelBehavior {
|
||||||
|
|
||||||
|
protected $_key = 'link';
|
||||||
|
|
||||||
|
protected $_options = array(
|
||||||
|
'type' => true, 'table' => true, 'alias' => true, 'joins' => true,
|
||||||
|
'conditions' => true, 'fields' => true, 'reference' => true,
|
||||||
|
'class' => true, 'defaults' => true, 'linkalias' => true,
|
||||||
|
);
|
||||||
|
|
||||||
|
protected $_defaults = array('type' => 'LEFT');
|
||||||
|
|
||||||
|
function pr($lev, $mixed) {
|
||||||
|
if ($lev >= 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pr($mixed);
|
||||||
|
return;
|
||||||
|
|
||||||
|
$trace = debug_backtrace(false);
|
||||||
|
//array_shift($trace);
|
||||||
|
$calls = array();
|
||||||
|
foreach ($trace AS $call) {
|
||||||
|
$call = array_intersect_key($call,
|
||||||
|
array('file'=>1,
|
||||||
|
'line'=>1,
|
||||||
|
//'class'=>1,
|
||||||
|
'function'=>1,
|
||||||
|
));
|
||||||
|
$calls[] = implode("; ", $call);
|
||||||
|
}
|
||||||
|
pr(array('debug' => $mixed, 'stack' => $calls));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a function for made recursive str_replaces in an array
|
||||||
|
* NOTE: The palacement of this function is terrible, but I don't
|
||||||
|
* know if I really want to go down this path or not.
|
||||||
|
*/
|
||||||
|
function recursive_array_replace($find, $replace, &$data) {
|
||||||
|
if (!isset($data))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (is_array($data)) {
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
if (is_array($value)) {
|
||||||
|
$this->recursive_array_replace($find, $replace, $data[$key]);
|
||||||
|
} else {
|
||||||
|
$data[$key] = str_replace($find, $replace, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$data = str_replace($find, $replace, $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function beforeFind(&$Model, $query) {
|
||||||
|
if (!isset($query[$this->_key]))
|
||||||
|
return $query;
|
||||||
|
|
||||||
|
if (!isset($query['fields']) || $query['fields'] === true) {
|
||||||
|
$query['fields'] = $Model->getDataSource()->fields($Model);
|
||||||
|
} elseif (!is_array($query['fields'])) {
|
||||||
|
$query['fields'] = array($query['fields']);
|
||||||
|
}
|
||||||
|
$query = am(array('joins' => array()), $query, array('recursive' => -1));
|
||||||
|
|
||||||
|
$reference = array('class' => $Model->alias,
|
||||||
|
'alias' => $Model->alias,
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = array_diff_key($query, array($this->_key => 1));
|
||||||
|
$this->buildQuery($Model, $Model->alias, $Model->alias, $Model->findQueryType,
|
||||||
|
$query[$this->_key], $result);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildQuery(&$Reference, $referenceClass, $referenceAlias, $query_type, $links, &$result) {
|
||||||
|
if (empty($links))
|
||||||
|
return;
|
||||||
|
|
||||||
|
$this->pr(10,
|
||||||
|
array('begin' => 'Linkable::buildQuery',
|
||||||
|
'args' => compact('referenceClass', 'referenceAlias', 'query_type', 'links'),
|
||||||
|
));
|
||||||
|
|
||||||
|
//$defaults = $this->_defaults;// + array($this->_key => array());
|
||||||
|
//$optionsKeys = $this->_options + array($this->_key => true);
|
||||||
|
|
||||||
|
$links = Set::normalize($links);
|
||||||
|
$this->pr(24,
|
||||||
|
array('checkpoint' => 'Normalized links',
|
||||||
|
compact('links'),
|
||||||
|
));
|
||||||
|
foreach ($links as $alias => $options) {
|
||||||
|
if (is_null($options)) {
|
||||||
|
$options = array();
|
||||||
|
}
|
||||||
|
//$options = array_intersect_key($options, $optionsKeys);
|
||||||
|
//$options = am($this->_defaults, compact('alias'), $options);
|
||||||
|
|
||||||
|
$options += compact('alias');
|
||||||
|
$options += $this->_defaults;
|
||||||
|
|
||||||
|
if (empty($options['alias'])) {
|
||||||
|
throw new InvalidArgumentException(sprintf('%s::%s must receive aliased links', get_class($this), __FUNCTION__));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($options['class']))
|
||||||
|
$options['class'] = $alias;
|
||||||
|
|
||||||
|
if (!isset($options['conditions']))
|
||||||
|
$options['conditions'] = null;
|
||||||
|
elseif (!is_array($options['conditions']))
|
||||||
|
$options['conditions'] = array($options['conditions']);
|
||||||
|
|
||||||
|
$this->pr(20,
|
||||||
|
array('checkpoint' => 'Begin Model Work',
|
||||||
|
compact('referenceAlias', 'alias', 'options'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$modelClass = $options['class'];
|
||||||
|
$modelAlias = $options['alias'];
|
||||||
|
$Model =& ClassRegistry::init($modelClass); // the incoming model to be linked in query
|
||||||
|
|
||||||
|
$this->pr(12,
|
||||||
|
array('checkpoint' => 'Model Established',
|
||||||
|
'Reference' => ($referenceAlias .' : '. $referenceClass .
|
||||||
|
' ('. $Reference->alias .' : '. $Reference->name .')'),
|
||||||
|
'Model' => ($modelAlias .' : '. $modelClass .
|
||||||
|
' ('. $Model->alias .' : '. $Model->name .')'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$db =& $Model->getDataSource();
|
||||||
|
|
||||||
|
$associatedThroughReference = 0;
|
||||||
|
$association = null;
|
||||||
|
|
||||||
|
// Figure out how these two models are related, creating
|
||||||
|
// a relationship if one doesn't otherwise already exists.
|
||||||
|
if (($associations = $Reference->getAssociated()) &&
|
||||||
|
isset($associations[$Model->alias])) {
|
||||||
|
$this->pr(12, array('checkpoint' => "Reference ($referenceClass) defines association to Model ($modelClass)"));
|
||||||
|
$associatedThroughReference = 1;
|
||||||
|
$type = $associations[$Model->alias];
|
||||||
|
$association = $Reference->{$type}[$Model->alias];
|
||||||
|
}
|
||||||
|
elseif (($associations = $Model->getAssociated()) &&
|
||||||
|
isset($associations[$Reference->alias])) {
|
||||||
|
$this->pr(12, array('checkpoint' => "Model ($modelClass) defines association to Reference ($referenceClass)"));
|
||||||
|
$type = $associations[$Reference->alias];
|
||||||
|
$association = $Model->{$type}[$Reference->alias];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// No relationship... make our best effort to create one.
|
||||||
|
$this->pr(12, array('checkpoint' => "No assocation between Reference ($referenceClass) and Model ($modelClass)"));
|
||||||
|
$type = 'belongsTo';
|
||||||
|
$Model->bind($Reference->alias);
|
||||||
|
// Grab the association now, since we'll unbind in a moment.
|
||||||
|
$association = $Model->{$type}[$Reference->alias];
|
||||||
|
$Model->unbindModel(array('belongsTo' => array($Reference->alias)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine which model holds the foreign key
|
||||||
|
if (($type === 'hasMany' || $type === 'hasOne') ^ $associatedThroughReference) {
|
||||||
|
$primaryAlias = $referenceAlias;
|
||||||
|
$foreignAlias = $modelAlias;
|
||||||
|
$primaryModel = $Reference;
|
||||||
|
$foreignModel = $Model;
|
||||||
|
} else {
|
||||||
|
$primaryAlias = $modelAlias;
|
||||||
|
$foreignAlias = $referenceAlias;
|
||||||
|
$primaryModel = $Model;
|
||||||
|
$foreignModel = $Reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($associatedThroughReference)
|
||||||
|
$associationAlias = $referenceAlias;
|
||||||
|
else
|
||||||
|
$associationAlias = $modelAlias;
|
||||||
|
|
||||||
|
$this->pr(30,
|
||||||
|
array('checkpoint' => 'Options/Association pre-merge',
|
||||||
|
compact('association', 'options'),
|
||||||
|
));
|
||||||
|
|
||||||
|
// A couple exceptions before performing a union of
|
||||||
|
// options and association. Namely, most fields result
|
||||||
|
// in either/or, but a couple should include BOTH the
|
||||||
|
// options AND the association settings.
|
||||||
|
foreach (array('fields', 'conditions') AS $fld) {
|
||||||
|
$this->pr(31,
|
||||||
|
array('checkpoint' => 'Options/Associations field original',
|
||||||
|
compact('fld') +
|
||||||
|
array("options[$fld]" =>
|
||||||
|
array('value' => array_key_exists($fld, $options) ? (isset($options[$fld]) ? $options[$fld] : '-null-') : '-unset-',
|
||||||
|
'type' => array_key_exists($fld, $options) ? (isset($options[$fld]) ? gettype($options[$fld]) : '-null-') : '-unset-'),
|
||||||
|
"association[$fld]" =>
|
||||||
|
array('value' => array_key_exists($fld, $association) ? (isset($association[$fld]) ? $association[$fld] : '-null-') : '-unset-',
|
||||||
|
'type' => array_key_exists($fld, $association) ? (isset($association[$fld]) ? gettype($association[$fld]) : '-null-') : '-unset-'),
|
||||||
|
)));
|
||||||
|
|
||||||
|
if (!isset($options[$fld]) ||
|
||||||
|
(empty($options[$fld]) && !is_array($options[$fld])))
|
||||||
|
unset($options[$fld]);
|
||||||
|
elseif (!empty($options[$fld]) && !is_array($options[$fld]))
|
||||||
|
$options[$fld] = array($options[$fld]);
|
||||||
|
|
||||||
|
if (!isset($association[$fld]) ||
|
||||||
|
(empty($association[$fld]) && !is_array($association[$fld])))
|
||||||
|
unset($association[$fld]);
|
||||||
|
elseif (!empty($association[$fld]) && !is_array($association[$fld]))
|
||||||
|
$association[$fld] = array($association[$fld]);
|
||||||
|
|
||||||
|
|
||||||
|
$this->pr(31,
|
||||||
|
array('checkpoint' => 'Options/Associations field normalize',
|
||||||
|
compact('fld') +
|
||||||
|
array("options[$fld]" =>
|
||||||
|
array('value' => array_key_exists($fld, $options) ? (isset($options[$fld]) ? $options[$fld] : '-null-') : '-unset-',
|
||||||
|
'type' => array_key_exists($fld, $options) ? (isset($options[$fld]) ? gettype($options[$fld]) : '-null-') : '-unset-'),
|
||||||
|
"association[$fld]" =>
|
||||||
|
array('value' => array_key_exists($fld, $association) ? (isset($association[$fld]) ? $association[$fld] : '-null-') : '-unset-',
|
||||||
|
'type' => array_key_exists($fld, $association) ? (isset($association[$fld]) ? gettype($association[$fld]) : '-null-') : '-unset-'),
|
||||||
|
)));
|
||||||
|
|
||||||
|
if (isset($options[$fld]) && isset($association[$fld]))
|
||||||
|
$options[$fld] = array_merge($options[$fld],
|
||||||
|
$association[$fld]);
|
||||||
|
|
||||||
|
$this->pr(31,
|
||||||
|
array('checkpoint' => 'Options/Associations field merge complete',
|
||||||
|
compact('fld') +
|
||||||
|
array("options[$fld]" =>
|
||||||
|
array('value' => array_key_exists($fld, $options) ? (isset($options[$fld]) ? $options[$fld] : '-null-') : '-unset-',
|
||||||
|
'type' => array_key_exists($fld, $options) ? (isset($options[$fld]) ? gettype($options[$fld]) : '-null-') : '-unset-'),
|
||||||
|
"association[$fld]" =>
|
||||||
|
array('value' => array_key_exists($fld, $association) ? (isset($association[$fld]) ? $association[$fld] : '-null-') : '-unset-',
|
||||||
|
'type' => array_key_exists($fld, $association) ? (isset($association[$fld]) ? gettype($association[$fld]) : '-null-') : '-unset-'),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->pr(30,
|
||||||
|
array('checkpoint' => 'Options/Association post-merge',
|
||||||
|
compact('association', 'options'),
|
||||||
|
));
|
||||||
|
|
||||||
|
// For any option that's not already set, use
|
||||||
|
// whatever is specified by the assocation.
|
||||||
|
$options += array_intersect_key($association, $this->_options);
|
||||||
|
|
||||||
|
// Replace all instances of the MODEL_ALIAS variable
|
||||||
|
// tag with the correct model alias.
|
||||||
|
$this->recursive_array_replace("%{MODEL_ALIAS}",
|
||||||
|
$associationAlias,
|
||||||
|
$options['conditions']);
|
||||||
|
|
||||||
|
$this->pr(15,
|
||||||
|
array('checkpoint' => 'Models Established - Check Associations',
|
||||||
|
'primaryModel' => $primaryAlias .' : '. $primaryModel->name,
|
||||||
|
'foreignModel' => $foreignAlias .' : '. $foreignModel->name,
|
||||||
|
compact('type', 'association', 'options'),
|
||||||
|
));
|
||||||
|
|
||||||
|
if ($type === 'hasAndBelongsToMany') {
|
||||||
|
if (isset($association['with']))
|
||||||
|
$linkClass = $association['with'];
|
||||||
|
else
|
||||||
|
$linkClass = Inflector::classify($association['joinTable']);
|
||||||
|
|
||||||
|
$Link =& $Model->{$linkClass};
|
||||||
|
|
||||||
|
if (isset($options['linkalias']))
|
||||||
|
$linkAlias = $options['linkalias'];
|
||||||
|
else
|
||||||
|
$linkAlias = $Link->alias;
|
||||||
|
|
||||||
|
// foreignKey and associationForeignKey can refer to either
|
||||||
|
// the model or the reference, depending on which class
|
||||||
|
// actually defines the association. Make sure to we're
|
||||||
|
// using the foreign keys to point to the right class.
|
||||||
|
if ($associatedThroughReference) {
|
||||||
|
$modelAFK = 'associationForeignKey';
|
||||||
|
$referenceAFK = 'foreignKey';
|
||||||
|
} else {
|
||||||
|
$modelAFK = 'foreignKey';
|
||||||
|
$referenceAFK = 'associationForeignKey';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->pr(17,
|
||||||
|
array('checkpoint' => 'Linking HABTM',
|
||||||
|
compact('linkClass', 'linkAlias',
|
||||||
|
'modelAFK', 'referenceAFK'),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Get the foreign key fields (for the link table) directly from
|
||||||
|
// the defined model associations, if they exists. This is the
|
||||||
|
// users direct specification, and therefore definitive if present.
|
||||||
|
$modelLink = $Link->escapeField($association[$modelAFK], $linkAlias);
|
||||||
|
$referenceLink = $Link->escapeField($association[$referenceAFK], $linkAlias);
|
||||||
|
|
||||||
|
// If we haven't figured out the foreign keys, see if there is a
|
||||||
|
// model for the link table, and if it has the appropriate
|
||||||
|
// associations with the two tables we're trying to join.
|
||||||
|
if (empty($modelLink) && isset($Link->belongsTo[$Model->alias]))
|
||||||
|
$modelLink = $Link->escapeField($Link->belongsTo[$Model->alias]['foreignKey'], $linkAlias);
|
||||||
|
if (empty($referenceLink) && isset($Link->belongsTo[$Reference->alias]))
|
||||||
|
$referenceLink = $Link->escapeField($Link->belongsTo[$Reference->alias]['foreignKey'], $linkAlias);
|
||||||
|
|
||||||
|
// We're running quite thin here. None of the models spell
|
||||||
|
// out the appropriate linkages. We'll have to SWAG it.
|
||||||
|
if (empty($modelLink))
|
||||||
|
$modelLink = $Link->escapeField(Inflector::underscore($Model->alias) . '_id', $linkAlias);
|
||||||
|
if (empty($referenceLink))
|
||||||
|
$referenceLink = $Link->escapeField(Inflector::underscore($Reference->alias) . '_id', $linkAlias);
|
||||||
|
|
||||||
|
// Get the primary key from the tables we're joining.
|
||||||
|
$referenceKey = $Reference->escapeField(null, $referenceAlias);
|
||||||
|
$modelKey = $Model->escapeField(null, $modelAlias);
|
||||||
|
|
||||||
|
$this->pr(21,
|
||||||
|
array('checkpoint' => 'HABTM links/keys',
|
||||||
|
array(compact('modelLink', 'modelKey'),
|
||||||
|
compact('referenceLink', 'referenceKey')),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Join the linkage table to our model. We'll use an inner join,
|
||||||
|
// as the whole purpose of the linkage table is to make this
|
||||||
|
// connection. As we are embedding this join, the INNER will not
|
||||||
|
// cause any problem with the overall query, should the user not
|
||||||
|
// be concerned with whether or not the join has any results.
|
||||||
|
// They control that with the 'type' parameter which will be at
|
||||||
|
// the top level join.
|
||||||
|
$options['joins'][] = array('type' => 'INNER',
|
||||||
|
'alias' => $modelAlias,
|
||||||
|
'conditions' => "{$modelKey} = {$modelLink}",
|
||||||
|
'table' => $db->fullTableName($Model, true));
|
||||||
|
|
||||||
|
// Now for the top level join. This will be added into the list
|
||||||
|
// of joins down below, outside of the HABTM specific code.
|
||||||
|
$options['class'] = $linkClass;
|
||||||
|
$options['alias'] = $linkAlias;
|
||||||
|
$options['table'] = $Link->getDataSource()->fullTableName($Link);
|
||||||
|
$options['conditions'][] = "{$referenceLink} = {$referenceKey}";
|
||||||
|
}
|
||||||
|
elseif (isset($association['foreignKey']) && $association['foreignKey']) {
|
||||||
|
$foreignKey = $primaryModel->escapeField($association['foreignKey'], $primaryAlias);
|
||||||
|
$primaryKey = $foreignModel->escapeField($foreignModel->primaryKey, $foreignAlias);
|
||||||
|
|
||||||
|
$this->pr(17,
|
||||||
|
array('checkpoint' => 'Linking due to foreignKey',
|
||||||
|
compact('foreignKey', 'primaryKey'),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Only differentiating to help show the logical flow.
|
||||||
|
// Either way works and this test can be tossed out
|
||||||
|
if (($type === 'hasMany' || $type === 'hasOne') ^ $associatedThroughReference)
|
||||||
|
$options['conditions'][] = "{$primaryKey} = {$foreignKey}";
|
||||||
|
else
|
||||||
|
$options['conditions'][] = "{$foreignKey} = {$primaryKey}";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->pr(17,
|
||||||
|
array('checkpoint' => 'Linking with no logic (expecting user defined)',
|
||||||
|
));
|
||||||
|
|
||||||
|
// No Foreign Key... nothing we can do.
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->pr(19,
|
||||||
|
array('checkpoint' => 'Conditions',
|
||||||
|
array('options[conditions]' => $options['conditions'],
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
if (empty($options['table'])) {
|
||||||
|
$options['table'] = $db->fullTableName($Model, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($options['fields']) || !is_array($options['fields']))
|
||||||
|
$options['fields'] = $db->fields($Model, $modelAlias);
|
||||||
|
elseif (!empty($options['fields']))
|
||||||
|
$options['fields'] = $db->fields($Model, $modelAlias, $options['fields']);
|
||||||
|
|
||||||
|
// When performing a count query, fields are useless.
|
||||||
|
// For everything else, we need to add them into the set.
|
||||||
|
if ($query_type !== 'count')
|
||||||
|
$result['fields'] = array_merge($result['fields'], $options['fields']);
|
||||||
|
|
||||||
|
$result['joins'][] = array_intersect_key($options,
|
||||||
|
array('type' => true,
|
||||||
|
'alias' => true,
|
||||||
|
'table' => true,
|
||||||
|
'joins' => true,
|
||||||
|
'conditions' => true));
|
||||||
|
|
||||||
|
$sublinks = array_diff_key($options, $this->_options);
|
||||||
|
$this->buildQuery($Model, $modelClass, $modelAlias, $query_type, $sublinks, $result);
|
||||||
|
|
||||||
|
$this->pr(19,
|
||||||
|
array('checkpoint' => 'Model Join Complete',
|
||||||
|
compact('referenceAlias', 'modelAlias', 'options', 'result'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->pr(20,
|
||||||
|
array('return' => 'Linkable::buildQuery',
|
||||||
|
compact('referenceAlias'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
129
models/contact.php
Normal file
129
models/contact.php
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
class Contact extends AppModel {
|
||||||
|
|
||||||
|
var $displayField = 'display_name';
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'ContactsMethod',
|
||||||
|
'ContactsCustomer',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
'Customer',
|
||||||
|
'ContactAddress' => array(
|
||||||
|
'joinTable' => 'contacts_methods',
|
||||||
|
'associationForeignKey' => 'method_id',
|
||||||
|
'unique' => true,
|
||||||
|
'conditions' => "method = 'ADDRESS'",
|
||||||
|
),
|
||||||
|
'ContactPhone' => array(
|
||||||
|
'joinTable' => 'contacts_methods',
|
||||||
|
'associationForeignKey' => 'method_id',
|
||||||
|
'unique' => true,
|
||||||
|
'conditions' => "method = 'PHONE'",
|
||||||
|
),
|
||||||
|
'ContactEmail' => array(
|
||||||
|
'joinTable' => 'contacts_methods',
|
||||||
|
'associationForeignKey' => 'method_id',
|
||||||
|
'unique' => true,
|
||||||
|
'conditions' => "method = 'EMAIL'",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: saveContact
|
||||||
|
* - Saves the contact and related data
|
||||||
|
*/
|
||||||
|
|
||||||
|
function saveContact($id, $data) {
|
||||||
|
|
||||||
|
// Establish a display name if not already given
|
||||||
|
if (!$data['Contact']['display_name'])
|
||||||
|
$data['Contact']['display_name'] =
|
||||||
|
(($data['Contact']['first_name'] &&
|
||||||
|
$data['Contact']['last_name'])
|
||||||
|
? $data['Contact']['last_name'] . ', ' . $data['Contact']['first_name']
|
||||||
|
: ($data['Contact']['first_name']
|
||||||
|
? $data['Contact']['first_name']
|
||||||
|
: $data['Contact']['last_name']));
|
||||||
|
|
||||||
|
// Save the contact data
|
||||||
|
$this->create();
|
||||||
|
if ($id)
|
||||||
|
$this->id = $id;
|
||||||
|
if (!$this->save($data, false)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$id = $this->id;
|
||||||
|
|
||||||
|
// Remove all associated ContactMethods, as it ensures
|
||||||
|
// any entries deleted by the user actually get deleted
|
||||||
|
// in the system. We'll recreate the needed ones anyway.
|
||||||
|
// REVISIT <AP>: 20090706
|
||||||
|
// Appears that $this->save() is already doing the
|
||||||
|
// delete. I would have thought this would only happen
|
||||||
|
// on a saveAll??
|
||||||
|
/* $this->ContactsMethod->deleteAll */
|
||||||
|
/* (array('contact_id' => $id), false); */
|
||||||
|
|
||||||
|
// At this point, since we've saved data to contact,
|
||||||
|
// we'll proceed forward as much as possible, even
|
||||||
|
// if we encounter an error. For now, we'll assume
|
||||||
|
// the operation will succeed.
|
||||||
|
$ret = true;
|
||||||
|
|
||||||
|
// Iterate each type of contact method, adding them into
|
||||||
|
// the database as needed and associating with this contact.
|
||||||
|
foreach (array('phone', 'address', 'email') AS $type) {
|
||||||
|
$class = 'Contact' . ucfirst($type);
|
||||||
|
$enum = strtoupper($type);
|
||||||
|
|
||||||
|
// Nothing to do if this contact method isn't used
|
||||||
|
if (!isset($data[$class]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Go through each entry of this contact method
|
||||||
|
foreach ($data[$class] AS &$item) {
|
||||||
|
|
||||||
|
// If the user has entered all new data, we need to
|
||||||
|
// save that as a brand new entry.
|
||||||
|
if (!isset($item['id'])) {
|
||||||
|
$I = new $class();
|
||||||
|
$I->create();
|
||||||
|
if (!$I->save($item, false)) {
|
||||||
|
$ret = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$item['id'] = $I->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the ContactsMethod to reflect the appropriate IDs
|
||||||
|
$item['ContactsMethod']['contact_id'] = $id;
|
||||||
|
$item['ContactsMethod']['method_id'] = $item['id'];
|
||||||
|
$item['ContactsMethod']['method'] = $enum;
|
||||||
|
|
||||||
|
// Save the relationship between contact and phone/email/address
|
||||||
|
$CM = new ContactsMethod();
|
||||||
|
if (!$CM->save($item['ContactsMethod'], false)) {
|
||||||
|
$ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the result
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function contactList() {
|
||||||
|
return $this->find('list',
|
||||||
|
array('order' =>
|
||||||
|
//array('last_name', 'first_name', 'middle_name'),
|
||||||
|
array('display_name'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
46
models/contact_address.php
Normal file
46
models/contact_address.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
class ContactAddress extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'ContactAddress';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'postcode' => array('postal')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'ContactsMethod' => array(
|
||||||
|
'foreignKey' => 'method_id',
|
||||||
|
'conditions' => "method = 'ADDRESS'",
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
'Contact' => array(
|
||||||
|
'className' => 'Contact',
|
||||||
|
'joinTable' => 'contacts_methods',
|
||||||
|
'foreignKey' => 'method_id',
|
||||||
|
'associationForeignKey' => 'contact_id',
|
||||||
|
'unique' => true,
|
||||||
|
'conditions' => "method = 'ADDRESS'",
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
function addressList() {
|
||||||
|
$results = $this->find('all',
|
||||||
|
array('contain' => false,
|
||||||
|
'fields' => array('id', 'address', 'city', 'state', 'postcode'),
|
||||||
|
'order' => array('state', 'city', 'postcode', 'address')));
|
||||||
|
|
||||||
|
$list = array();
|
||||||
|
foreach ($results as $key => $val) {
|
||||||
|
$list[$val['ContactAddress']['id']]
|
||||||
|
= preg_replace("/\n/", ", ", $val['ContactAddress']['address'])
|
||||||
|
. ', ' . $val['ContactAddress']['city']
|
||||||
|
. ', ' . $val['ContactAddress']['state']
|
||||||
|
. ' ' . $val['ContactAddress']['postcode']
|
||||||
|
;
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
27
models/contact_email.php
Normal file
27
models/contact_email.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
class ContactEmail extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'ContactEmail';
|
||||||
|
var $displayField = 'email';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'email' => array('email')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
'Contact' => array(
|
||||||
|
'className' => 'Contact',
|
||||||
|
'joinTable' => 'contacts_methods',
|
||||||
|
'foreignKey' => 'method_id',
|
||||||
|
'associationForeignKey' => 'contact_id',
|
||||||
|
'unique' => true,
|
||||||
|
'conditions' => "method = 'EMAIL'",
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
function emailList() {
|
||||||
|
return $this->find('list');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
46
models/contact_phone.php
Normal file
46
models/contact_phone.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
class ContactPhone extends AppModel {
|
||||||
|
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
//'type' => array('inlist'),
|
||||||
|
'phone' => array('phone'),
|
||||||
|
'ext' => array('numeric')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'ContactsMethod' => array(
|
||||||
|
'foreignKey' => 'method_id',
|
||||||
|
'conditions' => "method = 'PHONE'",
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
'Contact' => array(
|
||||||
|
'className' => 'Contact',
|
||||||
|
'joinTable' => 'contacts_methods',
|
||||||
|
'foreignKey' => 'method_id',
|
||||||
|
'associationForeignKey' => 'contact_id',
|
||||||
|
'unique' => true,
|
||||||
|
'conditions' => "method = 'PHONE'",
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
function phoneList() {
|
||||||
|
$results = $this->find('all',
|
||||||
|
array('contain' => false,
|
||||||
|
'fields' => array('id', 'phone', 'ext'),
|
||||||
|
'order' => array('phone', 'ext')));
|
||||||
|
|
||||||
|
App::Import('Helper', 'Format');
|
||||||
|
$list = array();
|
||||||
|
foreach ($results as $key => $val) {
|
||||||
|
$list[$val['ContactPhone']['id']]
|
||||||
|
= FormatHelper::phone($val['ContactPhone']['phone'],
|
||||||
|
$val['ContactPhone']['ext']);
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
11
models/contacts_customer.php
Normal file
11
models/contacts_customer.php
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
class ContactsCustomer extends AppModel {
|
||||||
|
var $primaryKey = false;
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'Contact',
|
||||||
|
'Customer',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
25
models/contacts_method.php
Normal file
25
models/contacts_method.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
class ContactsMethod extends AppModel {
|
||||||
|
var $primaryKey = false;
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'Contact',
|
||||||
|
'ContactAddress' => array(
|
||||||
|
'foreignKey' => 'method_id',
|
||||||
|
'conditions' => "method = 'ADDRESS'",
|
||||||
|
//'unique' => true,
|
||||||
|
),
|
||||||
|
'ContactPhone' => array(
|
||||||
|
'foreignKey' => 'method_id',
|
||||||
|
'conditions' => "method = 'PHONE'",
|
||||||
|
//'unique' => true,
|
||||||
|
),
|
||||||
|
'ContactEmail' => array(
|
||||||
|
'foreignKey' => 'method_id',
|
||||||
|
'conditions' => "method = 'EMAIL'",
|
||||||
|
//'unique' => true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
377
models/customer.php
Normal file
377
models/customer.php
Normal file
@@ -0,0 +1,377 @@
|
|||||||
|
<?php
|
||||||
|
class Customer extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'Customer';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'name' => array('notempty'),
|
||||||
|
);
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'PrimaryContact' => array(
|
||||||
|
'className' => 'Contact',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'CurrentLease' => array(
|
||||||
|
'className' => 'Lease',
|
||||||
|
'conditions' => 'CurrentLease.close_date IS NULL',
|
||||||
|
),
|
||||||
|
'Lease',
|
||||||
|
'StatementEntry',
|
||||||
|
'ContactsCustomer',
|
||||||
|
|
||||||
|
'Transaction',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
'Contact',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: accountId
|
||||||
|
* - Returns the account ID for the given customer
|
||||||
|
*/
|
||||||
|
function accountId($id) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$customer = $this->find('first',
|
||||||
|
array('contain' => false,
|
||||||
|
'fields' => array('account_id'),
|
||||||
|
'conditions' => array(array('Customer.id' => $id))));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
return $customer['Customer']['account_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: leaseIds
|
||||||
|
* - Returns the lease IDs for the given customer
|
||||||
|
*/
|
||||||
|
function leaseIds($id) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$customer = $this->find('first',
|
||||||
|
array('contain' =>
|
||||||
|
array('Lease' => array('fields' => array('id'))),
|
||||||
|
'fields' => array(),
|
||||||
|
'conditions' => array(array('Customer.id' => $id))));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
$ids = array();
|
||||||
|
foreach ($customer['Lease'] AS $lease)
|
||||||
|
$ids[] = $lease['id'];
|
||||||
|
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: securityDeposits
|
||||||
|
* - Returns an array of security deposit entries
|
||||||
|
*/
|
||||||
|
function securityDeposits($id, $query = null) {
|
||||||
|
$this->prEnter(compact('id', 'query'));
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||||
|
$query['conditions'][] = array('StatementEntry.account_id' =>
|
||||||
|
$this->StatementEntry->Account->securityDepositAccountID());
|
||||||
|
|
||||||
|
$set = $this->StatementEntry->reconciledSet('CHARGE', $query, false, true);
|
||||||
|
return $this->prReturn($set);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: securityDepositBalance
|
||||||
|
* - Returns the balance of the customer security deposit(s)
|
||||||
|
*/
|
||||||
|
|
||||||
|
function securityDepositBalance($id, $query = null) {
|
||||||
|
$this->prEnter(compact('id', 'query'));
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$sd_account_id =
|
||||||
|
$this->StatementEntry->Account->securityDepositAccountID();
|
||||||
|
|
||||||
|
$squery = $query;
|
||||||
|
$squery['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||||
|
$squery['conditions'][] = array('StatementEntry.account_id' => $sd_account_id);
|
||||||
|
$stats = $this->StatementEntry->stats(null, $squery);
|
||||||
|
$this->pr(26, compact('squery', 'stats'));
|
||||||
|
|
||||||
|
// OK, we know now how much we charged for a security
|
||||||
|
// deposit, as well as how much we received to pay for it.
|
||||||
|
// Now we need to know if any has been released.
|
||||||
|
// Yes... this sucks.
|
||||||
|
$lquery = $query;
|
||||||
|
$lquery['link'] = array('Transaction' =>
|
||||||
|
array('fields' => array(),
|
||||||
|
'Customer' =>
|
||||||
|
(empty($query['link'])
|
||||||
|
? array('fields' => array())
|
||||||
|
: $query['link'])));
|
||||||
|
$lquery['conditions'][] = array('Transaction.customer_id' => $id);
|
||||||
|
$lquery['conditions'][] = array('LedgerEntry.account_id' => $sd_account_id);
|
||||||
|
$lquery['conditions'][] = array('LedgerEntry.crdr' => 'DEBIT');
|
||||||
|
$lquery['fields'][] = 'SUM(LedgerEntry.amount) AS total';
|
||||||
|
$released = $this->StatementEntry->Transaction->LedgerEntry->find
|
||||||
|
('first', $lquery);
|
||||||
|
$this->pr(26, compact('lquery', 'released'));
|
||||||
|
|
||||||
|
return $this->prReturn($stats['Charge']['disbursement'] - $released[0]['total']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: unreconciledCharges
|
||||||
|
* - Returns charges have not yet been fully paid
|
||||||
|
*/
|
||||||
|
|
||||||
|
function unreconciledCharges($id, $query = null) {
|
||||||
|
$this->prEnter(compact('id', 'query'));
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||||
|
$set = $this->StatementEntry->reconciledSet('CHARGE', $query, true);
|
||||||
|
return $this->prReturn($set);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: saveCustomer
|
||||||
|
* - Saves the customer and related data
|
||||||
|
*/
|
||||||
|
|
||||||
|
function saveCustomer($id, $data, $primary_contact_entry) {
|
||||||
|
|
||||||
|
// Go through each contact, and create new ones as needed
|
||||||
|
foreach ($data['Contact'] AS &$contact) {
|
||||||
|
if (isset($contact['id']))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$I = new Contact();
|
||||||
|
if (!$I->saveContact(null, array('Contact' => $contact)))
|
||||||
|
return false;
|
||||||
|
$contact['id'] = $I->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the primary contact ID based on caller selection
|
||||||
|
$data['Customer']['primary_contact_id']
|
||||||
|
= $data['Contact'][$primary_contact_entry]['id'];
|
||||||
|
|
||||||
|
// Provide a default customer name if not specified
|
||||||
|
if (!$data['Customer']['name']) {
|
||||||
|
$this->Contact->recursive = -1;
|
||||||
|
$pcontact = $this->Contact->read(null, $data['Customer']['primary_contact_id']);
|
||||||
|
$data['Customer']['name'] = $pcontact['Contact']['display_name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the customer data
|
||||||
|
$this->create();
|
||||||
|
if ($id)
|
||||||
|
$this->id = $id;
|
||||||
|
if (!$this->save($data, false)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$id = $this->id;
|
||||||
|
|
||||||
|
// Remove all associated Customer Contacts, as it ensures
|
||||||
|
// any entries deleted by the user actually get deleted
|
||||||
|
// in the system. We'll recreate the needed ones anyway.
|
||||||
|
// REVISIT <AP>: 20090706
|
||||||
|
// Appears that $this->save() is already doing the
|
||||||
|
// delete. I would have thought this would only happen
|
||||||
|
// on a saveAll??
|
||||||
|
/* $this->ContactsCustomer->deleteAll */
|
||||||
|
/* (array('customer_id' => $id), false); */
|
||||||
|
|
||||||
|
// At this point, since we've saved data to customer,
|
||||||
|
// we'll proceed forward as much as possible, even
|
||||||
|
// if we encounter an error. For now, we'll assume
|
||||||
|
// the operation will succeed.
|
||||||
|
$ret = true;
|
||||||
|
|
||||||
|
// Go through each entry of this customer method
|
||||||
|
foreach ($data['Contact'] AS &$contact) {
|
||||||
|
// Update the ContactsCustomer to reflect the appropriate IDs
|
||||||
|
$contact['ContactsCustomer']['customer_id'] = $id;
|
||||||
|
$contact['ContactsCustomer']['contact_id'] = $contact['id'];
|
||||||
|
|
||||||
|
// Save the relationship between customer and contact
|
||||||
|
$CM = new ContactsCustomer();
|
||||||
|
if (!$CM->save($contact['ContactsCustomer'], false)) {
|
||||||
|
$ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the result
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: update
|
||||||
|
* - Update any cached or calculated fields
|
||||||
|
*/
|
||||||
|
function update($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
|
||||||
|
if (empty($id)) {
|
||||||
|
$customers = $this->find('all', array('contain' => false, 'fields' => array('id')));
|
||||||
|
foreach ($customers AS $customer) {
|
||||||
|
// This SHOULDN'T happen, but check to be sure
|
||||||
|
// or we'll get infinite recursion.
|
||||||
|
if (empty($customer['Customer']['id']))
|
||||||
|
continue;
|
||||||
|
$this->update($customer['Customer']['id']);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090812
|
||||||
|
// updateLeaseCount is handled directly when needed.
|
||||||
|
// Should we simplify by just doing it anyway?
|
||||||
|
//$this->updateLeaseCount($id);
|
||||||
|
|
||||||
|
$current_leases =
|
||||||
|
$this->find('all',
|
||||||
|
// REVISIT <AP>: 20090816
|
||||||
|
// Do we need to update leases other than the current ones?
|
||||||
|
// It may be necessary. For example, a non-current lease
|
||||||
|
// can still be hit with an NSF item. In that case, it
|
||||||
|
// could have stale data if we look only to current leases.
|
||||||
|
//array('link' => array('CurrentLease' => array('type' => 'INNER')),
|
||||||
|
array('link' => array('Lease' => array('type' => 'INNER')),
|
||||||
|
'conditions' => array('Customer.id' => $id)));
|
||||||
|
|
||||||
|
foreach ($current_leases AS $lease) {
|
||||||
|
if (!empty($lease['CurrentLease']['id']))
|
||||||
|
$this->Lease->update($lease['CurrentLease']['id']);
|
||||||
|
if (!empty($lease['Lease']['id']))
|
||||||
|
$this->Lease->update($lease['Lease']['id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: updateLeaseCount
|
||||||
|
* - Updates the internal lease count
|
||||||
|
*/
|
||||||
|
|
||||||
|
function updateLeaseCount($id) {
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
$lease_count =
|
||||||
|
$this->find('count',
|
||||||
|
array('link' => array('Lease' => array('type' => 'INNER')),
|
||||||
|
'conditions' => array('Customer.id' => $id)));
|
||||||
|
$current_count =
|
||||||
|
$this->find('count',
|
||||||
|
array('link' => array('CurrentLease' => array('type' => 'INNER')),
|
||||||
|
'conditions' => array('Customer.id' => $id)));
|
||||||
|
|
||||||
|
$this->saveField('lease_count', $lease_count);
|
||||||
|
$this->saveField('current_lease_count', $current_count);
|
||||||
|
$this->saveField('past_lease_count', $lease_count - $current_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: balance
|
||||||
|
* - Returns the balance of money owed on the lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function balance($id) {
|
||||||
|
$stats = $this->stats($id);
|
||||||
|
return $stats['balance'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns summary data from the requested customer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function stats($id = null, $query = null) {
|
||||||
|
//$this->prFunctionLevel(20);
|
||||||
|
$this->prEnter(compact('id', 'query'));
|
||||||
|
if (!$id)
|
||||||
|
return $this->prExit(null);
|
||||||
|
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090725
|
||||||
|
// We'll need to go directly to the statement entries if
|
||||||
|
// transactions are not always associated with the customer.
|
||||||
|
// This could happen if either we remove the customer_id
|
||||||
|
// field from Transaction, or we allow multiple customers
|
||||||
|
// to be part of the same transaction (essentially making
|
||||||
|
// the Transaction.customer_id meaningless).
|
||||||
|
|
||||||
|
/* $stats = $this->StatementEntry->find */
|
||||||
|
/* ('first', array */
|
||||||
|
/* ('contain' => false, */
|
||||||
|
/* 'fields' => $this->StatementEntry->chargeDisbursementFields(true), */
|
||||||
|
/* 'conditions' => array('StatementEntry.customer_id' => $id), */
|
||||||
|
/* )); */
|
||||||
|
|
||||||
|
$find_stats = $this->StatementEntry->find
|
||||||
|
('first', array
|
||||||
|
('contain' => false,
|
||||||
|
'fields' => $this->StatementEntry->chargeDisbursementFields(true),
|
||||||
|
'conditions' => array('StatementEntry.customer_id' => $id),
|
||||||
|
));
|
||||||
|
$find_stats = $find_stats[0];
|
||||||
|
$this->pr(17, compact('find_stats'));
|
||||||
|
|
||||||
|
$tquery = $query;
|
||||||
|
$tquery['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||||
|
$statement_stats = $this->StatementEntry->stats(null, $tquery);
|
||||||
|
$statement_stats['balance'] = $statement_stats['Charge']['balance'];
|
||||||
|
$this->pr(17, compact('statement_stats'));
|
||||||
|
|
||||||
|
$tquery = $query;
|
||||||
|
//$tquery['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||||
|
$tquery['conditions'][] = array('Transaction.customer_id' => $id);
|
||||||
|
$transaction_stats = $this->Transaction->stats(null, $tquery);
|
||||||
|
$transaction_stats += $transaction_stats['StatementEntry'];
|
||||||
|
$this->pr(17, compact('transaction_stats'));
|
||||||
|
|
||||||
|
$tquery = $query;
|
||||||
|
//$tquery['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||||
|
$tquery['conditions'][] = array('Transaction.customer_id' => $id);
|
||||||
|
$ar_transaction_stats = $this->Transaction->stats(null, $tquery,
|
||||||
|
$this->Transaction->Account->accountReceivableAccountID());
|
||||||
|
$ar_transaction_stats += $ar_transaction_stats['LedgerEntry'];
|
||||||
|
$this->pr(17, compact('ar_transaction_stats'));
|
||||||
|
|
||||||
|
//$stats = $ar_transaction_stats;
|
||||||
|
$stats = $find_stats;
|
||||||
|
return $this->prReturn($stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
109
models/double_entry.php
Normal file
109
models/double_entry.php
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
<?php
|
||||||
|
class DoubleEntry extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'DebitEntry' => array(
|
||||||
|
'className' => 'LedgerEntry',
|
||||||
|
),
|
||||||
|
'CreditEntry' => array(
|
||||||
|
'className' => 'LedgerEntry',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: verifyDoubleEntry
|
||||||
|
* - Verifies consistenty of new double entry data
|
||||||
|
* (not in a pre-existing double entry)
|
||||||
|
*/
|
||||||
|
function verifyDoubleEntry($entry1, $entry2, $entry1_tender = null) {
|
||||||
|
/* pr(array("DoubleEntry::verifyDoubleEntry()" */
|
||||||
|
/* => compact('entry1', 'entry2', 'entry1_tender'))); */
|
||||||
|
|
||||||
|
$LE = new LedgerEntry();
|
||||||
|
if (!$LE->verifyLedgerEntry($entry1, $entry1_tender)) {
|
||||||
|
/* pr(array("DoubleEntry::verifyDoubleEntry()" */
|
||||||
|
/* => "Entry1 verification failed")); */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!$LE->verifyLedgerEntry($entry2)) {
|
||||||
|
/* pr(array("DoubleEntry::verifyDoubleEntry()" */
|
||||||
|
/* => "Entry2 verification failed")); */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(($entry1['crdr'] === 'DEBIT' && $entry2['crdr'] === 'CREDIT') ||
|
||||||
|
($entry1['crdr'] === 'CREDIT' && $entry2['crdr'] === 'DEBIT')) ||
|
||||||
|
($entry1['amount'] != $entry2['amount'])) {
|
||||||
|
/* pr(array("DoubleEntry::verifyDoubleEntry()" */
|
||||||
|
/* => "Double Entry verification failed")); */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: addDoubleEntry
|
||||||
|
* - Inserts new Double Entry into the database
|
||||||
|
*/
|
||||||
|
|
||||||
|
function addDoubleEntry($entry1, $entry2, $entry1_tender = null) {
|
||||||
|
//$this->prFunctionLevel(16);
|
||||||
|
$this->prEnter(compact('entry1', 'entry2', 'entry1_tender'));
|
||||||
|
|
||||||
|
$ret = array();
|
||||||
|
if (!$this->verifyDoubleEntry($entry1, $entry2, $entry1_tender))
|
||||||
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
|
// Handle the case where a double entry involves the same
|
||||||
|
// exact ledger. This would not serve any useful purpose.
|
||||||
|
// It is not, however, an error. It is semantically correct
|
||||||
|
// just not really logically correct. To make this easier,
|
||||||
|
// just ensure ledger_id is set for each entry, even though
|
||||||
|
// it would be handled later by the LedgerEntry model.
|
||||||
|
//array($entry1, $entry2) AS &$entry) {
|
||||||
|
for ($i=1; $i <= 2; ++$i) {
|
||||||
|
if (empty(${'entry'.$i}['ledger_id']))
|
||||||
|
${'entry'.$i}['ledger_id'] =
|
||||||
|
$this->DebitEntry->Account->currentLedgerID(${'entry'.$i}['account_id']);
|
||||||
|
}
|
||||||
|
if ($entry1['ledger_id'] == $entry2['ledger_id'])
|
||||||
|
return $this->prReturn(array('error' => false));
|
||||||
|
|
||||||
|
// Since this model only relates to DebitEntry and CreditEntry...
|
||||||
|
$LE = new LedgerEntry();
|
||||||
|
|
||||||
|
// Add the first ledger entry to the database
|
||||||
|
$result = $LE->addLedgerEntry($entry1, $entry1_tender);
|
||||||
|
$ret['Entry1'] = $result;
|
||||||
|
if ($result['error'])
|
||||||
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
|
// Add the second ledger entry to the database
|
||||||
|
$result = $LE->addLedgerEntry($entry2);
|
||||||
|
$ret['Entry2'] = $result;
|
||||||
|
if ($result['error'])
|
||||||
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
|
// Now link them as a double entry
|
||||||
|
$double_entry = array();
|
||||||
|
$double_entry['debit_entry_id'] =
|
||||||
|
($entry1['crdr'] === 'DEBIT') ? $ret['Entry1']['ledger_entry_id'] : $ret['Entry2']['ledger_entry_id'];
|
||||||
|
$double_entry['credit_entry_id'] =
|
||||||
|
($entry1['crdr'] === 'CREDIT') ? $ret['Entry1']['ledger_entry_id'] : $ret['Entry2']['ledger_entry_id'];
|
||||||
|
|
||||||
|
$ret['data'] = $double_entry;
|
||||||
|
|
||||||
|
$this->create();
|
||||||
|
if (!$this->save($double_entry))
|
||||||
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
|
$ret['double_entry_id'] = $this->id;
|
||||||
|
return $this->prReturn($ret + array('error' => false));
|
||||||
|
}
|
||||||
|
}
|
||||||
849
models/lease.php
Normal file
849
models/lease.php
Normal file
@@ -0,0 +1,849 @@
|
|||||||
|
<?php
|
||||||
|
class Lease extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'LeaseType',
|
||||||
|
'Unit',
|
||||||
|
'Customer',
|
||||||
|
'LateSchedule',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'StatementEntry',
|
||||||
|
);
|
||||||
|
|
||||||
|
//var $default_log_level = array('log' => 30, 'show' => 30);
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: securityDeposits
|
||||||
|
* - Returns an array of security deposit entries
|
||||||
|
*/
|
||||||
|
function securityDeposits($id, $query = null) {
|
||||||
|
$this->prEnter(compact('id', 'query'));
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['conditions'][] = array('StatementEntry.lease_id' => $id);
|
||||||
|
$query['conditions'][] = array('StatementEntry.account_id' =>
|
||||||
|
$this->StatementEntry->Account->securityDepositAccountID());
|
||||||
|
|
||||||
|
$set = $this->StatementEntry->reconciledSet('CHARGE', $query, false, true);
|
||||||
|
return $this->prReturn($set);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: securityDepositBalance
|
||||||
|
* - Returns the balance of the lease security deposit(s)
|
||||||
|
*/
|
||||||
|
|
||||||
|
function securityDepositBalance($id, $query = null) {
|
||||||
|
$this->prEnter(compact('id', 'query'));
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090807
|
||||||
|
// Let's try simplifying the security deposit issue.
|
||||||
|
// Presume that security deposits are NOT used at all,
|
||||||
|
// until the customer moves out of the unit. At that
|
||||||
|
// time, the ENTIRE deposit is converted to customer
|
||||||
|
// credit. Piece of cake.
|
||||||
|
// For more information, see file revision history,
|
||||||
|
// including the revision just before this, r503.
|
||||||
|
|
||||||
|
$this->id = $id;
|
||||||
|
$moveout_date = $this->field('moveout_date');
|
||||||
|
if (!empty($moveout_date))
|
||||||
|
return $this->prReturn(0);
|
||||||
|
|
||||||
|
$query['conditions'][] = array('StatementEntry.lease_id' => $id);
|
||||||
|
$query['conditions'][] = array('StatementEntry.account_id' =>
|
||||||
|
$this->StatementEntry->Account->securityDepositAccountID());
|
||||||
|
|
||||||
|
$stats = $this->StatementEntry->stats(null, $query);
|
||||||
|
return $this->prReturn($stats['Charge']['disbursement']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: releaseSecurityDeposits
|
||||||
|
* - Releases all security deposits associated with this lease.
|
||||||
|
* That simply makes a disbursement out of them, which can be used
|
||||||
|
* to pay outstanding customer charges, or simply to become
|
||||||
|
* a customer surplus (customer credit).
|
||||||
|
*/
|
||||||
|
function releaseSecurityDeposits($id, $stamp = null, $query = null) {
|
||||||
|
//$this->prFunctionLevel(30);
|
||||||
|
$this->prEnter(compact('id', 'stamp', 'query'));
|
||||||
|
|
||||||
|
$secdeps = $this->securityDeposits($id, $query);
|
||||||
|
$secdeps = $secdeps['entries'];
|
||||||
|
$this->pr(20, compact('secdeps'));
|
||||||
|
|
||||||
|
// If there are no paid security deposits, then
|
||||||
|
// we can consider all security deposits released.
|
||||||
|
if (count($secdeps) == 0)
|
||||||
|
return $this->prReturn(true);
|
||||||
|
|
||||||
|
// Build a transaction
|
||||||
|
$release = array('Transaction' => array(), 'Entry' => array());
|
||||||
|
$release['Transaction']['stamp'] = $stamp;
|
||||||
|
$release['Transaction']['comment'] = "Security Deposit Release";
|
||||||
|
foreach ($secdeps AS $charge) {
|
||||||
|
if ($charge['StatementEntry']['type'] !== 'CHARGE')
|
||||||
|
die("INTERNAL ERROR: SECURITY DEPOSIT IS NOT CHARGE");
|
||||||
|
|
||||||
|
// Since security deposits are being released, this also means
|
||||||
|
// any unpaid (or only partially paid) security deposit should
|
||||||
|
// have the remaining balance reversed.
|
||||||
|
if ($charge['StatementEntry']['balance'] > 0)
|
||||||
|
$this->StatementEntry->reverse($charge['StatementEntry']['id'], true, $stamp);
|
||||||
|
|
||||||
|
$release['Entry'][] =
|
||||||
|
array('amount' => $charge['StatementEntry']['reconciled'],
|
||||||
|
'account_id' => $this->StatementEntry->Account->securityDepositAccountID(),
|
||||||
|
'comment' => "Released Security Deposit",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer_id = $secdeps[0]['StatementEntry']['customer_id'];
|
||||||
|
$lease_id = $secdeps[0]['StatementEntry']['lease_id'];
|
||||||
|
|
||||||
|
// Add receipt of the security deposit funds. Do NOT
|
||||||
|
// flag them as part of the lease, as all received funds
|
||||||
|
// are only associated with the customer, for future
|
||||||
|
// (or present) disbursement on any lease.
|
||||||
|
$result = $this->StatementEntry->Transaction->addReceipt
|
||||||
|
($release, $customer_id, null);
|
||||||
|
|
||||||
|
return $this->prReturn($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: rentLastCharges
|
||||||
|
* - Returns a list of rent charges from this lease that
|
||||||
|
* do not have sequential followup charges. Under normal
|
||||||
|
* circumstances, there would only be one entry, which is
|
||||||
|
* the most recent rent charge. However, it's possible
|
||||||
|
* that there are several, indicating a problem with lease.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function rentLastCharges($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
$rent_account_id = $this->StatementEntry->Account->rentAccountID();
|
||||||
|
$entries = $this->find
|
||||||
|
('all',
|
||||||
|
array('link' =>
|
||||||
|
array(// Models
|
||||||
|
'StatementEntry',
|
||||||
|
|
||||||
|
'SEx' =>
|
||||||
|
array('class' => 'StatementEntry',
|
||||||
|
'fields' => array(),
|
||||||
|
'conditions' => array
|
||||||
|
('SEx.effective_date = DATE_ADD(StatementEntry.through_date, INTERVAL 1 day)',
|
||||||
|
'SEx.lease_id = StatementEntry.lease_id',
|
||||||
|
'SEx.reverse_transaction_id IS NULL',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
//'fields' => array('id', 'amount', 'effective_date', 'through_date'),
|
||||||
|
'fields' => array(),
|
||||||
|
'conditions' => array(array('Lease.id' => $id),
|
||||||
|
array('StatementEntry.type' => 'CHARGE'),
|
||||||
|
array('StatementEntry.account_id' => $rent_account_id),
|
||||||
|
array('StatementEntry.reverse_transaction_id IS NULL'),
|
||||||
|
array('SEx.id' => null),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->prReturn($entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: lateCharges
|
||||||
|
* - Returns a list of late charges from this lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function lateCharges($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
$late_account_id = $this->StatementEntry->Account->lateChargeAccountID();
|
||||||
|
$entries = $this->StatementEntry->find
|
||||||
|
('all',
|
||||||
|
array('link' =>
|
||||||
|
array(// Models
|
||||||
|
'Lease',
|
||||||
|
),
|
||||||
|
|
||||||
|
//'fields' => array('id', 'amount', 'effective_date', 'through_date'),
|
||||||
|
'conditions' => array(array('Lease.id' => $id),
|
||||||
|
array('StatementEntry.type' => 'CHARGE'),
|
||||||
|
array('StatementEntry.account_id' => $late_account_id),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->prReturn($entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: rentChargeGaps
|
||||||
|
* - Checks for gaps in rent charges
|
||||||
|
*/
|
||||||
|
|
||||||
|
function rentChargeGaps($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
$entries = $this->rentLastCharges($id);
|
||||||
|
if ($entries && count($entries) > 1)
|
||||||
|
return $this->prReturn(true);
|
||||||
|
return $this->prReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: rentChargeThrough
|
||||||
|
* - Determines the date that rent has been charged through
|
||||||
|
* Returns one of:
|
||||||
|
* null: There are gaps in the charges
|
||||||
|
* false: There are not yet any charges
|
||||||
|
* date: The date rent has been charged through
|
||||||
|
*/
|
||||||
|
|
||||||
|
function rentChargeThrough($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
$entries = $this->rentLastCharges($id);
|
||||||
|
if (!$entries)
|
||||||
|
return $this->prReturn(false);
|
||||||
|
if (count($entries) != 1)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
return $this->prReturn($entries[0]['StatementEntry']['through_date']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: rentPaidThrough
|
||||||
|
* - Determines the date of the first unpaid rent
|
||||||
|
*/
|
||||||
|
|
||||||
|
function rentPaidThrough($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
$rent_account_id = $this->StatementEntry->Account->rentAccountID();
|
||||||
|
|
||||||
|
// First, see if we can find any unpaid entries. Of course,
|
||||||
|
// the first unpaid entry gives us a very direct indication
|
||||||
|
// of when the customer is paid up through, which is 1 day
|
||||||
|
// prior to the effective date of that first unpaid charge.
|
||||||
|
$rent = $this->StatementEntry->reconciledSet
|
||||||
|
('CHARGE',
|
||||||
|
array('fields' =>
|
||||||
|
array('StatementEntry.*',
|
||||||
|
'DATE_SUB(StatementEntry.effective_date, INTERVAL 1 DAY) AS paid_through',
|
||||||
|
),
|
||||||
|
|
||||||
|
'conditions' =>
|
||||||
|
array(array('StatementEntry.lease_id' => $id),
|
||||||
|
array('StatementEntry.account_id' => $rent_account_id),
|
||||||
|
array('StatementEntry.reverse_transaction_id IS NULL'),
|
||||||
|
),
|
||||||
|
|
||||||
|
'order' => array('StatementEntry.effective_date'),
|
||||||
|
),
|
||||||
|
true);
|
||||||
|
$this->pr(20, $rent, "Unpaid rent");
|
||||||
|
|
||||||
|
if ($rent['entries'])
|
||||||
|
return $this->prReturn($rent['entries'][0]['StatementEntry']['paid_through']);
|
||||||
|
|
||||||
|
|
||||||
|
// If we don't have any unpaid charges (great!), then the
|
||||||
|
// customer is paid up through the last day of the last
|
||||||
|
// charge. So, search for paid charges, which already
|
||||||
|
// have the paid through date saved as part of the entry.
|
||||||
|
$rent = $this->StatementEntry->reconciledSet
|
||||||
|
('CHARGE',
|
||||||
|
array('conditions' =>
|
||||||
|
array(array('StatementEntry.lease_id' => $id),
|
||||||
|
array('StatementEntry.account_id' => $rent_account_id),
|
||||||
|
array('StatementEntry.reverse_transaction_id IS NULL'),
|
||||||
|
),
|
||||||
|
|
||||||
|
'order' => array('StatementEntry.through_date DESC'),
|
||||||
|
),
|
||||||
|
false);
|
||||||
|
$this->pr(20, $rent, "Paid rent");
|
||||||
|
|
||||||
|
if ($rent['entries'])
|
||||||
|
return $this->prReturn($rent['entries'][0]['StatementEntry']['through_date']);
|
||||||
|
|
||||||
|
|
||||||
|
// After all that, having found that there are no unpaid
|
||||||
|
// charges, and in fact, no paid charges either, we cannot
|
||||||
|
// possibly say when the customer is paid through.
|
||||||
|
return $this->prReturn(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: assessMonthlyRent
|
||||||
|
* - Charges rent for the month, if not already charged.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function assessMonthlyRent($id, $date = null) {
|
||||||
|
$this->prEnter(compact('id', 'date'));
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
if (empty($date))
|
||||||
|
$date = time();
|
||||||
|
|
||||||
|
if (is_string($date))
|
||||||
|
$date = strtotime($date);
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090808
|
||||||
|
// Anniversary Billing not supported
|
||||||
|
$anniversary = 0 && $this->field('anniversary_billing');
|
||||||
|
if (empty($anniversary)) {
|
||||||
|
$date_parts = getdate($date);
|
||||||
|
$date = mktime(0, 0, 0, $date_parts['mon'], 1, $date_parts['year']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we're not trying to assess rent on a closed lease
|
||||||
|
$close_date = $this->field('close_date');
|
||||||
|
$this->pr(17, compact('close_date'));
|
||||||
|
if (!empty($close_date))
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Don't assess rent after customer has moved out
|
||||||
|
$moveout_date = $this->field('moveout_date');
|
||||||
|
$this->pr(17, compact('moveout_date'));
|
||||||
|
if (!empty($moveout_date) && strtotime($moveout_date) < $date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Determine when the customer has already been charged through
|
||||||
|
// and, of course, don't charge them if they've already been.
|
||||||
|
$charge_through_date = strtotime($this->rentChargeThrough($id));
|
||||||
|
$this->pr(17, compact('date', 'charge_through_date')
|
||||||
|
+ array('date_str' => date('Y-m-d', $date),
|
||||||
|
'charge_through_date_str' => date('Y-m-d', $charge_through_date)));
|
||||||
|
if ($charge_through_date >= $date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// OK, it seems we're going to go ahead and charge the customer
|
||||||
|
// on this lease. Calculate the new charge through date, which
|
||||||
|
// is 1 day shy of 1 month from $date. For example, if we're
|
||||||
|
// charging for 8/1/09, charge through will be 8/31/09, and
|
||||||
|
// charging for 8/15/09, charge through will be 9/14/09.
|
||||||
|
$date_parts = getdate($date);
|
||||||
|
$charge_through_date = mktime(0, 0, 0,
|
||||||
|
$date_parts['mon']+1,
|
||||||
|
$date_parts['mday']-1,
|
||||||
|
$date_parts['year']);
|
||||||
|
|
||||||
|
// Build the invoice transaction
|
||||||
|
$invoice = array('Transaction' => array(), 'Entry' => array());
|
||||||
|
// REVISIT <AP>: 20090808
|
||||||
|
// Keeping Transaction.stamp until the existing facility
|
||||||
|
// is up to date. Then we want the stamp to be now()
|
||||||
|
// (and so can just delete the next line).
|
||||||
|
$invoice['Transaction']['stamp'] = date('Y-m-d', $date);
|
||||||
|
$invoice['Entry'][] =
|
||||||
|
array('effective_date' => date('Y-m-d', $date),
|
||||||
|
'through_date' => date('Y-m-d', $charge_through_date),
|
||||||
|
'amount' => $this->field('rent'),
|
||||||
|
'account_id' => $this->StatementEntry->Account->rentAccountId(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Record the invoice and return the result
|
||||||
|
$this->pr(21, compact('invoice'));
|
||||||
|
$result = $this->StatementEntry->Transaction->addInvoice
|
||||||
|
($invoice, null, $id);
|
||||||
|
return $this->prReturn($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: assessMonthlyRentAll
|
||||||
|
* - Ensures rent has been charged on all open leases
|
||||||
|
*/
|
||||||
|
|
||||||
|
function assessMonthlyRentAll($date = null) {
|
||||||
|
$this->prEnter(compact('date'));
|
||||||
|
$leases = $this->find
|
||||||
|
('all', array('contain' => false,
|
||||||
|
'conditions' => array('Lease.close_date' => null),
|
||||||
|
));
|
||||||
|
|
||||||
|
$ret = array('Lease' => array());
|
||||||
|
foreach ($leases AS $lease) {
|
||||||
|
$result = $this->assessMonthlyRent($lease['Lease']['id'], $date);
|
||||||
|
$ret['Lease'][$lease['Lease']['id']] = $result;
|
||||||
|
if ($result['error'])
|
||||||
|
$ret['error'] = true;
|
||||||
|
}
|
||||||
|
return $this->prReturn($ret + array('error' => false));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: assessMonthlyLate
|
||||||
|
* - Assess late charges for the month, if not already charged.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function assessMonthlyLate($id, $date = null) {
|
||||||
|
$this->prEnter(compact('id', 'date'));
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
if (empty($date))
|
||||||
|
$date = time();
|
||||||
|
|
||||||
|
if (is_string($date))
|
||||||
|
$date = strtotime($date);
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090808
|
||||||
|
// Anniversary Billing not supported
|
||||||
|
$anniversary = 0 && $this->field('anniversary_billing');
|
||||||
|
if (empty($anniversary)) {
|
||||||
|
$date_parts = getdate($date);
|
||||||
|
$date = mktime(0, 0, 0, $date_parts['mon'], 11, $date_parts['year']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't assess a late charge if the late charge date hasn't
|
||||||
|
// even come yet. This is questionable whether we really
|
||||||
|
// should restrict, since the user could know what they're
|
||||||
|
// doing, and/or the server clock could be off (although that
|
||||||
|
// would certainly have much larger ramifications). But, the
|
||||||
|
// fact is that this check likely handles the vast majority
|
||||||
|
// of the expected behavior, and presents an issue for very
|
||||||
|
// few users, if any at all.
|
||||||
|
if ($date > time())
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Make sure we're not trying to assess late charges on a closed lease
|
||||||
|
$close_date = $this->field('close_date');
|
||||||
|
$this->pr(17, compact('close_date'));
|
||||||
|
if (!empty($close_date))
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Don't assess late charges after customer has moved out
|
||||||
|
$moveout_date = $this->field('moveout_date');
|
||||||
|
$this->pr(17, compact('moveout_date'));
|
||||||
|
if (!empty($moveout_date) && strtotime($moveout_date) < $date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Determine when the customer has been charged through for rent
|
||||||
|
// and don't mark them as late if they haven't even been charged rent
|
||||||
|
$charge_through_date = strtotime($this->rentChargeThrough($id));
|
||||||
|
$this->pr(17, compact('date', 'charge_through_date')
|
||||||
|
+ array('date_str' => date('Y-m-d', $date),
|
||||||
|
'charge_through_date_str' => date('Y-m-d', $charge_through_date)));
|
||||||
|
if ($charge_through_date <= $date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Determine if the customer is actually late. This is based on
|
||||||
|
// when they've paid through, plus 10 days before they're late.
|
||||||
|
// REVISIT <AP>: 20090813
|
||||||
|
// Of course, 10 days is a terrible hardcode. This should be
|
||||||
|
// driven from the late schedule, saved as part of the lease
|
||||||
|
// (when finally implemented).
|
||||||
|
$paid_through_date = strtotime($this->rentPaidThrough($id));
|
||||||
|
$this->pr(17, compact('date', 'paid_through_date')
|
||||||
|
+ array('date_str' => date('Y-m-d', $date),
|
||||||
|
'paid_through_date_str' => date('Y-m-d', $paid_through_date)));
|
||||||
|
$date_parts = getdate($paid_through_date);
|
||||||
|
$paid_through_date = mktime(0, 0, 0, $date_parts['mon'], $date_parts['mday']+10, $date_parts['year']);
|
||||||
|
if ($paid_through_date >= $date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Determine if the customer has already been charged a late fee
|
||||||
|
// and, of course, don't charge them if they've already been.
|
||||||
|
$late_charges = $this->lateCharges($id);
|
||||||
|
foreach ($late_charges AS $late) {
|
||||||
|
if (strtotime($late['StatementEntry']['effective_date']) == $date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the invoice transaction
|
||||||
|
$invoice = array('Transaction' => array(), 'Entry' => array());
|
||||||
|
// REVISIT <AP>: 20090808
|
||||||
|
// Keeping Transaction.stamp until the existing facility
|
||||||
|
// is up to date. Then we want the stamp to be now()
|
||||||
|
// (and so can just delete the next line).
|
||||||
|
$invoice['Transaction']['stamp'] = date('Y-m-d', $date);
|
||||||
|
$invoice['Entry'][] =
|
||||||
|
array('effective_date' => date('Y-m-d', $date),
|
||||||
|
'amount' => 10,
|
||||||
|
'account_id' => $this->StatementEntry->Account->lateChargeAccountId(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Record the invoice and return the result
|
||||||
|
$this->pr(21, compact('invoice'));
|
||||||
|
$result = $this->StatementEntry->Transaction->addInvoice
|
||||||
|
($invoice, null, $id);
|
||||||
|
return $this->prReturn($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: assessMonthlyLateAll
|
||||||
|
* - Ensures rent has been charged on all open leases
|
||||||
|
*/
|
||||||
|
|
||||||
|
function assessMonthlyLateAll($date = null) {
|
||||||
|
$this->prEnter(compact('date'));
|
||||||
|
$leases = $this->find
|
||||||
|
('all', array('contain' => false,
|
||||||
|
'conditions' => array('Lease.close_date' => null),
|
||||||
|
));
|
||||||
|
|
||||||
|
$ret = array('Lease' => array());
|
||||||
|
foreach ($leases AS $lease) {
|
||||||
|
$result = $this->assessMonthlyLate($lease['Lease']['id'], $date);
|
||||||
|
$ret['Lease'][$lease['Lease']['id']] = $result;
|
||||||
|
if ($result['error'])
|
||||||
|
$ret['error'] = true;
|
||||||
|
}
|
||||||
|
return $this->prReturn($ret + array('error' => false));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* functions: delinquency
|
||||||
|
* - SQL fragments to determine whether a lease is delinquent
|
||||||
|
*/
|
||||||
|
|
||||||
|
function conditionDelinquent($table_name = 'Lease') {
|
||||||
|
if (empty($table_name)) $t = ''; else $t = $table_name . '.';
|
||||||
|
return ("({$t}close_date IS NULL AND" .
|
||||||
|
" NOW() > DATE_ADD({$t}paid_through_date, INTERVAL 10 DAY))");
|
||||||
|
}
|
||||||
|
|
||||||
|
function delinquentDaysSQL($table_name = 'Lease') {
|
||||||
|
if (empty($table_name)) $t = ''; else $t = $table_name . '.';
|
||||||
|
return ("IF(" . $this->conditionDelinquent($table_name) . "," .
|
||||||
|
" DATEDIFF(NOW(), {$t}paid_through_date)-1," .
|
||||||
|
" NULL)");
|
||||||
|
}
|
||||||
|
|
||||||
|
function delinquentField($table_name = 'Lease') {
|
||||||
|
return ($this->delinquentDaysSQL($table_name) . " AS 'delinquent'");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: moveIn
|
||||||
|
* - Moves the specified customer into the specified lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function moveIn($customer_id, $unit_id,
|
||||||
|
$deposit = null, $rent = null,
|
||||||
|
$stamp = null, $comment = null)
|
||||||
|
{
|
||||||
|
$this->prEnter(compact('customer_id', 'unit_id',
|
||||||
|
'deposit', 'rent', 'stamp', 'comment'));
|
||||||
|
|
||||||
|
$lt = $this->LeaseType->find('first',
|
||||||
|
array('conditions' =>
|
||||||
|
array('code' => 'SL')));
|
||||||
|
|
||||||
|
// Use NOW if not given a movein date
|
||||||
|
if (!isset($stamp))
|
||||||
|
$stamp = date('Y-m-d G:i:s');
|
||||||
|
|
||||||
|
if (!$comment)
|
||||||
|
$comment = null;
|
||||||
|
|
||||||
|
if (!isset($deposit) || !isset($rent)) {
|
||||||
|
$rates = $this->Unit->find
|
||||||
|
('first',
|
||||||
|
array('contain' =>
|
||||||
|
array('UnitSize' =>
|
||||||
|
array('deposit', 'rent'),
|
||||||
|
),
|
||||||
|
'fields' => array('deposit', 'rent'),
|
||||||
|
'conditions' => array('Unit.id' => $unit_id),
|
||||||
|
));
|
||||||
|
|
||||||
|
$deposit =
|
||||||
|
(isset($deposit)
|
||||||
|
? $deposit
|
||||||
|
: (isset($rates['Unit']['deposit'])
|
||||||
|
? $rates['Unit']['deposit']
|
||||||
|
: (isset($rates['UnitSize']['deposit'])
|
||||||
|
? $rates['UnitSize']['deposit']
|
||||||
|
: 0)));
|
||||||
|
|
||||||
|
$rent =
|
||||||
|
(isset($rent)
|
||||||
|
? $rent
|
||||||
|
: (isset($rates['Unit']['rent'])
|
||||||
|
? $rates['Unit']['rent']
|
||||||
|
: (isset($rates['UnitSize']['rent'])
|
||||||
|
? $rates['UnitSize']['rent']
|
||||||
|
: 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Save this new lease.
|
||||||
|
$this->create();
|
||||||
|
if (!$this->save(array('lease_type_id' => $lt['LeaseType']['id'],
|
||||||
|
'unit_id' => $unit_id,
|
||||||
|
'customer_id' => $customer_id,
|
||||||
|
'lease_date' => $stamp,
|
||||||
|
'movein_date' => $stamp,
|
||||||
|
'deposit' => $deposit,
|
||||||
|
'rent' => $rent,
|
||||||
|
'comment' => $comment), false)) {
|
||||||
|
return $this->prReturn(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the lease number to be the same as the lease ID
|
||||||
|
$this->id;
|
||||||
|
$this->saveField('number', $this->id);
|
||||||
|
|
||||||
|
// Update the current lease count for the customer
|
||||||
|
$this->Customer->updateLeaseCount($customer_id);
|
||||||
|
|
||||||
|
// Update the unit status
|
||||||
|
$this->Unit->updateStatus($unit_id, 'OCCUPIED');
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090702
|
||||||
|
// We need to assess the security deposit charge,
|
||||||
|
// and probably rent as well. Rent, however, will
|
||||||
|
// require user parameters to indicate whether it
|
||||||
|
// was waived, pro-rated, etc.
|
||||||
|
|
||||||
|
// Return the new lease ID
|
||||||
|
return $this->prReturn($this->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: moveOut
|
||||||
|
* - Moves the customer out of the specified lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function moveOut($id, $status = 'VACANT',
|
||||||
|
$stamp = null, $close = true)
|
||||||
|
{
|
||||||
|
$this->prEnter(compact('id', 'status', 'stamp', 'close'));
|
||||||
|
|
||||||
|
// Use NOW if not given a moveout date
|
||||||
|
if (!isset($stamp))
|
||||||
|
$stamp = date('Y-m-d G:i:s');
|
||||||
|
|
||||||
|
// Reset the data
|
||||||
|
$this->create();
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
// Set the customer move-out date
|
||||||
|
$this->data['Lease']['moveout_date'] = $stamp;
|
||||||
|
|
||||||
|
// Save it!
|
||||||
|
$this->save($this->data, false);
|
||||||
|
|
||||||
|
// Release the security deposit(s)
|
||||||
|
$this->releaseSecurityDeposits($id, $stamp);
|
||||||
|
|
||||||
|
// Close the lease, if so requested
|
||||||
|
if ($close)
|
||||||
|
$this->close($id, $stamp);
|
||||||
|
|
||||||
|
// Update the current lease count for the customer
|
||||||
|
$this->Customer->updateLeaseCount($this->field('customer_id'));
|
||||||
|
|
||||||
|
// Finally, update the unit status
|
||||||
|
$this->recursive = -1;
|
||||||
|
$this->read();
|
||||||
|
$this->Unit->updateStatus($this->data['Lease']['unit_id'], $status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: close
|
||||||
|
* - Closes the lease to further action
|
||||||
|
*/
|
||||||
|
|
||||||
|
function close($id, $stamp = null) {
|
||||||
|
$this->prEnter(compact('id', 'stamp'));
|
||||||
|
|
||||||
|
if (!$this->closeable($id))
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
// Reset the data
|
||||||
|
$this->create();
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
// Use NOW if not given a moveout date
|
||||||
|
if (!isset($stamp))
|
||||||
|
$stamp = date('Y-m-d G:i:s');
|
||||||
|
|
||||||
|
// Set the close date
|
||||||
|
$this->data['Lease']['close_date'] = $stamp;
|
||||||
|
|
||||||
|
// Save it!
|
||||||
|
$this->save($this->data, false);
|
||||||
|
|
||||||
|
// Update the current lease count for the customer
|
||||||
|
$this->Customer->updateLeaseCount($this->field('customer_id'));
|
||||||
|
|
||||||
|
return $this->prReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: closeable
|
||||||
|
* - Indicates whether or not the lease can be closed
|
||||||
|
*/
|
||||||
|
|
||||||
|
function closeable($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
|
||||||
|
$this->recursive = -1;
|
||||||
|
$this->read(null, $id);
|
||||||
|
|
||||||
|
// We can't close a lease that's still in use
|
||||||
|
if (!isset($this->data['Lease']['moveout_date']))
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
// We can't close a lease that's already closed
|
||||||
|
if (isset($this->data['Lease']['close_date']))
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
// A lease can only be closed if there are no outstanding
|
||||||
|
// security deposits ...
|
||||||
|
if ($this->securityDepositBalance($id) != 0)
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
// ... and if the account balance is zero.
|
||||||
|
if ($this->balance($id) != 0)
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
// Apparently this lease meets all the criteria!
|
||||||
|
return $this->prReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: refund
|
||||||
|
* - Marks any lease balance as payable to the customer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function refund($id, $stamp = null) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
$balance = $this->balance($id);
|
||||||
|
|
||||||
|
if ($balance >= 0)
|
||||||
|
return $this->prReturn(array('error' => true));
|
||||||
|
|
||||||
|
$balance *= -1;
|
||||||
|
|
||||||
|
// Build a transaction
|
||||||
|
$refund = array('Transaction' => array(), 'Entry' => array());
|
||||||
|
$refund['Transaction']['stamp'] = $stamp;
|
||||||
|
$refund['Transaction']['comment'] = "Lease Refund";
|
||||||
|
|
||||||
|
$refund['Entry'][] =
|
||||||
|
array('amount' => $balance);
|
||||||
|
|
||||||
|
$result = $this->StatementEntry->Transaction->addRefund
|
||||||
|
($refund, null, $id);
|
||||||
|
|
||||||
|
return $this->prReturn($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: update
|
||||||
|
* - Update any cached or calculated fields
|
||||||
|
*/
|
||||||
|
function update($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
|
||||||
|
$this->id = $id;
|
||||||
|
$this->saveField('charge_through_date', $this->rentChargeThrough($id));
|
||||||
|
$this->saveField('paid_through_date', $this->rentPaidThrough($id));
|
||||||
|
|
||||||
|
$moveout = $this->field('moveout_date');
|
||||||
|
if (empty($moveout))
|
||||||
|
$this->Unit->update($this->field('unit_id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: balance
|
||||||
|
* - Returns the balance of money owed on the lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function balance($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
$stats = $this->stats($id);
|
||||||
|
return $this->prReturn($stats['balance']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns summary data from the requested lease.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function stats($id = null, $query = null) {
|
||||||
|
$this->prEnter(compact('id', 'query'));
|
||||||
|
if (!$id)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
$find_stats = $this->StatementEntry->find
|
||||||
|
('first', array
|
||||||
|
('contain' => false,
|
||||||
|
'fields' => $this->StatementEntry->chargeDisbursementFields(true),
|
||||||
|
'conditions' => array('StatementEntry.lease_id' => $id),
|
||||||
|
));
|
||||||
|
$find_stats = $find_stats[0];
|
||||||
|
return $this->prReturn($find_stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
15
models/lease_type.php
Normal file
15
models/lease_type.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
class LeaseType extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'LeaseType';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'name' => array('notempty')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'Lease',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
179
models/ledger.php
Normal file
179
models/ledger.php
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
<?php
|
||||||
|
class Ledger extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'Account',
|
||||||
|
'PriorLedger' => array('className' => 'Ledger'),
|
||||||
|
'CloseTransaction' => array('className' => 'Transaction'),
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'Transaction',
|
||||||
|
'LedgerEntry',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: accountID
|
||||||
|
* - Returns the account ID for the given ledger
|
||||||
|
*/
|
||||||
|
function accountID($id) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$item = $this->find('first', array
|
||||||
|
('link' => array('Account'),
|
||||||
|
'conditions' => array('Ledger.id' => $id),
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
//pr(compact('id', 'item'));
|
||||||
|
return $item['Account']['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: currentLedgerID
|
||||||
|
* - Returns the current ledger ID of the account for the given ledger.
|
||||||
|
*/
|
||||||
|
function currentLedgerID($id) {
|
||||||
|
return $this->Account->currentLedgerID($this->accountID($id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: closeLedger
|
||||||
|
* - Closes the current ledger, and returns a fresh one
|
||||||
|
*/
|
||||||
|
function closeLedgers($ids) {
|
||||||
|
$ret = array('new_ledger_ids' => array());
|
||||||
|
|
||||||
|
$entries = array();
|
||||||
|
foreach ($ids AS $id) {
|
||||||
|
// Query stats to get the balance forward
|
||||||
|
$stats = $this->stats($id);
|
||||||
|
|
||||||
|
// Populate fields from the current ledger
|
||||||
|
$this->recursive = -1;
|
||||||
|
$this->id = $id;
|
||||||
|
$this->read();
|
||||||
|
|
||||||
|
// Build a new ledger to replace the current one
|
||||||
|
$this->data['Ledger']['id'] = null;
|
||||||
|
$this->data['Ledger']['close_transaction_id'] = null;
|
||||||
|
$this->data['Ledger']['prior_ledger_id'] = $id;
|
||||||
|
$this->data['Ledger']['comment'] = null;
|
||||||
|
++$this->data['Ledger']['sequence'];
|
||||||
|
$this->data['Ledger']['name'] =
|
||||||
|
($this->data['Ledger']['account_id'] .
|
||||||
|
'-' .
|
||||||
|
$this->data['Ledger']['sequence']);
|
||||||
|
|
||||||
|
// Save the new ledger
|
||||||
|
$this->id = null;
|
||||||
|
if (!$this->save($this->data, false))
|
||||||
|
return array('error' => true, 'new_ledger_data' => $this->data) + $ret;
|
||||||
|
$ret['new_ledger_ids'][] = $this->id;
|
||||||
|
|
||||||
|
$entries[] = array('old_ledger_id' => $id,
|
||||||
|
'new_ledger_id' => $this->id,
|
||||||
|
'amount' => $stats['balance']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the close
|
||||||
|
$result = $this->Transaction->addClose(array('Transaction' => array(),
|
||||||
|
'Ledger' => $entries));
|
||||||
|
$ret['Transaction'] = $result;
|
||||||
|
if ($result['error'])
|
||||||
|
return array('error' => true) + $ret;
|
||||||
|
|
||||||
|
return $ret + array('error' => false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: debitCreditFields
|
||||||
|
* - Returns the fields necessary to determine whether the queried
|
||||||
|
* entries are a debit, or a credit, and also the effect each have
|
||||||
|
* on the overall balance of the ledger.
|
||||||
|
*/
|
||||||
|
function debitCreditFields($sum = false, $balance = true,
|
||||||
|
$entry_name = 'LedgerEntry', $account_name = 'Account') {
|
||||||
|
return $this->LedgerEntry->debitCreditFields
|
||||||
|
($sum, $balance, $entry_name, $account_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: ledgerEntries
|
||||||
|
* - Returns an array of ledger entries that belong to a given
|
||||||
|
* ledger. There is extra work done to establish debit/credit
|
||||||
|
*/
|
||||||
|
function ledgerEntries($ids, $query = null) {
|
||||||
|
if (empty($ids))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
$entries = $this->LedgerEntry->find
|
||||||
|
('all', array
|
||||||
|
('link' => array('Ledger' => array('Account')),
|
||||||
|
'fields' => array_merge(array("LedgerEntry.*"),
|
||||||
|
$this->LedgerEntry->debitCreditFields()),
|
||||||
|
'conditions' => array('LedgerEntry.ledger_id' => $ids),
|
||||||
|
));
|
||||||
|
|
||||||
|
//pr(compact('entries'));
|
||||||
|
return $entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns summary data from the requested ledger.
|
||||||
|
*/
|
||||||
|
function stats($id, $query = null) {
|
||||||
|
if (!$id)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
if (!isset($query['link']['Account']))
|
||||||
|
$query['link']['Account'] = array();
|
||||||
|
if (!isset($query['link']['Account']['fields']))
|
||||||
|
$query['link']['Account']['fields'] = array();
|
||||||
|
if (!isset($query['fields']))
|
||||||
|
$query['fields'] = array();
|
||||||
|
|
||||||
|
$query['fields'] = array_merge($query['fields'],
|
||||||
|
$this->debitCreditFields(true));
|
||||||
|
|
||||||
|
$query['conditions'][] = array('LedgerEntry.ledger_id' => $id);
|
||||||
|
$query['group'][] = 'LedgerEntry.ledger_id';
|
||||||
|
|
||||||
|
$stats = $this->LedgerEntry->find('first', $query);
|
||||||
|
|
||||||
|
// The fields are all tucked into the [0] index,
|
||||||
|
// and the rest of the array is useless (empty).
|
||||||
|
$stats = $stats[0];
|
||||||
|
|
||||||
|
// Make sure we have a member for debit/credit
|
||||||
|
foreach(array('debits', 'credits') AS $crdr)
|
||||||
|
if (!isset($stats[$crdr]))
|
||||||
|
$stats[$crdr] = null;
|
||||||
|
|
||||||
|
// Make sure we have a non-null balance
|
||||||
|
if (!isset($stats['balance']))
|
||||||
|
$stats['balance'] = 0;
|
||||||
|
|
||||||
|
return $stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
177
models/ledger_entry.php
Normal file
177
models/ledger_entry.php
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
<?php
|
||||||
|
class LedgerEntry extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'Transaction',
|
||||||
|
'Account',
|
||||||
|
'Ledger',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasOne = array(
|
||||||
|
'Tender' => array(
|
||||||
|
'dependent' => true,
|
||||||
|
),
|
||||||
|
'DebitDoubleEntry' => array(
|
||||||
|
'className' => 'DoubleEntry',
|
||||||
|
'foreignKey' => 'debit_entry_id',
|
||||||
|
'dependent' => true,
|
||||||
|
),
|
||||||
|
'CreditDoubleEntry' => array(
|
||||||
|
'className' => 'DoubleEntry',
|
||||||
|
'foreignKey' => 'credit_entry_id',
|
||||||
|
'dependent' => true,
|
||||||
|
),
|
||||||
|
'DoubleEntry' => array(
|
||||||
|
'foreignKey' => false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
// The Debit half of the double entry matching THIS Credit (if it is one)
|
||||||
|
'DebitEntry' => array(
|
||||||
|
'className' => 'LedgerEntry',
|
||||||
|
'joinTable' => 'double_entries',
|
||||||
|
'linkalias' => 'DDE',
|
||||||
|
'foreignKey' => 'credit_entry_id',
|
||||||
|
'associationForeignKey' => 'debit_entry_id',
|
||||||
|
),
|
||||||
|
|
||||||
|
// The Credit half of the double entry matching THIS Debit (if it is one)
|
||||||
|
'CreditEntry' => array(
|
||||||
|
'className' => 'LedgerEntry',
|
||||||
|
'joinTable' => 'double_entries',
|
||||||
|
'linkalias' => 'CDE',
|
||||||
|
'foreignKey' => 'debit_entry_id',
|
||||||
|
'associationForeignKey' => 'credit_entry_id',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: debitCreditFields
|
||||||
|
* - Returns the fields necessary to determine whether the queried
|
||||||
|
* entries are a debit, or a credit, and also the effect each have
|
||||||
|
* on the overall balance of the account/ledger.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function debitCreditFields($sum = false, $balance = true,
|
||||||
|
$entry_name = 'LedgerEntry', $account_name = 'Account') {
|
||||||
|
$fields = array
|
||||||
|
(
|
||||||
|
($sum ? 'SUM(' : '') .
|
||||||
|
"IF({$entry_name}.crdr = 'DEBIT'," .
|
||||||
|
" {$entry_name}.amount, NULL)" .
|
||||||
|
($sum ? ')' : '') . ' AS debit' . ($sum ? 's' : ''),
|
||||||
|
|
||||||
|
($sum ? 'SUM(' : '') .
|
||||||
|
"IF({$entry_name}.crdr = 'CREDIT'," .
|
||||||
|
" {$entry_name}.amount, NULL)" .
|
||||||
|
($sum ? ')' : '') . ' AS credit' . ($sum ? 's' : ''),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($balance)
|
||||||
|
$fields[] =
|
||||||
|
($sum ? 'SUM(' : '') .
|
||||||
|
"IF(${account_name}.type IN ('ASSET', 'EXPENSE')," .
|
||||||
|
" IF({$entry_name}.crdr = 'DEBIT', 1, -1)," .
|
||||||
|
" IF({$entry_name}.crdr = 'CREDIT', 1, -1))" .
|
||||||
|
" * IF({$entry_name}.amount, {$entry_name}.amount, 0)" .
|
||||||
|
($sum ? ')' : '') . ' AS balance';
|
||||||
|
|
||||||
|
if ($sum)
|
||||||
|
$fields[] = "COUNT({$entry_name}.id) AS entries";
|
||||||
|
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: verifyLedgerEntry
|
||||||
|
* - Verifies consistenty of new ledger entry data
|
||||||
|
* (not in a pre-existing ledger entry)
|
||||||
|
*/
|
||||||
|
function verifyLedgerEntry($entry, $tender = null) {
|
||||||
|
/* pr(array("LedgerEntry::verifyLedgerEntry()" */
|
||||||
|
/* => compact('entry', 'tender'))); */
|
||||||
|
|
||||||
|
if (empty($entry['account_id']) ||
|
||||||
|
empty($entry['crdr']) ||
|
||||||
|
empty($entry['amount'])
|
||||||
|
) {
|
||||||
|
/* pr(array("LedgerEntry::verifyLedgerEntry()" */
|
||||||
|
/* => "Entry verification failed")); */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($tender) && !$this->Tender->verifyTender($tender)) {
|
||||||
|
/* pr(array("LedgerEntry::verifyLedgerEntry()" */
|
||||||
|
/* => "Tender verification failed")); */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: addLedgerEntry
|
||||||
|
* - Inserts new Ledger Entry into the database
|
||||||
|
*/
|
||||||
|
function addLedgerEntry($entry, $tender = null) {
|
||||||
|
//$this->prFunctionLevel(16);
|
||||||
|
$this->prEnter(compact('entry', 'tender'));
|
||||||
|
|
||||||
|
$ret = array('data' => $entry);
|
||||||
|
if (!$this->verifyLedgerEntry($entry, $tender))
|
||||||
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
|
if (empty($entry['ledger_id']))
|
||||||
|
$entry['ledger_id'] =
|
||||||
|
$this->Account->currentLedgerID($entry['account_id']);
|
||||||
|
|
||||||
|
$this->create();
|
||||||
|
if (!$this->save($entry))
|
||||||
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
|
$ret['ledger_entry_id'] = $this->id;
|
||||||
|
|
||||||
|
if (isset($tender)) {
|
||||||
|
$tender['account_id'] = $entry['account_id'];
|
||||||
|
$tender['ledger_entry_id'] = $ret['ledger_entry_id'];
|
||||||
|
$result = $this->Tender->addTender($tender);
|
||||||
|
$ret['Tender'] = $result;
|
||||||
|
if ($result['error'])
|
||||||
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn($ret + array('error' => false));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns summary data from the requested ledger entry
|
||||||
|
*/
|
||||||
|
function stats($id = null, $query = null, $set = null) {
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090816
|
||||||
|
// This function appeared to be dramatically broken,
|
||||||
|
// a throwback to an earlier time. I deleted its
|
||||||
|
// contents and added this error to ensure it does
|
||||||
|
// not get used.
|
||||||
|
$this->INTERNAL_ERROR('This function should not be used');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
23
models/map.php
Normal file
23
models/map.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
class Map extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'Map';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'site_id' => array('numeric'),
|
||||||
|
'site_area_id' => array('numeric'),
|
||||||
|
'name' => array('notempty'),
|
||||||
|
'width' => array('numeric'),
|
||||||
|
'depth' => array('numeric')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'SiteArea',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
'Unit',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
16
models/site.php
Normal file
16
models/site.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
class Site extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'Site';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'name' => array('notempty')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'SiteArea',
|
||||||
|
'SiteOption',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
20
models/site_area.php
Normal file
20
models/site_area.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
class SiteArea extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'SiteArea';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'site_id' => array('numeric'),
|
||||||
|
'name' => array('notempty')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'Site',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasOne = array(
|
||||||
|
'Map',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
725
models/statement_entry.php
Normal file
725
models/statement_entry.php
Normal file
@@ -0,0 +1,725 @@
|
|||||||
|
<?php
|
||||||
|
class StatementEntry extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'Transaction',
|
||||||
|
'Customer',
|
||||||
|
'Lease',
|
||||||
|
'Account',
|
||||||
|
|
||||||
|
// The charge to which this disbursement applies (if it is one)
|
||||||
|
'ChargeEntry' => array(
|
||||||
|
'className' => 'StatementEntry',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
// The disbursements that apply to this charge (if it is one)
|
||||||
|
'DisbursementEntry' => array(
|
||||||
|
'className' => 'StatementEntry',
|
||||||
|
'foreignKey' => 'charge_entry_id',
|
||||||
|
'dependent' => true,
|
||||||
|
),
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
//var $default_log_level = array('log' => 30, 'show' => 15);
|
||||||
|
var $max_log_level = 19;
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: debit/creditTypes
|
||||||
|
*/
|
||||||
|
|
||||||
|
function debitTypes() {
|
||||||
|
return array('CHARGE', 'PAYMENT', 'REFUND');
|
||||||
|
}
|
||||||
|
|
||||||
|
function creditTypes() {
|
||||||
|
return array('DISBURSEMENT', 'WAIVER', 'REVERSAL', 'WRITEOFF', 'SURPLUS');
|
||||||
|
}
|
||||||
|
|
||||||
|
function voidTypes() {
|
||||||
|
return array('VOID');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: chargeDisbursementFields
|
||||||
|
*/
|
||||||
|
|
||||||
|
function chargeDisbursementFields($sum = false, $entry_name = 'StatementEntry') {
|
||||||
|
$debits = $this->debitTypes();
|
||||||
|
$credits = $this->creditTypes();
|
||||||
|
$voids = $this->voidTypes();
|
||||||
|
|
||||||
|
foreach ($debits AS &$enum)
|
||||||
|
$enum = "'" . $enum . "'";
|
||||||
|
foreach ($credits AS &$enum)
|
||||||
|
$enum = "'" . $enum . "'";
|
||||||
|
foreach ($voids AS &$enum)
|
||||||
|
$enum = "'" . $enum . "'";
|
||||||
|
|
||||||
|
$debit_set = implode(", ", $debits);
|
||||||
|
$credit_set = implode(", ", $credits);
|
||||||
|
$void_set = implode(", ", $voids);
|
||||||
|
|
||||||
|
$fields = array
|
||||||
|
(
|
||||||
|
($sum ? 'SUM(' : '') .
|
||||||
|
"IF({$entry_name}.type IN ({$debit_set})," .
|
||||||
|
" {$entry_name}.amount, NULL)" .
|
||||||
|
($sum ? ')' : '') . ' AS charge' . ($sum ? 's' : ''),
|
||||||
|
|
||||||
|
($sum ? 'SUM(' : '') .
|
||||||
|
"IF({$entry_name}.type IN({$credit_set})," .
|
||||||
|
" {$entry_name}.amount, NULL)" .
|
||||||
|
($sum ? ')' : '') . ' AS disbursement' . ($sum ? 's' : ''),
|
||||||
|
|
||||||
|
($sum ? 'SUM(' : '') .
|
||||||
|
"IF({$entry_name}.type IN ({$debit_set}), 1," .
|
||||||
|
" IF({$entry_name}.type IN ({$credit_set}), -1, 0))" .
|
||||||
|
" * IF({$entry_name}.amount, {$entry_name}.amount, 0)" .
|
||||||
|
($sum ? ')' : '') . ' AS balance',
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($sum)
|
||||||
|
$fields[] = "COUNT({$entry_name}.id) AS entries";
|
||||||
|
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: verifyStatementEntry
|
||||||
|
* - Verifies consistenty of new statement entry data
|
||||||
|
* (not in a pre-existing statement entry)
|
||||||
|
*/
|
||||||
|
function verifyStatementEntry($entry) {
|
||||||
|
$this->prFunctionLevel(10);
|
||||||
|
$this->prEnter(compact('entry'));
|
||||||
|
|
||||||
|
if (empty($entry['type']) ||
|
||||||
|
//empty($entry['effective_date']) ||
|
||||||
|
empty($entry['account_id']) ||
|
||||||
|
empty($entry['amount'])
|
||||||
|
) {
|
||||||
|
return $this->prReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: addStatementEntry
|
||||||
|
* - Inserts new Statement Entry into the database
|
||||||
|
*/
|
||||||
|
function addStatementEntry($entry) {
|
||||||
|
$this->prEnter(compact('entry'));
|
||||||
|
|
||||||
|
$ret = array('data' => $entry);
|
||||||
|
if (!$this->verifyStatementEntry($entry))
|
||||||
|
return $this->prReturn(array('error' => true, 'verify_data' => $entry) + $ret);
|
||||||
|
|
||||||
|
$this->create();
|
||||||
|
if (!$this->save($entry))
|
||||||
|
return $this->prReturn(array('error' => true, 'save_data' => $entry) + $ret);
|
||||||
|
|
||||||
|
$ret['statement_entry_id'] = $this->id;
|
||||||
|
return $this->prReturn($ret + array('error' => false));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: waive
|
||||||
|
* - Waives the charge balance
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function waive($id, $stamp = null) {
|
||||||
|
$this->prEnter(compact('id', 'stamp'));
|
||||||
|
|
||||||
|
// Get the basic information about the entry to be waived.
|
||||||
|
$this->recursive = -1;
|
||||||
|
$charge = $this->read(null, $id);
|
||||||
|
$charge = $charge['StatementEntry'];
|
||||||
|
|
||||||
|
if ($charge['type'] !== 'CHARGE')
|
||||||
|
$this->INTERNAL_ERROR("Waiver item is not CHARGE.");
|
||||||
|
|
||||||
|
// Query the stats to get the remaining balance
|
||||||
|
$stats = $this->stats($id);
|
||||||
|
|
||||||
|
// Build a transaction
|
||||||
|
$waiver = array('Transaction' => array(), 'Entry' => array());
|
||||||
|
$waiver['Transaction']['stamp'] = $stamp;
|
||||||
|
$waiver['Transaction']['comment'] = "Charge Waiver";
|
||||||
|
|
||||||
|
// Add the charge waiver
|
||||||
|
$waiver['Entry'][] =
|
||||||
|
array('amount' => $stats['Charge']['balance'],
|
||||||
|
'comment' => null,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Record the waiver transaction
|
||||||
|
return $this->prReturn($this->Transaction->addWaiver
|
||||||
|
($waiver, $id, $charge['customer_id'], $charge['lease_id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: reversable
|
||||||
|
* - Returns true if the charge can be reversed; false otherwise
|
||||||
|
*/
|
||||||
|
function reversable($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
|
||||||
|
if (empty($id))
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
// Verify the item is an actual charge
|
||||||
|
$this->id = $id;
|
||||||
|
$charge_type = $this->field('type');
|
||||||
|
if ($charge_type !== 'CHARGE')
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
// Determine anything reconciled against the charge
|
||||||
|
$reverse_transaction_id = $this->field('reverse_transaction_id');
|
||||||
|
if (!empty($reverse_transaction_id))
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
return $this->prReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: reverse
|
||||||
|
* - Reverses the charges
|
||||||
|
*/
|
||||||
|
function reverse($id, $stamp = null, $comment) {
|
||||||
|
$this->prEnter(compact('id', 'stamp'));
|
||||||
|
|
||||||
|
// Verify the item can be reversed
|
||||||
|
if (!$this->reversable($id))
|
||||||
|
$this->INTERNAL_ERROR("Item is not reversable.");
|
||||||
|
|
||||||
|
// Get the basic information about this charge
|
||||||
|
$charge = $this->find('first', array('contain' => true));
|
||||||
|
//$charge = $charge['StatementEntry'];
|
||||||
|
|
||||||
|
// Query the stats to get the remaining balance
|
||||||
|
$stats = $this->stats($id);
|
||||||
|
$charge['paid'] = $stats['Charge']['disbursement'];
|
||||||
|
|
||||||
|
// Record the reversal transaction
|
||||||
|
$result = $this->Transaction->addReversal
|
||||||
|
($charge, $stamp, $comment ? $comment : 'Charge Reversal');
|
||||||
|
|
||||||
|
if (empty($result['error'])) {
|
||||||
|
// Mark the charge as reversed
|
||||||
|
$this->id = $id;
|
||||||
|
$this->saveField('reverse_transaction_id', $result['transaction_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: reconciledSet
|
||||||
|
* - Returns the set of entries satisfying the given conditions,
|
||||||
|
* along with any entries that they reconcile
|
||||||
|
*/
|
||||||
|
function reconciledSetQuery($set, $query) {
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
if (in_array($set, $this->debitTypes()))
|
||||||
|
$query['link']['DisbursementEntry'] = array('fields' => array("SUM(DisbursementEntry.amount) AS reconciled"));
|
||||||
|
elseif (in_array($set, $this->creditTypes()))
|
||||||
|
$query['link']['ChargeEntry'] = array('fields' => array("SUM(ChargeEntry.amount) AS reconciled"));
|
||||||
|
else
|
||||||
|
die("INVALID RECONCILE SET");
|
||||||
|
|
||||||
|
$query['conditions'][] = array('StatementEntry.type' => $set);
|
||||||
|
$query['group'] = 'StatementEntry.id';
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reconciledSet($set, $query = null, $unrec = false, $if_rec_include_partial = false) {
|
||||||
|
//$this->prFunctionLevel(array('log' => 16, 'show' => 10));
|
||||||
|
$this->prEnter(compact('set', 'query', 'unrec', 'if_rec_include_partial'));
|
||||||
|
$lquery = $this->reconciledSetQuery($set, $query);
|
||||||
|
$result = $this->find('all', $lquery);
|
||||||
|
|
||||||
|
$this->pr(20, compact('lquery', 'result'));
|
||||||
|
|
||||||
|
$resultset = array();
|
||||||
|
foreach ($result AS $i => $entry) {
|
||||||
|
$this->pr(25, compact('entry'));
|
||||||
|
if (!empty($entry[0]))
|
||||||
|
$entry['StatementEntry'] = $entry[0] + $entry['StatementEntry'];
|
||||||
|
unset($entry[0]);
|
||||||
|
|
||||||
|
$entry['StatementEntry']['balance'] =
|
||||||
|
$entry['StatementEntry']['amount'] - $entry['StatementEntry']['reconciled'];
|
||||||
|
|
||||||
|
// Since HAVING isn't a builtin feature of CakePHP,
|
||||||
|
// we'll have to post-process to get the desired entries
|
||||||
|
|
||||||
|
if ($entry['StatementEntry']['balance'] == 0)
|
||||||
|
$reconciled = true;
|
||||||
|
elseif ($entry['StatementEntry']['reconciled'] == 0)
|
||||||
|
$reconciled = false;
|
||||||
|
else // Partial disbursement; depends on unrec
|
||||||
|
$reconciled = (!$unrec && $if_rec_include_partial);
|
||||||
|
|
||||||
|
// Add to the set, if it's been requested
|
||||||
|
if ($reconciled == !$unrec)
|
||||||
|
$resultset[] = $entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn(array('entries' => $resultset,
|
||||||
|
'summary' => $this->stats(null, $query)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: reconciledEntries
|
||||||
|
* - Returns a list of entries that reconcile against the given entry.
|
||||||
|
* (such as disbursements towards a charge).
|
||||||
|
*/
|
||||||
|
function reconciledEntriesQuery($id, $query = null) {
|
||||||
|
$this->queryInit($query, false);
|
||||||
|
|
||||||
|
$this->id = $id;
|
||||||
|
$this->recursive = -1;
|
||||||
|
$this->read();
|
||||||
|
|
||||||
|
$query['conditions'][] = array('StatementEntry.id' => $id);
|
||||||
|
|
||||||
|
if (in_array($this->data['StatementEntry']['type'], $this->debitTypes())) {
|
||||||
|
$query['link']['DisbursementEntry'] = array();
|
||||||
|
$query['conditions'][] = array('DisbursementEntry.id !=' => null);
|
||||||
|
}
|
||||||
|
if (in_array($this->data['StatementEntry']['type'], $this->creditTypes())) {
|
||||||
|
$query['link']['ChargeEntry'] = array();
|
||||||
|
$query['conditions'][] = array('ChargeEntry.id !=' => null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reconciledEntries($id, $query = null) {
|
||||||
|
$this->prEnter(compact('id', 'query'));
|
||||||
|
$lquery = $this->reconciledEntriesQuery($id, $query);
|
||||||
|
|
||||||
|
$result = $this->find('all', $lquery);
|
||||||
|
foreach (array_keys($result) AS $i)
|
||||||
|
unset($result[$i]['StatementEntry']);
|
||||||
|
|
||||||
|
return $this->prReturn(array('entries' => $result));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: assignCredits
|
||||||
|
* - Assigns all credits to existing charges
|
||||||
|
*
|
||||||
|
* REVISIT <AP>: 20090726
|
||||||
|
* This algorithm shouldn't be hardcoded. We need to allow
|
||||||
|
* the user to specify how disbursements should be applied.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function assignCredits($query = null, $receipt_id = null,
|
||||||
|
$charge_ids = null, $disbursement_type = null,
|
||||||
|
$customer_id = null, $lease_id = null)
|
||||||
|
{
|
||||||
|
//$this->prFunctionLevel(25);
|
||||||
|
$this->prEnter(compact('query', 'receipt_id',
|
||||||
|
'charge_ids', 'disbursement_type',
|
||||||
|
'customer_id', 'lease_id'));
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
if (!empty($customer_id))
|
||||||
|
$query['conditions'][] = array('StatementEntry.customer_id' => $customer_id);
|
||||||
|
|
||||||
|
if (empty($disbursement_type))
|
||||||
|
$disbursement_type = 'DISBURSEMENT';
|
||||||
|
|
||||||
|
$ret = array();
|
||||||
|
|
||||||
|
// First, find all known credits, unless this call is to make
|
||||||
|
// credit adjustments to a specific charge
|
||||||
|
if (empty($receipt_id)) {
|
||||||
|
|
||||||
|
if (!empty($charge_ids))
|
||||||
|
$this->INTERNAL_ERROR("Charge IDs, yet no corresponding receipt");
|
||||||
|
|
||||||
|
$lquery = $query;
|
||||||
|
$lquery['conditions'][] = array('StatementEntry.type' => 'SURPLUS');
|
||||||
|
// REVISIT <AP>: 20090804
|
||||||
|
// We need to ensure that we're using surplus credits ONLY from either
|
||||||
|
// the given lease, or those that do not apply to any specific lease.
|
||||||
|
// However, by doing this, it forces any lease surplus amounts to
|
||||||
|
// remain frozen with that lease until either there is a lease charge,
|
||||||
|
// we refund the money, or we "promote" that surplus to the customer
|
||||||
|
// level and out of the leases direct control.
|
||||||
|
// That seems like a pain. Perhaps we should allow any customer
|
||||||
|
// surplus to be used on any customer charge.
|
||||||
|
$lquery['conditions'][] =
|
||||||
|
array('OR' =>
|
||||||
|
array(array('StatementEntry.lease_id' => null),
|
||||||
|
(!empty($lease_id)
|
||||||
|
? array('StatementEntry.lease_id' => $lease_id)
|
||||||
|
: array()),
|
||||||
|
));
|
||||||
|
$lquery['order'][] = 'StatementEntry.effective_date ASC';
|
||||||
|
$credits = $this->find('all', $lquery);
|
||||||
|
$this->pr(18, compact('credits'),
|
||||||
|
"Credits Established");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Establish credit from the (newly added) receipt
|
||||||
|
$lquery =
|
||||||
|
array('link' =>
|
||||||
|
array('StatementEntry',
|
||||||
|
'LedgerEntry' =>
|
||||||
|
array('conditions' =>
|
||||||
|
array('LedgerEntry.account_id <> Transaction.account_id')
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'conditions' => array('Transaction.id' => $receipt_id),
|
||||||
|
'fields' => array('Transaction.id', 'Transaction.stamp', 'Transaction.amount'),
|
||||||
|
);
|
||||||
|
$receipt_credit = $this->Transaction->find('first', $lquery);
|
||||||
|
if (!$receipt_credit)
|
||||||
|
$this->INTERNAL_ERROR("Unable to locate receipt.");
|
||||||
|
|
||||||
|
$stats = $this->Transaction->stats($receipt_id);
|
||||||
|
$receipt_credit['balance'] = $stats['undisbursed'];
|
||||||
|
|
||||||
|
$receipt_credit['receipt'] = true;
|
||||||
|
$credits = array($receipt_credit);
|
||||||
|
$this->pr(18, compact('credits'),
|
||||||
|
"Receipt Credit Added");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now find all unpaid charges
|
||||||
|
if (isset($charge_ids)) {
|
||||||
|
$lquery = array('contain' => false,
|
||||||
|
'conditions' => array('StatementEntry.id' => $charge_ids));
|
||||||
|
} else {
|
||||||
|
$lquery = $query;
|
||||||
|
// If we're working with a specific lease, then limit charges to it
|
||||||
|
if (!empty($lease_id))
|
||||||
|
$lquery['conditions'][] = array('StatementEntry.lease_id' => $lease_id);
|
||||||
|
}
|
||||||
|
$lquery['order'] = 'StatementEntry.effective_date ASC';
|
||||||
|
$charges = array();
|
||||||
|
foreach ($this->debitTypes() AS $dtype) {
|
||||||
|
$rset = $this->reconciledSet($dtype, $lquery, true);
|
||||||
|
$entries = $rset['entries'];
|
||||||
|
$charges = array_merge($charges, $entries);
|
||||||
|
$this->pr(18, compact('dtype', 'entries'), "Outstanding Debit Entries");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Work through all unpaid charges, applying disbursements as we go
|
||||||
|
foreach ($charges AS $charge) {
|
||||||
|
$this->pr(20, compact('charge'),
|
||||||
|
'Process Charge');
|
||||||
|
|
||||||
|
$charge['balance'] = $charge['StatementEntry']['balance'];
|
||||||
|
|
||||||
|
// Use explicit credits before using the new receipt credit
|
||||||
|
foreach ($credits AS &$credit) {
|
||||||
|
if (empty($charge['balance']))
|
||||||
|
break;
|
||||||
|
if ($charge['balance'] < 0)
|
||||||
|
$this->INTERNAL_ERROR("Negative Charge Balance");
|
||||||
|
|
||||||
|
if (!isset($credit['balance']))
|
||||||
|
$credit['balance'] = $credit['StatementEntry']['amount'];
|
||||||
|
|
||||||
|
if (empty($credit['balance']))
|
||||||
|
continue;
|
||||||
|
if ($credit['balance'] < 0)
|
||||||
|
$this->INTERNAL_ERROR("Negative Credit Balance");
|
||||||
|
|
||||||
|
$this->pr(20, compact('charge'),
|
||||||
|
'Attempt Charge Reconciliation');
|
||||||
|
|
||||||
|
if (empty($credit['receipt']))
|
||||||
|
$disbursement_account_id = $credit['StatementEntry']['account_id'];
|
||||||
|
else
|
||||||
|
$disbursement_account_id = $credit['LedgerEntry']['account_id'];
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090811
|
||||||
|
// Need to come up with a better strategy for handling
|
||||||
|
// concessions. For now, just restricting concessions
|
||||||
|
// to apply only towards rent will resolve the most
|
||||||
|
// predominant (or only) needed usage case.
|
||||||
|
if ($disbursement_account_id == $this->Account->concessionAccountID() &&
|
||||||
|
$charge['StatementEntry']['account_id'] != $this->Account->rentAccountID())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Set the disbursement amount to the maximum amount
|
||||||
|
// possible without exceeding the charge or credit balance
|
||||||
|
$disbursement_amount = min($charge['balance'], $credit['balance']);
|
||||||
|
if (!isset($credit['applied']))
|
||||||
|
$credit['applied'] = 0;
|
||||||
|
|
||||||
|
$credit['applied'] += $disbursement_amount;
|
||||||
|
$credit['balance'] -= $disbursement_amount;
|
||||||
|
|
||||||
|
$this->pr(20, compact('credit'),
|
||||||
|
($credit['balance'] > 0 ? 'Utilized' : 'Exhausted') .
|
||||||
|
(empty($credit['receipt']) ? ' Credit' : ' Receipt'));
|
||||||
|
|
||||||
|
if (strtotime($charge['StatementEntry']['effective_date']) >
|
||||||
|
strtotime($credit['StatementEntry']['effective_date']))
|
||||||
|
$disbursement_edate = $charge['StatementEntry']['effective_date'];
|
||||||
|
else
|
||||||
|
$disbursement_edate = $credit['StatementEntry']['effective_date'];
|
||||||
|
|
||||||
|
if (empty($credit['receipt'])) {
|
||||||
|
// Explicit Credit
|
||||||
|
$result = $this->Transaction->addTransactionEntries
|
||||||
|
(array('include_ledger_entry' => true,
|
||||||
|
'include_statement_entry' => true),
|
||||||
|
array('type' => 'INVOICE',
|
||||||
|
'id' => $credit['StatementEntry']['transaction_id'],
|
||||||
|
'account_id' => $this->Account->accountReceivableAccountID(),
|
||||||
|
'crdr' => 'CREDIT',
|
||||||
|
'customer_id' => $charge['StatementEntry']['customer_id'],
|
||||||
|
'lease_id' => $charge['StatementEntry']['lease_id'],
|
||||||
|
),
|
||||||
|
array
|
||||||
|
(array('type' => $disbursement_type,
|
||||||
|
'effective_date' => $disbursement_edate,
|
||||||
|
'account_id' => $credit['StatementEntry']['account_id'],
|
||||||
|
'amount' => $disbursement_amount,
|
||||||
|
'charge_entry_id' => $charge['StatementEntry']['id'],
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$ret['Disbursement'][] = $result;
|
||||||
|
if ($result['error'])
|
||||||
|
$ret['error'] = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Receipt Credit
|
||||||
|
|
||||||
|
if (strtotime($charge['StatementEntry']['effective_date']) >
|
||||||
|
strtotime($credit['Transaction']['stamp']))
|
||||||
|
$disbursement_edate = $charge['StatementEntry']['effective_date'];
|
||||||
|
else
|
||||||
|
$disbursement_edate = $credit['Transaction']['stamp'];
|
||||||
|
|
||||||
|
// Add a disbursement that uses the available credit to pay the charge
|
||||||
|
$disbursement =
|
||||||
|
array('type' => $disbursement_type,
|
||||||
|
'effective_date' => $disbursement_edate,
|
||||||
|
'amount' => $disbursement_amount,
|
||||||
|
'account_id' => $credit['LedgerEntry']['account_id'],
|
||||||
|
'transaction_id' => $credit['Transaction']['id'],
|
||||||
|
'customer_id' => $charge['StatementEntry']['customer_id'],
|
||||||
|
'lease_id' => $charge['StatementEntry']['lease_id'],
|
||||||
|
'charge_entry_id' => $charge['StatementEntry']['id'],
|
||||||
|
'comment' => null,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->pr(20, compact('disbursement'), 'New Disbursement Entry');
|
||||||
|
$result = $this->addStatementEntry($disbursement);
|
||||||
|
$ret['Disbursement'][] = $result;
|
||||||
|
if ($result['error'])
|
||||||
|
$ret['error'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust the charge balance to reflect the new disbursement
|
||||||
|
$charge['balance'] -= $disbursement_amount;
|
||||||
|
if ($charge['balance'] < 0)
|
||||||
|
die("HOW DID WE GET A NEGATIVE CHARGE AMOUNT?");
|
||||||
|
|
||||||
|
if ($charge['balance'] <= 0)
|
||||||
|
$this->pr(20, 'Fully Paid Charge');
|
||||||
|
}
|
||||||
|
// Break the $credit reference to avoid future problems
|
||||||
|
unset($credit);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->pr(18, compact('credits'),
|
||||||
|
'Disbursements complete');
|
||||||
|
|
||||||
|
// Clean up any explicit credits that have been used
|
||||||
|
foreach ($credits AS $credit) {
|
||||||
|
if (!empty($credit['receipt']))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (empty($credit['applied']))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ($credit['balance'] > 0) {
|
||||||
|
$this->pr(20, compact('credit'),
|
||||||
|
'Update Credit Entry');
|
||||||
|
|
||||||
|
$this->id = $credit['StatementEntry']['id'];
|
||||||
|
$this->saveField('amount', $credit['balance']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->pr(20, compact('credit'),
|
||||||
|
'Delete Exhausted Credit Entry');
|
||||||
|
|
||||||
|
$this->delete($credit['StatementEntry']['id'], false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for any implicit receipt credits, converting
|
||||||
|
// into explicit credits if there is a remaining balance.
|
||||||
|
foreach ($credits AS $credit) {
|
||||||
|
if (empty($credit['receipt']))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (empty($credit['balance']))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// See if there is an existing explicit credit
|
||||||
|
// for this transaction.
|
||||||
|
$explicit_credit = $this->find
|
||||||
|
('first', array('contain' => false,
|
||||||
|
'conditions' =>
|
||||||
|
array(array('transaction_id' => $credit['Transaction']['id']),
|
||||||
|
array('type' => 'SURPLUS')),
|
||||||
|
));
|
||||||
|
|
||||||
|
if (!empty($explicit_credit)) {
|
||||||
|
// REVISIT <AP>: 20090815
|
||||||
|
// Testing whether or not this case occurs
|
||||||
|
$this->INTERNAL_ERROR('Existing explicit credit unexpected');
|
||||||
|
|
||||||
|
// Since there IS an existing explicit credit, we must update
|
||||||
|
// its balance instead of creating a new one, since it has
|
||||||
|
// already been incorporated in the overall credit balance.
|
||||||
|
// If we were to create a new one, we would erroneously create
|
||||||
|
// an excess of credit available.
|
||||||
|
$this->pr(18, compact('explicit_credit', 'credit'),
|
||||||
|
'Update existing explicit credit');
|
||||||
|
$EC = new StatementEntry();
|
||||||
|
$EC->id = $explicit_credit['StatementEntry']['id'];
|
||||||
|
$EC->saveField('amount', $credit['balance']);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($ret['receipt_balance']))
|
||||||
|
$this->INTERNAL_ERROR('Only one receipt expected in assignCredits');
|
||||||
|
|
||||||
|
// Give caller the information necessary to create an explicit
|
||||||
|
// credit from the passed receipt, which we've not exhausted.
|
||||||
|
$this->pr(18, compact('credit'), 'Convert to explicit credit');
|
||||||
|
$ret['receipt_balance'] = $credit['balance'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn($ret + array('error' => false));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns summary data from the requested statement entry
|
||||||
|
*/
|
||||||
|
function stats($id = null, $query = null) {
|
||||||
|
//$this->prFunctionLevel(array('log' => 16, 'show' => 10));
|
||||||
|
$this->prEnter(compact('id', 'query'));
|
||||||
|
|
||||||
|
$this->queryInit($query);
|
||||||
|
unset($query['group']);
|
||||||
|
|
||||||
|
$stats = array();
|
||||||
|
if (isset($id))
|
||||||
|
$query['conditions'][] = array('StatementEntry.id' => $id);
|
||||||
|
|
||||||
|
$types = array('Charge', 'Disbursement');
|
||||||
|
foreach ($types AS $type_index => $this_name) {
|
||||||
|
$that_name = $types[($type_index + 1) % 2];
|
||||||
|
if ($this_name === 'Charge') {
|
||||||
|
$this_types = $this->debitTypes();
|
||||||
|
$that_types = $this->creditTypes();
|
||||||
|
} else {
|
||||||
|
$this_types = $this->creditTypes();
|
||||||
|
$that_types = $this->debitTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this_query = $query;
|
||||||
|
$this_query['fields'] = array();
|
||||||
|
$this_query['fields'][] = "SUM(StatementEntry.amount) AS total";
|
||||||
|
$this_query['conditions'][] = array('StatementEntry.type' => $this_types);
|
||||||
|
$result = $this->find('first', $this_query);
|
||||||
|
$stats[$this_name] = $result[0];
|
||||||
|
|
||||||
|
$this->pr(17, compact('this_query', 'result'), $this_name.'s');
|
||||||
|
|
||||||
|
// Tally the different types that result in credits towards the charges
|
||||||
|
$stats[$this_name]['reconciled'] = 0;
|
||||||
|
foreach ($that_types AS $that_type) {
|
||||||
|
$lc_that_type = strtolower($that_type);
|
||||||
|
$that_query = $this_query;
|
||||||
|
$that_query['link']["{$that_name}Entry"] = array('fields' => array());
|
||||||
|
$that_query['fields'] = array();
|
||||||
|
if ($this_name == 'Charge')
|
||||||
|
$that_query['fields'][] = "COALESCE(SUM(${that_name}Entry.amount),0) AS $lc_that_type";
|
||||||
|
else
|
||||||
|
$that_query['fields'][] = "COALESCE(SUM(StatementEntry.amount), 0) AS $lc_that_type";
|
||||||
|
$that_query['conditions'][] = array("{$that_name}Entry.type" => $that_type);
|
||||||
|
$result = $this->find('first', $that_query);
|
||||||
|
$stats[$this_name] += $result[0];
|
||||||
|
|
||||||
|
$this->pr(17, compact('that_query', 'result'), "{$this_name}s: $that_type");
|
||||||
|
$stats[$this_name]['reconciled'] += $stats[$this_name][$lc_that_type];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute balance information for charges
|
||||||
|
$stats[$this_name]['balance'] =
|
||||||
|
$stats[$this_name]['total'] - $stats[$this_name]['reconciled'];
|
||||||
|
if (!isset($stats[$this_name]['balance']))
|
||||||
|
$stats[$this_name]['balance'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'balance' is simply the difference between
|
||||||
|
// the balances of charges and disbursements
|
||||||
|
$stats['balance'] = $stats['Charge']['balance'] - $stats['Disbursement']['balance'];
|
||||||
|
if (!isset($stats['balance']))
|
||||||
|
$stats['balance'] = 0;
|
||||||
|
|
||||||
|
// 'account_balance' is really only relevant to
|
||||||
|
// callers that have requested charge and disbursement
|
||||||
|
// stats with respect to a particular account.
|
||||||
|
// It represents the difference between inflow
|
||||||
|
// and outflow from that account.
|
||||||
|
$stats['account_balance'] = $stats['Charge']['reconciled'] - $stats['Disbursement']['total'];
|
||||||
|
if (!isset($stats['account_balance']))
|
||||||
|
$stats['account_balance'] = 0;
|
||||||
|
|
||||||
|
return $this->prReturn($stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
166
models/tender.php
Normal file
166
models/tender.php
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
<?php
|
||||||
|
class Tender extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'TenderType',
|
||||||
|
'Customer',
|
||||||
|
'LedgerEntry',
|
||||||
|
'DepositTransaction' => array(
|
||||||
|
'className' => 'Transaction',
|
||||||
|
),
|
||||||
|
'DepositLedgerEntry' => array(
|
||||||
|
'className' => 'LedgerEntry',
|
||||||
|
),
|
||||||
|
'NsfTransaction' => array(
|
||||||
|
'className' => 'Transaction',
|
||||||
|
'dependent' => true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: afterSave
|
||||||
|
* - Performs any work needed after the save occurs
|
||||||
|
*/
|
||||||
|
|
||||||
|
function afterSave($created) {
|
||||||
|
// Come up with a (not necessarily unique) name for the tender.
|
||||||
|
// For checks & money orders, this will be based on the check
|
||||||
|
// number. For other types of tender, we'll just use the
|
||||||
|
// generic name of the tender type, and the tender ID
|
||||||
|
|
||||||
|
// Determine our tender type, and set the ID of that model
|
||||||
|
$this->TenderType->id = $this->field('tender_type_id');
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090810
|
||||||
|
// The only tender expected to have no tender type
|
||||||
|
// is our special "Closing" tender.
|
||||||
|
if (empty($this->TenderType->id))
|
||||||
|
$newname = 'Closing';
|
||||||
|
else {
|
||||||
|
$newname = $this->TenderType->field('name');
|
||||||
|
$naming_field = $this->TenderType->field('naming_field');
|
||||||
|
if (!empty($naming_field))
|
||||||
|
$newname .= ' #' . $this->field($naming_field);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($newname !== $this->field('name'))
|
||||||
|
$this->saveField('name', $newname);
|
||||||
|
|
||||||
|
return parent::afterSave($created);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: beforeDelete
|
||||||
|
* - Performs any work needed before the delete occurs
|
||||||
|
*/
|
||||||
|
|
||||||
|
function beforeDelete($cascade = true) {
|
||||||
|
// REVISIT <AP>: 20090814
|
||||||
|
// Experimental, and incomplete mechanism to protect
|
||||||
|
// against trying to delete data that shouldn't be deleted.
|
||||||
|
|
||||||
|
$deposit_id = $this->field('deposit_transaction_id');
|
||||||
|
pr(compact('deposit_id'));
|
||||||
|
// If this tender has already been deposited, it would
|
||||||
|
// be a rats nest to figure out how to delete this tender.
|
||||||
|
if (!empty($deposit_id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return parent::beforeDelete($cascade);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: verifyTender
|
||||||
|
* - Verifies consistenty of new tender data
|
||||||
|
* (not in a pre-existing tender)
|
||||||
|
*/
|
||||||
|
function verifyTender($tender) {
|
||||||
|
$this->prFunctionLevel(10);
|
||||||
|
$this->prEnter(compact('tender'));
|
||||||
|
|
||||||
|
if (empty($tender['tender_type_id'])) {
|
||||||
|
return $this->prReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: addTender
|
||||||
|
* - Inserts new Tender into the database
|
||||||
|
*/
|
||||||
|
|
||||||
|
function addTender($tender) {
|
||||||
|
$this->prEnter(compact('tender'));
|
||||||
|
|
||||||
|
$ret = array('data' => $tender);
|
||||||
|
if (!$this->verifyTender($tender))
|
||||||
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
|
$this->create();
|
||||||
|
if (!$this->save($tender))
|
||||||
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
|
$ret['tender_id'] = $this->id;
|
||||||
|
return $this->prReturn($ret + array('error' => false));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: nsf
|
||||||
|
* - Flags the ledger entry as having insufficient funds
|
||||||
|
*/
|
||||||
|
|
||||||
|
function nsf($id, $stamp = null, $comment = null) {
|
||||||
|
$this->prEnter(compact('id', 'stamp', 'comment'));
|
||||||
|
|
||||||
|
// Get information about this NSF item.
|
||||||
|
$this->id = $id;
|
||||||
|
$tender = $this->find
|
||||||
|
('first', array
|
||||||
|
('contain' =>
|
||||||
|
array('LedgerEntry',
|
||||||
|
'DepositTransaction',
|
||||||
|
'DepositLedgerEntry',
|
||||||
|
'NsfTransaction'),
|
||||||
|
));
|
||||||
|
$this->pr(20, compact('tender'));
|
||||||
|
|
||||||
|
if (!empty($tender['NsfTransaction']['id']))
|
||||||
|
die("Item has already been set as NSF");
|
||||||
|
|
||||||
|
if (empty($tender['DepositTransaction']['id']))
|
||||||
|
die("Item has not been deposited yet");
|
||||||
|
|
||||||
|
$tender['Transaction'] = $tender['DepositTransaction'];
|
||||||
|
unset($tender['DepositTransaction']);
|
||||||
|
unset($tender['NsfTransaction']);
|
||||||
|
|
||||||
|
$T = new Transaction();
|
||||||
|
$result = $T->addNsf($tender, $stamp, $comment);
|
||||||
|
if (empty($result['error'])) {
|
||||||
|
// Flag the tender as NSF, using the items created from addNsf
|
||||||
|
$this->id = $id;
|
||||||
|
$this->saveField('nsf_transaction_id', $result['nsf_transaction_id']);
|
||||||
|
$this->saveField('nsf_ledger_entry_id', $result['nsf_ledger_entry_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
115
models/tender_type.php
Normal file
115
models/tender_type.php
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
<?php
|
||||||
|
class TenderType extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'Account',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'Tender',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: accountID
|
||||||
|
* - Returns the intended account ID for receipt of the given tender
|
||||||
|
*/
|
||||||
|
|
||||||
|
function accountID($id) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$item = $this->find('first', array
|
||||||
|
('contain' => false,
|
||||||
|
'conditions' => array('TenderType.id' => $id),
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
return $item['TenderType']['account_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: paymentTypes
|
||||||
|
* - Returns an array of types that can be used for payments
|
||||||
|
*/
|
||||||
|
|
||||||
|
function paymentTypes($query = null) {
|
||||||
|
$this->queryInit($query);
|
||||||
|
$query['order'][] = 'name';
|
||||||
|
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$types = $this->find('all', $query);
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
return $types;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: paymentTypes
|
||||||
|
* - Returns an array of types that can be deposited
|
||||||
|
*/
|
||||||
|
|
||||||
|
function depositTypes($query = null) {
|
||||||
|
$this->queryInit($query);
|
||||||
|
$query['order'][] = 'name';
|
||||||
|
$query['conditions'][] = array('tillable' => true);
|
||||||
|
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$types = $this->find('all', $query);
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
// Rearrange to be of the form (id => name)
|
||||||
|
$result = array();
|
||||||
|
foreach ($types AS $type)
|
||||||
|
$result[$type['TenderType']['id']] = $type['TenderType']['name'];
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: defaultPaymentType
|
||||||
|
* - Returns the ID of the default payment type
|
||||||
|
*/
|
||||||
|
|
||||||
|
function defaultPaymentType() {
|
||||||
|
return $this->nameToID('Check');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns the stats for the given tender type
|
||||||
|
*/
|
||||||
|
|
||||||
|
function stats($id = null, $query = null) {
|
||||||
|
if (!$id)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
if (!isset($query['link']['Tender']))
|
||||||
|
$query['link']['Tender'] = array('fields' => array());
|
||||||
|
if (!isset($query['link']['Tender']['LedgerEntry']))
|
||||||
|
$query['link']['Tender']['LedgerEntry'] = array('fields' => array());
|
||||||
|
|
||||||
|
$query['fields'][] = "SUM(COALESCE(LedgerEntry.amount,0)) AS 'total'";
|
||||||
|
$query['fields'][] = "SUM(IF(deposit_transaction_id IS NULL, COALESCE(LedgerEntry.amount,0), 0)) AS 'undeposited'";
|
||||||
|
$query['fields'][] = "SUM(IF(deposit_transaction_id IS NULL, 0, COALESCE(LedgerEntry.amount,0))) AS 'deposited'";
|
||||||
|
$query['fields'][] = "SUM(IF(nsf_transaction_id IS NULL, 0, COALESCE(LedgerEntry.amount,0))) AS 'nsf'";
|
||||||
|
|
||||||
|
$this->id = $id;
|
||||||
|
$stats = $this->find('first', $query);
|
||||||
|
return $stats[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
1344
models/transaction.php
Normal file
1344
models/transaction.php
Normal file
File diff suppressed because it is too large
Load Diff
230
models/unit.php
Normal file
230
models/unit.php
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
<?php
|
||||||
|
class Unit extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'Unit';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'unit_size_id' => array('numeric'),
|
||||||
|
'name' => array('notempty'),
|
||||||
|
'sort_order' => array('numeric'),
|
||||||
|
'walk_order' => array('numeric'),
|
||||||
|
'deposit' => array('money'),
|
||||||
|
'amount' => array('money')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'UnitSize',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasOne = array(
|
||||||
|
'CurrentLease' => array(
|
||||||
|
'className' => 'Lease',
|
||||||
|
'conditions' => 'CurrentLease.moveout_date IS NULL',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'Lease',
|
||||||
|
);
|
||||||
|
|
||||||
|
//var $default_log_level = array('log' => 30, 'show' => 15);
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* helpers: status enumerations
|
||||||
|
*/
|
||||||
|
|
||||||
|
function statusEnums() {
|
||||||
|
static $status_enums;
|
||||||
|
if (!isset($status_enums))
|
||||||
|
$status_enums = $this->getEnumValues('status');
|
||||||
|
return $status_enums;
|
||||||
|
}
|
||||||
|
|
||||||
|
function activeStatusEnums() {
|
||||||
|
return array_diff_key($this->statusEnums(), array(''=>1, 'DELETED'=>1));
|
||||||
|
}
|
||||||
|
|
||||||
|
function statusValue($enum) {
|
||||||
|
$enums = $this->statusEnums();
|
||||||
|
return $enums[$enum];
|
||||||
|
}
|
||||||
|
|
||||||
|
function occupiedEnumValue() {
|
||||||
|
return $this->statusValue('OCCUPIED');
|
||||||
|
}
|
||||||
|
|
||||||
|
function statusCheck($id_or_enum,
|
||||||
|
$min = null, $min_strict = false,
|
||||||
|
$max = null, $max_strict = false)
|
||||||
|
{
|
||||||
|
$this->prEnter(compact('id_or_enum', 'min', 'min_strict', 'max', 'max_strict'));
|
||||||
|
|
||||||
|
if (is_int($id_or_enum)) {
|
||||||
|
$this->id = $id_or_enum;
|
||||||
|
$id_or_enum = $this->field('status');
|
||||||
|
}
|
||||||
|
|
||||||
|
$enum_val = $this->statusValue($id_or_enum);
|
||||||
|
if (isset($min) && is_string($min))
|
||||||
|
$min = $this->statusValue($min);
|
||||||
|
if (isset($max) && is_string($max))
|
||||||
|
$max = $this->statusValue($max);
|
||||||
|
|
||||||
|
$this->pr(17, compact('enum_val', 'min', 'min_strict', 'max', 'max_strict'));
|
||||||
|
|
||||||
|
if (isset($min) &&
|
||||||
|
($enum_val < $min ||
|
||||||
|
($min_strict && $enum_val == $min)))
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
if (isset($max) &&
|
||||||
|
($enum_val > $max ||
|
||||||
|
($max_strict && $enum_val == $max)))
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
return $this->prReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function occupied($enum) {
|
||||||
|
return $this->statusCheck($enum, 'OCCUPIED', false, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function conditionOccupied() {
|
||||||
|
return ('Unit.status >= ' . $this->statusValue('OCCUPIED'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function vacant($enum) {
|
||||||
|
return $this->statusCheck($enum, 'UNAVAILABLE', true, 'OCCUPIED', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function conditionVacant() {
|
||||||
|
return ('Unit.status BETWEEN ' .
|
||||||
|
($this->statusValue('UNAVAILABLE')+1) .
|
||||||
|
' AND ' .
|
||||||
|
($this->statusValue('OCCUPIED')-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
function unavailable($enum) {
|
||||||
|
return $this->statusCheck($enum, null, false, 'UNAVAILABLE', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function conditionUnavailable() {
|
||||||
|
return ('Unit.status <= ' . $this->statusValue('UNAVAILABLE'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function available($enum) { return $this->vacant($enum); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: allowedStatusSet
|
||||||
|
* - Returns the status set allowed for the given unit
|
||||||
|
*/
|
||||||
|
function allowedStatusSet($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
$this->id = $id;
|
||||||
|
$old_status = $this->field('status');
|
||||||
|
$old_val = $this->statusValue($old_status);
|
||||||
|
$this->pr(17, compact('old_status', 'old_val'));
|
||||||
|
|
||||||
|
$enums = $this->activeStatusEnums();
|
||||||
|
$this->pr(21, compact('enums'));
|
||||||
|
|
||||||
|
foreach ($enums AS $enum => $val) {
|
||||||
|
if (($old_val < $this->occupiedEnumValue()) !=
|
||||||
|
($val < $this->occupiedEnumValue())) {
|
||||||
|
unset($enums[$enum]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn($enums);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: updateStatus
|
||||||
|
* - Update the given unit to the given status
|
||||||
|
*/
|
||||||
|
function updateStatus($id, $status, $check = false) {
|
||||||
|
$this->prEnter(compact('id', 'status', 'check'));
|
||||||
|
|
||||||
|
/* if ($check) { */
|
||||||
|
/* $old_status = $this->field('status'); */
|
||||||
|
/* $this->pr(17, compact('old_status')); */
|
||||||
|
/* if ($this->statusValue($old_status) < $this->occupiedEnumValue() && */
|
||||||
|
/* $this->statusValue($status) >= $this->occupiedEnumValue()) */
|
||||||
|
/* { */
|
||||||
|
/* die("Can't transition a unit from vacant to occupied"); */
|
||||||
|
/* return $this->prReturn(false); */
|
||||||
|
/* } */
|
||||||
|
/* if ($this->statusValue($old_status) >= $this->occupiedEnumValue() && */
|
||||||
|
/* $this->statusValue($status) < $this->occupiedEnumValue()) */
|
||||||
|
/* { */
|
||||||
|
/* die("Can't transition a unit from occupied to vacant"); */
|
||||||
|
/* return $this->prReturn(false); */
|
||||||
|
/* } */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
if ($check) {
|
||||||
|
if (!array_key_exists($status, $this->allowedStatusSet($id)))
|
||||||
|
return $this->prReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->id = $id;
|
||||||
|
$this->saveField('status', $status);
|
||||||
|
return $this->prReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: update
|
||||||
|
* - Update any cached or calculated fields
|
||||||
|
*/
|
||||||
|
function update($id) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns summary data from the requested customer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function stats($id = null) {
|
||||||
|
if (!$id)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Get the basic information necessary
|
||||||
|
$unit = $this->find('first',
|
||||||
|
array('contain' => array
|
||||||
|
('Lease' => array
|
||||||
|
('fields' => array('Lease.id')),
|
||||||
|
|
||||||
|
'CurrentLease' => array
|
||||||
|
('fields' => array('CurrentLease.id'))),
|
||||||
|
|
||||||
|
'conditions' => array
|
||||||
|
(array('Unit.id' => $id)),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Get the stats for the current lease
|
||||||
|
$stats['CurrentLease'] = $this->Lease->stats($unit['CurrentLease']['id']);
|
||||||
|
|
||||||
|
// Sum the stats for all leases together
|
||||||
|
foreach ($unit['Lease'] AS $lease) {
|
||||||
|
$this->statsMerge($stats['Lease'], $this->Lease->stats($lease['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the collection
|
||||||
|
return $stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
25
models/unit_size.php
Normal file
25
models/unit_size.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
class UnitSize extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'UnitSize';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'unit_type_id' => array('numeric'),
|
||||||
|
'code' => array('notempty'),
|
||||||
|
'name' => array('notempty'),
|
||||||
|
'width' => array('numeric'),
|
||||||
|
'depth' => array('numeric'),
|
||||||
|
'deposit' => array('money'),
|
||||||
|
'amount' => array('money')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'UnitType',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'Unit',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
16
models/unit_type.php
Normal file
16
models/unit_type.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
class UnitType extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'UnitType';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'code' => array('notempty'),
|
||||||
|
'name' => array('notempty')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'UnitSize',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
5
plugins/debug_kit/README
Normal file
5
plugins/debug_kit/README
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
To install copy the debug_kit directory to the plugins folder and include the toolbar component in your app_controller.php:
|
||||||
|
|
||||||
|
$components = array('DebugKit.Toolbar');
|
||||||
|
|
||||||
|
+ Set debug mode to at least 1.
|
||||||
0
plugins/debug_kit/controllers/components/empty
Normal file
0
plugins/debug_kit/controllers/components/empty
Normal file
471
plugins/debug_kit/controllers/components/toolbar.php
Normal file
471
plugins/debug_kit/controllers/components/toolbar.php
Normal file
@@ -0,0 +1,471 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* DebugKit DebugToolbar Component
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
class ToolbarComponent extends Object {
|
||||||
|
/**
|
||||||
|
* Controller instance reference
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
var $controller;
|
||||||
|
/**
|
||||||
|
* Components used by DebugToolbar
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
var $components = array('RequestHandler');
|
||||||
|
/**
|
||||||
|
* The default panels the toolbar uses.
|
||||||
|
* which panels are used can be configured when attaching the component
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
var $_defaultPanels = array('session', 'request', 'sqlLog', 'timer', 'log', 'memory', 'variables');
|
||||||
|
/**
|
||||||
|
* Loaded panel objects.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
var $panels = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fallback for javascript settings
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
**/
|
||||||
|
var $_defaultJavascript = array(
|
||||||
|
'behavior' => '/debug_kit/js/js_debug_toolbar'
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* javascript files component will be using.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
**/
|
||||||
|
var $javascript = array();
|
||||||
|
/**
|
||||||
|
* initialize
|
||||||
|
*
|
||||||
|
* If debug is off the component will be disabled and not do any further time tracking
|
||||||
|
* or load the toolbar helper.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
**/
|
||||||
|
function initialize(&$controller, $settings) {
|
||||||
|
if (Configure::read('debug') == 0) {
|
||||||
|
$this->enabled = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
App::import('Vendor', 'DebugKit.DebugKitDebugger');
|
||||||
|
|
||||||
|
DebugKitDebugger::startTimer('componentInit', __('Component initialization and startup', true));
|
||||||
|
if (!isset($settings['panels'])) {
|
||||||
|
$settings['panels'] = $this->_defaultPanels;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($settings['javascript'])) {
|
||||||
|
$settings['javascript'] = $this->_setJavascript($settings['javascript']);
|
||||||
|
} else {
|
||||||
|
$settings['javascript'] = $this->_defaultJavascript;
|
||||||
|
}
|
||||||
|
$this->_loadPanels($settings['panels']);
|
||||||
|
unset($settings['panels']);
|
||||||
|
|
||||||
|
$this->_set($settings);
|
||||||
|
$this->controller =& $controller;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component Startup
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
**/
|
||||||
|
function startup(&$controller) {
|
||||||
|
$currentViewClass = $controller->view;
|
||||||
|
$this->_makeViewClass($currentViewClass);
|
||||||
|
$controller->view = 'DebugKit.Debug';
|
||||||
|
if (!isset($controller->params['url']['ext']) || (isset($controller->params['url']['ext']) && $controller->params['url']['ext'] == 'html')) {
|
||||||
|
$format = 'Html';
|
||||||
|
} else {
|
||||||
|
$format = 'FirePhp';
|
||||||
|
}
|
||||||
|
$controller->helpers['DebugKit.Toolbar'] = array('output' => sprintf('DebugKit.%sToolbar', $format));
|
||||||
|
$panels = array_keys($this->panels);
|
||||||
|
foreach ($panels as $panelName) {
|
||||||
|
$this->panels[$panelName]->startup($controller);
|
||||||
|
}
|
||||||
|
DebugKitDebugger::stopTimer('componentInit');
|
||||||
|
DebugKitDebugger::startTimer('controllerAction', __('Controller Action', true));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* beforeRender callback
|
||||||
|
*
|
||||||
|
* Calls beforeRender on all the panels and set the aggregate to the controller.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function beforeRender(&$controller) {
|
||||||
|
DebugKitDebugger::stopTimer('controllerAction');
|
||||||
|
$vars = array();
|
||||||
|
$panels = array_keys($this->panels);
|
||||||
|
|
||||||
|
foreach ($panels as $panelName) {
|
||||||
|
$panel =& $this->panels[$panelName];
|
||||||
|
$vars[$panelName]['content'] = $panel->beforeRender($controller);
|
||||||
|
$elementName = Inflector::underscore($panelName) . '_panel';
|
||||||
|
if (isset($panel->elementName)) {
|
||||||
|
$elementName = $panel->elementName;
|
||||||
|
}
|
||||||
|
$vars[$panelName]['elementName'] = $elementName;
|
||||||
|
$vars[$panelName]['plugin'] = $panel->plugin;
|
||||||
|
$vars[$panelName]['disableTimer'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$controller->set(array('debugToolbarPanels' => $vars, 'debugToolbarJavascript' => $this->javascript));
|
||||||
|
DebugKitDebugger::startTimer('controllerRender', __('Render Controller Action', true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load Panels used in the debug toolbar
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @access protected
|
||||||
|
**/
|
||||||
|
function _loadPanels($panels) {
|
||||||
|
foreach ($panels as $panel) {
|
||||||
|
$className = $panel . 'Panel';
|
||||||
|
if (!class_exists($className) && !App::import('Vendor', $className)) {
|
||||||
|
trigger_error(sprintf(__('Could not load DebugToolbar panel %s', true), $panel), E_USER_WARNING);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$panelObj =& new $className();
|
||||||
|
if (is_subclass_of($panelObj, 'DebugPanel') || is_subclass_of($panelObj, 'debugpanel')) {
|
||||||
|
$this->panels[$panel] =& $panelObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the javascript to user scripts.
|
||||||
|
*
|
||||||
|
* Set either script key to false to exclude it from the rendered layout.
|
||||||
|
*
|
||||||
|
* @param array $scripts Javascript config information
|
||||||
|
* @return array
|
||||||
|
* @access protected
|
||||||
|
**/
|
||||||
|
function _setJavascript($scripts) {
|
||||||
|
$behavior = false;
|
||||||
|
if (!is_array($scripts)) {
|
||||||
|
$scripts = (array)$scripts;
|
||||||
|
}
|
||||||
|
if (isset($scripts[0])) {
|
||||||
|
$behavior = $scripts[0];
|
||||||
|
}
|
||||||
|
if (isset($scripts['behavior'])) {
|
||||||
|
$behavior = $scripts['behavior'];
|
||||||
|
}
|
||||||
|
if (!$behavior) {
|
||||||
|
return array();
|
||||||
|
} elseif ($behavior === true) {
|
||||||
|
$behavior = 'js';
|
||||||
|
}
|
||||||
|
if (strpos($behavior, '/') !== 0) {
|
||||||
|
$behavior .= '_debug_toolbar';
|
||||||
|
}
|
||||||
|
$pluginFile = APP . 'plugins' . DS . 'debug_kit' . DS . 'vendors' . DS . 'js' . DS . $behavior . '.js';
|
||||||
|
if (file_exists($pluginFile)) {
|
||||||
|
$behavior = '/debug_kit/js/' . $behavior . '.js';
|
||||||
|
}
|
||||||
|
return compact('behavior');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Makes the DoppleGangerView class if it doesn't already exist.
|
||||||
|
* This allows DebugView to be compatible with all view classes.
|
||||||
|
*
|
||||||
|
* @param string $baseClassName
|
||||||
|
* @access protected
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function _makeViewClass($baseClassName) {
|
||||||
|
if (!class_exists('DoppelGangerView')) {
|
||||||
|
App::import('View', $baseClassName);
|
||||||
|
if (strpos('View', $baseClassName) === false) {
|
||||||
|
$baseClassName .= 'View';
|
||||||
|
}
|
||||||
|
$class = "class DoppelGangerView extends $baseClassName {}";
|
||||||
|
eval($class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug Panel
|
||||||
|
*
|
||||||
|
* Abstract class for debug panels.
|
||||||
|
*
|
||||||
|
* @package cake.debug_kit
|
||||||
|
*/
|
||||||
|
class DebugPanel extends Object {
|
||||||
|
/**
|
||||||
|
* Defines which plugin this panel is from so the element can be located.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $plugin = null;
|
||||||
|
/**
|
||||||
|
* startup the panel
|
||||||
|
*
|
||||||
|
* Pull information from the controller / request
|
||||||
|
*
|
||||||
|
* @param object $controller Controller reference.
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function startup(&$controller) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare output vars before Controller Rendering.
|
||||||
|
*
|
||||||
|
* @param object $controller Controller reference.
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function beforeRender(&$controller) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variables Panel
|
||||||
|
*
|
||||||
|
* Provides debug information on the View variables.
|
||||||
|
*
|
||||||
|
* @package cake.debug_kit.panels
|
||||||
|
**/
|
||||||
|
class VariablesPanel extends DebugPanel {
|
||||||
|
var $plugin = 'debug_kit';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session Panel
|
||||||
|
*
|
||||||
|
* Provides debug information on the Session contents.
|
||||||
|
*
|
||||||
|
* @package cake.debug_kit.panels
|
||||||
|
**/
|
||||||
|
class SessionPanel extends DebugPanel {
|
||||||
|
var $plugin = 'debug_kit';
|
||||||
|
/**
|
||||||
|
* beforeRender callback
|
||||||
|
*
|
||||||
|
* @param object $controller
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function beforeRender(&$controller) {
|
||||||
|
return $controller->Session->read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request Panel
|
||||||
|
*
|
||||||
|
* Provides debug information on the Current request params.
|
||||||
|
*
|
||||||
|
* @package cake.debug_kit.panels
|
||||||
|
**/
|
||||||
|
class RequestPanel extends DebugPanel {
|
||||||
|
var $plugin = 'debug_kit';
|
||||||
|
/**
|
||||||
|
* beforeRender callback - grabs request params
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
**/
|
||||||
|
function beforeRender(&$controller) {
|
||||||
|
$out = array();
|
||||||
|
$out['params'] = $controller->params;
|
||||||
|
if (isset($controller->Cookie)) {
|
||||||
|
$out['cookie'] = $controller->Cookie->read();
|
||||||
|
}
|
||||||
|
$out['get'] = $_GET;
|
||||||
|
$out['currentRoute'] = Router::currentRoute();
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timer Panel
|
||||||
|
*
|
||||||
|
* Provides debug information on all timers used in a request.
|
||||||
|
*
|
||||||
|
* @package cake.debug_kit.panels
|
||||||
|
**/
|
||||||
|
class TimerPanel extends DebugPanel {
|
||||||
|
var $plugin = 'debug_kit';
|
||||||
|
/**
|
||||||
|
* startup - add in necessary helpers
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function startup(&$controller) {
|
||||||
|
if (!in_array('Number', $controller->helpers)) {
|
||||||
|
$controller->helpers[] = 'Number';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memory Panel
|
||||||
|
*
|
||||||
|
* Provides debug information on the memory consumption.
|
||||||
|
*
|
||||||
|
* @package cake.debug_kit.panels
|
||||||
|
**/
|
||||||
|
class MemoryPanel extends DebugPanel {
|
||||||
|
var $plugin = 'debug_kit';
|
||||||
|
/**
|
||||||
|
* startup - add in necessary helpers
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function startup(&$controller) {
|
||||||
|
if (!in_array('Number', $controller->helpers)) {
|
||||||
|
$controller->helpers[] = 'Number';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sqlLog Panel
|
||||||
|
*
|
||||||
|
* Provides debug information on the SQL logs and provides links to an ajax explain interface.
|
||||||
|
*
|
||||||
|
* @package cake.debug_kit.panels
|
||||||
|
**/
|
||||||
|
class sqlLogPanel extends DebugPanel {
|
||||||
|
var $plugin = 'debug_kit';
|
||||||
|
|
||||||
|
var $dbConfigs = array();
|
||||||
|
/**
|
||||||
|
* get db configs.
|
||||||
|
*
|
||||||
|
* @param string $controller
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function startUp(&$controller) {
|
||||||
|
if (!class_exists('ConnectionManager')) {
|
||||||
|
$this->dbConfigs = array();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->dbConfigs = ConnectionManager::sourceList();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get Sql Logs for each DB config
|
||||||
|
*
|
||||||
|
* @param string $controller
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function beforeRender(&$controller) {
|
||||||
|
$queryLogs = array();
|
||||||
|
if (!class_exists('ConnectionManager')) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
foreach ($this->dbConfigs as $configName) {
|
||||||
|
$db =& ConnectionManager::getDataSource($configName);
|
||||||
|
if ($db->isInterfaceSupported('showLog')) {
|
||||||
|
ob_start();
|
||||||
|
$db->showLog();
|
||||||
|
$queryLogs[$configName] = ob_get_clean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $queryLogs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log Panel - Reads log entries made this request.
|
||||||
|
*
|
||||||
|
* @package cake.debug_kit.panels
|
||||||
|
*/
|
||||||
|
class LogPanel extends DebugPanel {
|
||||||
|
var $plugin = 'debug_kit';
|
||||||
|
/**
|
||||||
|
* Log files to scan
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
var $logFiles = array('error.log', 'debug.log');
|
||||||
|
/**
|
||||||
|
* startup
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function startup(&$controller) {
|
||||||
|
if (!class_exists('CakeLog')) {
|
||||||
|
App::import('Core', 'Log');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* beforeRender Callback
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
**/
|
||||||
|
function beforeRender(&$controller) {
|
||||||
|
$this->startTime = DebugKitDebugger::requestStartTime();
|
||||||
|
$this->currentTime = DebugKitDebugger::requestTime();
|
||||||
|
$out = array();
|
||||||
|
foreach ($this->logFiles as $log) {
|
||||||
|
$file = LOGS . $log;
|
||||||
|
if (!file_exists($file)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$out[$log] = $this->_parseFile($file);
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* parse a log file and find the relevant entries
|
||||||
|
*
|
||||||
|
* @param string $filename Name of file to read
|
||||||
|
* @access protected
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function _parseFile($filename) {
|
||||||
|
$file =& new File($filename);
|
||||||
|
$contents = $file->read();
|
||||||
|
$timePattern = '/(\d{4}-\d{2}\-\d{2}\s\d{1,2}\:\d{1,2}\:\d{1,2})/';
|
||||||
|
$chunks = preg_split($timePattern, $contents, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||||
|
for ($i = 0, $len = count($chunks); $i < $len; $i += 2) {
|
||||||
|
if (strtotime($chunks[$i]) < $this->startTime) {
|
||||||
|
unset($chunks[$i], $chunks[$i + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array_values($chunks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
32
plugins/debug_kit/debug_kit_app_controller.php
Normal file
32
plugins/debug_kit/debug_kit_app_controller.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Debug Kit App Controller
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
class DebugKitAppController extends AppController {
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
32
plugins/debug_kit/debug_kit_app_model.php
Normal file
32
plugins/debug_kit/debug_kit_app_model.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Debug Kit App Model
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
class DebugKitAppModel extends AppModel {
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
0
plugins/debug_kit/models/empty
Normal file
0
plugins/debug_kit/models/empty
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* DebugToolbar Test
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
App::import('Component', 'DebugKit.Toolbar');
|
||||||
|
|
||||||
|
class TestToolbarComponent extends ToolbarComponent {
|
||||||
|
|
||||||
|
function loadPanels($panels) {
|
||||||
|
$this->_loadPanels($panels);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock::generate('DebugPanel');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DebugToolbar Test case
|
||||||
|
*/
|
||||||
|
class DebugToolbarTestCase extends CakeTestCase {
|
||||||
|
|
||||||
|
function setUp() {
|
||||||
|
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
|
||||||
|
Router::parse('/');
|
||||||
|
$this->Controller =& ClassRegistry::init('Controller');
|
||||||
|
$this->Controller->Component =& ClassRegistry::init('Component');
|
||||||
|
$this->Controller->Toolbar =& ClassRegistry::init('TestToolBarComponent', 'Component');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test Loading of panel classes
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testLoadPanels() {
|
||||||
|
$this->Controller->Toolbar->loadPanels(array('session', 'request'));
|
||||||
|
$this->assertTrue(is_a($this->Controller->Toolbar->panels['session'], 'SessionPanel'));
|
||||||
|
$this->assertTrue(is_a($this->Controller->Toolbar->panels['request'], 'RequestPanel'));
|
||||||
|
|
||||||
|
$this->expectError();
|
||||||
|
$this->Controller->Toolbar->loadPanels(array('randomNonExisting', 'request'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test loading of vendor panels from test_app folder
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testVendorPanels() {
|
||||||
|
$_back = Configure::read('vendorPaths');
|
||||||
|
Configure::write('vendorPaths', array(APP . 'plugins' . DS . 'debug_kit' . DS . 'tests' . DS . 'test_app' . DS . 'vendors' . DS));
|
||||||
|
$this->Controller->components = array(
|
||||||
|
'DebugKit.Toolbar' => array(
|
||||||
|
'panels' => array('test'),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->Controller->Component->init($this->Controller);
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->assertTrue(isset($this->Controller->Toolbar->panels['test']));
|
||||||
|
$this->assertTrue(is_a($this->Controller->Toolbar->panels['test'], 'TestPanel'));
|
||||||
|
|
||||||
|
Configure::write('vendorPaths', $_back);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test initialize
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @access public
|
||||||
|
**/
|
||||||
|
function testInitialize() {
|
||||||
|
$this->Controller->components = array('DebugKit.Toolbar');
|
||||||
|
$this->Controller->Component->init($this->Controller);
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
|
||||||
|
$this->assertFalse(empty($this->Controller->Toolbar->panels));
|
||||||
|
|
||||||
|
$timers = DebugKitDebugger::getTimers();
|
||||||
|
$this->assertTrue(isset($timers['componentInit']));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test startup
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testStartup() {
|
||||||
|
$this->Controller->components = array(
|
||||||
|
'DebugKit.Toolbar' => array(
|
||||||
|
'panels' => array('MockDebug')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->Controller->Component->init($this->Controller);
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Toolbar->panels['MockDebug']->expectOnce('startup');
|
||||||
|
$this->Controller->Toolbar->startup($this->Controller);
|
||||||
|
|
||||||
|
$this->assertEqual(count($this->Controller->Toolbar->panels), 1);
|
||||||
|
$this->assertTrue(isset($this->Controller->helpers['DebugKit.Toolbar']));
|
||||||
|
$this->assertEqual($this->Controller->helpers['DebugKit.Toolbar'], array('output' => 'DebugKit.HtmlToolbar'));
|
||||||
|
|
||||||
|
$timers = DebugKitDebugger::getTimers();
|
||||||
|
$this->assertTrue(isset($timers['controllerAction']));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Before Render callback
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testBeforeRender() {
|
||||||
|
$this->Controller->components = array(
|
||||||
|
'DebugKit.Toolbar' => array(
|
||||||
|
'panels' => array('MockDebug', 'session')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->Controller->Component->init($this->Controller);
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Toolbar->panels['MockDebug']->expectOnce('beforeRender');
|
||||||
|
$this->Controller->Toolbar->beforeRender($this->Controller);
|
||||||
|
|
||||||
|
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarPanels']));
|
||||||
|
$vars = $this->Controller->viewVars['debugToolbarPanels'];
|
||||||
|
|
||||||
|
$expected = array(
|
||||||
|
'plugin' => 'debug_kit',
|
||||||
|
'elementName' => 'session_panel',
|
||||||
|
'content' => $this->Controller->Session->read(),
|
||||||
|
'disableTimer' => true,
|
||||||
|
);
|
||||||
|
$this->assertEqual($expected, $vars['session']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test alternate javascript library use
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testAlternateJavascript() {
|
||||||
|
$this->Controller->components = array(
|
||||||
|
'DebugKit.Toolbar'
|
||||||
|
);
|
||||||
|
$this->Controller->Component->init($this->Controller);
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->Controller->Component->beforeRender($this->Controller);
|
||||||
|
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||||
|
$expected = array(
|
||||||
|
'behavior' => '/debug_kit/js/js_debug_toolbar',
|
||||||
|
);
|
||||||
|
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||||
|
|
||||||
|
$this->Controller->components = array(
|
||||||
|
'DebugKit.Toolbar' => array(
|
||||||
|
'javascript' => 'jquery',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->Controller->Component->init($this->Controller);
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->Controller->Component->beforeRender($this->Controller);
|
||||||
|
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||||
|
$expected = array(
|
||||||
|
'behavior' => '/debug_kit/js/jquery_debug_toolbar.js',
|
||||||
|
);
|
||||||
|
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||||
|
|
||||||
|
|
||||||
|
$this->Controller->components = array(
|
||||||
|
'DebugKit.Toolbar' => array(
|
||||||
|
'javascript' => false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->Controller->Component->init($this->Controller);
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->Controller->Component->beforeRender($this->Controller);
|
||||||
|
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||||
|
$expected = array();
|
||||||
|
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||||
|
|
||||||
|
|
||||||
|
$this->Controller->components = array(
|
||||||
|
'DebugKit.Toolbar' => array(
|
||||||
|
'javascript' => array('my_library'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->Controller->Component->init($this->Controller);
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->Controller->Component->beforeRender($this->Controller);
|
||||||
|
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||||
|
$expected = array(
|
||||||
|
'behavior' => 'my_library_debug_toolbar'
|
||||||
|
);
|
||||||
|
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||||
|
|
||||||
|
$this->Controller->components = array(
|
||||||
|
'DebugKit.Toolbar' => array(
|
||||||
|
'javascript' => array('/my/path/to/file')
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->Controller->Component->init($this->Controller);
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->Controller->Component->beforeRender($this->Controller);
|
||||||
|
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||||
|
$expected = array(
|
||||||
|
'behavior' => '/my/path/to/file',
|
||||||
|
);
|
||||||
|
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||||
|
|
||||||
|
$this->Controller->components = array(
|
||||||
|
'DebugKit.Toolbar' => array(
|
||||||
|
'javascript' => '/js/custom_behavior',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->Controller->Component->init($this->Controller);
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->Controller->Component->beforeRender($this->Controller);
|
||||||
|
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||||
|
$expected = array(
|
||||||
|
'behavior' => '/js/custom_behavior',
|
||||||
|
);
|
||||||
|
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Test alternate javascript existing in the plugin.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testExistingAlterateJavascript() {
|
||||||
|
$filename = APP . 'plugins' . DS . 'debug_kit' . DS . 'vendors' . DS . 'js' . DS . 'test_alternate_debug_toolbar.js';
|
||||||
|
$this->skipIf(!is_writable(dirname($filename)), 'Skipping existing javascript test, debug_kit/vendors/js must be writable');
|
||||||
|
|
||||||
|
@touch($filename);
|
||||||
|
$this->Controller->components = array(
|
||||||
|
'DebugKit.Toolbar' => array(
|
||||||
|
'javascript' => 'test_alternate',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->Controller->Component->init($this->Controller);
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->Controller->Component->beforeRender($this->Controller);
|
||||||
|
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||||
|
$expected = array(
|
||||||
|
'behavior' => '/debug_kit/js/test_alternate_debug_toolbar.js',
|
||||||
|
);
|
||||||
|
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||||
|
@unlink($filename);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test the Log panel log reading.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testLogPanel() {
|
||||||
|
usleep(20);
|
||||||
|
$this->Controller->log('This is a log I made this request');
|
||||||
|
$this->Controller->log('This is the second log I made this request');
|
||||||
|
$this->Controller->log('This time in the debug log!', LOG_DEBUG);
|
||||||
|
|
||||||
|
$this->Controller->components = array(
|
||||||
|
'DebugKit.Toolbar' => array(
|
||||||
|
'panels' => array('log', 'session')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->Controller->Component->init($this->Controller);
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->Controller->Component->beforeRender($this->Controller);
|
||||||
|
$result = $this->Controller->viewVars['debugToolbarPanels']['log'];
|
||||||
|
|
||||||
|
$this->assertEqual(count($result['content']), 2);
|
||||||
|
$this->assertEqual(count($result['content']['error.log']), 4);
|
||||||
|
$this->assertEqual(count($result['content']['debug.log']), 2);
|
||||||
|
|
||||||
|
$this->assertEqual(trim($result['content']['debug.log'][1]), 'Debug: This time in the debug log!');
|
||||||
|
$this->assertEqual(trim($result['content']['error.log'][1]), 'Error: This is a log I made this request');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* teardown
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function tearDown() {
|
||||||
|
unset($this->Controller);
|
||||||
|
if (class_exists('DebugKitDebugger')) {
|
||||||
|
DebugKitDebugger::clearTimers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
0
plugins/debug_kit/tests/cases/empty
Normal file
0
plugins/debug_kit/tests/cases/empty
Normal file
62
plugins/debug_kit/tests/cases/test_objects.php
Normal file
62
plugins/debug_kit/tests/cases/test_objects.php
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Common test objects used in DebugKit tests
|
||||||
|
*
|
||||||
|
* Long description for file
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The Open Group Test Suite License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests
|
||||||
|
* @package cake.tests
|
||||||
|
* @subpackage cake.tests.cases.libs
|
||||||
|
* @since CakePHP(tm) v 1.2.0.5432
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* TestFireCake class allows for testing of FireCake
|
||||||
|
*
|
||||||
|
* @package debug_kit.tests.
|
||||||
|
*/
|
||||||
|
class TestFireCake extends FireCake {
|
||||||
|
var $sentHeaders = array();
|
||||||
|
|
||||||
|
function _sendHeader($name, $value) {
|
||||||
|
$_this = FireCake::getInstance();
|
||||||
|
$_this->sentHeaders[$name] = $value;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* skip client detection as headers are not being sent.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function detectClientExtension() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Reset the fireCake
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function reset() {
|
||||||
|
$_this = FireCake::getInstance();
|
||||||
|
$_this->sentHeaders = array();
|
||||||
|
$_this->_messageIndex = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
157
plugins/debug_kit/tests/cases/vendors/debug_kit_debugger.test.php
vendored
Normal file
157
plugins/debug_kit/tests/cases/vendors/debug_kit_debugger.test.php
vendored
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* DebugKit Debugger Test Case File
|
||||||
|
*
|
||||||
|
* Long description for file
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The Open Group Test Suite License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests
|
||||||
|
* @package cake.tests
|
||||||
|
* @subpackage cake.tests.cases.libs
|
||||||
|
* @since CakePHP(tm) v 1.2.0.5432
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
|
||||||
|
*/
|
||||||
|
App::import('Core', 'Debugger');
|
||||||
|
App::import('Vendor', 'DebugKit.DebugKitDebugger');
|
||||||
|
|
||||||
|
require_once APP . 'plugins' . DS . 'debug_kit' . DS . 'tests' . DS . 'cases' . DS . 'test_objects.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Short description for class.
|
||||||
|
*
|
||||||
|
* @package cake.tests
|
||||||
|
* @subpackage cake.tests.cases.libs
|
||||||
|
*/
|
||||||
|
class DebugKitDebuggerTest extends CakeTestCase {
|
||||||
|
/**
|
||||||
|
* setUp method
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setUp() {
|
||||||
|
Configure::write('log', false);
|
||||||
|
if (!defined('SIMPLETESTVENDORPATH')) {
|
||||||
|
if (file_exists(APP . DS . 'vendors' . DS . 'simpletest' . DS . 'reporter.php')) {
|
||||||
|
define('SIMPLETESTVENDORPATH', 'APP' . DS . 'vendors');
|
||||||
|
} else {
|
||||||
|
define('SIMPLETESTVENDORPATH', 'CORE' . DS . 'vendors');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start Timer test
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testTimers() {
|
||||||
|
$this->assertTrue(DebugKitDebugger::startTimer('test1', 'this is my first test'));
|
||||||
|
usleep(5000);
|
||||||
|
$this->assertTrue(DebugKitDebugger::stopTimer('test1'));
|
||||||
|
$elapsed = DebugKitDebugger::elapsedTime('test1');
|
||||||
|
$this->assertTrue($elapsed > 0.0050);
|
||||||
|
|
||||||
|
$this->assertTrue(DebugKitDebugger::startTimer('test2', 'this is my second test'));
|
||||||
|
sleep(1);
|
||||||
|
$this->assertTrue(DebugKitDebugger::stopTimer('test2'));
|
||||||
|
$elapsed = DebugKitDebugger::elapsedTime('test2');
|
||||||
|
$this->assertTrue($elapsed > 1);
|
||||||
|
|
||||||
|
DebugKitDebugger::startTimer('test3');
|
||||||
|
$this->assertFalse(DebugKitDebugger::elapsedTime('test3'));
|
||||||
|
$this->assertFalse(DebugKitDebugger::stopTimer('wrong'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* testRequestTime
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testRequestTime() {
|
||||||
|
$result1 = DebugKitDebugger::requestTime();
|
||||||
|
usleep(50);
|
||||||
|
$result2 = DebugKitDebugger::requestTime();
|
||||||
|
$this->assertTrue($result1 < $result2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test getting all the set timers.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testGetTimers() {
|
||||||
|
DebugKitDebugger::clearTimers();
|
||||||
|
DebugKitDebugger::startTimer('test1', 'this is my first test');
|
||||||
|
DebugKitDebugger::stopTimer('test1');
|
||||||
|
usleep(50);
|
||||||
|
DebugKitDebugger::startTimer('test2');
|
||||||
|
DebugKitDebugger::stopTimer('test2');
|
||||||
|
$timers = DebugKitDebugger::getTimers();
|
||||||
|
|
||||||
|
$this->assertEqual(count($timers), 2);
|
||||||
|
$this->assertTrue(is_float($timers['test1']['time']));
|
||||||
|
$this->assertTrue(isset($timers['test1']['message']));
|
||||||
|
$this->assertTrue(isset($timers['test2']['message']));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test memory usage
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testMemoryUsage() {
|
||||||
|
$result = DebugKitDebugger::getMemoryUse();
|
||||||
|
$this->assertTrue(is_int($result));
|
||||||
|
|
||||||
|
$result = DebugKitDebugger::getPeakMemoryUse();
|
||||||
|
$this->assertTrue(is_int($result));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test _output switch to firePHP
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testOutput() {
|
||||||
|
$firecake =& FireCake::getInstance('TestFireCake');
|
||||||
|
Debugger::invoke(DebugKitDebugger::getInstance('DebugKitDebugger'));
|
||||||
|
Debugger::output('fb');
|
||||||
|
$foo .= '';
|
||||||
|
$result = $firecake->sentHeaders;
|
||||||
|
|
||||||
|
$this->assertPattern('/GROUP_START/', $result['X-Wf-1-1-1-1']);
|
||||||
|
$this->assertPattern('/ERROR/', $result['X-Wf-1-1-1-2']);
|
||||||
|
$this->assertPattern('/GROUP_END/', $result['X-Wf-1-1-1-5']);
|
||||||
|
|
||||||
|
Debugger::invoke(Debugger::getInstance('Debugger'));
|
||||||
|
Debugger::output();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tearDown method
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function tearDown() {
|
||||||
|
Configure::write('log', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
336
plugins/debug_kit/tests/cases/vendors/fire_cake.test.php
vendored
Normal file
336
plugins/debug_kit/tests/cases/vendors/fire_cake.test.php
vendored
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* CakeFirePHP test case
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package debug_kit
|
||||||
|
* @subpackage cake.debug_kit.tests
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version
|
||||||
|
* @modifiedby
|
||||||
|
* @lastmodified
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
App::import('Vendor', 'DebugKit.FireCake');
|
||||||
|
|
||||||
|
require_once APP . 'plugins' . DS . 'debug_kit' . DS . 'tests' . DS . 'cases' . DS . 'test_objects.php';
|
||||||
|
/**
|
||||||
|
* Test Case For FireCake
|
||||||
|
*
|
||||||
|
* @package debug_kit.tests
|
||||||
|
*/
|
||||||
|
class FireCakeTestCase extends CakeTestCase {
|
||||||
|
/**
|
||||||
|
* setup test
|
||||||
|
*
|
||||||
|
* Fill FireCake with TestFireCake instance.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setUp() {
|
||||||
|
$this->firecake =& FireCake::getInstance('TestFireCake');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test getInstance cheat.
|
||||||
|
*
|
||||||
|
* If this fails the rest of the test is going to fail too.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testGetInstanceOverride() {
|
||||||
|
$instance =& FireCake::getInstance();
|
||||||
|
$instance2 =& FireCake::getInstance();
|
||||||
|
$this->assertReference($instance, $instance2);
|
||||||
|
$this->assertIsA($instance, 'FireCake');
|
||||||
|
$this->assertIsA($instance, 'TestFireCake', 'Stored instance is not a copy of TestFireCake, test case is broken.');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* testsetoption
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testSetOptions() {
|
||||||
|
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||||
|
$this->assertEqual($this->firecake->options['includeLineNumbers'], false);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test Log()
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testLog() {
|
||||||
|
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||||
|
FireCake::log('Testing');
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 1);
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '26|[{"Type":"LOG"},"Testing"]|');
|
||||||
|
|
||||||
|
FireCake::log('Testing', 'log-info');
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '45|[{"Type":"LOG","Label":"log-info"},"Testing"]|');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test info()
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testInfo() {
|
||||||
|
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||||
|
FireCake::info('I have information');
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 1);
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '38|[{"Type":"INFO"},"I have information"]|');
|
||||||
|
|
||||||
|
FireCake::info('I have information', 'info-label');
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '59|[{"Type":"INFO","Label":"info-label"},"I have information"]|');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test info()
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testWarn() {
|
||||||
|
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||||
|
FireCake::warn('A Warning');
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 1);
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '29|[{"Type":"WARN"},"A Warning"]|');
|
||||||
|
|
||||||
|
FireCake::warn('A Warning', 'Bzzz');
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '44|[{"Type":"WARN","Label":"Bzzz"},"A Warning"]|');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test error()
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testError() {
|
||||||
|
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||||
|
FireCake::error('An error');
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 1);
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '29|[{"Type":"ERROR"},"An error"]|');
|
||||||
|
|
||||||
|
FireCake::error('An error', 'wonky');
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '45|[{"Type":"ERROR","Label":"wonky"},"An error"]|');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test dump()
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testDump() {
|
||||||
|
FireCake::dump('mydump', array('one' => 1, 'two' => 2));
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-2-1-1'], '28|{"mydump":{"one":1,"two":2}}|');
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-2']));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test table() generation
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testTable() {
|
||||||
|
$table[] = array('Col 1 Heading','Col 2 Heading');
|
||||||
|
$table[] = array('Row 1 Col 1','Row 1 Col 2');
|
||||||
|
$table[] = array('Row 2 Col 1','Row 2 Col 2');
|
||||||
|
$table[] = array('Row 3 Col 1','Row 3 Col 2');
|
||||||
|
FireCake::table('myTrace', $table);
|
||||||
|
$expected = '162|[{"Type":"TABLE","Label":"myTrace"},[["Col 1 Heading","Col 2 Heading"],["Row 1 Col 1","Row 1 Col 2"],["Row 2 Col 1","Row 2 Col 2"],["Row 3 Col 1","Row 3 Col 2"]]]|';
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], $expected);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* testStringEncoding
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testStringEncode() {
|
||||||
|
$result = $this->firecake->stringEncode(array(1,2,3));
|
||||||
|
$this->assertEqual($result, array(1,2,3));
|
||||||
|
|
||||||
|
$this->firecake->setOptions(array('maxArrayDepth' => 3));
|
||||||
|
$deep = array(1 => array(2 => array(3)));
|
||||||
|
$result = $this->firecake->stringEncode($deep);
|
||||||
|
$this->assertEqual($result, array(1 => array(2 => '** Max Array Depth (3) **')));
|
||||||
|
|
||||||
|
$obj =& FireCake::getInstance();
|
||||||
|
$result = $this->firecake->stringEncode($obj);
|
||||||
|
$this->assertTrue(is_array($result));
|
||||||
|
$this->assertEqual($result['_defaultOptions']['useNativeJsonEncode'], true);
|
||||||
|
$this->assertEqual($result['_log'], null);
|
||||||
|
$this->assertEqual($result['_encodedObjects'][0], '** Recursion (TestFireCake) **');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test trace()
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testTrace() {
|
||||||
|
FireCake::trace('myTrace');
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||||
|
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||||
|
$dump = $this->firecake->sentHeaders['X-Wf-1-1-1-1'];
|
||||||
|
$this->assertPattern('/"Message":"myTrace"/', $dump);
|
||||||
|
$this->assertPattern('/"Trace":\[/', $dump);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test enabling and disabling of FireCake output
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testEnableDisable() {
|
||||||
|
FireCake::disable();
|
||||||
|
FireCake::trace('myTrace');
|
||||||
|
$this->assertTrue(empty($this->firecake->sentHeaders));
|
||||||
|
|
||||||
|
FireCake::enable();
|
||||||
|
FireCake::trace('myTrace');
|
||||||
|
$this->assertFalse(empty($this->firecake->sentHeaders));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test correct line continuation markers on multi line headers.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testMultiLineOutput() {
|
||||||
|
FireCake::trace('myTrace');
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 3);
|
||||||
|
$header = $this->firecake->sentHeaders['X-Wf-1-1-1-1'];
|
||||||
|
$this->assertEqual(substr($header, -2), '|\\');
|
||||||
|
|
||||||
|
$header = $this->firecake->sentHeaders['X-Wf-1-1-1-2'];
|
||||||
|
$this->assertEqual(substr($header, -2), '|\\');
|
||||||
|
|
||||||
|
$header = $this->firecake->sentHeaders['X-Wf-1-1-1-3'];
|
||||||
|
$this->assertEqual(substr($header, -1), '|');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test inclusion of line numbers
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testIncludeLineNumbers() {
|
||||||
|
FireCake::setOptions(array('includeLineNumbers' => true));
|
||||||
|
FireCake::info('Testing');
|
||||||
|
$result = $this->firecake->sentHeaders['X-Wf-1-1-1-1'];
|
||||||
|
$this->assertPattern('/"File"\:"APP.*fire_cake.test.php/', $result);
|
||||||
|
$this->assertPattern('/"Line"\:\d+/', $result);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test Group messages
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testGroup() {
|
||||||
|
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||||
|
FireCake::group('test');
|
||||||
|
FireCake::info('my info');
|
||||||
|
FireCake::groupEnd();
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '44|[{"Type":"GROUP_START","Label":"test"},null]|');
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-3'], '27|[{"Type":"GROUP_END"},null]|');
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 3);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test fb() parameter parsing
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testFbParameterParsing() {
|
||||||
|
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||||
|
FireCake::fb('Test');
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '23|[{"Type":"LOG"},"Test"]|');
|
||||||
|
|
||||||
|
FireCake::fb('Test', 'warn');
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '24|[{"Type":"WARN"},"Test"]|');
|
||||||
|
|
||||||
|
FireCake::fb('Test', 'Custom label', 'warn');
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-3'], '47|[{"Type":"WARN","Label":"Custom label"},"Test"]|');
|
||||||
|
|
||||||
|
$this->expectError();
|
||||||
|
$this->assertFalse(FireCake::fb('Test', 'Custom label', 'warn', 'more parameters'));
|
||||||
|
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 3);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Test defaulting to log if incorrect message type is used
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testIncorrectMessageType() {
|
||||||
|
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||||
|
FireCake::fb('Hello World', 'foobared');
|
||||||
|
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '30|[{"Type":"LOG"},"Hello World"]|');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* testClientExtensionDetection.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testDetectClientExtension() {
|
||||||
|
$back = env('HTTP_USER_AGENT');
|
||||||
|
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4 FirePHP/0.2.1';
|
||||||
|
$this->assertTrue(FireCake::detectClientExtension());
|
||||||
|
|
||||||
|
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4 FirePHP/0.0.4';
|
||||||
|
$this->assertFalse(FireCake::detectClientExtension());
|
||||||
|
|
||||||
|
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4';
|
||||||
|
$this->assertFalse(FireCake::detectClientExtension());
|
||||||
|
$_SERVER['HTTP_USER_AGENT'] = $back;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test of Non Native JSON encoding.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testNonNativeEncoding() {
|
||||||
|
FireCake::setOptions(array('useNativeJsonEncode' => false));
|
||||||
|
$json = FireCake::jsonEncode(array('one' => 1, 'two' => 2));
|
||||||
|
$this->assertEqual($json, '{"one":1,"two":2}');
|
||||||
|
|
||||||
|
$json = FireCake::jsonEncode(array(1,2,3));
|
||||||
|
$this->assertEqual($json, '[1,2,3]');
|
||||||
|
|
||||||
|
$json = FireCake::jsonEncode(FireCake::getInstance());
|
||||||
|
$this->assertPattern('/"options"\:\{"maxObjectDepth"\:\d*,/', $json);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* reset the FireCake counters and headers.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function tearDown() {
|
||||||
|
TestFireCake::reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
144
plugins/debug_kit/tests/cases/views/debug.test.php
Normal file
144
plugins/debug_kit/tests/cases/views/debug.test.php
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* DebugView test Case
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
App::import('Core', 'View');
|
||||||
|
|
||||||
|
if (!class_exists('DoppelGangerView')) {
|
||||||
|
class DoppelGangerView extends View {}
|
||||||
|
}
|
||||||
|
|
||||||
|
App::import('View', 'DebugKit.Debug');
|
||||||
|
App::import('Vendor', 'DebugKit.DebugKitDebugger');
|
||||||
|
/**
|
||||||
|
* Debug View Test Case
|
||||||
|
*
|
||||||
|
* @package debug_kit.tests
|
||||||
|
*/
|
||||||
|
class DebugViewTestCase extends CakeTestCase {
|
||||||
|
/**
|
||||||
|
* set Up test case
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function setUp() {
|
||||||
|
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
|
||||||
|
Router::parse('/');
|
||||||
|
$this->Controller =& ClassRegistry::init('Controller');
|
||||||
|
$this->View =& new DebugView($this->Controller, false);
|
||||||
|
$this->_debug = Configure::read('debug');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* start Case - switch view paths
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function startCase() {
|
||||||
|
$this->_viewPaths = Configure::read('viewPaths');
|
||||||
|
Configure::write('viewPaths', array(
|
||||||
|
TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS,
|
||||||
|
APP . 'plugins' . DS . 'debug_kit' . DS . 'views'. DS,
|
||||||
|
ROOT . DS . LIBS . 'view' . DS
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test that element timers are working
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testElementTimers() {
|
||||||
|
$result = $this->View->element('test_element');
|
||||||
|
$this->assertPattern('/^this is the test element$/', $result);
|
||||||
|
|
||||||
|
$result = DebugKitDebugger::getTimers();
|
||||||
|
$this->assertTrue(isset($result['render_test_element.ctp']));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test rendering and ensure that timers are being set.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testRenderTimers() {
|
||||||
|
$this->Controller->viewPath = 'posts';
|
||||||
|
$this->Controller->action = 'index';
|
||||||
|
$this->Controller->params = array(
|
||||||
|
'action' => 'index',
|
||||||
|
'controller' => 'posts',
|
||||||
|
'plugin' => null,
|
||||||
|
'url' => array('url' => 'posts/index'),
|
||||||
|
'base' => null,
|
||||||
|
'here' => '/posts/index',
|
||||||
|
);
|
||||||
|
$this->Controller->layout = 'default';
|
||||||
|
$View =& new DebugView($this->Controller, false);
|
||||||
|
$View->render('index');
|
||||||
|
|
||||||
|
$result = DebugKitDebugger::getTimers();
|
||||||
|
$this->assertEqual(count($result), 3);
|
||||||
|
$this->assertTrue(isset($result['viewRender']));
|
||||||
|
$this->assertTrue(isset($result['render_default.ctp']));
|
||||||
|
$this->assertTrue(isset($result['render_index.ctp']));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for correct loading of helpers into custom view
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testLoadHelpers() {
|
||||||
|
$loaded = array();
|
||||||
|
$result = $this->View->_loadHelpers($loaded, array('Html', 'Javascript', 'Number'));
|
||||||
|
$this->assertTrue(is_object($result['Html']));
|
||||||
|
$this->assertTrue(is_object($result['Javascript']));
|
||||||
|
$this->assertTrue(is_object($result['Number']));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reset the view paths
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function endCase() {
|
||||||
|
Configure::write('viewPaths', $this->_viewPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tear down function
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function tearDown() {
|
||||||
|
unset($this->View, $this->Controller);
|
||||||
|
DebugKitDebugger::clearTimers();
|
||||||
|
Configure::write('debug', $this->_debug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Toolbar Abstract Helper Test Case
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage debug_kit.tests.views.helpers
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
App::import('Helper', 'DebugKit.FirePhpToolbar');
|
||||||
|
App::import('Core', array('View', 'Controller'));
|
||||||
|
require_once APP . 'plugins' . DS . 'debug_kit' . DS . 'tests' . DS . 'cases' . DS . 'test_objects.php';
|
||||||
|
|
||||||
|
FireCake::getInstance('TestFireCake');
|
||||||
|
|
||||||
|
class FirePhpToolbarHelperTestCase extends CakeTestCase {
|
||||||
|
/**
|
||||||
|
* setUp
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function setUp() {
|
||||||
|
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
|
||||||
|
Router::parse('/');
|
||||||
|
|
||||||
|
$this->Toolbar =& new ToolbarHelper(array('output' => 'DebugKit.FirePhpToolbar'));
|
||||||
|
$this->Toolbar->FirePhpToolbar =& new FirePhpToolbarHelper();
|
||||||
|
|
||||||
|
$this->Controller =& ClassRegistry::init('Controller');
|
||||||
|
if (isset($this->_debug)) {
|
||||||
|
Configure::write('debug', $this->_debug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* start Case - switch view paths
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function startCase() {
|
||||||
|
$this->_viewPaths = Configure::read('viewPaths');
|
||||||
|
Configure::write('viewPaths', array(
|
||||||
|
TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS,
|
||||||
|
APP . 'plugins' . DS . 'debug_kit' . DS . 'views'. DS,
|
||||||
|
ROOT . DS . LIBS . 'view' . DS
|
||||||
|
));
|
||||||
|
$this->_debug = Configure::read('debug');
|
||||||
|
$this->firecake =& FireCake::getInstance();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test neat array (dump)creation
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testMakeNeatArray() {
|
||||||
|
$this->Toolbar->makeNeatArray(array(1,2,3));
|
||||||
|
$result = $this->firecake->sentHeaders;
|
||||||
|
$this->assertTrue(isset($result['X-Wf-1-1-1-1']));
|
||||||
|
$this->assertPattern('/\[1,2,3\]/', $result['X-Wf-1-1-1-1']);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* testAfterlayout element rendering
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testAfterLayout(){
|
||||||
|
$this->Controller->viewPath = 'posts';
|
||||||
|
$this->Controller->action = 'index';
|
||||||
|
$this->Controller->params = array(
|
||||||
|
'action' => 'index',
|
||||||
|
'controller' => 'posts',
|
||||||
|
'plugin' => null,
|
||||||
|
'url' => array('url' => 'posts/index', 'ext' => 'xml'),
|
||||||
|
'base' => null,
|
||||||
|
'here' => '/posts/index',
|
||||||
|
);
|
||||||
|
$this->Controller->layout = 'default';
|
||||||
|
$this->Controller->uses = null;
|
||||||
|
$this->Controller->components = array('DebugKit.Toolbar');
|
||||||
|
$this->Controller->constructClasses();
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->Controller->Component->beforeRender($this->Controller);
|
||||||
|
$result = $this->Controller->render();
|
||||||
|
$this->assertNoPattern('/debug-toolbar/', $result);
|
||||||
|
$result = $this->firecake->sentHeaders;
|
||||||
|
$this->assertTrue(is_array($result));
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* endTest()
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function endTest() {
|
||||||
|
TestFireCake::reset();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* reset the view paths
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function endCase() {
|
||||||
|
Configure::write('viewPaths', $this->_viewPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tearDown
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function tearDown() {
|
||||||
|
unset($this->Toolbar, $this->Controller);
|
||||||
|
ClassRegistry::removeObject('view');
|
||||||
|
ClassRegistry::flush();
|
||||||
|
Router::reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -0,0 +1,358 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Toolbar HTML Helper Test Case
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage debug_kit.tests.views.helpers
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
App::import('Helper', array('DebugKit.HtmlToolbar', 'Html', 'Javascript'));
|
||||||
|
App::import('Core', array('View', 'Controller'));
|
||||||
|
|
||||||
|
class HtmlToolbarHelperTestCase extends CakeTestCase {
|
||||||
|
/**
|
||||||
|
* setUp
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function setUp() {
|
||||||
|
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
|
||||||
|
Router::parse('/');
|
||||||
|
|
||||||
|
$this->Toolbar =& new ToolbarHelper(array('output' => 'DebugKit.HtmlToolbar'));
|
||||||
|
$this->Toolbar->HtmlToolbar =& new HtmlToolbarHelper();
|
||||||
|
$this->Toolbar->HtmlToolbar->Html =& new HtmlHelper();
|
||||||
|
$this->Toolbar->HtmlToolbar->Javascript =& new JavascriptHelper();
|
||||||
|
|
||||||
|
$this->Controller =& ClassRegistry::init('Controller');
|
||||||
|
if (isset($this->_debug)) {
|
||||||
|
Configure::write('debug', $this->_debug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* start Case - switch view paths
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function startCase() {
|
||||||
|
$this->_viewPaths = Configure::read('viewPaths');
|
||||||
|
Configure::write('viewPaths', array(
|
||||||
|
TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS,
|
||||||
|
APP . 'plugins' . DS . 'debug_kit' . DS . 'views'. DS,
|
||||||
|
ROOT . DS . LIBS . 'view' . DS
|
||||||
|
));
|
||||||
|
$this->_debug = Configure::read('debug');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test Neat Array formatting
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testMakeNeatArray() {
|
||||||
|
$in = false;
|
||||||
|
$result = $this->Toolbar->makeNeatArray($in);
|
||||||
|
$expected = array(
|
||||||
|
'ul' => array('class' => 'neat-array depth-0'),
|
||||||
|
'<li', '<strong', '0' , '/strong', '(false)', '/li',
|
||||||
|
'/ul'
|
||||||
|
);
|
||||||
|
$this->assertTags($result, $expected);
|
||||||
|
|
||||||
|
$in = null;
|
||||||
|
$result = $this->Toolbar->makeNeatArray($in);
|
||||||
|
$expected = array(
|
||||||
|
'ul' => array('class' => 'neat-array depth-0'),
|
||||||
|
'<li', '<strong', '0' , '/strong', '(null)', '/li',
|
||||||
|
'/ul'
|
||||||
|
);
|
||||||
|
$this->assertTags($result, $expected);
|
||||||
|
|
||||||
|
$in = true;
|
||||||
|
$result = $this->Toolbar->makeNeatArray($in);
|
||||||
|
$expected = array(
|
||||||
|
'ul' => array('class' => 'neat-array depth-0'),
|
||||||
|
'<li', '<strong', '0' , '/strong', '(true)', '/li',
|
||||||
|
'/ul'
|
||||||
|
);
|
||||||
|
$this->assertTags($result, $expected);
|
||||||
|
|
||||||
|
$in = array('key' => 'value');
|
||||||
|
$result = $this->Toolbar->makeNeatArray($in);
|
||||||
|
$expected = array(
|
||||||
|
'ul' => array('class' => 'neat-array depth-0'),
|
||||||
|
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||||
|
'/ul'
|
||||||
|
);
|
||||||
|
$this->assertTags($result, $expected);
|
||||||
|
|
||||||
|
$in = array('key' => null);
|
||||||
|
$result = $this->Toolbar->makeNeatArray($in);
|
||||||
|
$expected = array(
|
||||||
|
'ul' => array('class' => 'neat-array depth-0'),
|
||||||
|
'<li', '<strong', 'key', '/strong', '(null)', '/li',
|
||||||
|
'/ul'
|
||||||
|
);
|
||||||
|
$this->assertTags($result, $expected);
|
||||||
|
|
||||||
|
$in = array('key' => 'value', 'foo' => 'bar');
|
||||||
|
$result = $this->Toolbar->makeNeatArray($in);
|
||||||
|
$expected = array(
|
||||||
|
'ul' => array('class' => 'neat-array depth-0'),
|
||||||
|
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||||
|
'<li', '<strong', 'foo', '/strong', 'bar', '/li',
|
||||||
|
'/ul'
|
||||||
|
);
|
||||||
|
$this->assertTags($result, $expected);
|
||||||
|
|
||||||
|
$in = array(
|
||||||
|
'key' => 'value',
|
||||||
|
'foo' => array(
|
||||||
|
'this' => 'deep',
|
||||||
|
'another' => 'value'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$result = $this->Toolbar->makeNeatArray($in);
|
||||||
|
$expected = array(
|
||||||
|
'ul' => array('class' => 'neat-array depth-0'),
|
||||||
|
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||||
|
'<li', '<strong', 'foo', '/strong',
|
||||||
|
array('ul' => array('class' => 'neat-array depth-1')),
|
||||||
|
'<li', '<strong', 'this', '/strong', 'deep', '/li',
|
||||||
|
'<li', '<strong', 'another', '/strong', 'value', '/li',
|
||||||
|
'/ul',
|
||||||
|
'/li',
|
||||||
|
'/ul'
|
||||||
|
);
|
||||||
|
$this->assertTags($result, $expected);
|
||||||
|
|
||||||
|
$in = array(
|
||||||
|
'key' => 'value',
|
||||||
|
'foo' => array(
|
||||||
|
'this' => 'deep',
|
||||||
|
'another' => 'value'
|
||||||
|
),
|
||||||
|
'lotr' => array(
|
||||||
|
'gandalf' => 'wizard',
|
||||||
|
'bilbo' => 'hobbit'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$result = $this->Toolbar->makeNeatArray($in, 1);
|
||||||
|
$expected = array(
|
||||||
|
'ul' => array('class' => 'neat-array depth-0 expanded'),
|
||||||
|
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||||
|
'<li', '<strong', 'foo', '/strong',
|
||||||
|
array('ul' => array('class' => 'neat-array depth-1')),
|
||||||
|
'<li', '<strong', 'this', '/strong', 'deep', '/li',
|
||||||
|
'<li', '<strong', 'another', '/strong', 'value', '/li',
|
||||||
|
'/ul',
|
||||||
|
'/li',
|
||||||
|
'<li', '<strong', 'lotr', '/strong',
|
||||||
|
array('ul' => array('class' => 'neat-array depth-1')),
|
||||||
|
'<li', '<strong', 'gandalf', '/strong', 'wizard', '/li',
|
||||||
|
'<li', '<strong', 'bilbo', '/strong', 'hobbit', '/li',
|
||||||
|
'/ul',
|
||||||
|
'/li',
|
||||||
|
'/ul'
|
||||||
|
);
|
||||||
|
$this->assertTags($result, $expected);
|
||||||
|
|
||||||
|
$result = $this->Toolbar->makeNeatArray($in, 2);
|
||||||
|
$expected = array(
|
||||||
|
'ul' => array('class' => 'neat-array depth-0 expanded'),
|
||||||
|
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||||
|
'<li', '<strong', 'foo', '/strong',
|
||||||
|
array('ul' => array('class' => 'neat-array depth-1 expanded')),
|
||||||
|
'<li', '<strong', 'this', '/strong', 'deep', '/li',
|
||||||
|
'<li', '<strong', 'another', '/strong', 'value', '/li',
|
||||||
|
'/ul',
|
||||||
|
'/li',
|
||||||
|
'<li', '<strong', 'lotr', '/strong',
|
||||||
|
array('ul' => array('class' => 'neat-array depth-1 expanded')),
|
||||||
|
'<li', '<strong', 'gandalf', '/strong', 'wizard', '/li',
|
||||||
|
'<li', '<strong', 'bilbo', '/strong', 'hobbit', '/li',
|
||||||
|
'/ul',
|
||||||
|
'/li',
|
||||||
|
'/ul'
|
||||||
|
);
|
||||||
|
$this->assertTags($result, $expected);
|
||||||
|
|
||||||
|
$in = array('key' => 'value', 'array' => array());
|
||||||
|
$result = $this->Toolbar->makeNeatArray($in);
|
||||||
|
$expected = array(
|
||||||
|
'ul' => array('class' => 'neat-array depth-0'),
|
||||||
|
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||||
|
'<li', '<strong', 'array', '/strong', '(empty)', '/li',
|
||||||
|
'/ul'
|
||||||
|
);
|
||||||
|
$this->assertTags($result, $expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test injection of toolbar
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testInjectToolbar() {
|
||||||
|
$this->Controller->viewPath = 'posts';
|
||||||
|
$this->Controller->action = 'index';
|
||||||
|
$this->Controller->params = array(
|
||||||
|
'action' => 'index',
|
||||||
|
'controller' => 'posts',
|
||||||
|
'plugin' => null,
|
||||||
|
'url' => array('url' => 'posts/index'),
|
||||||
|
'base' => null,
|
||||||
|
'here' => '/posts/index',
|
||||||
|
);
|
||||||
|
$this->Controller->helpers = array('Html', 'Javascript', 'DebugKit.Toolbar');
|
||||||
|
$this->Controller->layout = 'default';
|
||||||
|
$this->Controller->uses = null;
|
||||||
|
$this->Controller->components = array('DebugKit.Toolbar');
|
||||||
|
$this->Controller->constructClasses();
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->Controller->Component->beforeRender($this->Controller);
|
||||||
|
$result = $this->Controller->render();
|
||||||
|
$result = str_replace(array("\n", "\r"), '', $result);
|
||||||
|
$this->assertPattern('#<div id\="debug-kit-toolbar">.+</div></body>#', $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test injection of javascript
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testJavascriptInjection() {
|
||||||
|
$this->Controller->viewPath = 'posts';
|
||||||
|
$this->Controller->uses = null;
|
||||||
|
$this->Controller->action = 'index';
|
||||||
|
$this->Controller->params = array(
|
||||||
|
'action' => 'index',
|
||||||
|
'controller' => 'posts',
|
||||||
|
'plugin' => null,
|
||||||
|
'url' => array('url' => 'posts/index'),
|
||||||
|
'base' => '/',
|
||||||
|
'here' => '/posts/index',
|
||||||
|
);
|
||||||
|
$this->Controller->helpers = array('Javascript', 'Html');
|
||||||
|
$this->Controller->components = array('DebugKit.Toolbar');
|
||||||
|
$this->Controller->layout = 'default';
|
||||||
|
$this->Controller->constructClasses();
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->Controller->Component->beforeRender($this->Controller);
|
||||||
|
$result = $this->Controller->render();
|
||||||
|
$result = str_replace(array("\n", "\r"), '', $result);
|
||||||
|
$this->assertPattern('#<script\s*type="text/javascript"\s*src="/debug_kit/js/js_debug_toolbar.js"\s*>\s?</script>#', $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test Injection of user defined javascript
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testCustomJavascriptInjection() {
|
||||||
|
$this->Controller->viewPath = 'posts';
|
||||||
|
$this->Controller->uses = null;
|
||||||
|
$this->Controller->action = 'index';
|
||||||
|
$this->Controller->params = array(
|
||||||
|
'action' => 'index',
|
||||||
|
'controller' => 'posts',
|
||||||
|
'plugin' => null,
|
||||||
|
'url' => array('url' => 'posts/index'),
|
||||||
|
'base' => '/',
|
||||||
|
'here' => '/posts/index',
|
||||||
|
);
|
||||||
|
$this->Controller->helpers = array('Javascript', 'Html');
|
||||||
|
$this->Controller->components = array('DebugKit.Toolbar' => array('javascript' => array('my_custom')));
|
||||||
|
$this->Controller->layout = 'default';
|
||||||
|
$this->Controller->constructClasses();
|
||||||
|
$this->Controller->Component->initialize($this->Controller);
|
||||||
|
$this->Controller->Component->startup($this->Controller);
|
||||||
|
$this->Controller->Component->beforeRender($this->Controller);
|
||||||
|
$result = $this->Controller->render();
|
||||||
|
$result = str_replace(array("\n", "\r"), '', $result);
|
||||||
|
$this->assertPattern('#<script\s*type="text/javascript"\s*src="js/my_custom_debug_toolbar.js"\s*>\s?</script>#', $result);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test message creation
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testMessage() {
|
||||||
|
$result = $this->Toolbar->message('test', 'one, two');
|
||||||
|
$expected = array(
|
||||||
|
'<p',
|
||||||
|
'<strong', 'test', '/strong',
|
||||||
|
' one, two',
|
||||||
|
'/p',
|
||||||
|
);
|
||||||
|
$this->assertTags($result, $expected);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Test Table generation
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function testTable() {
|
||||||
|
$rows = array(
|
||||||
|
array(1,2),
|
||||||
|
array(3,4),
|
||||||
|
);
|
||||||
|
$result = $this->Toolbar->table($rows);
|
||||||
|
$expected = array(
|
||||||
|
'table' => array('class' =>'debug-table'),
|
||||||
|
array('tr' => array('class' => 'odd')),
|
||||||
|
'<td', '1', '/td',
|
||||||
|
'<td', '2', '/td',
|
||||||
|
'/tr',
|
||||||
|
array('tr' => array('class' => 'even')),
|
||||||
|
'<td', '3', '/td',
|
||||||
|
'<td', '4', '/td',
|
||||||
|
'/tr',
|
||||||
|
'/table'
|
||||||
|
);
|
||||||
|
$this->assertTags($result, $expected);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* reset the view paths
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function endCase() {
|
||||||
|
Configure::write('viewPaths', $this->_viewPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tearDown
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function tearDown() {
|
||||||
|
unset($this->Toolbar, $this->Controller);
|
||||||
|
ClassRegistry::removeObject('view');
|
||||||
|
ClassRegistry::flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
0
plugins/debug_kit/tests/fixtures/empty
vendored
Normal file
0
plugins/debug_kit/tests/fixtures/empty
vendored
Normal file
0
plugins/debug_kit/tests/groups/empty
Normal file
0
plugins/debug_kit/tests/groups/empty
Normal file
33
plugins/debug_kit/tests/test_app/vendors/test_panel.php
vendored
Normal file
33
plugins/debug_kit/tests/test_app/vendors/test_panel.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Test Panel
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake.debug_kit
|
||||||
|
* @subpackage cake.debug_kit.tests
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
class TestPanel extends DebugPanel {
|
||||||
|
function startup(&$controller) {
|
||||||
|
$controller->testPanel = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
165
plugins/debug_kit/vendors/css/debug_toolbar.css
vendored
Normal file
165
plugins/debug_kit/vendors/css/debug_toolbar.css
vendored
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/* @override http://localhost/cake_debug_kit/debug_kit/css/debug_toolbar.css */
|
||||||
|
#debug-kit-toolbar {
|
||||||
|
position: fixed;
|
||||||
|
top: 0px;
|
||||||
|
right:0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 1%;
|
||||||
|
overflow: visible;
|
||||||
|
z-index:10000;
|
||||||
|
}
|
||||||
|
/* panel tabs */
|
||||||
|
#debug-kit-toolbar #panel-tabs {
|
||||||
|
float: right;
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
#debug-kit-toolbar .panel-tab {
|
||||||
|
clear: none;
|
||||||
|
float: left;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#debug-kit-toolbar .panel-tab a {
|
||||||
|
float: left;
|
||||||
|
clear: none;
|
||||||
|
background: #efefef;
|
||||||
|
color: #222;
|
||||||
|
padding: 6px;
|
||||||
|
border-right: 1px solid #ccc;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
margin: 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#debug-kit-toolbar .panel-tab .active,
|
||||||
|
#debug-kit-toolbar .panel-tab a:hover {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
#debug-kit-toolbar .panel-tab.icon a {
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hovering over link shows tab, useful for no js */
|
||||||
|
#debug-kit-toolbar .panel-tab a:hover + .panel-content,
|
||||||
|
#debug-kit-toolbar .panel-tab a + .panel-content:hover {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* panel content */
|
||||||
|
#debug-kit-toolbar .panel-content {
|
||||||
|
position: absolute;
|
||||||
|
text-align: left;
|
||||||
|
width: auto;
|
||||||
|
top:28px;
|
||||||
|
right:0px;
|
||||||
|
background: #fff;
|
||||||
|
color: #000;
|
||||||
|
width:96%;
|
||||||
|
padding:20px 2%;
|
||||||
|
max-height: 550px;
|
||||||
|
overflow:auto;
|
||||||
|
border-bottom: 3px solid #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide panel content by default */
|
||||||
|
.panel-content {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-content p {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
.panel-content h2 {
|
||||||
|
padding: 0;
|
||||||
|
margin-top:0;
|
||||||
|
}
|
||||||
|
.panel-content h3 {
|
||||||
|
padding: 0;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
.panel-content .info {
|
||||||
|
padding: 4px;
|
||||||
|
border-top: 1px dashed #6c6cff;
|
||||||
|
border-bottom: 1px dashed #6c6cff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* panel tables */
|
||||||
|
table.debug-table {
|
||||||
|
width: auto;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
table.debug-table td,
|
||||||
|
table.debug-table th {
|
||||||
|
text-align: left;
|
||||||
|
border: 0;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
table.debug-table th {
|
||||||
|
border-bottom: 1px solid #222;
|
||||||
|
background: 0;;
|
||||||
|
}
|
||||||
|
table.debug-table tr.even td {
|
||||||
|
background:#efefef;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** code tables **/
|
||||||
|
#debug-kit-toolbar .code-table td {
|
||||||
|
white-space: pre;
|
||||||
|
font-family: monaco, corsiva, "courier new", courier, monospaced;
|
||||||
|
}
|
||||||
|
#debug-kit-toolbar .code-table td:first-child {
|
||||||
|
width: 15%;
|
||||||
|
}
|
||||||
|
#debug-kit-toolbar .code-table td:last-child {
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.panel-content.request {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Neat Array styles **/
|
||||||
|
.neat-array {
|
||||||
|
padding: 1px 2px 1px 20px;
|
||||||
|
background: #CE9E23;
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.neat-array .neat-array {
|
||||||
|
padding: 0 0 0 20px;
|
||||||
|
}
|
||||||
|
.neat-array li {
|
||||||
|
background: #FEF6E5;
|
||||||
|
border-top: 1px solid #CE9E23;
|
||||||
|
border-bottom: 1px solid #CE9E23;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
.neat-array li:hover {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.neat-array li strong {
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expandable sections */
|
||||||
|
.neat-array li.expandable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.neat-array li.expandable.expanded > strong:before {
|
||||||
|
content: 'v ';
|
||||||
|
}
|
||||||
|
.neat-array li.expandable.collapsed > strong:before,
|
||||||
|
.neat-array li.expandable.expanded .expandable.collapsed > strong:before {
|
||||||
|
content: '> ';
|
||||||
|
}
|
||||||
|
|
||||||
|
.neat-array li {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
226
plugins/debug_kit/vendors/debug_kit_debugger.php
vendored
Normal file
226
plugins/debug_kit/vendors/debug_kit_debugger.php
vendored
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* DebugKit Debugger class. Extends and enhances core
|
||||||
|
* debugger. Adds benchmarking and timing functionality.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
App::import('Core', 'Debugger');
|
||||||
|
App::import('Vendor', 'DebugKit.FireCake');
|
||||||
|
/**
|
||||||
|
* Debug Kit Temporary Debugger Class
|
||||||
|
*
|
||||||
|
* Provides the future features that are planned. Yet not implemented in the 1.2 code base
|
||||||
|
*
|
||||||
|
* This file will not be needed in future version of CakePHP.
|
||||||
|
* @todo merge these changes with core Debugger
|
||||||
|
*/
|
||||||
|
class DebugKitDebugger extends Debugger {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start an benchmarking timer.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the timer to start.
|
||||||
|
* @param string $message A message for your timer
|
||||||
|
* @return bool true
|
||||||
|
* @static
|
||||||
|
**/
|
||||||
|
function startTimer($name = 'default', $message = '') {
|
||||||
|
$now = getMicrotime();
|
||||||
|
$_this = DebugKitDebugger::getInstance();
|
||||||
|
$_this->__benchmarks[$name] = array(
|
||||||
|
'start' => $now,
|
||||||
|
'message' => $message,
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop a benchmarking timer.
|
||||||
|
*
|
||||||
|
* $name should be the same as the $name used in startTimer().
|
||||||
|
*
|
||||||
|
* @param string $name The name of the timer to end.
|
||||||
|
* @access public
|
||||||
|
* @return boolean true if timer was ended, false if timer was not started.
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
function stopTimer($name = 'default') {
|
||||||
|
$now = getMicrotime();
|
||||||
|
$_this = DebugKitDebugger::getInstance();
|
||||||
|
if (!isset($_this->__benchmarks[$name])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$_this->__benchmarks[$name]['end'] = $now;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all timers that have been started and stopped.
|
||||||
|
* Calculates elapsed time for each timer.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
**/
|
||||||
|
function getTimers() {
|
||||||
|
$_this =& DebugKitDebugger::getInstance();
|
||||||
|
$times = array();
|
||||||
|
foreach ($_this->__benchmarks as $name => $timer) {
|
||||||
|
$times[$name]['time'] = DebugKitDebugger::elapsedTime($name);
|
||||||
|
$times[$name]['message'] = $timer['message'];
|
||||||
|
}
|
||||||
|
return $times;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all existing timers
|
||||||
|
*
|
||||||
|
* @return bool true
|
||||||
|
**/
|
||||||
|
function clearTimers() {
|
||||||
|
$_this =& DebugKitDebugger::getInstance();
|
||||||
|
$_this->__benchmarks = array();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the difference in time between the timer start and timer end.
|
||||||
|
*
|
||||||
|
* @param $name string the name of the timer you want elapsed time for.
|
||||||
|
* @param $precision int the number of decimal places to return, defaults to 5.
|
||||||
|
* @return float number of seconds elapsed for timer name, 0 on missing key
|
||||||
|
* @static
|
||||||
|
**/
|
||||||
|
function elapsedTime($name = 'default', $precision = 5) {
|
||||||
|
$_this =& DebugKitDebugger::getInstance();
|
||||||
|
if (!isset($_this->__benchmarks[$name]['start']) || !isset($_this->__benchmarks[$name]['end'])) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return round($_this->__benchmarks[$name]['end'] - $_this->__benchmarks[$name]['start'], $precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the total execution time until this point
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return float elapsed time in seconds since script start.
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
function requestTime() {
|
||||||
|
$start = DebugKitDebugger::requestStartTime();
|
||||||
|
$now = getMicroTime();
|
||||||
|
return ($now - $start);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* get the time the current request started.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return float time of request start
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
function requestStartTime() {
|
||||||
|
if (defined('TIME_START')) {
|
||||||
|
$startTime = TIME_START;
|
||||||
|
} else if (isset($_GLOBALS['TIME_START'])) {
|
||||||
|
$startTime = $_GLOBALS['TIME_START'];
|
||||||
|
} else {
|
||||||
|
$startTime = env('REQUEST_TIME');
|
||||||
|
}
|
||||||
|
return $startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get current memory usage
|
||||||
|
*
|
||||||
|
* @return integer number of bytes ram currently in use. 0 if memory_get_usage() is not available.
|
||||||
|
* @static
|
||||||
|
**/
|
||||||
|
function getMemoryUse() {
|
||||||
|
if (!function_exists('memory_get_usage')) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return memory_get_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get peak memory use
|
||||||
|
*
|
||||||
|
* @return integer peak memory use (in bytes). Returns 0 if memory_get_peak_usage() is not available
|
||||||
|
* @static
|
||||||
|
**/
|
||||||
|
function getPeakMemoryUse() {
|
||||||
|
if (!function_exists('memory_get_peak_usage')) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return memory_get_peak_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles object conversion to debug string.
|
||||||
|
*
|
||||||
|
* @param string $var Object to convert
|
||||||
|
* @access protected
|
||||||
|
*/
|
||||||
|
function _output($level, $error, $code, $helpCode, $description, $file, $line, $kontext) {
|
||||||
|
$files = $this->trace(array('start' => 2, 'format' => 'points'));
|
||||||
|
$listing = $this->excerpt($files[0]['file'], $files[0]['line'] - 1, 1);
|
||||||
|
$trace = $this->trace(array('start' => 2, 'depth' => '20'));
|
||||||
|
$context = array();
|
||||||
|
|
||||||
|
foreach ((array)$kontext as $var => $value) {
|
||||||
|
$context[] = "\${$var}\t=\t" . $this->exportVar($value, 1);
|
||||||
|
}
|
||||||
|
if ($this->_outputFormat == 'fb') {
|
||||||
|
$this->_fireError($error, $code, $description, $file, $line, $trace, $context);
|
||||||
|
} else {
|
||||||
|
echo parent::_output($level, $error, $code, $helpCode, $description, $file, $line, $kontext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create a FirePHP error message
|
||||||
|
*
|
||||||
|
* @param string $error Name of error
|
||||||
|
* @param string $code Code of error
|
||||||
|
* @param string $description Description of error
|
||||||
|
* @param string $file File error occured in
|
||||||
|
* @param string $line Line error occured on
|
||||||
|
* @param string $trace Stack trace at time of error
|
||||||
|
* @param string $context context of error
|
||||||
|
* @return void
|
||||||
|
* @access protected
|
||||||
|
*/
|
||||||
|
function _fireError($error, $code, $description, $file, $line, $trace, $context) {
|
||||||
|
$name = $error . ' - ' . $description;
|
||||||
|
$message = "$error $code $description on line: $line in file: $file";
|
||||||
|
FireCake::group($name);
|
||||||
|
FireCake::error($message, $name);
|
||||||
|
FireCake::log($context, 'Context');
|
||||||
|
FireCake::log($trace, 'Trace');
|
||||||
|
FireCake::groupEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Debugger::invoke(DebugKitDebugger::getInstance());
|
||||||
|
Debugger::getInstance('DebugKitDebugger');
|
||||||
|
?>
|
||||||
539
plugins/debug_kit/vendors/fire_cake.php
vendored
Normal file
539
plugins/debug_kit/vendors/fire_cake.php
vendored
Normal file
@@ -0,0 +1,539 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* FirePHP Class for CakePHP
|
||||||
|
*
|
||||||
|
* Provides most of the functionality offered by FirePHPCore
|
||||||
|
* Interoperates with FirePHP extension for firefox
|
||||||
|
*
|
||||||
|
* For more information see: http://www.firephp.org/
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package debug_kit.
|
||||||
|
* @subpackage debug_kit.vendors
|
||||||
|
* @since
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
App::import('Core', 'Debugger');
|
||||||
|
|
||||||
|
class FireCake extends Object {
|
||||||
|
/**
|
||||||
|
* Options for FireCake.
|
||||||
|
*
|
||||||
|
* @see _defaultOptions and setOptions();
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $options = array();
|
||||||
|
/**
|
||||||
|
* Default Options used in CakeFirePhp
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @access protected
|
||||||
|
*/
|
||||||
|
var $_defaultOptions = array(
|
||||||
|
'maxObjectDepth' => 10,
|
||||||
|
'maxArrayDepth' => 20,
|
||||||
|
'useNativeJsonEncode' => true,
|
||||||
|
'includeLineNumbers' => true,
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* Message Levels for messages sent via FirePHP
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
var $_levels = array(
|
||||||
|
'log' => 'LOG',
|
||||||
|
'info' => 'INFO',
|
||||||
|
'warn' => 'WARN',
|
||||||
|
'error' => 'ERROR',
|
||||||
|
'dump' => 'DUMP',
|
||||||
|
'trace' => 'TRACE',
|
||||||
|
'exception' => 'EXCEPTION',
|
||||||
|
'table' => 'TABLE',
|
||||||
|
'groupStart' => 'GROUP_START',
|
||||||
|
'groupEnd' => 'GROUP_END',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $_version = '0.2.1';
|
||||||
|
/**
|
||||||
|
* internal messageIndex counter
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @access protected
|
||||||
|
*/
|
||||||
|
var $_messageIndex = 1;
|
||||||
|
/**
|
||||||
|
* stack of objects encoded by stringEncode()
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
**/
|
||||||
|
var $_encodedObjects = array();
|
||||||
|
/**
|
||||||
|
* methodIndex to include in tracebacks when using includeLineNumbers
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
**/
|
||||||
|
var $_methodIndex = array('info', 'log', 'warn', 'error', 'table', 'trace');
|
||||||
|
/**
|
||||||
|
* FireCake output status
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
**/
|
||||||
|
var $_enabled = true;
|
||||||
|
/**
|
||||||
|
* get Instance of the singleton
|
||||||
|
*
|
||||||
|
* @param string $class Class instance to store in the singleton. Used with subclasses and Tests.
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function &getInstance($class = null) {
|
||||||
|
static $instance = array();
|
||||||
|
if (!empty($class)) {
|
||||||
|
if (!$instance || strtolower($class) != strtolower(get_class($instance[0]))) {
|
||||||
|
$instance[0] = new $class();
|
||||||
|
$instance[0]->setOptions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isset($instance[0]) || !$instance[0]) {
|
||||||
|
$instance[0] = new FireCake();
|
||||||
|
$instance[0]->setOptions();
|
||||||
|
}
|
||||||
|
return $instance[0];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* setOptions
|
||||||
|
*
|
||||||
|
* @param array $options Array of options to set.
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setOptions($options = array()) {
|
||||||
|
$_this = FireCake::getInstance();
|
||||||
|
if (empty($_this->options)) {
|
||||||
|
$_this->options = array_merge($_this->_defaultOptions, $options);
|
||||||
|
} else {
|
||||||
|
$_this->options = array_merge($_this->options, $options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Return boolean based on presence of FirePHP extension
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return boolean
|
||||||
|
**/
|
||||||
|
function detectClientExtension() {
|
||||||
|
$ua = FireCake::getUserAgent();
|
||||||
|
if (!preg_match('/\sFirePHP\/([\.|\d]*)\s?/si', $ua, $match) || !version_compare($match[1], '0.0.6', '>=')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get the Current UserAgent
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
* @return string UserAgent string of active client connection
|
||||||
|
**/
|
||||||
|
function getUserAgent() {
|
||||||
|
return env('HTTP_USER_AGENT');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Disable FireCake output
|
||||||
|
* All subsequent output calls will not be run.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function disable() {
|
||||||
|
$_this = FireCake::getInstance();
|
||||||
|
$_this->_enabled = false;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Enable FireCake output
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function enable() {
|
||||||
|
$_this = FireCake::getInstance();
|
||||||
|
$_this->_enabled = true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convenience wrapper for LOG messages
|
||||||
|
*
|
||||||
|
* @param string $message Message to log
|
||||||
|
* @param string $label Label for message (optional)
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function log($message, $label = null) {
|
||||||
|
FireCake::fb($message, $label, 'log');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convenience wrapper for WARN messages
|
||||||
|
*
|
||||||
|
* @param string $message Message to log
|
||||||
|
* @param string $label Label for message (optional)
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function warn($message, $label = null) {
|
||||||
|
FireCake::fb($message, $label, 'warn');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convenience wrapper for INFO messages
|
||||||
|
*
|
||||||
|
* @param string $message Message to log
|
||||||
|
* @param string $label Label for message (optional)
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function info($message, $label = null) {
|
||||||
|
FireCake::fb($message, $label, 'info');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convenience wrapper for ERROR messages
|
||||||
|
*
|
||||||
|
* @param string $message Message to log
|
||||||
|
* @param string $label Label for message (optional)
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function error($message, $label = null) {
|
||||||
|
FireCake::fb($message, $label, 'error');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convenience wrapper for TABLE messages
|
||||||
|
*
|
||||||
|
* @param string $message Message to log
|
||||||
|
* @param string $label Label for message (optional)
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function table($label, $message) {
|
||||||
|
FireCake::fb($message, $label, 'table');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convenience wrapper for DUMP messages
|
||||||
|
*
|
||||||
|
* @param string $message Message to log
|
||||||
|
* @param string $label Unique label for message
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function dump($label, $message) {
|
||||||
|
FireCake::fb($message, $label, 'dump');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convenience wrapper for TRACE messages
|
||||||
|
*
|
||||||
|
* @param string $label Label for message (optional)
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function trace($label) {
|
||||||
|
FireCake::fb($label, 'trace');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convenience wrapper for GROUP messages
|
||||||
|
* Messages following the group call will be nested in a group block
|
||||||
|
*
|
||||||
|
* @param string $label Label for group (optional)
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function group($label) {
|
||||||
|
FireCake::fb(null, $label, 'groupStart');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convenience wrapper for GROUPEND messages
|
||||||
|
* Closes a group block
|
||||||
|
*
|
||||||
|
* @param string $label Label for group (optional)
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function groupEnd() {
|
||||||
|
FireCake::fb(null, null, 'groupEnd');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* fb - Send messages with FireCake to FirePHP
|
||||||
|
*
|
||||||
|
* Much like FirePHP's fb() this method can be called with various parameter counts
|
||||||
|
* fb($message) - Just send a message defaults to LOG type
|
||||||
|
* fb($message, $type) - Send a message with a specific type
|
||||||
|
* fb($message, $label, $type) - Send a message with a custom label and type.
|
||||||
|
*
|
||||||
|
* @param mixed $message Message to output. For other parameters see usage above.
|
||||||
|
* @static
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function fb($message) {
|
||||||
|
$_this = FireCake::getInstance();
|
||||||
|
|
||||||
|
if (headers_sent($filename, $linenum)) {
|
||||||
|
trigger_error(sprintf(__('Headers already sent in %s on line %s. Cannot send log data to FirePHP.', true), $filename, $linenum), E_USER_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!$_this->_enabled || !$_this->detectClientExtension()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$args = func_get_args();
|
||||||
|
$type = $label = null;
|
||||||
|
switch (count($args)) {
|
||||||
|
case 1:
|
||||||
|
$type = $_this->_levels['log'];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
$type = $args[1];
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
$type = $args[2];
|
||||||
|
$label = $args[1];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
trigger_error(__('Incorrect parameter count for FireCake::fb()', true), E_USER_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isset($_this->_levels[$type])) {
|
||||||
|
$type = $_this->_levels[$type];
|
||||||
|
} else {
|
||||||
|
$type = $_this->_levels['log'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$meta = array();
|
||||||
|
$skipFinalObjectEncode = false;
|
||||||
|
if ($type == $_this->_levels['trace']) {
|
||||||
|
$trace = debug_backtrace();
|
||||||
|
if (!$trace) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$message = $_this->_parseTrace($trace, $args[0]);
|
||||||
|
$skipFinalObjectEncode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_this->options['includeLineNumbers']) {
|
||||||
|
if (!isset($meta['file']) || !isset($meta['line'])) {
|
||||||
|
$trace = debug_backtrace();
|
||||||
|
for ($i = 0, $len = count($trace); $i < $len ; $i++) {
|
||||||
|
$keySet = (isset($trace[$i]['class']) && isset($trace[$i]['function']));
|
||||||
|
$selfCall = ($keySet && $trace[$i]['class'] == 'FireCake' && in_array($trace[$i]['function'], $_this->_methodIndex));
|
||||||
|
if ($selfCall) {
|
||||||
|
$meta['File'] = isset($trace[$i]['file']) ? Debugger::trimPath($trace[$i]['file']) : '';
|
||||||
|
$meta['Line'] = isset($trace[$i]['line']) ? $trace[$i]['line'] : '';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$structureIndex = 1;
|
||||||
|
if ($type == $_this->_levels['dump']) {
|
||||||
|
$structureIndex = 2;
|
||||||
|
$_this->_sendHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');
|
||||||
|
} else {
|
||||||
|
$_this->_sendHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
|
||||||
|
}
|
||||||
|
|
||||||
|
$_this->_sendHeader('X-Wf-Protocol-1', 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
|
||||||
|
$_this->_sendHeader('X-Wf-1-Plugin-1', 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'. $_this->_version);
|
||||||
|
|
||||||
|
if ($type == $_this->_levels['dump']) {
|
||||||
|
$dump = $_this->jsonEncode($message);
|
||||||
|
$msg = '{"' . $label .'":' . $dump .'}';
|
||||||
|
} else {
|
||||||
|
$meta['Type'] = $type;
|
||||||
|
if ($label !== null) {
|
||||||
|
$meta['Label'] = $label;
|
||||||
|
}
|
||||||
|
$msg = '[' . $_this->jsonEncode($meta) . ',' . $_this->jsonEncode($message, $skipFinalObjectEncode).']';
|
||||||
|
}
|
||||||
|
|
||||||
|
$lines = explode("\n", chunk_split($msg, 5000, "\n"));
|
||||||
|
foreach ($lines as $i => $line) {
|
||||||
|
if (empty($line)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$header = 'X-Wf-1-' . $structureIndex . '-1-' . $_this->_messageIndex;
|
||||||
|
if (count($lines) > 2) {
|
||||||
|
$first = ($i == 0) ? strlen($msg) : '';
|
||||||
|
$end = ($i < count($lines) - 2) ? '\\' : '';
|
||||||
|
$message = $first . '|' . $line . '|' . $end;
|
||||||
|
$_this->_sendHeader($header, $message);
|
||||||
|
} else {
|
||||||
|
$_this->_sendHeader($header, strlen($line) . '|' . $line . '|');
|
||||||
|
}
|
||||||
|
$_this->_messageIndex++;
|
||||||
|
if ($_this->_messageIndex > 99999) {
|
||||||
|
trigger_error(__('Maximum number (99,999) of messages reached!', true), E_USER_WARNING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$_this->_sendHeader('X-Wf-1-Index', $_this->_messageIndex - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse a debug backtrace
|
||||||
|
*
|
||||||
|
* @param array $trace Debug backtrace output
|
||||||
|
* @access protected
|
||||||
|
* @return array
|
||||||
|
**/
|
||||||
|
function _parseTrace($trace, $messageName) {
|
||||||
|
$message = array();
|
||||||
|
for ($i = 0, $len = count($trace); $i < $len ; $i++) {
|
||||||
|
$keySet = (isset($trace[$i]['class']) && isset($trace[$i]['function']));
|
||||||
|
$selfCall = ($keySet && $trace[$i]['class'] == 'FireCake');
|
||||||
|
if (!$selfCall) {
|
||||||
|
$message = array(
|
||||||
|
'Class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : '',
|
||||||
|
'Type' => isset($trace[$i]['type']) ? $trace[$i]['type'] : '',
|
||||||
|
'Function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : '',
|
||||||
|
'Message' => $messageName,
|
||||||
|
'File' => isset($trace[$i]['file']) ? Debugger::trimPath($trace[$i]['file']) : '',
|
||||||
|
'Line' => isset($trace[$i]['line']) ? $trace[$i]['line'] : '',
|
||||||
|
'Args' => isset($trace[$i]['args']) ? $this->stringEncode($trace[$i]['args']) : '',
|
||||||
|
'Trace' => $this->_escapeTrace(array_splice($trace, $i + 1))
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Fix a trace for use in output
|
||||||
|
*
|
||||||
|
* @param mixed $trace Trace to fix
|
||||||
|
* @access protected
|
||||||
|
* @static
|
||||||
|
* @return string
|
||||||
|
**/
|
||||||
|
function _escapeTrace($trace) {
|
||||||
|
for ($i = 0, $len = count($trace); $i < $len; $i++) {
|
||||||
|
if (isset($trace[$i]['file'])) {
|
||||||
|
$trace[$i]['file'] = Debugger::trimPath($trace[$i]['file']);
|
||||||
|
}
|
||||||
|
if (isset($trace[$i]['args'])) {
|
||||||
|
$trace[$i]['args'] = $this->stringEncode($trace[$i]['args']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $trace;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Encode non string objects to string.
|
||||||
|
* Filter out recursion, so no errors are raised by json_encode or $javascript->object()
|
||||||
|
*
|
||||||
|
* @param mixed $object Object or variable to encode to string.
|
||||||
|
* @param int $objectDepth Current Depth in object chains.
|
||||||
|
* @param int $arrayDepth Current Depth in array chains.
|
||||||
|
* @static
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function stringEncode($object, $objectDepth = 1, $arrayDepth = 1) {
|
||||||
|
$_this = FireCake::getInstance();
|
||||||
|
$return = array();
|
||||||
|
if (is_resource($object)) {
|
||||||
|
return '** ' . (string)$object . '**';
|
||||||
|
}
|
||||||
|
if (is_object($object)) {
|
||||||
|
if ($objectDepth == $_this->options['maxObjectDepth']) {
|
||||||
|
return '** Max Object Depth (' . $_this->options['maxObjectDepth'] . ') **';
|
||||||
|
}
|
||||||
|
foreach ($_this->_encodedObjects as $encoded) {
|
||||||
|
if ($encoded === $object) {
|
||||||
|
return '** Recursion (' . get_class($object) . ') **';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$_this->_encodedObjects[] = $object;
|
||||||
|
|
||||||
|
$return['__className'] = $class = get_class($object);
|
||||||
|
$properties = (array) $object;
|
||||||
|
foreach ($properties as $name => $property) {
|
||||||
|
$return[$name] = FireCake::stringEncode($property, 1, $objectDepth + 1);
|
||||||
|
}
|
||||||
|
array_pop($_this->_encodedObjects);
|
||||||
|
}
|
||||||
|
if (is_array($object)) {
|
||||||
|
if ($arrayDepth == $_this->options['maxArrayDepth']) {
|
||||||
|
return '** Max Array Depth ('. $_this->options['maxArrayDepth'] . ') **';
|
||||||
|
}
|
||||||
|
foreach ($object as $key => $value) {
|
||||||
|
$return[$key] = FireCake::stringEncode($value, 1, $arrayDepth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_string($object) || is_numeric($object) || is_bool($object) || is_null($object)) {
|
||||||
|
return $object;
|
||||||
|
}
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Encode an object into JSON
|
||||||
|
*
|
||||||
|
* @param mixed $object Object or array to json encode
|
||||||
|
* @param boolean $doIt
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
* @return string
|
||||||
|
**/
|
||||||
|
function jsonEncode($object, $skipEncode = false) {
|
||||||
|
$_this = FireCake::getInstance();
|
||||||
|
if (!$skipEncode) {
|
||||||
|
$object = FireCake::stringEncode($object);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (function_exists('json_encode') && $_this->options['useNativeJsonEncode']) {
|
||||||
|
return json_encode($object);
|
||||||
|
} else {
|
||||||
|
return FireCake::_jsonEncode($object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* jsonEncode Helper method for PHP4 compatibility
|
||||||
|
*
|
||||||
|
* @param mixed $object Something to encode
|
||||||
|
* @access protected
|
||||||
|
* @static
|
||||||
|
* @return string
|
||||||
|
**/
|
||||||
|
function _jsonEncode($object) {
|
||||||
|
if (!class_exists('JavascriptHelper')) {
|
||||||
|
App::import('Helper', 'Javascript');
|
||||||
|
}
|
||||||
|
$javascript = new JavascriptHelper();
|
||||||
|
$javascript->useNative = false;
|
||||||
|
return $javascript->object($object);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Send Headers - write headers.
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function _sendHeader($name, $value) {
|
||||||
|
header($name . ': ' . $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
BIN
plugins/debug_kit/vendors/img/cake.icon.png
vendored
Normal file
BIN
plugins/debug_kit/vendors/img/cake.icon.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
84
plugins/debug_kit/vendors/js/jquery_debug_toolbar.js
vendored
Normal file
84
plugins/debug_kit/vendors/js/jquery_debug_toolbar.js
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Debug Toolbar Javascript. jQuery 1.2.x compatible.
|
||||||
|
*
|
||||||
|
* Long description here.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function($) {
|
||||||
|
$(document).ready(function(){
|
||||||
|
DebugKit.Toolbar();
|
||||||
|
DebugKit.NeatArray();
|
||||||
|
});
|
||||||
|
|
||||||
|
var DebugKit = {};
|
||||||
|
/**
|
||||||
|
* Create all behaviors for neat array elements
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
DebugKit.NeatArray = function() {
|
||||||
|
$('.neat-array').find('li:has(ul)').toggle(
|
||||||
|
function() {
|
||||||
|
$(this).toggleClass('expanded').removeClass('collapsed').find('ul:first').show();
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
$(this).toggleClass('expanded').addClass('collapsed').find('ul:first').hide();
|
||||||
|
}
|
||||||
|
).addClass('expandable').addClass('collapsed').find('ul').hide();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add behavior for toolbar buttons
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
DebugKit.Toolbar = function() {
|
||||||
|
var tabCollection = $('#debug-kit-toolbar li > div');
|
||||||
|
|
||||||
|
$('#debug-kit-toolbar .panel-tab > a').click(
|
||||||
|
function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
var targetPanel = $(this.hash + '-tab');
|
||||||
|
if (targetPanel.hasClass('active')) {
|
||||||
|
tabCollection.hide().removeClass('active');
|
||||||
|
} else {
|
||||||
|
tabCollection
|
||||||
|
.hide().removeClass('active')
|
||||||
|
.filter(this.hash + '-tab').show().addClass('active');
|
||||||
|
}
|
||||||
|
$('#debug-kit-toolbar .panel-tab > a').removeClass('active');
|
||||||
|
$(this).addClass('active');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
//enable hiding of toolbar.
|
||||||
|
var panelButtons = $('#debug-kit-toolbar .panel-tab:not(.panel-tab.icon)');
|
||||||
|
$('#debug-kit-toolbar #hide-toolbar').toggle(
|
||||||
|
function() {
|
||||||
|
panelButtons.hide();
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
panelButtons.show();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})(jQuery);
|
||||||
212
plugins/debug_kit/vendors/js/js_debug_toolbar.js
vendored
Normal file
212
plugins/debug_kit/vendors/js/js_debug_toolbar.js
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Debug Toolbar Javascript.
|
||||||
|
*
|
||||||
|
* Long description here.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
var DebugKit = function(id) {
|
||||||
|
var undefined,
|
||||||
|
elements = {},
|
||||||
|
panels = {},
|
||||||
|
hidden = false;
|
||||||
|
|
||||||
|
this.initialize = function(id) {
|
||||||
|
elements.toolbar = document.getElementById(id || 'debug-kit-toolbar');
|
||||||
|
|
||||||
|
if (elements.toolbar === undefined) {
|
||||||
|
throw new Exception('Toolbar not found, make sure you loaded it.');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i in elements.toolbar.childNodes) {
|
||||||
|
var element = elements.toolbar.childNodes[i];
|
||||||
|
if (element.nodeName && element.id === 'panel-tabs') {
|
||||||
|
elements.panel = element;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i in elements.panel.childNodes) {
|
||||||
|
var element = elements.panel.childNodes[i];
|
||||||
|
if (element.className && element.className.match(/panel-tab/)) {
|
||||||
|
this.addPanel(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var lists = document.getElementsByTagName('ul'), index = 0;
|
||||||
|
while (lists[index] !== undefined) {
|
||||||
|
var element = lists[index];
|
||||||
|
if (element.className && element.className.match(/neat-array/)) {
|
||||||
|
neatArray(element);
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add a panel to the toolbar
|
||||||
|
*/
|
||||||
|
this.addPanel = function(tab, callback) {
|
||||||
|
if (!tab.nodeName || tab.nodeName.toUpperCase() !== 'LI') {
|
||||||
|
throw new Exception('Toolbar not found, make sure you loaded it.');
|
||||||
|
}
|
||||||
|
var panel = {
|
||||||
|
id : false,
|
||||||
|
element : tab,
|
||||||
|
callback : callback,
|
||||||
|
button : undefined,
|
||||||
|
content : undefined,
|
||||||
|
active : false
|
||||||
|
};
|
||||||
|
for (var i in tab.childNodes) {
|
||||||
|
var element = tab.childNodes[i],
|
||||||
|
tag = element.nodeName? element.nodeName.toUpperCase(): false;
|
||||||
|
if (tag === 'A') {
|
||||||
|
panel.id = element.hash.replace(/^#/, '');
|
||||||
|
panel.button = element;
|
||||||
|
} else if (tag === 'DIV') {
|
||||||
|
panel.content = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!panel.id) {
|
||||||
|
throw new Exception('invalid element');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (panel.button.id && panel.button.id === 'hide-toolbar') {
|
||||||
|
panel.callback = this.toggleToolbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (panel.callback !== undefined) {
|
||||||
|
panel.button.onclick = function() { return panel.callback(); };
|
||||||
|
} else {
|
||||||
|
panel.button.onclick = function() { return window.DebugKit.togglePanel(panel.id); };
|
||||||
|
}
|
||||||
|
|
||||||
|
panels[panel.id] = panel;
|
||||||
|
return panel.id;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Hide/show the toolbar (minimize cake)
|
||||||
|
*/
|
||||||
|
this.toggleToolbar = function() {
|
||||||
|
for (var i in panels) {
|
||||||
|
var panel = panels[i],
|
||||||
|
display = hidden? 'block': 'none';
|
||||||
|
if (panel.content !== undefined) {
|
||||||
|
panel.element.style.display = display;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hidden = !hidden;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Toggle a panel
|
||||||
|
*/
|
||||||
|
this.togglePanel = function(id) {
|
||||||
|
if (panels[id] && panels[id].active) {
|
||||||
|
this.deactivatePanel(true);
|
||||||
|
} else {
|
||||||
|
this.deactivatePanel(true);
|
||||||
|
this.activatePanel(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Make a panel active.
|
||||||
|
*/
|
||||||
|
this.activatePanel = function(id, unique) {
|
||||||
|
if (panels[id] !== undefined && !panels[id].active) {
|
||||||
|
var panel = panels[id];
|
||||||
|
this.deactivatePanel(true);
|
||||||
|
if (panel.content !== undefined) {
|
||||||
|
panel.content.style.display = 'block';
|
||||||
|
}
|
||||||
|
panel.button.className = panel.button.className.replace(/^(.*)$/, '$1 active');
|
||||||
|
panel.active = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Deactivate a panel. use true to hide all panels.
|
||||||
|
*/
|
||||||
|
this.deactivatePanel = function(id) {
|
||||||
|
if (id === true) {
|
||||||
|
for (var i in panels) {
|
||||||
|
this.deactivatePanel(i);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (panels[id] !== undefined && panels[id].active) {
|
||||||
|
var panel = panels[id];
|
||||||
|
if (panel.content !== undefined) {
|
||||||
|
panel.content.style.display = 'none';
|
||||||
|
}
|
||||||
|
panel.button.className = panel.button.className.replace(/ ?(active) ?/, '');
|
||||||
|
panel.active = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Add neat array functionality.
|
||||||
|
*/
|
||||||
|
function neatArray(list) {
|
||||||
|
if (!list.className.match(/depth-0/)) {
|
||||||
|
var item = list.parentNode;
|
||||||
|
list.style.display = 'none';
|
||||||
|
item.className = (item.className || '').replace(/^(.*)$/, '$1 expandable collapsed');
|
||||||
|
item.onclick = function(event) {
|
||||||
|
//var element = (event === undefined)? this: event.target;
|
||||||
|
var element = this,
|
||||||
|
event = event || window.event,
|
||||||
|
act = Boolean(item === element),
|
||||||
|
hide = Boolean(list.style.display === 'block');
|
||||||
|
if (act && hide) {
|
||||||
|
list.style.display = 'none';
|
||||||
|
item.className = item.className.replace(/expanded|$/, 'collapsed');
|
||||||
|
} else if (act) {
|
||||||
|
list.style.display = 'block';
|
||||||
|
item.className = item.className.replace('collapsed', 'expanded');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.cancelBubble !== undefined) {
|
||||||
|
event.cancelBubble = true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialize(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugKit.install = function() {
|
||||||
|
var initializer = window.onload || function() {};
|
||||||
|
window.onload = function() {
|
||||||
|
initializer();
|
||||||
|
// makes DebugKit a singletone instance
|
||||||
|
window.DebugKit = new DebugKit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugKit.install();
|
||||||
95
plugins/debug_kit/vendors/js/mootools_debug_toolbar.js
vendored
Normal file
95
plugins/debug_kit/vendors/js/mootools_debug_toolbar.js
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Debug Toolbar Javascript. Mootools 1.2 compatible.
|
||||||
|
*
|
||||||
|
* Requires Class, Event, Element, and Selectors
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
window.addEvent('domready', function() {
|
||||||
|
new DebugKit();
|
||||||
|
});
|
||||||
|
var DebugKit = new Class({
|
||||||
|
initialize : function() {
|
||||||
|
this.neatArray();
|
||||||
|
this.toolbar();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Create all behaviors for neat array elements
|
||||||
|
*/
|
||||||
|
neatArray : function() {
|
||||||
|
$$('#debug-kit-toolbar .neat-array li').each(function(listItem) {
|
||||||
|
var subUl = listItem.getElement('ul');
|
||||||
|
if (subUl) {
|
||||||
|
listItem.addClass('expandable').addClass('collapsed');
|
||||||
|
subUl.setStyle('display', 'none').set('state', 'closed');
|
||||||
|
listItem.addEvent('click', function(event) {
|
||||||
|
event.stop();
|
||||||
|
this.toggleClass('expanded').toggleClass('collapsed');
|
||||||
|
if (subUl.get('state') == 'closed') {
|
||||||
|
subUl.setStyle('display', 'block').set('state', 'open');
|
||||||
|
} else {
|
||||||
|
subUl.setStyle('display', 'none').set('state', 'closed');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add behavior for toolbar buttons
|
||||||
|
*/
|
||||||
|
toolbar : function() {
|
||||||
|
var tabCollection = $$('#debug-kit-toolbar li > div');
|
||||||
|
|
||||||
|
$$('#debug-kit-toolbar .panel-tab > a').addEvent('click', function(event) {
|
||||||
|
event.stop();
|
||||||
|
var buttonId = this.hash.substring(1, this.hash.length) + '-tab';
|
||||||
|
var targetPanel = $(buttonId);
|
||||||
|
if (!targetPanel) return;
|
||||||
|
$$('#debug-kit-toolbar .panel-tab > a').removeClass('active');
|
||||||
|
if (targetPanel.hasClass('active')) {
|
||||||
|
tabCollection.removeClass('active').setStyle('display', 'none');
|
||||||
|
} else {
|
||||||
|
tabCollection.setStyle('display', 'none').removeClass('active');
|
||||||
|
targetPanel.addClass('active').setStyle('display', 'block');
|
||||||
|
this.addClass('active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//enable hiding of toolbar.
|
||||||
|
var panelButtons = $$('#debug-kit-toolbar .panel-tab:not(.panel-tab.icon)');
|
||||||
|
var toolbarHide = $('hide-toolbar').set('state', 'open');
|
||||||
|
toolbarHide.addEvent('click', function(event) {
|
||||||
|
event.stop();
|
||||||
|
var state = this.get('state');
|
||||||
|
if (state == 'open') {
|
||||||
|
panelButtons.setStyle('display', 'none');
|
||||||
|
this.set('state', 'closed')
|
||||||
|
} else {
|
||||||
|
panelButtons.setStyle('display');
|
||||||
|
this.set('state', 'open');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
95
plugins/debug_kit/vendors/js/prototype_debug_toolbar.js
vendored
Normal file
95
plugins/debug_kit/vendors/js/prototype_debug_toolbar.js
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Debug Toolbar Javascript. Prototype 1.6.x compatible.
|
||||||
|
*
|
||||||
|
* Long description here.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
document.observe('dom:loaded', function() {
|
||||||
|
new DebugKit();
|
||||||
|
});
|
||||||
|
|
||||||
|
var DebugKit = Class.create({
|
||||||
|
|
||||||
|
initialize: function(){
|
||||||
|
this.toolbar();
|
||||||
|
this.neatArray();
|
||||||
|
},
|
||||||
|
|
||||||
|
toolbar: function(){
|
||||||
|
var tabCollection = $('debug-kit-toolbar').select('li > div');
|
||||||
|
|
||||||
|
$('debug-kit-toolbar').select('.panel-tab > a').invoke('observe', 'click', function(e){
|
||||||
|
e.stop();
|
||||||
|
var targetPanel = $(e.element().hash.replace(/#/, '') + '-tab');
|
||||||
|
if (targetPanel.hasClassName('active')) {
|
||||||
|
tabCollection.each(function(ele){
|
||||||
|
ele.hide().removeClassName('active');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
tabCollection.each(function(ele){
|
||||||
|
ele.hide().removeClassName('active');
|
||||||
|
if (targetPanel.id == ele.id) {
|
||||||
|
ele.setStyle({display: 'block'}).addClassName('active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$('debug-kit-toolbar').select('.panel-tab > a').invoke('removeClassName', 'active');
|
||||||
|
e.element().addClassName('active');
|
||||||
|
});
|
||||||
|
|
||||||
|
// enable hiding of toolbar.
|
||||||
|
var panelButtons = $('debug-kit-toolbar').select('.panel-tab');
|
||||||
|
$('hide-toolbar').observe('click', function(eve){
|
||||||
|
eve.stop();
|
||||||
|
panelButtons.each(function(panel){
|
||||||
|
if (!panel.hasClassName('icon')) {
|
||||||
|
panel.toggle();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create all behaviors for neat array elements
|
||||||
|
*/
|
||||||
|
neatArray: function() {
|
||||||
|
$('debug-kit-toolbar').select('.neat-array li').each(function(ele){
|
||||||
|
var sub = ele.select('ul');
|
||||||
|
if (sub.length > 0) {
|
||||||
|
ele.addClassName('collapsed').addClassName('expandable');
|
||||||
|
sub.invoke('hide');
|
||||||
|
ele.observe('click', function(eve){
|
||||||
|
if (eve.element() == ele || eve.element().up() == ele) {
|
||||||
|
if (sub.length > 0) {
|
||||||
|
ele.toggleClassName('expanded').toggleClassName('collapsed');
|
||||||
|
sub[0].toggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
126
plugins/debug_kit/vendors/js/yui_debug_toolbar.js
vendored
Normal file
126
plugins/debug_kit/vendors/js/yui_debug_toolbar.js
vendored
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Debug Toolbar Javascript. YUI 2.6 compatible.
|
||||||
|
*
|
||||||
|
* Long description here.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
YAHOO.namespace('CakePHP.DebugKit');
|
||||||
|
|
||||||
|
YAHOO.CakePHP.DebugKit = function() {
|
||||||
|
|
||||||
|
var Event = YAHOO.util.Event;
|
||||||
|
var Dom = YAHOO.util.Dom;
|
||||||
|
var Selector = YAHOO.util.Selector;
|
||||||
|
|
||||||
|
|
||||||
|
var toggle = function(el) {
|
||||||
|
Dom.setStyle(el, 'display', ((Dom.getStyle(el, 'display') == 'none') ? '' : 'none'));
|
||||||
|
};
|
||||||
|
|
||||||
|
var toggleClass = function(element, className) {
|
||||||
|
(Dom.hasClass(element, className)) ? Dom.removeClass(element, className) : Dom.addClass(element, className);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var toolbar = function() {
|
||||||
|
var tabCollection = Selector.query('#debug-kit-toolbar li > div');
|
||||||
|
|
||||||
|
Dom.batch(Selector.query('#debug-kit-toolbar .panel-tab > a'), function(el) {
|
||||||
|
Event.on(el, 'click', function(ev) {
|
||||||
|
Event.preventDefault(ev);
|
||||||
|
targetPanel =Dom.get(el.hash.replace(/#/, '') + '-tab');
|
||||||
|
|
||||||
|
if (Dom.hasClass(targetPanel, 'active')) {
|
||||||
|
Dom.batch(tabCollection, function(ele) {
|
||||||
|
toggle(ele);
|
||||||
|
Dom.removeClass(ele, 'active');
|
||||||
|
Dom.setStyle(ele, 'display', '');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Dom.batch(tabCollection, function(ele) {
|
||||||
|
toggle(ele);
|
||||||
|
Dom.removeClass(ele, 'active');
|
||||||
|
|
||||||
|
if (targetPanel && targetPanel.id == ele.id) {
|
||||||
|
Dom.setStyle(ele, 'display', 'block');
|
||||||
|
Dom.addClass(ele, 'active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Dom.removeClass(Selector.query('#debug-kit-toolbar .panel-tab > a'), 'active');
|
||||||
|
Dom.addClass(el, 'active');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var neatArray = function() {
|
||||||
|
nodes = Selector.query('#debug-kit-toolbar .panel-content > ul.neat-array li > ul');
|
||||||
|
|
||||||
|
if (nodes.length > 0) {
|
||||||
|
Dom.batch(nodes, function(el) {
|
||||||
|
|
||||||
|
var parent = el.parentNode;
|
||||||
|
|
||||||
|
Dom.addClass(parent, 'collapsed');
|
||||||
|
Dom.addClass(parent, 'expandable');
|
||||||
|
toggle(nodes);
|
||||||
|
|
||||||
|
Event.on(parent, 'click', function(ev) {
|
||||||
|
sub = Selector.query('ul', parent);
|
||||||
|
toggleClass(parent, 'expanded');
|
||||||
|
toggleClass(parent, 'collapsed');
|
||||||
|
toggle(sub);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var panelButtons = function() {
|
||||||
|
Event.on('hide-toolbar', 'click', function(ev) {
|
||||||
|
Event.preventDefault(ev);
|
||||||
|
|
||||||
|
Dom.getElementsByClassName('panel-tab', 'li', 'debug-kit-toolbar', function (el) {
|
||||||
|
if (!Dom.hasClass(el, 'icon')) {
|
||||||
|
toggle(el);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
initialize: function() {
|
||||||
|
neatArray();
|
||||||
|
toolbar();
|
||||||
|
panelButtons();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}(); // Execute annonymous closure & return results
|
||||||
|
|
||||||
|
YAHOO.util.Event.onDOMReady(YAHOO.CakePHP.DebugKit.initialize);
|
||||||
79
plugins/debug_kit/vendors/shells/benchmark.php
vendored
Normal file
79
plugins/debug_kit/vendors/shells/benchmark.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Benchmark Shell.
|
||||||
|
*
|
||||||
|
* Provides basic benchmarking of application requests
|
||||||
|
* functionally similar to Apache AB
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.debug_kit.vendors.shells
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
class BenchmarkShell extends Shell {
|
||||||
|
function main() {
|
||||||
|
$url = $this->args[0];
|
||||||
|
$this->out(sprintf('-> Testing %s', $url));
|
||||||
|
|
||||||
|
$n = 100;
|
||||||
|
$t = $i = 0;
|
||||||
|
if (isset($this->params['n'])) {
|
||||||
|
$n = $this->params['n'];
|
||||||
|
}
|
||||||
|
if (isset($this->params['t'])) {
|
||||||
|
$t = $this->params['t'];
|
||||||
|
}
|
||||||
|
$start = microtime(true);
|
||||||
|
while (true) {
|
||||||
|
if ($t && $t <= floor(microtime(true) - $start)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($n <= $i) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
file_get_contents($url);
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
$duration = microtime(true) - $start;
|
||||||
|
$this->out('Total Requests made: ' . $i);
|
||||||
|
$this->out('Total Time elapsed: ' . $duration . '(s)');
|
||||||
|
$this->out(round($n / $duration, 2).' req/sec');
|
||||||
|
}
|
||||||
|
|
||||||
|
function help() {
|
||||||
|
$out = <<<EOL
|
||||||
|
DebugKit Benchmark Shell
|
||||||
|
|
||||||
|
Test a fully qualified url to get avg requests per second.
|
||||||
|
By default it does 100 requests to the provided url.
|
||||||
|
|
||||||
|
Use:
|
||||||
|
cake benchmark [params] [url]
|
||||||
|
|
||||||
|
Params
|
||||||
|
-n The maximum number of iterations to do.
|
||||||
|
|
||||||
|
-t The maximum time to take. If a single request takes more
|
||||||
|
than this time. Only one request will be made.
|
||||||
|
EOL;
|
||||||
|
$this->out($out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
154
plugins/debug_kit/views/debug.php
Normal file
154
plugins/debug_kit/views/debug.php
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Debug View
|
||||||
|
*
|
||||||
|
* Custom Debug View class, helps with development.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.
|
||||||
|
* @since CakePHP v 1.2.0.4487
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
App::import('Vendor', 'DebugKit.DebugKitDebugger');
|
||||||
|
App::import('Component', 'DebugKit.Toolbar');
|
||||||
|
/**
|
||||||
|
* DebugView used by DebugKit
|
||||||
|
*
|
||||||
|
* @package debug_kit.views
|
||||||
|
* @todo Remove workarounds.
|
||||||
|
*/
|
||||||
|
class DebugView extends DoppelGangerView {
|
||||||
|
/**
|
||||||
|
* The old extension of the current template.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $_oldExtension = null;
|
||||||
|
/**
|
||||||
|
* Overload _render to capture filenames and time actual rendering of each view file
|
||||||
|
*
|
||||||
|
* @param string $___viewFn Filename of the view
|
||||||
|
* @param array $___dataForView Data to include in rendered view
|
||||||
|
* @return string Rendered output
|
||||||
|
* @access protected
|
||||||
|
*/
|
||||||
|
function _render($___viewFn, $___dataForView, $loadHelpers = true, $cached = false) {
|
||||||
|
/* pr(array('function' => 'DebugView::_render', */
|
||||||
|
/* 'args' => compact('__viewFn', '__dataForView', 'loadHelpers'), */
|
||||||
|
/* 'this-output-len' => strlen($this->output), */
|
||||||
|
/* )); */
|
||||||
|
if (isset($this->_oldExtension) && strstr($___viewFn, '.debug_view')) {
|
||||||
|
$___viewFn = substr($___viewFn, 0, -10) . $this->_oldExtension;
|
||||||
|
}
|
||||||
|
if (!isset($___dataForView['disableTimer'])) {
|
||||||
|
DebugKitDebugger::startTimer('render_' . basename($___viewFn), sprintf(__('Rendering %s', true), Debugger::trimPath($___viewFn)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$out = parent::_render($___viewFn, $___dataForView, $loadHelpers, $cached);
|
||||||
|
|
||||||
|
if (!isset($___dataForView['disableTimer'])) {
|
||||||
|
DebugKitDebugger::stopTimer('render_' . basename($___viewFn));
|
||||||
|
}
|
||||||
|
/* pr(array('function' => 'DebugView::_render', */
|
||||||
|
/* 'out-len' => strlen($out), */
|
||||||
|
/* 'this-output-len' => strlen($this->output), */
|
||||||
|
/* 'return' => $out ? 'not-empty' : 'empty')); */
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders view for given action and layout. If $file is given, that is used
|
||||||
|
* for a view filename (e.g. customFunkyView.ctp).
|
||||||
|
* Adds timers, for all subsequent rendering, and injects the debugKit toolbar.
|
||||||
|
*
|
||||||
|
* @param string $action Name of action to render for
|
||||||
|
* @param string $layout Layout to use
|
||||||
|
* @param string $file Custom filename for view
|
||||||
|
* @return string Rendered Element
|
||||||
|
*/
|
||||||
|
function render($action = null, $layout = null, $file = null) {
|
||||||
|
/* pr(array('function' => 'DebugView::render', */
|
||||||
|
/* 'args' => compact('action', 'layout', 'file'), */
|
||||||
|
/* 'this-output-len' => strlen($this->output), */
|
||||||
|
/* )); */
|
||||||
|
DebugKitDebugger::startTimer('viewRender', __('Rendering View', true));
|
||||||
|
$out = parent::render($action, $layout, $file);
|
||||||
|
/* pr(array('function' => 'DebugView::render', */
|
||||||
|
/* 'checkpoint' => 'parent::render', */
|
||||||
|
/* 'out' => $out ? 'not-empty' : 'empty')); */
|
||||||
|
DebugKitDebugger::stopTimer('viewRender');
|
||||||
|
DebugKitDebugger::stopTimer('controllerRender');
|
||||||
|
|
||||||
|
if (isset($this->loaded['toolbar'])) {
|
||||||
|
/* pr(array('function' => 'DebugView::render', */
|
||||||
|
/* 'checkpoint' => 'toolbarLoaded')); */
|
||||||
|
$this->loaded['toolbar']->postRender();
|
||||||
|
}
|
||||||
|
//Temporary work around to hide the SQL dump at page bottom
|
||||||
|
Configure::write('debug', 0);
|
||||||
|
/* pr(array('function' => 'DebugView::render', */
|
||||||
|
/* 'out-len' => strlen($out), */
|
||||||
|
/* 'this-output-len' => strlen($this->output), */
|
||||||
|
/* 'return' => $this->output ? 'not-empty' : 'empty')); */
|
||||||
|
return $this->output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Workaround _render() limitation in core. Which forces View::_render() for .ctp and .thtml templates
|
||||||
|
* Creates temporary extension to trick View::render() & View::renderLayout()
|
||||||
|
*
|
||||||
|
* @param string $name Action name.
|
||||||
|
* @return string
|
||||||
|
**/
|
||||||
|
function _getViewFileName($name = null) {
|
||||||
|
$filename = parent::_getViewFileName($name);
|
||||||
|
return $this->_replaceExtension($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Workaround _render() limitation in core. Which forces View::_render() for .ctp and .thtml templates
|
||||||
|
* Creates temporary extension to trick View::render() & View::renderLayout()
|
||||||
|
*
|
||||||
|
* @param string $name Layout Name
|
||||||
|
* @return string
|
||||||
|
**/
|
||||||
|
function _getLayoutFileName($name = null) {
|
||||||
|
$filename = parent::_getLayoutFileName($name);
|
||||||
|
return $this->_replaceExtension($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replace the Extension on a filename and set the temporary workaround extension.
|
||||||
|
*
|
||||||
|
* @param string $filename Filename to replace extension for.
|
||||||
|
* @return string
|
||||||
|
**/
|
||||||
|
function _replaceExtension($filename) {
|
||||||
|
if (substr($filename, -3) == 'ctp') {
|
||||||
|
$this->_oldExtension = 'ctp';
|
||||||
|
$filename = substr($filename, 0, strlen($filename) -3) . 'debug_view';
|
||||||
|
} elseif (substr($filename, -5) == 'thtml') {
|
||||||
|
$this->_oldExtension = 'thtml';
|
||||||
|
$filename = substr($filename, 0, strlen($filename) -5) . 'debug_view';
|
||||||
|
}
|
||||||
|
return $filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
52
plugins/debug_kit/views/elements/debug_toolbar.ctp
Normal file
52
plugins/debug_kit/views/elements/debug_toolbar.ctp
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Debug Toolbar Element
|
||||||
|
*
|
||||||
|
* Renders all of the other panel elements.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.debug_kit.views.elements
|
||||||
|
* @since
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<div id="debug-kit-toolbar">
|
||||||
|
<?php if (empty($debugToolbarPanels)) :?>
|
||||||
|
<p class="warning"><?php __('There are no active panels. You must enable a panel to see its output.'); ?></p>
|
||||||
|
<?php else: ?>
|
||||||
|
<ul id="panel-tabs">
|
||||||
|
<li class="panel-tab icon">
|
||||||
|
<a href="#hide" id="hide-toolbar">
|
||||||
|
<?php echo $html->image('/debug_kit/img/cake.icon.png', array('alt' => 'cakePHP')); ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<?php foreach ($debugToolbarPanels as $panelName => $panelInfo): ?>
|
||||||
|
<li class="panel-tab">
|
||||||
|
<a href="#<?php echo Inflector::underscore($panelName); ?>">
|
||||||
|
<?php echo Inflector::humanize(Inflector::underscore($panelName)); ?>
|
||||||
|
</a>
|
||||||
|
<div class="panel-content" id="<?php echo Inflector::underscore($panelName); ?>-tab">
|
||||||
|
<?php echo $this->element($panelInfo['elementName'], $panelInfo); ?>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</ul>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
0
plugins/debug_kit/views/elements/empty
Normal file
0
plugins/debug_kit/views/elements/empty
Normal file
48
plugins/debug_kit/views/elements/log_panel.ctp
Normal file
48
plugins/debug_kit/views/elements/log_panel.ctp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Log Panel Element
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.debug_kit.views.elements
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<h2><?php __('Logs') ?></h2>
|
||||||
|
<div class="code-table">
|
||||||
|
<?php foreach ($content as $logName => $logs): ?>
|
||||||
|
<h3><?php echo $logName ?></h3>
|
||||||
|
<?php
|
||||||
|
$len = count($logs);
|
||||||
|
if ($len > 0):
|
||||||
|
$headers = array(__('Time', true), __('Message', true));
|
||||||
|
$rows = array();
|
||||||
|
for ($i = 0; $i < $len; $i += 2):
|
||||||
|
$rows[] = array(
|
||||||
|
$logs[$i], $logs[$i + 1]
|
||||||
|
);
|
||||||
|
endfor;
|
||||||
|
echo $toolbar->table($rows, $headers, array('title' => $logName));
|
||||||
|
else: ?>
|
||||||
|
<p class="info"><?php __('There were no log entries made this request'); ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
43
plugins/debug_kit/views/elements/memory_panel.ctp
Normal file
43
plugins/debug_kit/views/elements/memory_panel.ctp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Session Panel Element
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.debug_kit.views.elements
|
||||||
|
* @since
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<h2><?php __('Memory'); ?></h2>
|
||||||
|
<div class="current-mem-use">
|
||||||
|
<?php echo $toolbar->message(
|
||||||
|
__('Current Memory Use',true),
|
||||||
|
$number->toReadableSize(DebugKitDebugger::getMemoryUse())
|
||||||
|
);?>
|
||||||
|
</div>
|
||||||
|
<div class="peak-mem-use">
|
||||||
|
<?php
|
||||||
|
echo $toolbar->message(
|
||||||
|
__('Peak Memory Use', true),
|
||||||
|
$number->toReadableSize(DebugKitDebugger::getPeakMemoryUse())
|
||||||
|
);
|
||||||
|
?></div>
|
||||||
45
plugins/debug_kit/views/elements/request_panel.ctp
Normal file
45
plugins/debug_kit/views/elements/request_panel.ctp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Request Panel Element
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.debug_kit.views.elements
|
||||||
|
* @since
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<h2> <?php __('Request'); ?></h2>
|
||||||
|
<h4>Cake Params</h4>
|
||||||
|
<?php echo $toolbar->makeNeatArray($content['params']); ?>
|
||||||
|
|
||||||
|
<h4>$_GET</h4>
|
||||||
|
<?php echo $toolbar->makeNeatArray($content['get']); ?>
|
||||||
|
|
||||||
|
<h4>Cookie</h4>
|
||||||
|
<?php if (isset($content['cookie'])): ?>
|
||||||
|
<?php echo $toolbar->makeNeatArray($content['cookie']); ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<p class="warning">To view Cookies, add CookieComponent to Controller
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<h4><?php __('Current Route') ?></h4>
|
||||||
|
<?php echo $toolbar->makeNeatArray($content['currentRoute']); ?>
|
||||||
31
plugins/debug_kit/views/elements/session_panel.ctp
Normal file
31
plugins/debug_kit/views/elements/session_panel.ctp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Session Panel Element
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.debug_kit.views.elements
|
||||||
|
* @since
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<h2><?php __('Session'); ?></h2>
|
||||||
|
<?php echo $toolbar->makeNeatArray($content); ?>
|
||||||
40
plugins/debug_kit/views/elements/sql_log_panel.ctp
Normal file
40
plugins/debug_kit/views/elements/sql_log_panel.ctp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Session Panel Element
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.debug_kit.views.elements
|
||||||
|
* @since
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<h2><?php __('Sql Logs')?></h2>
|
||||||
|
<?php if (!empty($content)) : ?>
|
||||||
|
<?php foreach ($content as $dbName => $queryLog) : ?>
|
||||||
|
<div class="sql-log-panel-query-log">
|
||||||
|
<h4><?php echo $dbName ?></h4>
|
||||||
|
<?php echo $queryLog; ?>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<p class="warning"><?php __('No active database connections'); ?>
|
||||||
|
<?php endif; ?>
|
||||||
44
plugins/debug_kit/views/elements/timer_panel.ctp
Normal file
44
plugins/debug_kit/views/elements/timer_panel.ctp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Timer Panel Element
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.debug_kit.views.elements
|
||||||
|
* @since
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
$timers = DebugKitDebugger::getTimers();
|
||||||
|
?>
|
||||||
|
<h2><?php __('Timers'); ?></h2>
|
||||||
|
<p class="request-time">
|
||||||
|
<?php $totalTime = sprintf(__('%s (seconds)', true), $number->precision(DebugKitDebugger::requestTime(), 6)); ?>
|
||||||
|
<?php echo $toolbar->message(__('Total Request Time:', true), $totalTime)?>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<?php foreach ($timers as $timerName => $timeInfo):
|
||||||
|
$rows[] = array(
|
||||||
|
$timeInfo['message'],
|
||||||
|
$number->precision($timeInfo['time'], 6)
|
||||||
|
);
|
||||||
|
$headers = array(__('Message', true), __('time in seconds', true));
|
||||||
|
endforeach;
|
||||||
|
echo $toolbar->table($rows, $headers, array('title' => 'Timers')); ?>
|
||||||
35
plugins/debug_kit/views/elements/variables_panel.ctp
Normal file
35
plugins/debug_kit/views/elements/variables_panel.ctp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* View Variables Panel Element
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.debug_kit.views.elements
|
||||||
|
* @since
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<h2> <?php __('View Variables'); ?></h2>
|
||||||
|
<?php
|
||||||
|
$vars = $this->viewVars;
|
||||||
|
unset($vars['debugToolbarPanels'], $vars['debugToolbarJavascript']);
|
||||||
|
?>
|
||||||
|
<?php echo $toolbar->makeNeatArray($vars); ?>
|
||||||
79
plugins/debug_kit/views/helpers/fire_php_toolbar.php
Normal file
79
plugins/debug_kit/views/helpers/fire_php_toolbar.php
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* FirePHP Toolbar Helper
|
||||||
|
*
|
||||||
|
* Injects the toolbar elements into non-HTML layouts via FireCake.
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package debug_kit
|
||||||
|
* @subpackage debug_kit.views.helpers
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
App::import('helper', 'DebugKit.Toolbar');
|
||||||
|
App::import('Vendor', 'DebugKit.FireCake');
|
||||||
|
|
||||||
|
class FirePhpToolbarHelper extends ToolbarHelper {
|
||||||
|
/**
|
||||||
|
* send method
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @access protected
|
||||||
|
*/
|
||||||
|
function _send() {
|
||||||
|
$view =& ClassRegistry::getObject('view');
|
||||||
|
$view->element('debug_toolbar', array('plugin' => 'debug_kit', 'disableTimer' => true));
|
||||||
|
Configure::write('debug', 1);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* makeNeatArray.
|
||||||
|
*
|
||||||
|
* wraps FireCake::dump() allowing panel elements to continue functioning
|
||||||
|
*
|
||||||
|
* @param string $values
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function makeNeatArray($values) {
|
||||||
|
FireCake::info($values);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create a simple message
|
||||||
|
*
|
||||||
|
* @param string $label Label of message
|
||||||
|
* @param string $message Message content
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function message($label, $message) {
|
||||||
|
FireCake::log($message, $label);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Generate a table with FireCake
|
||||||
|
*
|
||||||
|
* @param array $rows Rows to print
|
||||||
|
* @param array $headers Headers for table
|
||||||
|
* @param array $options Additional options and params
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function table($rows, $headers, $options = array()) {
|
||||||
|
$title = $headers[0];
|
||||||
|
if (isset($options['title'])) {
|
||||||
|
$title = $options['title'];
|
||||||
|
}
|
||||||
|
array_unshift($rows, $headers);
|
||||||
|
FireCake::table($title, $rows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
150
plugins/debug_kit/views/helpers/html_toolbar.php
Normal file
150
plugins/debug_kit/views/helpers/html_toolbar.php
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Html Toolbar Helper
|
||||||
|
*
|
||||||
|
* Injects the toolbar elements into HTML layouts.
|
||||||
|
* Contains helper methods for
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* 1785 E. Sahara Avenue, Suite 490-204
|
||||||
|
* Las Vegas, Nevada 89104
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package debug_kit
|
||||||
|
* @subpackage debug_kit.views.helpers
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
App::import('helper', 'DebugKit.Toolbar');
|
||||||
|
|
||||||
|
class HtmlToolbarHelper extends ToolbarHelper {
|
||||||
|
/**
|
||||||
|
* helpers property
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
var $helpers = array('Html', 'Javascript');
|
||||||
|
/**
|
||||||
|
* settings property
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
var $settings = array('format' => 'html');
|
||||||
|
/**
|
||||||
|
* Recursively goes through an array and makes neat HTML out of it.
|
||||||
|
*
|
||||||
|
* @param mixed $values Array to make pretty.
|
||||||
|
* @param int $openDepth Depth to add open class
|
||||||
|
* @param int $currentDepth current depth.
|
||||||
|
* @return string
|
||||||
|
**/
|
||||||
|
function makeNeatArray($values, $openDepth = 0, $currentDepth = 0) {
|
||||||
|
$className ="neat-array depth-$currentDepth";
|
||||||
|
if ($openDepth > $currentDepth) {
|
||||||
|
$className .= ' expanded';
|
||||||
|
}
|
||||||
|
$nextDepth = $currentDepth + 1;
|
||||||
|
$out = "<ul class=\"$className\">";
|
||||||
|
if (!is_array($values)) {
|
||||||
|
if (is_bool($values)) {
|
||||||
|
$values = array($values);
|
||||||
|
}
|
||||||
|
if (is_null($values)) {
|
||||||
|
$values = array(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($values as $key => $value) {
|
||||||
|
$out .= '<li><strong>' . $key . '</strong>';
|
||||||
|
if ($value === null) {
|
||||||
|
$value = '(null)';
|
||||||
|
}
|
||||||
|
if ($value === false) {
|
||||||
|
$value = '(false)';
|
||||||
|
}
|
||||||
|
if ($value === true) {
|
||||||
|
$value = '(true)';
|
||||||
|
}
|
||||||
|
if (empty($value) && $value != 0) {
|
||||||
|
$value = '(empty)';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_object($value)) {
|
||||||
|
$value = Set::reverse($value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($value) && !empty($value)) {
|
||||||
|
$out .= $this->makeNeatArray($value, $openDepth, $nextDepth);
|
||||||
|
} else {
|
||||||
|
$out .= $value;
|
||||||
|
}
|
||||||
|
$out .= '</li>';
|
||||||
|
}
|
||||||
|
$out .= '</ul>';
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create an HTML message
|
||||||
|
*
|
||||||
|
* @param string $label label content
|
||||||
|
* @param string $message message content
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function message($label, $message) {
|
||||||
|
return sprintf('<p><strong>%s</strong> %s</p>', $label, $message);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create a table.
|
||||||
|
*
|
||||||
|
* @param array $rows Rows to make.
|
||||||
|
* @param array $headers Optional header row.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function table($rows, $headers = array()) {
|
||||||
|
$out = '<table class="debug-table">';
|
||||||
|
if (!empty($headers)) {
|
||||||
|
$out .= $this->Html->tableHeaders($headers);
|
||||||
|
}
|
||||||
|
$out .= $this->Html->tableCells($rows, array('class' => 'odd'), array('class' => 'even'));
|
||||||
|
$out .= '</table>';
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* send method
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @access protected
|
||||||
|
*/
|
||||||
|
function _send() {
|
||||||
|
if (Configure::read('debug') == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$view =& ClassRegistry::getObject('view');
|
||||||
|
$head = $this->Html->css('/debug_kit/css/debug_toolbar');
|
||||||
|
if (isset($view->viewVars['debugToolbarJavascript'])) {
|
||||||
|
foreach ($view->viewVars['debugToolbarJavascript'] as $script) {
|
||||||
|
if ($script) {
|
||||||
|
$head .= $this->Javascript->link($script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (preg_match('#</head>#', $view->output)) {
|
||||||
|
$view->output = preg_replace('#</head>#', $head . "\n</head>", $view->output, 1);
|
||||||
|
}
|
||||||
|
$toolbar = $view->element('debug_toolbar', array('plugin' => 'debug_kit', 'disableTimer' => true));
|
||||||
|
if (preg_match('#</body>#', $view->output)) {
|
||||||
|
$view->output = preg_replace('#</body>#', $toolbar . "\n</body>", $view->output, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
90
plugins/debug_kit/views/helpers/toolbar.php
Normal file
90
plugins/debug_kit/views/helpers/toolbar.php
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id$ */
|
||||||
|
/**
|
||||||
|
* Abstract Toolbar helper. Provides Base methods for content
|
||||||
|
* specific debug toolbar helpers. Acts as a facade for other toolbars helpers as well.
|
||||||
|
*
|
||||||
|
* helps with development.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||||
|
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||||
|
* @package debug_kit
|
||||||
|
* @subpackage debug_kit.views.helpers
|
||||||
|
* @since v 1.0
|
||||||
|
* @version $Revision$
|
||||||
|
* @modifiedby $LastChangedBy$
|
||||||
|
* @lastmodified $Date$
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
App::import('Vendor', 'DebugKit.DebugKitDebugger');
|
||||||
|
|
||||||
|
class ToolbarHelper extends AppHelper {
|
||||||
|
/**
|
||||||
|
* settings property to be overloaded. Subclasses should specify a format
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
var $settings = array();
|
||||||
|
/**
|
||||||
|
* Construct the helper and make the backend helper.
|
||||||
|
*
|
||||||
|
* @param string $options
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function __construct($options = array()) {
|
||||||
|
$this->_myName = strtolower(get_class($this));
|
||||||
|
if ($this->_myName !== 'toolbarhelper') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isset($options['output'])) {
|
||||||
|
$options['output'] = 'DebugKit.HtmlToolbar';
|
||||||
|
}
|
||||||
|
App::import('Helper', $options['output']);
|
||||||
|
$className = $options['output'];
|
||||||
|
if (strpos($options['output'], '.') !== false) {
|
||||||
|
list($plugin, $className) = explode('.', $options['output']);
|
||||||
|
}
|
||||||
|
$this->_backEndClassName = $className;
|
||||||
|
$this->helpers = array($options['output']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* call__
|
||||||
|
*
|
||||||
|
* Allows method calls on backend helper
|
||||||
|
*
|
||||||
|
* @param string $method
|
||||||
|
* @param mixed $params
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function call__($method, $params) {
|
||||||
|
if (method_exists($this->{$this->_backEndClassName}, $method)) {
|
||||||
|
return $this->{$this->_backEndClassName}->dispatchMethod($method, $params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* postRender method
|
||||||
|
*
|
||||||
|
* Custom Callback defined in DebugView to allow helpers to modify
|
||||||
|
* View output after all rendering is complete.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function postRender() {
|
||||||
|
$this->_send();
|
||||||
|
}
|
||||||
|
}
|
||||||
207
views/accounts/collected.ctp
Normal file
207
views/accounts/collected.ctp
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
<?php /* -*- mode:PHP -*- */
|
||||||
|
|
||||||
|
echo '<div class="account collected">' . "\n";
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Javascript
|
||||||
|
*/
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
|
||||||
|
// Reset the form
|
||||||
|
function resetForm() {
|
||||||
|
// Kick off the grid
|
||||||
|
updateEntriesGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onGridLoadComplete() {
|
||||||
|
var userdata = $('#collected-entries-jqGrid').getGridParam('userData');
|
||||||
|
$('#collected-total').html(fmtCurrency(userdata['total']));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateEntriesGrid() {
|
||||||
|
var account_ids = new Array();
|
||||||
|
$("INPUT[type='checkbox']:checked").each(function(i) {
|
||||||
|
account_ids.push($(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
var cust = new Array();
|
||||||
|
cust['from_date'] = $('#TxFromDate').val();
|
||||||
|
cust['through_date'] = $('#TxThroughDate').val();
|
||||||
|
cust['account_id'] = account_ids;
|
||||||
|
|
||||||
|
var dynamic_post = new Array();
|
||||||
|
dynamic_post['custom'] = cust;
|
||||||
|
|
||||||
|
$('#collected-total').html('Calculating...');
|
||||||
|
$('#collected-entries-jqGrid').clearGridData();
|
||||||
|
$('#collected-entries-jqGrid').setPostDataItem('dynamic_post_replace', serialize(dynamic_post));
|
||||||
|
$('#collected-entries-jqGrid')
|
||||||
|
.setGridParam({ page: 1 })
|
||||||
|
.trigger("reloadGrid");
|
||||||
|
|
||||||
|
//$('#debug').html("<PRE>\n"+htmlEncode(dump($('#collected-entries-jqGrid').getGridParam()))+"\n</PRE>")
|
||||||
|
var gridstate = $('#collected-entries-jqGrid').getGridParam('gridstate');
|
||||||
|
if (gridstate == 'hidden')
|
||||||
|
$('#collected-entries .HeaderButton').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
--></script>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Summary Info Box
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo '<div class="infobox">' . "\n";
|
||||||
|
|
||||||
|
$rows = array();
|
||||||
|
$rows[] = array('Total:', '<SPAN id="collected-total"></SPAN>');
|
||||||
|
echo $this->element('table',
|
||||||
|
array('class' => 'summary',
|
||||||
|
'rows' => $rows,
|
||||||
|
'column_class' => array('field', 'value'),
|
||||||
|
'suppress_alternate_rows' => true,
|
||||||
|
));
|
||||||
|
echo '</div>' . "\n";
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* User Configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo $form->create(null, array('id' => 'collected-form',
|
||||||
|
'onsubmit' => 'return false',
|
||||||
|
'url' => null));
|
||||||
|
|
||||||
|
echo $form->input("id",
|
||||||
|
array('id' => 'account-id',
|
||||||
|
'type' => 'hidden',
|
||||||
|
'value' => 0));
|
||||||
|
|
||||||
|
/* echo '<fieldset class="account collected entry">'; */
|
||||||
|
/* echo ' <legend>Payment Account</legend>'; */
|
||||||
|
/* echo $form->input('Tx.account_id', */
|
||||||
|
/* array(//'label' => 'Payment<BR>Account', */
|
||||||
|
/* 'label' => false, */
|
||||||
|
/* 'type' => 'select', */
|
||||||
|
/* 'multiple' => 'checkbox', */
|
||||||
|
/* 'options' => $paymentAccounts, */
|
||||||
|
/* 'selected' => array_keys($defaultAccounts), */
|
||||||
|
/* ) */
|
||||||
|
/* ); */
|
||||||
|
/* echo '</fieldset>'; */
|
||||||
|
|
||||||
|
echo $this->element('form_table',
|
||||||
|
array('class' => "item account collected entry",
|
||||||
|
//'with_name_after' => ':',
|
||||||
|
'field_prefix' => 'Tx.',
|
||||||
|
'fields' => array
|
||||||
|
("account_id" => array('name' => 'Payment<BR>Account',
|
||||||
|
'opts' =>
|
||||||
|
array('type' => 'select',
|
||||||
|
'multiple' => 'checkbox',
|
||||||
|
'options' => $paymentAccounts,
|
||||||
|
'selected' => array_keys($defaultAccounts),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
echo $this->element('form_table',
|
||||||
|
array('class' => "item account collected entry",
|
||||||
|
//'with_name_after' => ':',
|
||||||
|
'field_prefix' => 'Tx.',
|
||||||
|
'fields' => array
|
||||||
|
("from_date" => array('opts' =>
|
||||||
|
array('type' => 'text'),
|
||||||
|
'between' => '<A HREF="#" ONCLICK="datepickerBOM(null,\'TxFromDate\'); return false;">BOM</A>',
|
||||||
|
),
|
||||||
|
"through_date" => array('opts' =>
|
||||||
|
array('type' => 'text'),
|
||||||
|
'between' => '<A HREF="#" ONCLICK="datepickerEOM(\'TxFromDate\',\'TxThroughDate\'); return false;">EOM</A>',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
echo $form->button('Update',
|
||||||
|
array('onclick' => 'updateEntriesGrid(); return false',
|
||||||
|
));
|
||||||
|
|
||||||
|
echo $form->end();
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Supporting Elements Section
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo '<div CLASS="detail supporting">' . "\n";
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Entries
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo $this->element('statement_entries', array
|
||||||
|
(// Grid configuration
|
||||||
|
'config' => array
|
||||||
|
(
|
||||||
|
'grid_div_id' => 'collected-entries',
|
||||||
|
'grid_div_class' => 'text-below',
|
||||||
|
'grid_events' => array('loadComplete' => 'onGridLoadComplete()'),
|
||||||
|
'grid_setup' => array('hiddengrid' => true),
|
||||||
|
'caption' => 'Collected ' . Inflector::pluralize($account['name']),
|
||||||
|
'action' => 'collected',
|
||||||
|
'filter' => array('ChargeEntry.account_id' => $account['id']),
|
||||||
|
'include' => array('Amount'),
|
||||||
|
'exclude' => array(/*'Type',*/ 'Debit', 'Credit'),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("#TxFromDate")
|
||||||
|
.attr('autocomplete', 'off')
|
||||||
|
.datepicker({ constrainInput: true,
|
||||||
|
numberOfMonths: [1, 1],
|
||||||
|
showCurrentAtPos: 0,
|
||||||
|
dateFormat: 'mm/dd/yy' });
|
||||||
|
|
||||||
|
$("#TxThroughDate")
|
||||||
|
.attr('autocomplete', 'off')
|
||||||
|
.datepicker({ constrainInput: true,
|
||||||
|
numberOfMonths: [1, 1],
|
||||||
|
showCurrentAtPos: 0,
|
||||||
|
dateFormat: 'mm/dd/yy' });
|
||||||
|
|
||||||
|
resetForm();
|
||||||
|
});
|
||||||
|
--></script>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/* End "detail supporting" div */
|
||||||
|
echo '</div>' . "\n";
|
||||||
|
|
||||||
|
/* End page div */
|
||||||
|
echo '</div>' . "\n";
|
||||||
|
|
||||||
|
?>
|
||||||
113
views/accounts/view.ctp
Normal file
113
views/accounts/view.ctp
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
<?php /* -*- mode:PHP -*- */
|
||||||
|
|
||||||
|
echo '<div class="account view">' . "\n";
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Account Detail Main Section
|
||||||
|
*/
|
||||||
|
|
||||||
|
$ledger = $account['Ledger'];
|
||||||
|
$current_ledger = $account['CurrentLedger'];
|
||||||
|
|
||||||
|
if (isset($account['Account']))
|
||||||
|
$account = $account['Account'];
|
||||||
|
|
||||||
|
$rows = array();
|
||||||
|
$rows[] = array('ID', $account['id']);
|
||||||
|
$rows[] = array('Name', $account['name']);
|
||||||
|
$rows[] = array('Type', $account['type']);
|
||||||
|
$rows[] = array('External Name', $account['external_name']);
|
||||||
|
$rows[] = array('External Account', $account['external_account']);
|
||||||
|
$rows[] = array('Comment', $account['comment']);
|
||||||
|
|
||||||
|
echo $this->element('table',
|
||||||
|
array('class' => 'item account detail',
|
||||||
|
'caption' => 'Account Detail',
|
||||||
|
'rows' => $rows,
|
||||||
|
'column_class' => array('field', 'value')));
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Account Info Box
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo '<div class="infobox">' . "\n";
|
||||||
|
$rows = array();
|
||||||
|
$rows[] = array('Debits:', FormatHelper::currency($stats['debits']));
|
||||||
|
$rows[] = array('Credits:', FormatHelper::currency($stats['credits']));
|
||||||
|
$rows[] = array('Account Balance:', FormatHelper::currency($stats['balance']));
|
||||||
|
echo $this->element('table',
|
||||||
|
array('class' => 'summary',
|
||||||
|
'rows' => $rows,
|
||||||
|
'column_class' => array('field', 'value'),
|
||||||
|
'suppress_alternate_rows' => true,
|
||||||
|
));
|
||||||
|
echo '</div>' . "\n";
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Supporting Elements Section
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo '<div CLASS="detail supporting">' . "\n";
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Ledgers
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo $this->element('ledgers', array
|
||||||
|
(// Grid configuration
|
||||||
|
'config' => array
|
||||||
|
('caption' => $account['name'] . " Ledgers",
|
||||||
|
'filter' => array('Account.id' => $account['id']),
|
||||||
|
)));
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Current Ledger
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo $this->element('ledger_entries', array
|
||||||
|
(// Grid configuration
|
||||||
|
'config' => array
|
||||||
|
('grid_div_id' => 'ledger-ledger-entry-list',
|
||||||
|
'caption' => ("Current Ledger: " .
|
||||||
|
"(". $current_ledger['name'] .")"),
|
||||||
|
'filter' => array('Ledger.id' => $current_ledger['id']),
|
||||||
|
'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Balance',
|
||||||
|
empty($account['receipts']) ? 'Tender' : null),
|
||||||
|
'include' => array('Debit', 'Credit', 'Sub-Total'),
|
||||||
|
)));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Entire Account
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo $this->element('ledger_entries', array
|
||||||
|
(// Grid configuration
|
||||||
|
'config' => array
|
||||||
|
('grid_div_id' => 'account-ledger-entry-list',
|
||||||
|
'grid_setup' => array('hiddengrid' => true),
|
||||||
|
'caption' => "Entire Ledger",
|
||||||
|
'filter' => array('Account.id' => $account['id']),
|
||||||
|
'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Balance',
|
||||||
|
empty($account['receipts']) ? 'Tender' : null),
|
||||||
|
'include' => array('Debit', 'Credit', 'Sub-Total'),
|
||||||
|
)));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* End "detail supporting" div */
|
||||||
|
echo '</div>' . "\n";
|
||||||
|
|
||||||
|
/* End page div */
|
||||||
|
echo '</div>' . "\n";
|
||||||
403
views/contacts/edit.ctp
Normal file
403
views/contacts/edit.ctp
Normal file
@@ -0,0 +1,403 @@
|
|||||||
|
<?php /* -*- mode:PHP -*- */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Because we make use of functions here,
|
||||||
|
* we need to put our top level variables somewhere
|
||||||
|
* we can access them.
|
||||||
|
*/
|
||||||
|
$this->varstore = compact('methodTypes', 'methodPreferences',
|
||||||
|
'contactPhones', 'phoneTypes',
|
||||||
|
'contactAddresses',
|
||||||
|
'contactEmails');
|
||||||
|
|
||||||
|
//pr($this->data);
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Javascript
|
||||||
|
*/
|
||||||
|
|
||||||
|
function contactMethodDiv($obj, $type, $legend, $values = null) {
|
||||||
|
|
||||||
|
$div =
|
||||||
|
// BEGIN type-div
|
||||||
|
'<DIV>' . "\n" .
|
||||||
|
// BEGIN type-fieldset
|
||||||
|
'<FIELDSET CLASS="'.$type.' subset">' . "\n" .
|
||||||
|
'<LEGEND>'.$legend.' #%{id} (%{remove})</LEGEND>' . "\n" .
|
||||||
|
|
||||||
|
// BEGIN source-div
|
||||||
|
'<DIV ID="'.$type.'-%{id}-source-div">' . "\n" .
|
||||||
|
// BEGIN source-fieldset
|
||||||
|
'<FIELDSET>' . "\n" .
|
||||||
|
//'<LEGEND>Source</LEGEND>' . "\n" .
|
||||||
|
''
|
||||||
|
;
|
||||||
|
|
||||||
|
if (!isset($values)) {
|
||||||
|
foreach (array('Existing', 'New') AS $sname) {
|
||||||
|
$stype = strtolower($sname);
|
||||||
|
$div .=
|
||||||
|
'<INPUT TYPE="radio" ' . "\n" .
|
||||||
|
' NAME="data[Contact'.ucfirst($type).'][%{id}][source]"' . "\n" .
|
||||||
|
' ONCLICK="switchMethodSource(%{id}, '."'{$type}', '{$stype}'".')"' . "\n" .
|
||||||
|
' CLASS="'.$type.'-method-%{id}-source" ' . "\n" .
|
||||||
|
' ID="'.$type.'-method-%{id}-source-'.$stype.'"' . "\n" .
|
||||||
|
' VALUE="'.$stype.'"' . "\n" .
|
||||||
|
' />' . "\n" .
|
||||||
|
' <LABEL FOR="'.$type.'-method-%{id}-source-'.$stype.'">'.$sname.'</LABEL>' . "\n" .
|
||||||
|
' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$div .= "\n";
|
||||||
|
|
||||||
|
if (isset($values)) {
|
||||||
|
$div .= contactMethodTypeDiv($obj, $type, 'show', $values);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$div .= contactMethodTypeDiv($obj, $type, 'existing');
|
||||||
|
$div .= contactMethodTypeDiv($obj, $type, 'new');
|
||||||
|
}
|
||||||
|
|
||||||
|
$div .=
|
||||||
|
// END source-fieldset
|
||||||
|
'</FIELDSET>' . "\n" .
|
||||||
|
// END source-div
|
||||||
|
'</DIV>' . "\n" .
|
||||||
|
|
||||||
|
// BEGIN method-div
|
||||||
|
'<div id="'.$type.'-%{id}-method-div"' . "\n" .
|
||||||
|
|
||||||
|
$obj->element
|
||||||
|
('form_table',
|
||||||
|
array('class' => "item contact-{$type} entry",
|
||||||
|
'field_prefix' => 'Contact'.ucfirst($type).'.%{id}.ContactsMethod',
|
||||||
|
'fields' => array
|
||||||
|
(
|
||||||
|
'preference' => array
|
||||||
|
('opts' => array
|
||||||
|
('options' => $obj->varstore['methodPreferences'],
|
||||||
|
'selected' => (isset($values) ? $values['ContactsMethod']['preference'] : null),
|
||||||
|
)),
|
||||||
|
|
||||||
|
'type' => array
|
||||||
|
('opts' => array
|
||||||
|
('options' => $obj->varstore['methodTypes'],
|
||||||
|
'selected' => (isset($values) ? $values['ContactsMethod']['type'] : null),
|
||||||
|
)),
|
||||||
|
|
||||||
|
'comment' => array
|
||||||
|
('opts' => array
|
||||||
|
('value' => (isset($values) ? $values['ContactsMethod']['comment'] : null),
|
||||||
|
)),
|
||||||
|
|
||||||
|
))) . "\n" .
|
||||||
|
|
||||||
|
// END method-div
|
||||||
|
'</div>' . "\n" .
|
||||||
|
|
||||||
|
// END type-fieldset
|
||||||
|
'</FIELDSET>' . "\n" .
|
||||||
|
// END type-div
|
||||||
|
'</DIV>'
|
||||||
|
;
|
||||||
|
|
||||||
|
return $div;
|
||||||
|
}
|
||||||
|
|
||||||
|
function contactMethodTypeDiv($obj, $type, $stype, $values = null) {
|
||||||
|
|
||||||
|
$element = 'form_table';
|
||||||
|
|
||||||
|
if ($type === 'phone') {
|
||||||
|
if ($stype === 'existing') {
|
||||||
|
$fields = array
|
||||||
|
('id' => array('name' => 'Phone/Ext',
|
||||||
|
'opts' => array('options' => $obj->varstore['contactPhones'])),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
elseif ($stype === 'new') {
|
||||||
|
$fields = array
|
||||||
|
('type' => array('opts' => array('options' => $obj->varstore['phoneTypes'])),
|
||||||
|
'phone' => true,
|
||||||
|
'ext' => array('name' => "Extension"),
|
||||||
|
'comment' => true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
elseif ($stype === 'show') {
|
||||||
|
$element = 'table';
|
||||||
|
$column_class = array('field', 'value');
|
||||||
|
$rows = array
|
||||||
|
(array('Type', $values['type']),
|
||||||
|
array('Phone', $values['phone']),
|
||||||
|
array('Extension', $values['ext']),
|
||||||
|
array('Comment', $values['comment']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die("\n\nInvalid stype ($stype)\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
elseif ($type === 'address') {
|
||||||
|
if ($stype === 'existing') {
|
||||||
|
$fields = array
|
||||||
|
('id' => array('name' => 'Address',
|
||||||
|
'opts' => array('options' => $obj->varstore['contactAddresses'])),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
elseif ($stype === 'new') {
|
||||||
|
$fields = array
|
||||||
|
('address' => true,
|
||||||
|
'city' => true,
|
||||||
|
'state' => true,
|
||||||
|
'postcode' => array('name' => 'Zip Code'),
|
||||||
|
'country' => true,
|
||||||
|
'comment' => true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
elseif ($stype === 'show') {
|
||||||
|
$element = 'table';
|
||||||
|
$column_class = array('field', 'value');
|
||||||
|
$rows = array
|
||||||
|
(array('Address', preg_replace("/\n/", "<BR>", $values['address'])),
|
||||||
|
array('City', $values['city']),
|
||||||
|
array('State', $values['state']),
|
||||||
|
array('Zip Code', $values['postcode']),
|
||||||
|
array('Country', $values['country']),
|
||||||
|
array('Comment', $values['comment']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die("\n\nInvalid stype ($stype)\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($type === 'email') {
|
||||||
|
if ($stype === 'existing') {
|
||||||
|
$fields = array
|
||||||
|
('id' => array('name' => 'Email',
|
||||||
|
'opts' => array('options' => $obj->varstore['contactEmails'])),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
elseif ($stype === 'new') {
|
||||||
|
$fields = array
|
||||||
|
('email' => true,
|
||||||
|
'comment' => true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
elseif ($stype === 'show') {
|
||||||
|
$element = 'table';
|
||||||
|
$column_class = array('field', 'value');
|
||||||
|
$rows = array
|
||||||
|
(array('Email', $values['email']),
|
||||||
|
array('Comment', $values['comment']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die("\n\nInvalid type ($type)\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
// BEGIN sourcetype-div
|
||||||
|
'<div ' . "\n" .
|
||||||
|
' class="'.$type.'-%{id}-div"' . "\n" .
|
||||||
|
' id="'.$type.'-%{id}-'.$stype.'-div"' . "\n" .
|
||||||
|
(isset($values) ? '' : ' STYLE="display:none;"' . "\n") .
|
||||||
|
'>' . "\n" .
|
||||||
|
|
||||||
|
$obj->element
|
||||||
|
($element,
|
||||||
|
array('class' => "item contact-{$type} {$stype}",
|
||||||
|
'field_prefix' => 'Contact'.ucfirst($type).'.%{id}')
|
||||||
|
+ compact('rows', 'fields', 'column_class')) .
|
||||||
|
|
||||||
|
($stype === 'show'
|
||||||
|
? '<input type="hidden" name="data[Contact'.ucfirst($type).'][%{id}][id]" value="'.$values['id'].'"/>' . "\n"
|
||||||
|
: '') .
|
||||||
|
|
||||||
|
// END sourcetype-div
|
||||||
|
'</div>' . "\n" .
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//pr($this->data);
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
|
||||||
|
function addPhone(flash) {
|
||||||
|
addDiv('phone-entry-id', 'phone', 'phones', flash, <?php
|
||||||
|
echo FormatHelper::phpVarToJavascript(contactMethodDiv($this,
|
||||||
|
'phone',
|
||||||
|
'Phone Number'),
|
||||||
|
null,
|
||||||
|
' ');
|
||||||
|
?>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addAddress(flash) {
|
||||||
|
addDiv('address-entry-id', 'address', 'addresses', flash, <?php
|
||||||
|
echo FormatHelper::phpVarToJavascript(contactMethodDiv($this,
|
||||||
|
'address',
|
||||||
|
'Address'),
|
||||||
|
null,
|
||||||
|
' ');
|
||||||
|
?>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addEmail(flash) {
|
||||||
|
addDiv('email-entry-id', 'email', 'emails', flash, <?php
|
||||||
|
echo FormatHelper::phpVarToJavascript(contactMethodDiv($this,
|
||||||
|
'email',
|
||||||
|
'Email Address'),
|
||||||
|
null,
|
||||||
|
' ');
|
||||||
|
?>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the form
|
||||||
|
function resetForm() {
|
||||||
|
$('#phones').html('');
|
||||||
|
$('#addresses').html('');
|
||||||
|
$('#emails').html('');
|
||||||
|
$('#phone-entry-id').val(1);
|
||||||
|
$('#address-entry-id').val(1);
|
||||||
|
$('#email-entry-id').val(1);
|
||||||
|
|
||||||
|
<?php foreach ($this->data['ContactPhone'] AS $phone): ?>
|
||||||
|
addDiv('phone-entry-id', 'phone', 'phones', false, <?php
|
||||||
|
echo FormatHelper::phpVarToJavascript(contactMethodDiv($this,
|
||||||
|
'phone',
|
||||||
|
'Phone Number',
|
||||||
|
$phone
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
' ');
|
||||||
|
?>
|
||||||
|
);
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
<?php foreach ($this->data['ContactAddress'] AS $address): ?>
|
||||||
|
addDiv('address-entry-id', 'address', 'addresses', false, <?php
|
||||||
|
echo FormatHelper::phpVarToJavascript(contactMethodDiv($this,
|
||||||
|
'address',
|
||||||
|
'Address',
|
||||||
|
$address
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
' ');
|
||||||
|
?>
|
||||||
|
);
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
<?php foreach ($this->data['ContactEmail'] AS $email): ?>
|
||||||
|
addDiv('email-entry-id', 'email', 'emails', false, <?php
|
||||||
|
echo FormatHelper::phpVarToJavascript(contactMethodDiv($this,
|
||||||
|
'email',
|
||||||
|
'Email Address',
|
||||||
|
$email
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
' ');
|
||||||
|
?>
|
||||||
|
);
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function switchMethodSource(id, type, source) {
|
||||||
|
$("."+type+"-"+id+"-div")
|
||||||
|
.slideUp();
|
||||||
|
|
||||||
|
$("#"+type+"-"+id+"-"+source+"-div")
|
||||||
|
.slideDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
resetForm();
|
||||||
|
});
|
||||||
|
|
||||||
|
--></script>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
; // alignment
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Contact Edit
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo '<div class="contact edit">' . "\n";
|
||||||
|
|
||||||
|
echo $form->create('Contact', array('action' => 'edit')) . "\n";
|
||||||
|
echo $form->input('id') . "\n";
|
||||||
|
|
||||||
|
echo($this->element
|
||||||
|
('form_table',
|
||||||
|
array('class' => 'item contact detail',
|
||||||
|
'caption' => isset($this->data['Contact']) ? 'Edit Contact' : 'New Contact',
|
||||||
|
'fields' => array
|
||||||
|
('first_name' => true,
|
||||||
|
'last_name' => true,
|
||||||
|
'middle_name' => true,
|
||||||
|
'display_name' => true,
|
||||||
|
'company_name' => array('name' => 'Company'),
|
||||||
|
'id_federal' => array('name' => 'SSN'),
|
||||||
|
'id_local' => array('name' => 'ID #'),
|
||||||
|
'id_local_state' => array('name' => 'ID State'),
|
||||||
|
/* 'id_local_exp' => array('name' => 'ID Expiration', */
|
||||||
|
/* 'opts' => array('empty' => true)), */
|
||||||
|
'comment' => true,
|
||||||
|
))) . "\n");
|
||||||
|
|
||||||
|
echo $form->submit('Update') . "\n";
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div CLASS="dynamic-set">
|
||||||
|
<fieldset CLASS="phone superset">
|
||||||
|
<legend>Phone Numbers</legend>
|
||||||
|
<input type="hidden" id="phone-entry-id" value="0">
|
||||||
|
<div id="phones"></div>
|
||||||
|
<fieldset> <legend>
|
||||||
|
<a href="#" onClick="addPhone(true); return false;">Add a Phone Number</a>
|
||||||
|
</legend> </fieldset>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div CLASS="dynamic-set">
|
||||||
|
<fieldset CLASS="address superset">
|
||||||
|
<legend>Mailing Addresses</legend>
|
||||||
|
<input type="hidden" id="address-entry-id" value="0">
|
||||||
|
<div id="addresses"></div>
|
||||||
|
<fieldset> <legend>
|
||||||
|
<a href="#" onClick="addAddress(true); return false;">Add a Mailing Address</a>
|
||||||
|
</legend> </fieldset>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div CLASS="dynamic-set">
|
||||||
|
<fieldset CLASS="email superset">
|
||||||
|
<legend>Email Addresses</legend>
|
||||||
|
<input type="hidden" id="email-entry-id" value="0">
|
||||||
|
<div id="emails"></div>
|
||||||
|
<fieldset> <legend>
|
||||||
|
<a href="#" onClick="addEmail(true); return false;">Add an Email Address</a>
|
||||||
|
</legend> </fieldset>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
; // Alignment
|
||||||
|
|
||||||
|
echo $form->submit('Update') . "\n";
|
||||||
|
echo $form->submit('Cancel', array('name' => 'cancel')) . "\n";
|
||||||
|
echo $form->end() . "\n";
|
||||||
|
echo '</div>' . "\n";
|
||||||
145
views/contacts/view.ctp
Normal file
145
views/contacts/view.ctp
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
<?php /* -*- mode:PHP -*- */
|
||||||
|
|
||||||
|
echo '<div class="contact view">' . "\n";
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Contact Detail Main Section
|
||||||
|
*/
|
||||||
|
|
||||||
|
$phones = $contact['ContactPhone'];
|
||||||
|
$addresses = $contact['ContactAddress'];
|
||||||
|
$emails = $contact['ContactEmail'];
|
||||||
|
|
||||||
|
if (isset($contact['Contact']))
|
||||||
|
$contact = $contact['Contact'];
|
||||||
|
|
||||||
|
$rows = array();
|
||||||
|
$rows[] = array('First Name', $contact['first_name']);
|
||||||
|
$rows[] = array('Middle Name', $contact['middle_name']);
|
||||||
|
$rows[] = array('Last Name', $contact['last_name']);
|
||||||
|
$rows[] = array('Company', $contact['company_name']);
|
||||||
|
$rows[] = array('SSN', $contact['id_federal']);
|
||||||
|
$rows[] = array('ID', ($contact['id_local']
|
||||||
|
. ($contact['id_local']
|
||||||
|
? " - ".$contact['id_local_state']
|
||||||
|
: "")));
|
||||||
|
$rows[] = array('Comment', $contact['comment']);
|
||||||
|
|
||||||
|
echo $this->element('table',
|
||||||
|
array('class' => 'item contact detail',
|
||||||
|
'caption' => 'Contact Details',
|
||||||
|
'rows' => $rows,
|
||||||
|
'column_class' => array('field', 'value')));
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Contact Info Box
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo '<div class="infobox">' . "\n";
|
||||||
|
$rows = array();
|
||||||
|
echo $this->element('table',
|
||||||
|
array('class' => 'summary',
|
||||||
|
'rows' => $rows,
|
||||||
|
'column_class' => array('field', 'value'),
|
||||||
|
'suppress_alternate_rows' => true,
|
||||||
|
));
|
||||||
|
echo '</div>' . "\n";
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Supporting Elements Section
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo '<div CLASS="detail supporting">' . "\n";
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Phones
|
||||||
|
*/
|
||||||
|
$headers = array('Phone', 'Preference', 'Comment');
|
||||||
|
$rows = array();
|
||||||
|
foreach($phones AS $phone) {
|
||||||
|
$rows[] = array(FormatHelper::phone($phone['phone']) .
|
||||||
|
($phone['ext'] ? " x".$phone['ext'] : ""),
|
||||||
|
$phone['ContactsMethod']['preference'] . " / " .
|
||||||
|
$phone['ContactsMethod']['type'] . " / " .
|
||||||
|
$phone['type'],
|
||||||
|
$phone['comment']);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $this->element('table',
|
||||||
|
array('class' => 'item phone list',
|
||||||
|
'caption' => 'Phone',
|
||||||
|
'headers' => $headers,
|
||||||
|
'rows' => $rows,
|
||||||
|
'column_class' => $headers));
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Addresses
|
||||||
|
*/
|
||||||
|
$headers = array('Address', 'Preference', 'Comment');
|
||||||
|
$rows = array();
|
||||||
|
foreach($addresses AS $address) {
|
||||||
|
$rows[] = array(preg_replace("/\n/", "<BR>\n", $address['address']) . "<BR>\n" .
|
||||||
|
$address['city'] . ", " .
|
||||||
|
$address['state'] . " " .
|
||||||
|
$address['postcode'],
|
||||||
|
//. ? "<BR>\n" . $address['country'],
|
||||||
|
$address['ContactsMethod']['preference'] . " / " .
|
||||||
|
$address['ContactsMethod']['type'],
|
||||||
|
$address['comment']);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $this->element('table',
|
||||||
|
array('class' => 'item address list',
|
||||||
|
'caption' => 'Address',
|
||||||
|
'headers' => $headers,
|
||||||
|
'rows' => $rows,
|
||||||
|
'column_class' => $headers));
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Emails
|
||||||
|
*/
|
||||||
|
$headers = array('Email', 'Preference', 'Comment');
|
||||||
|
$rows = array();
|
||||||
|
foreach($emails AS $email) {
|
||||||
|
$rows[] = array($email['email'],
|
||||||
|
$email['ContactsMethod']['preference'] . " / " .
|
||||||
|
$email['ContactsMethod']['type'],
|
||||||
|
$email['comment']);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $this->element('table',
|
||||||
|
array('class' => 'item email list',
|
||||||
|
'caption' => 'Email',
|
||||||
|
'headers' => $headers,
|
||||||
|
'rows' => $rows,
|
||||||
|
'column_class' => $headers));
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Customers
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo $this->element('customers', array
|
||||||
|
(// Grid configuration
|
||||||
|
'config' => array
|
||||||
|
('caption' => 'Related Customers',
|
||||||
|
'filter' => array('Contact.id' => $contact['id']),
|
||||||
|
)));
|
||||||
|
|
||||||
|
|
||||||
|
/* End "detail supporting" div */
|
||||||
|
echo '</div>' . "\n";
|
||||||
|
|
||||||
|
/* End page div */
|
||||||
|
echo '</div>' . "\n";
|
||||||
274
views/customers/edit.ctp
Normal file
274
views/customers/edit.ctp
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
<?php /* -*- mode:PHP -*- */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Because we make use of functions here,
|
||||||
|
* we need to put our top level variables somewhere
|
||||||
|
* we can access them.
|
||||||
|
*/
|
||||||
|
$this->varstore = compact('contactTypes', 'contacts');
|
||||||
|
|
||||||
|
//pr($this->data);
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Javascript
|
||||||
|
*/
|
||||||
|
|
||||||
|
function customerContactDiv($obj, $values = null, $primary = false) {
|
||||||
|
|
||||||
|
$div =
|
||||||
|
// BEGIN type-div
|
||||||
|
'<DIV>' . "\n" .
|
||||||
|
// BEGIN type-fieldset
|
||||||
|
'<FIELDSET CLASS="contact subset">' . "\n" .
|
||||||
|
'<LEGEND>Contact #%{id} (%{remove})</LEGEND>' . "\n" .
|
||||||
|
|
||||||
|
// BEGIN source-div
|
||||||
|
'<DIV ID="contact-%{id}-source-div">' . "\n" .
|
||||||
|
// BEGIN source-fieldset
|
||||||
|
'<FIELDSET>' . "\n" .
|
||||||
|
//'<LEGEND>Source</LEGEND>' . "\n" .
|
||||||
|
''
|
||||||
|
;
|
||||||
|
|
||||||
|
if (!isset($values)) {
|
||||||
|
foreach (array('Existing', 'New') AS $sname) {
|
||||||
|
$stype = strtolower($sname);
|
||||||
|
$div .=
|
||||||
|
'<INPUT TYPE="radio" ' . "\n" .
|
||||||
|
' NAME="data[Contact][%{id}][source]"' . "\n" .
|
||||||
|
' ONCLICK="switchContactSource(%{id}, '."'{$stype}'".')"' . "\n" .
|
||||||
|
' CLASS="contact-%{id}-source" ' . "\n" .
|
||||||
|
' ID="contact-%{id}-source-'.$stype.'"' . "\n" .
|
||||||
|
' VALUE="'.$stype.'"' . "\n" .
|
||||||
|
//' CHECKED' . "\n" .
|
||||||
|
' />' . "\n" .
|
||||||
|
' <LABEL FOR="contact-%{id}-source-'.$stype.'">'.$sname.'</LABEL>' . "\n" .
|
||||||
|
' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$div .= "\n";
|
||||||
|
|
||||||
|
if (isset($values)) {
|
||||||
|
$div .= customerContactTypeDiv($obj, 'show', $values);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$div .= customerContactTypeDiv($obj, 'existing');
|
||||||
|
$div .= customerContactTypeDiv($obj, 'new');
|
||||||
|
}
|
||||||
|
|
||||||
|
$div .=
|
||||||
|
// END source-fieldset
|
||||||
|
'</FIELDSET>' . "\n" .
|
||||||
|
// END source-div
|
||||||
|
'</DIV>' . "\n" .
|
||||||
|
|
||||||
|
// BEGIN contact-div
|
||||||
|
'<div id="contact-%{id}-contact-div"' . "\n" .
|
||||||
|
|
||||||
|
$obj->element
|
||||||
|
('form_table',
|
||||||
|
array('class' => "item contact entry",
|
||||||
|
'field_prefix' => 'Contact.%{id}.ContactsCustomer',
|
||||||
|
'fields' => array
|
||||||
|
(
|
||||||
|
'Customer.primary_contact_entry' => array
|
||||||
|
('name' => 'Primary Contact',
|
||||||
|
'no_prefix' => true,
|
||||||
|
'opts' => array
|
||||||
|
('type' => 'radio',
|
||||||
|
'options' => array('%{id}' => false),
|
||||||
|
'value' => ($primary ? '%{id}' : 'bogus-value-to-suppress-hidden-input'),
|
||||||
|
)),
|
||||||
|
|
||||||
|
'type' => array
|
||||||
|
('opts' => array
|
||||||
|
('options' => $obj->varstore['contactTypes'],
|
||||||
|
'selected' => (isset($values) ? $values['ContactsCustomer']['type'] : null),
|
||||||
|
)),
|
||||||
|
|
||||||
|
'comment' => array
|
||||||
|
('opts' => array
|
||||||
|
('value' => (isset($values) ? $values['ContactsCustomer']['comment'] : null),
|
||||||
|
)),
|
||||||
|
|
||||||
|
))) . "\n" .
|
||||||
|
|
||||||
|
// END contact-div
|
||||||
|
'</div>' . "\n" .
|
||||||
|
|
||||||
|
// END type-fieldset
|
||||||
|
'</FIELDSET>' . "\n" .
|
||||||
|
// END type-div
|
||||||
|
'</DIV>'
|
||||||
|
;
|
||||||
|
|
||||||
|
return $div;
|
||||||
|
}
|
||||||
|
|
||||||
|
function customerContactTypeDiv($obj, $stype, $values = null) {
|
||||||
|
|
||||||
|
$element = 'form_table';
|
||||||
|
$class = $stype;
|
||||||
|
|
||||||
|
if ($stype === 'existing') {
|
||||||
|
$fields = array
|
||||||
|
('id' => array('name' => 'Contact',
|
||||||
|
'opts' => array('options' => $obj->varstore['contacts'])),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
elseif ($stype === 'new') {
|
||||||
|
$fields = array
|
||||||
|
('first_name' => true,
|
||||||
|
'last_name' => true,
|
||||||
|
'middle_name' => true,
|
||||||
|
'display_name' => true,
|
||||||
|
'company_name' => array('name' => 'Company'),
|
||||||
|
'id_federal' => array('name' => 'SSN'),
|
||||||
|
'id_local' => array('name' => 'ID #'),
|
||||||
|
'id_local_state' => array('name' => 'ID State'),
|
||||||
|
/* 'id_local_exp' => array('name' => 'ID Expiration', */
|
||||||
|
/* 'opts' => array('empty' => true)), */
|
||||||
|
'comment' => true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
elseif ($stype === 'show') {
|
||||||
|
$element = 'table';
|
||||||
|
$class = 'detail';
|
||||||
|
$column_class = array('field', 'value');
|
||||||
|
$rows = array(array('First Name', $values['first_name']),
|
||||||
|
array('Last Name', $values['last_name']),
|
||||||
|
array('Company', $values['company_name']),
|
||||||
|
array('Comment', $values['comment']));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die("\n\nInvalid stype ($stype)\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
// BEGIN sourcetype-div
|
||||||
|
'<div ' . "\n" .
|
||||||
|
' class="contact-%{id}-div"' . "\n" .
|
||||||
|
' id="contact-%{id}-'.$stype.'-div"' . "\n" .
|
||||||
|
(isset($values) ? '' : ' STYLE="display:none;"' . "\n") .
|
||||||
|
'>' . "\n" .
|
||||||
|
|
||||||
|
$obj->element
|
||||||
|
($element,
|
||||||
|
array('class' => "item contact {$class}",
|
||||||
|
'field_prefix' => 'Contact.%{id}')
|
||||||
|
+ compact('rows', 'fields', 'column_class')) .
|
||||||
|
|
||||||
|
($stype === 'show'
|
||||||
|
? '<input type="hidden" name="data[Contact][%{id}][id]" value="'.$values['id'].'"/>' . "\n"
|
||||||
|
: '') .
|
||||||
|
|
||||||
|
// END sourcetype-div
|
||||||
|
'</div>' . "\n" .
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
|
||||||
|
function addContact(flash) {
|
||||||
|
addDiv('contact-entry-id', 'contact', 'contacts', flash, <?php
|
||||||
|
echo FormatHelper::phpVarToJavascript
|
||||||
|
(customerContactDiv($this),
|
||||||
|
null,
|
||||||
|
' ');
|
||||||
|
?>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the form
|
||||||
|
function resetForm() {
|
||||||
|
$('#contacts').html('');
|
||||||
|
$('#contact-entry-id').val(1);
|
||||||
|
|
||||||
|
<?php foreach ($this->data['Contact'] AS $contact): ?>
|
||||||
|
addDiv('contact-entry-id', 'contact', 'contacts', false, <?php
|
||||||
|
echo FormatHelper::phpVarToJavascript
|
||||||
|
(customerContactDiv($this,
|
||||||
|
$contact,
|
||||||
|
$contact['id'] == $this->data['Customer']['primary_contact_id']
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
' ');
|
||||||
|
?>
|
||||||
|
);
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
if ($("#contact-entry-id").val() == 1) {
|
||||||
|
addDiv('contact-entry-id', 'contact', 'contacts', false, <?php
|
||||||
|
echo FormatHelper::phpVarToJavascript
|
||||||
|
(customerContactDiv($this, null, true),
|
||||||
|
null,
|
||||||
|
' ');
|
||||||
|
?>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function switchContactSource(id, source) {
|
||||||
|
$(".contact-"+id+"-div")
|
||||||
|
.slideUp();
|
||||||
|
|
||||||
|
$("#contact-"+id+"-"+source+"-div")
|
||||||
|
.slideDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
resetForm();
|
||||||
|
});
|
||||||
|
|
||||||
|
--></script>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
; // alignment
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Customer Edit
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo '<div class="customer edit">' . "\n";
|
||||||
|
|
||||||
|
echo $form->create('Customer', array('action' => 'edit')) . "\n";
|
||||||
|
echo $form->input('id') . "\n";
|
||||||
|
|
||||||
|
echo($this->element
|
||||||
|
('form_table',
|
||||||
|
array('class' => 'item customer detail',
|
||||||
|
'caption' => isset($this->data['Customer']) ? 'Edit Customer' : 'New Customer',
|
||||||
|
'fields' => array
|
||||||
|
('name' => true,
|
||||||
|
'comment' => true,
|
||||||
|
))) . "\n");
|
||||||
|
|
||||||
|
echo $form->submit(isset($this->data['Customer']) ? 'Update' : 'Add New Customer') . "\n";
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div CLASS="dynamic-set">
|
||||||
|
<fieldset CLASS="contact superset">
|
||||||
|
<legend>Contacts</legend>
|
||||||
|
<input type="hidden" id="contact-entry-id" value="0">
|
||||||
|
<div id="contacts"></div>
|
||||||
|
<fieldset> <legend>
|
||||||
|
<a href="#" onClick="addContact(true); return false;">Add a Contact</a>
|
||||||
|
</legend> </fieldset>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
; // Alignment
|
||||||
|
|
||||||
|
echo $form->submit(isset($this->data['Customer']) ? 'Update' : 'Add New Customer') . "\n";
|
||||||
|
echo $form->submit('Cancel', array('name' => 'cancel')) . "\n";
|
||||||
|
echo $form->end() . "\n";
|
||||||
|
echo '</div>' . "\n";
|
||||||
421
views/customers/receipt.ctp
Normal file
421
views/customers/receipt.ctp
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
<?php /* -*- mode:PHP -*- */ ?>
|
||||||
|
|
||||||
|
<div class="receipt input">
|
||||||
|
<?php
|
||||||
|
; // Editor alignment
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Javascript
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Warnings _really_ screw up javascript
|
||||||
|
$saved_debug_state = Configure::read('debug');
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
|
||||||
|
// prepare the form when the DOM is ready
|
||||||
|
$(document).ready(function() {
|
||||||
|
var options = {
|
||||||
|
target: '#output-debug', // target element(s) to be updated with server response
|
||||||
|
beforeSubmit: verifyRequest, // pre-submit callback
|
||||||
|
success: showResponse, // post-submit callback
|
||||||
|
|
||||||
|
// other available options:
|
||||||
|
//clearForm: true, // clear all form fields after successful submit
|
||||||
|
//resetForm: true, // reset the form after successful submit
|
||||||
|
};
|
||||||
|
|
||||||
|
// bind form using 'ajaxForm'
|
||||||
|
$('#receipt-form').ajaxForm(options);
|
||||||
|
});
|
||||||
|
|
||||||
|
// pre-submit callback
|
||||||
|
function verifyRequest(formData, jqForm, options) {
|
||||||
|
$('#results').html('Working <BLINK>...</BLINK>');
|
||||||
|
// here we could return false to prevent the form from being submitted;
|
||||||
|
// returning anything other than false will allow the form submit to continue
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// post-submit callback
|
||||||
|
function showResponse(responseText, statusText) {
|
||||||
|
if (statusText == 'success') {
|
||||||
|
var amount = 0;
|
||||||
|
$("input.payment.amount").each(function(i) {
|
||||||
|
amount += $(this).val();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#results').html('<H3>Receipt Saved<BR>' +
|
||||||
|
$("#receipt-customer-name").html() +
|
||||||
|
' : ' + fmtCurrency(amount) +
|
||||||
|
'</H3>');
|
||||||
|
|
||||||
|
if (!$("#repeat").attr("checked")) {
|
||||||
|
window.location.href =
|
||||||
|
"<?php echo $html->url(array('controller' => 'customers',
|
||||||
|
'action' => 'view')); ?>"
|
||||||
|
+ "/" + $("#customer-id").val();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get a clean slate
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#results').html('<H2>Failed to save receipt!</H2>');
|
||||||
|
alert('Failed to save receipt.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the form
|
||||||
|
function resetForm() {
|
||||||
|
$('#payment-entry-id').val(1);
|
||||||
|
$('#payments').html('');
|
||||||
|
|
||||||
|
addPaymentSource(false);
|
||||||
|
updateCharges($("#customer-id").val());
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCharges(id) {
|
||||||
|
$('#charge-entries-jqGrid').clearGridData();
|
||||||
|
$("#receipt-balance").html("Calculating...");
|
||||||
|
$("#receipt-charges-caption").html("Please Wait...");
|
||||||
|
|
||||||
|
var custom = new Array();
|
||||||
|
custom['customer_id'] = id;
|
||||||
|
|
||||||
|
var dynamic_post = new Array();
|
||||||
|
dynamic_post['custom'] = custom;
|
||||||
|
|
||||||
|
$('#charge-entries-jqGrid').setPostDataItem('dynamic_post_replace', serialize(dynamic_post));
|
||||||
|
$('#charge-entries-jqGrid')
|
||||||
|
.setGridParam({ page: 1 })
|
||||||
|
.trigger("reloadGrid");
|
||||||
|
|
||||||
|
var gridstate = $('#charge-entries-jqGrid').getGridParam('gridstate');
|
||||||
|
if (gridstate == 'hidden')
|
||||||
|
$('#charge-entries .HeaderButton').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onGridLoadComplete() {
|
||||||
|
var userdata = $('#charge-entries-jqGrid').getGridParam('userData');
|
||||||
|
$('#receipt-balance').html(fmtCurrency(userdata['balance']));
|
||||||
|
$("#receipt-charges-caption").html("Outstanding Charges");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRowSelect(grid_id, customer_id) {
|
||||||
|
// Set the customer id that will be returned with the form
|
||||||
|
$("#customer-id").val(customer_id);
|
||||||
|
|
||||||
|
// Get the item names from the grid
|
||||||
|
//$("#receipt-customer-id").html($(grid_id).getCell(customer_id, 'Customer-id'));
|
||||||
|
// REVISIT <AP>: 20090708
|
||||||
|
// This is not intended as a long term solution,
|
||||||
|
// but I need a way to enter data and then view
|
||||||
|
// the results. This link will help.
|
||||||
|
$("#receipt-customer-id").html('<A HREF="' +
|
||||||
|
"<?php echo $html->url(array('controller' => 'customers',
|
||||||
|
'action' => 'view')); ?>"
|
||||||
|
+ "/" +
|
||||||
|
$(grid_id).getCell(customer_id, 'Customer-id').replace(/^#/,'') +
|
||||||
|
'">' +
|
||||||
|
$(grid_id).getCell(customer_id, 'Customer-id') +
|
||||||
|
'</A>');
|
||||||
|
$("#receipt-customer-name").html($(grid_id).getCell(customer_id, 'Customer-name'));
|
||||||
|
|
||||||
|
// Hide the "no customer" message and show the current customer
|
||||||
|
$(".customer-selection-invalid").hide();
|
||||||
|
$(".customer-selection-valid").show();
|
||||||
|
|
||||||
|
// Update the charges grid to reflect this customer
|
||||||
|
updateCharges(customer_id);
|
||||||
|
|
||||||
|
// Collapse the grid now that the user has selected
|
||||||
|
$("#customers-list .HeaderButton").click();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onGridState(grid_id, state) {
|
||||||
|
if (state == 'visible') {
|
||||||
|
$(".customer-selection-invalid").hide();
|
||||||
|
$(".customer-selection-valid").hide();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($("#customer-id").val() > 0) {
|
||||||
|
$(".customer-selection-valid").show();
|
||||||
|
$(".customer-selection-invalid").hide();
|
||||||
|
} else {
|
||||||
|
$(".customer-selection-valid").hide();
|
||||||
|
$(".customer-selection-invalid").show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addPaymentSource(flash) {
|
||||||
|
addDiv('payment-entry-id', 'payment', 'payments', flash,
|
||||||
|
// HTML section
|
||||||
|
'<FIELDSET CLASS="payment subset">' +
|
||||||
|
<?php /* '<LEGEND>Payment #%{id} (%{remove})</LEGEND>' + */ ?>
|
||||||
|
'<LEGEND>Payment</LEGEND>' +
|
||||||
|
|
||||||
|
'<DIV ID="payment-div-%{id}">' +
|
||||||
|
<?php
|
||||||
|
// Rearrange to be of the form (id => name)
|
||||||
|
$radioOptions = array();
|
||||||
|
foreach ($paymentTypes AS $type)
|
||||||
|
$radioOptions[$type['TenderType']['id']] = $type['TenderType']['name'];
|
||||||
|
|
||||||
|
echo FormatHelper::phpVarToJavascript
|
||||||
|
($form->input('Entry.%{id}.tender_type_id',
|
||||||
|
array('type' => 'radio',
|
||||||
|
'separator' => '<BR>',
|
||||||
|
'onclick' => ('switchPaymentType(' .
|
||||||
|
'\\\'payment-type-div\\\', ' .
|
||||||
|
'%{id}, ' .
|
||||||
|
'$(this).attr("id")' .
|
||||||
|
')' .
|
||||||
|
//' return false;'
|
||||||
|
''
|
||||||
|
),
|
||||||
|
'legend' => false,
|
||||||
|
'value' => $defaultType,
|
||||||
|
'options' => $radioOptions))) . "+\n";
|
||||||
|
?>
|
||||||
|
'</DIV>' +
|
||||||
|
|
||||||
|
'<DIV ID="payment-amount-div-%{id}" CLASS="input text required">' +
|
||||||
|
' <INPUT TYPE="text" SIZE="20"' +
|
||||||
|
' NAME="data[Entry][%{id}][amount]"' +
|
||||||
|
' CLASS="payment amount"' +
|
||||||
|
' ID="payment-amount-%{id}" />' +
|
||||||
|
' <LABEL CLASS="payment" FOR="payment-amount-%{id}">Amount</LABEL>' +
|
||||||
|
'</DIV>' +
|
||||||
|
|
||||||
|
<?php
|
||||||
|
foreach ($paymentTypes AS $type) {
|
||||||
|
$type = $type['TenderType'];
|
||||||
|
$div = '<DIV';
|
||||||
|
$div .= ' ID="payment-type-div-%{id}-'.$type['id'].'"';
|
||||||
|
$div .= ' CLASS="payment-type-div-%{id}"';
|
||||||
|
if ($type['id'] != $defaultType)
|
||||||
|
$div .= ' STYLE="display:none;"';
|
||||||
|
$div .= '>';
|
||||||
|
|
||||||
|
$div .= ' <INPUT TYPE="hidden"';
|
||||||
|
$div .= ' NAME="data[Entry][%{id}][type]['.$type['id'].'][tender_type_id]"';
|
||||||
|
$div .= ' VALUE="'.$type['id'].'"';
|
||||||
|
$div .= '>';
|
||||||
|
|
||||||
|
for ($i=1; $i<=4; ++$i) {
|
||||||
|
if (!empty($type["data{$i}_name"])) {
|
||||||
|
$div .= '<DIV CLASS="input text required">';
|
||||||
|
$div .= ' <INPUT TYPE="text" SIZE="20"';
|
||||||
|
$div .= ' NAME="data[Entry][%{id}][type]['.$type['id'].'][data'.$i.']"';
|
||||||
|
$div .= ' CLASS="payment"';
|
||||||
|
$div .= ' ID="payment-data'.$i.'-%{id}" />';
|
||||||
|
$div .= ' <LABEL';
|
||||||
|
$div .= ' CLASS="payment"';
|
||||||
|
$div .= ' FOR="payment-data'.$i.'-%{id}">';
|
||||||
|
$div .= $type["data{$i}_name"];
|
||||||
|
$div .= ' </LABEL>';
|
||||||
|
$div .= '</DIV>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$div .= '</DIV>';
|
||||||
|
echo "'$div' +\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
'</FIELDSET>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function switchPaymentType(paymentid_base, paymentid, radioid) {
|
||||||
|
var type_id = $("#"+radioid).val();
|
||||||
|
$("."+paymentid_base+"-"+paymentid+
|
||||||
|
":not(" +
|
||||||
|
"#"+paymentid_base+"-"+paymentid+"-"+type_id +
|
||||||
|
")").slideUp();
|
||||||
|
$("#"+paymentid_base+"-"+paymentid+"-"+type_id).slideDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
--></script>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
; // align
|
||||||
|
// Re-Enable warnings
|
||||||
|
Configure::write('debug', $saved_debug_state);
|
||||||
|
|
||||||
|
echo $this->element('customers', array
|
||||||
|
('config' => array
|
||||||
|
('grid_div_id' => 'customers-list',
|
||||||
|
'grid_div_class' => 'text-below',
|
||||||
|
'caption' => ('<A HREF="#" ONCLICK="$(\'#customers-list .HeaderButton\').click();'.
|
||||||
|
' return false;">Select Customer</A>'),
|
||||||
|
'grid_setup' => array('hiddengrid' => isset($customer['id'])),
|
||||||
|
'grid_events' => array('onSelectRow' =>
|
||||||
|
array('ids' =>
|
||||||
|
'if (ids != null){onRowSelect("#"+$(this).attr("id"), ids);}'),
|
||||||
|
'onHeaderClick' =>
|
||||||
|
array('gridstate' =>
|
||||||
|
'onGridState("#"+$(this).attr("id"), gridstate)'),
|
||||||
|
),
|
||||||
|
'action' => 'current',
|
||||||
|
'nolinks' => true,
|
||||||
|
'limit' => 10,
|
||||||
|
)));
|
||||||
|
|
||||||
|
echo ('<DIV CLASS="receipt grid-selection-text">' .
|
||||||
|
|
||||||
|
'<DIV CLASS="customer-selection-valid" style="display:none">' .
|
||||||
|
'Customer <SPAN id="receipt-customer-id"></SPAN>' .
|
||||||
|
': <SPAN id="receipt-customer-name"></SPAN>' .
|
||||||
|
|
||||||
|
/* '<DIV CLASS="supporting">' . */
|
||||||
|
/* '<TABLE>' . */
|
||||||
|
/* '<TR><TD CLASS="field">Balance:</TD><TD CLASS="value"><SPAN id="receipt-balance"></SPAN></TD></TR>' . */
|
||||||
|
/* '</TABLE>' . */
|
||||||
|
/* '</DIV>' . */
|
||||||
|
|
||||||
|
'</DIV>' . // END customer-selection-valid
|
||||||
|
|
||||||
|
'<DIV CLASS="customer-selection-invalid" style="display:none">' .
|
||||||
|
'Please select customer' .
|
||||||
|
'</DIV>' .
|
||||||
|
|
||||||
|
'</DIV>' . "\n");
|
||||||
|
|
||||||
|
|
||||||
|
echo $this->element('statement_entries', array
|
||||||
|
(// Grid configuration
|
||||||
|
'config' => array
|
||||||
|
(
|
||||||
|
'grid_div_id' => 'charge-entries',
|
||||||
|
'grid_div_class' => 'text-below',
|
||||||
|
'grid_events' => array('loadComplete' => 'onGridLoadComplete()'),
|
||||||
|
'grid_setup' => array('hiddengrid' => true),
|
||||||
|
'caption' => '<SPAN id="receipt-charges-caption"></SPAN>',
|
||||||
|
'action' => 'unreconciled',
|
||||||
|
'exclude' => array('Customer', 'Type', 'Debit', 'Credit'),
|
||||||
|
'include' => array('Applied', 'Balance'),
|
||||||
|
'remap' => array('Applied' => 'Paid'),
|
||||||
|
'limit' => 8,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
echo('<DIV CLASS="receipt grid-selection-text">' .
|
||||||
|
'<DIV CLASS="customer-selection-valid" style="display:none">' .
|
||||||
|
|
||||||
|
//'<DIV CLASS="supporting">' .
|
||||||
|
'<TABLE ID="supporting-table">' .
|
||||||
|
'<TR><TD CLASS="field">Balance:</TD><TD CLASS="value"><SPAN id="receipt-balance"></SPAN></TD></TR>' .
|
||||||
|
'</TABLE>' .
|
||||||
|
//'</DIV>' .
|
||||||
|
|
||||||
|
'</DIV>' . // END customer-selection-valid
|
||||||
|
'</DIV>' .
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
echo $form->create(null, array('id' => 'receipt-form',
|
||||||
|
'url' => array('controller' => 'transactions',
|
||||||
|
'action' => 'postReceipt')));
|
||||||
|
|
||||||
|
|
||||||
|
echo $form->input("id",
|
||||||
|
array('id' => 'customer-id',
|
||||||
|
'type' => 'hidden',
|
||||||
|
'value' => 0));
|
||||||
|
|
||||||
|
echo $this->element('form_table',
|
||||||
|
array('class' => "item receipt transaction entry",
|
||||||
|
//'with_name_after' => ':',
|
||||||
|
'field_prefix' => 'Transaction',
|
||||||
|
'fields' => array
|
||||||
|
("stamp" => array('opts' => array('type' => 'text'),
|
||||||
|
'between' => '<A HREF="#" ONCLICK="datepickerNow(\'TransactionStamp\'); return false;">Now</A>',
|
||||||
|
),
|
||||||
|
"comment" => array('opts' => array('size' => 50),
|
||||||
|
),
|
||||||
|
)));
|
||||||
|
|
||||||
|
echo "<BR>\n";
|
||||||
|
echo $form->input('repeat', array('type' => 'checkbox',
|
||||||
|
'id' => 'repeat',
|
||||||
|
'label' => 'Enter Multiple Receipts')) . "\n";
|
||||||
|
echo $form->submit('Generate Receipt') . "\n";
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php /*
|
||||||
|
<fieldset CLASS="payment superset">
|
||||||
|
<legend>Payments</legend>
|
||||||
|
*/ ?>
|
||||||
|
<input type="hidden" id="payment-entry-id" value="0">
|
||||||
|
<div id="payments"></div>
|
||||||
|
<?php /*
|
||||||
|
<fieldset> <legend>
|
||||||
|
<a href="#" onClick="addPaymentSource(true); return false;">Add Another Payment</a>
|
||||||
|
</legend> </fieldset>
|
||||||
|
</fieldset>
|
||||||
|
*/ ?>
|
||||||
|
|
||||||
|
<?php echo $form->end('Generate Receipt'); ?>
|
||||||
|
|
||||||
|
<?php /* echo '</DIV>' . "\n"; // End of the dialog DIV */ ?>
|
||||||
|
|
||||||
|
<div id="results"></div>
|
||||||
|
<div id="output-debug" style="display:none"></div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// Warnings _really_ screw up javascript
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("#TransactionStamp")
|
||||||
|
.attr('autocomplete', 'off')
|
||||||
|
.datepicker({ constrainInput: true,
|
||||||
|
numberOfMonths: [1, 1],
|
||||||
|
showCurrentAtPos: 0,
|
||||||
|
dateFormat: 'mm/dd/yy' });
|
||||||
|
|
||||||
|
$("#receipt-customer-id").html("INTERNAL ERROR");
|
||||||
|
$("#receipt-customer-name").html("INTERNAL ERROR");
|
||||||
|
$("#receipt-balance").html("INTERNAL ERROR");
|
||||||
|
$("#receipt-charges-caption").html("Outstanding Charges");
|
||||||
|
|
||||||
|
<?php if (isset($customer['id'])): ?>
|
||||||
|
$("#customer-id").val(<?php echo $customer['id']; ?>);
|
||||||
|
//$("#receipt-customer-id").html("<?php echo '#'.$customer['id']; ?>");
|
||||||
|
$("#receipt-customer-id").html('<A HREF="' +
|
||||||
|
"<?php echo $html->url(array('controller' => 'customers',
|
||||||
|
'action' => 'view')); ?>"
|
||||||
|
+ "/" +
|
||||||
|
"<?php echo $customer['id']; ?>" +
|
||||||
|
'">#' +
|
||||||
|
"<?php echo $customer['id']; ?>" +
|
||||||
|
'</A>');
|
||||||
|
$("#receipt-customer-name").html("<?php echo $customer['name']; ?>");
|
||||||
|
$("#receipt-balance").html(fmtCurrency("<?php echo $stats['balance']; ?>"));
|
||||||
|
onGridState(null, 'hidden');
|
||||||
|
<?php else: ?>
|
||||||
|
onGridState(null, 'visible');
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
resetForm();
|
||||||
|
datepickerNow('TransactionStamp');
|
||||||
|
|
||||||
|
<?php if ($this->params['dev']): ?>
|
||||||
|
$('#output-debug').html('Post Output');
|
||||||
|
$('#output-debug').show();
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
});
|
||||||
|
--></script>
|
||||||
|
|
||||||
|
</div>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user