TimeTrex/classes/ChequeForms/ChequeForms_Base.class.php

679 lines
20 KiB
PHP

<?php
/*********************************************************************************
*
* TimeTrex is a Workforce Management program developed by
* TimeTrex Software Inc. Copyright (C) 2003 - 2021 TimeTrex Software Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY TIMETREX, TIMETREX DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
*
* You should have received a copy of the GNU Affero General Public License along
* with this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
*
* You can contact TimeTrex headquarters at Unit 22 - 2475 Dobbin Rd. Suite
* #292 West Kelowna, BC V4T 2E9, Canada or at email address info@timetrex.com.
*
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Powered by TimeTrex" logo. If the display of the logo is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Powered by TimeTrex".
*
********************************************************************************/
/**
* @package ChequeForms
*/
class ChequeForms_Base {
public $debug = FALSE;
public $data = NULL; //Form data is stored here in an array.
public $records = array(); //Store multiple records here to process on a single form. ie: T4's where two employees can be on a single page.
public $class_directory = NULL;
/*
* PDF related variables
*/
public $pdf_object = NULL;
public $template_index = array();
public $current_template_index = NULL;
public $page_offsets = array( 0, 0 ); //x, y
public $template_offsets = array( 0, 0 ); //x, y
public $show_background = FALSE; //Do not show the PDF background
public $default_font = 'helvetica'; // helvetica
function setDebug( $bool ) {
$this->debug = $bool;
}
function getDebug() {
return $this->debug;
}
function setClassDirectory( $dir ) {
$this->class_directory = $dir;
}
function Output( $type ) {
switch ( strtolower($type) ) {
case 'pdf':
return $this->_outputPDF( $type );
break;
case 'xml':
return $this->_outputXML( $type );
break;
}
}
function getRecords() {
return $this->records;
}
function setRecords( $data ) {
$this->records = $data;
return TRUE;
}
function addRecord( $data ) {
$this->records[] = $data;
return TRUE;
}
function clearRecords() {
$this->records = array();
}
function countRecords() {
return count($this->records);
}
function getFilterFunction( $name ) {
$variable_function_map = array();
if ( isset($variable_function_map[$name]) ) {
return $variable_function_map[$name];
}
return FALSE;
}
function getDisplayDateFormat() {
$formats = array(
'd/m/Y' => 'd / m / y ',
'm/d/Y' => 'm / d / y ',
);
if ( isset($formats[$this->getDateFormat()]) ) {
return $formats[$this->getDateFormat()];
}
return FALSE;
}
function getDateFormat() {
if ( isset( $this->country ) && strtolower($this->country) == 'ca' ) {
$date_format = 'd/m/Y';
} else {
$date_format = 'm/d/Y';
}
return $date_format;
}
/*
*
*
* Automatically calculate the amount_words
*
*/
function filterAmountWords( $value ) {
if ( isset( $this->amount ) ) {
require_once( 'Numbers/Words.php' );
$numbers_words = new Numbers_Words();
$value = str_pad( ucwords( $numbers_words->toWords( floor($this->amount), 'en_US' ) ).' ', 65, "-", STR_PAD_RIGHT );
}
return $value;
}
/*
*
*
* Automatically calculate the amount_cents
*
*/
function filterAmountCents( $value ) {
if ( isset( $this->amount ) ) {
$value = Misc::getAfterDecimal($this->amount) .'/100';
}
return $value;
}
function filterAmountWordsCents( $value ) {
return $this->filterAmountWords($value) . ' '. TTi18n::gettext('and') . ' '. $this->filterAmountCents($value) . ' *****';
}
/*
*
*
* Automatically calculate the amount_padded
*
*/
function filterAmountPadded( $value ) {
if ( isset( $this->amount ) ) {
$value = str_pad( Misc::MoneyFormat( $this->amount ), 12, '*', STR_PAD_LEFT);
}
if ( get_class($this) === 'ChequeForms_9085' ) {
return ' ' . $this->symbol . $value;
}
if ( get_class($this) === 'ChequeForms_FORM1' ) {
return ' ' . $this->symbol . $value;
}
if ( get_class($this) === 'ChequeForms_FORM2' ) {
return $this->symbol . ' ' . $value;
}
return $value;
}
// Format date as the country
function filterDate( $epoch ) {
return date( $this->getDateFormat(), $epoch );
}
function filterAddress( $value ) {
if ( isset( $this->address1 ) ) {
$value = $this->address1 . ' ';
}
if ( isset( $this->address2 ) ) {
$value .= $this->address2;
}
return $value;
}
function filterProvince( $value ) {
if ( isset( $this->city ) ) {
$value = $this->city;
}
if ( isset( $this->province ) ) {
$value .= ', ' . $this->province;
}
if ( isset( $this->postal_code ) ) {
$value .= ' ' . $this->postal_code;
}
return $value;
}
/*
*
* PDF helper functions
*
*/
function setPDFObject( &$obj ) {
$this->pdf_object = $obj;
return TRUE;
}
function getPDFObject() {
return $this->pdf_object;
}
function setShowBackground( $bool ) {
$this->show_background = $bool;
return TRUE;
}
function getShowBackground() {
return $this->show_background;
}
function setPageOffsets( $x, $y ) {
$this->page_offsets = array( (float)$x, (float)$y );
return TRUE;
}
function getPageOffsets( $type = NULL ) {
switch ( strtolower($type) ) {
case 'x':
return $this->page_offsets[0];
break;
case 'y':
return $this->page_offsets[1];
break;
default:
return $this->page_offsets;
break;
}
}
function setTemplateOffsets( $x, $y ) {
$this->template_offsets = array( $x, $y );
return TRUE;
}
function getTemplateOffsets( $type = NULL ) {
switch ( strtolower($type) ) {
case 'x':
return $this->template_offsets[0];
break;
case 'y':
return $this->template_offsets[1];
break;
default:
return $this->template_offsets;
break;
}
}
//This gives the same affect of adding a new page on the next time Draw() is called.
//Can be used when multiple records are processed for a single form.
function resetTemplatePage() {
$this->current_template_index = NULL;
return TRUE;
}
function getSchemaSpecificCoordinates( $schema, $key, $sub_key1 = NULL ) {
unset($schema['function']);
if ( $sub_key1 !== NULL ) {
if ( isset($schema['coordinates'][$key][$sub_key1]) ) {
return array( 'coordinates' => $schema['coordinates'][$key][$sub_key1] );
}
} else {
if ( isset($schema['coordinates'][$key]) ) {
/*
$tmp = $schema['coordinates'][$key];
unset($schema['coordinates']);
$schema['coordinates'] = $tmp;
return $schema;
*/
return array( 'coordinates' => $schema['coordinates'][$key], 'font' => $schema['font'] );
}
}
return FALSE;
}
// Draw the same data at different locations
// value should be string
function drawPiecemeal( $value, $schema ) {
unset( $schema['function'] );
foreach( $schema['coordinates'] as $key => $coordinates ) {
if ( is_array( $coordinates ) ) {
$mode['coordinates'] = $coordinates;
if ( isset( $schema['font'] ) ) {
$mode['font'] = $schema['font'];
}
if ( isset( $schema['multicell'] ) ) {
$mode['multicell'] = $schema['multicell'];
}
$this->Draw( $value, $mode );
}
}
return TRUE;
}
//Draw each element of an array at different locations.
//Value must be an array.
function drawSegments( $value, $schema ) {
if ( is_array($value) ) {
$i=0;
foreach( $value as $segment ) {
$this->Draw( $segment, $this->getSchemaSpecificCoordinates( $schema, $i ) );
$i++;
}
}
return TRUE;
}
function drawNormal( $value, $schema ) {
if ( $value !== FALSE ) { //If value is FALSE don't draw anything, this prevents a blank cell from being drawn overtop of other text.
unset($schema['function']); //Strip off the function element to prevent infinite loop
$this->Draw( $value, $schema );
return TRUE;
}
return FALSE;
}
function drawImage( $file_name, $schema) {
if ( $file_name == '' ) {
return FALSE;
}
$pdf = $this->getPDFObject();
if ( $this->getDebug() == TRUE ) { //Outline the image.
$pdf->setXY( ( $schema['coordinates']['x'] + $this->getPageOffsets( 'x' ) ), ( ( $schema['coordinates']['y'] + $this->getPageOffsets( 'y' ) ) ) );
$pdf->Cell( $schema['coordinates']['w'], $schema['coordinates']['h'], '', 1, 0, 'C', 0 );
}
$pdf->setImageScale( PDF_IMAGE_SCALE_RATIO );
$pdf->Image( $file_name, ( $schema['coordinates']['x'] + $this->getPageOffsets('x') ), ( $schema['coordinates']['y'] + $this->getPageOffsets('y') ), $schema['coordinates']['w'], $schema['coordinates']['h'], '', '', '', FALSE, 300, '', FALSE, FALSE, 0, TRUE);
return TRUE;
}
function drawAlignmentGrid( $value, $schema ) {
if ( $value !== TRUE ) {
return TRUE;
}
unset($schema['function']); //Strip off the function element to prevent infinite loop
$pdf = $this->getPDFObject();
$cell_size = 2; //In 'mm'
//Alignment Grid Label.
$pdf->setFontSize( 6 );
$pdf->setXY( ( $schema['coordinates']['x'] + $this->getPageOffsets('x') ), ( ( $schema['coordinates']['y'] + $this->getPageOffsets('y') ) - 3 ) );
$pdf->Cell( $schema['coordinates']['w'], 3, TTi18n::getText('Alignment Grid') .': '. $cell_size .' x '. $cell_size .'mm Offset: '. $this->getPageOffsets('x') .' x '. $this->getPageOffsets('y') .'mm', 1, 0, 'C', 0 );
//Blue
$pdf->SetTextColor( 0, 0, 255 );
$pdf->setFontSize( 0 );
$pdf->setCellPadding( 0 );
$pdf->SetLineWidth( 0.1 );
//Draw grid.
$x = $schema['coordinates']['x'];
$y = $schema['coordinates']['y'];
$w = $schema['coordinates']['w'];
$h = $schema['coordinates']['h'];
$i = 0;
while( TRUE && $i < 1000000 ) {
if ( $x == $schema['coordinates']['x'] || $x == ( $schema['coordinates']['x'] + ( $schema['coordinates']['w'] - $cell_size ) )
|| $y == $schema['coordinates']['y'] || $y == ( $schema['coordinates']['y'] + ( $schema['coordinates']['h'] - $cell_size ) ) ) {
$pdf->setDrawColor( 0, 0, 0 ); //Black - All cells on the border of the grid will be black, so we know its bounds.
} else {
$pdf->setDrawColor( 128, 128, 128 ); //Gray
}
$pdf->setXY( ( $x + $this->getPageOffsets('x') ), ( $y + $this->getPageOffsets('y') ) );
$pdf->Cell( $cell_size, $cell_size, '', 1, 0, 'L', 0 );
$x = ( $x + $cell_size );
if ( $x >= ( $schema['coordinates']['x'] + $w ) ) {
$x = $schema['coordinates']['x'];
$y = ( $y + $cell_size );
}
if ( $y >= ( $schema['coordinates']['y'] + $h ) ) {
break;
}
$i++;
}
return TRUE;
}
function addPage( $schema = NULL ) {
$pdf = $this->getPDFObject();
$pdf->AddPage();
if ( $this->getShowBackground() == TRUE && isset($this->template_index[$schema['template_page']]) ) {
if ( isset($schema['combine_templates']) && is_array($schema['combine_templates']) ) {
$template_schema = $this->getTemplateSchema();
//Handle combining multiple template together with a X,Y offset.
foreach( $schema['combine_templates'] as $combine_template ) {
Debug::text('Combining Template Pages... Template: '. $combine_template['template_page'] .' Y: '. $combine_template['y'], __FILE__, __LINE__, __METHOD__, 10);
$pdf->useTemplate( $this->template_index[$combine_template['template_page']], $combine_template['x']+$this->getTemplateOffsets('x'), $combine_template['y']+$this->getTemplateOffsets('y') );
$this->setPageOffsets( $combine_template['x'], $combine_template['y']);
$this->current_template_index = $schema['template_page'];
$this->initPage( $template_schema );
}
unset($combine_templates);
$this->setPageOffsets( 0, 0 ); //Reset page offsets after each template is initialized.
} else {
$pdf->useTemplate( $this->template_index[$schema['template_page']], $this->getTemplateOffsets('x'), $this->getTemplateOffsets('y') );
}
}
$this->current_template_index = $schema['template_page'];
return TRUE;
}
function initPage( $template_schema ) {
if ( is_array($template_schema) ) {
foreach( $template_schema as $field => $init_schema ) {
if ( is_numeric($field) ) {
//Debug::text(' Initializing Template Page... Field: '. $field, __FILE__, __LINE__, __METHOD__, 10);
$this->Draw( $this->$field, $init_schema );
}
}
unset($template_schema, $field, $init_schema);
return TRUE;
}
return FALSE;
}
//Generic draw function that works strictly off the coordinate map.
//It checks for a variable specific function before running though, so we can handle more complex
//drawing functionality.
function Draw( $value, $schema ) {
if ( !is_array($schema) ) {
return FALSE;
}
//If its set, use the static value from the schema.
if ( isset($schema['value'])) {
$value = $schema['value'];
unset($schema['value']);
}
//If custom function is defined, pass off to that immediate.
//Else, try the generic drawing method.
if ( isset($schema['function']) ) {
if ( !is_array($schema['function']) ) {
$schema['function'] = (array)$schema['function'];
}
foreach( $schema['function'] as $function ) {
if ( method_exists( $this, $function) ) {
$value = $this->$function($value, $schema);
}
}
unset($function);
return $value;
}
$pdf = $this->getPDFObject();
//Make sure we don't load the same template more than once.
if ( isset($schema['template_page']) && $schema['template_page'] != $this->current_template_index ) {
//Debug::text('Adding new page: '. $schema .' Template Page: '. $schema['template_page'], __FILE__, __LINE__, __METHOD__, 10);
$this->addPage( $schema );
} else {
//Debug::text('Skipping template... Value: '. $value, __FILE__, __LINE__, __METHOD__, 10);
}
//on_background flag forces that item to only be shown if the background is as well.
//This has to go below any addPage() call, otherwise pages won't be added if the first cell is only to be shown on the background.
if ( isset($schema['on_background']) && $schema['on_background'] == TRUE && $this->getShowBackground() == FALSE ) {
return FALSE;
}
if ( isset($schema['font']) ) {
if ( !isset($schema['font']['font']) ) {
$schema['font']['font'] = $this->default_font;
}
if ( !isset($schema['font']['type']) ) {
$schema['font']['type'] = '';
}
if ( !isset($schema['font']['size']) ) {
$schema['font']['size'] = 8;
}
$pdf->SetFont( $schema['font']['font'], $schema['font']['type'], $schema['font']['size']);
} else {
$pdf->SetFont( $this->default_font, '', 8 );
}
if ( isset($schema['coordinates']) ) {
$coordinates = $schema['coordinates'];
//var_dump( Debug::BackTrace() );
if ( isset($coordinates['text_color']) && is_array( $coordinates['text_color'] ) ) {
$pdf->setTextColor( $coordinates['text_color'][0], $coordinates['text_color'][1], $coordinates['text_color'][2] );
} else {
$pdf->setTextColor( 0, 0, 0 ); //Black text.
}
if ( isset($coordinates['fill_color']) && is_array( $coordinates['fill_color'] ) ) {
$pdf->setFillColor( $coordinates['fill_color'][0], $coordinates['fill_color'][1], $coordinates['fill_color'][2] );
$coordinates['fill'] = 1;
} else {
$pdf->setFillColor( 255, 255, 255 ); //White
$coordinates['fill'] = 0;
}
$pdf->setXY( $coordinates['x']+$this->getPageOffsets('x'), $coordinates['y']+$this->getPageOffsets('y') );
if ( $this->getDebug() == TRUE ) {
$pdf->setDrawColor( 0, 0, 255 );
$coordinates['border'] = 1;
} else {
if ( !isset($coordinates['border']) ) {
$coordinates['border'] = 0;
}
}
if ( isset($schema['multicell']) && $schema['multicell'] == TRUE ) {
//Debug::text('Drawing MultiCell... Value: '. $value, __FILE__, __LINE__, __METHOD__, 10);
$pdf->MultiCell( $coordinates['w'], $coordinates['h'], $value, $coordinates['border'], strtoupper($coordinates['halign']), $coordinates['fill'] );
} else {
//Debug::text('Drawing Cell... Value: '. $value, __FILE__, __LINE__, __METHOD__, 10);
$pdf->Cell( $coordinates['w'], $coordinates['h'], $value, $coordinates['border'], 0, strtoupper($coordinates['halign']), $coordinates['fill'] );
}
unset($coordinates);
} else {
Debug::text('NOT Drawing Cell... Value: '. $value, __FILE__, __LINE__, __METHOD__, 10);
}
return TRUE;
}
//Make sure we pass *ALL* data to this function, as it will overwrite existing data, but if one record has a field and another one doesn't,
//we need to send blank fields so the data is overwritten correctly.
function arrayToObject( $array ) {
if ( is_array($array) ) {
foreach( $array as $key => $value ) {
$this->$key = $value;
}
}
return TRUE;
}
function _outputPDF() {
//Initialize PDF with template.
$pdf = $this->getPDFObject();
//Get location map, start looping over each variable and drawing
$records = $this->getRecords();
if ( is_array($records) && count($records) > 0 ) {
$template_schema = $this->getTemplateSchema();
$e=0;
foreach( $records as $employee_data ) {
//Debug::Arr($employee_data, 'Employee Data: ', __FILE__, __LINE__, __METHOD__,10);
$this->arrayToObject( $employee_data ); //Convert record array to object
$template_page = NULL;
foreach( $template_schema as $field => $schema ) {
$this->Draw( $this->$field, $schema );
}
$this->resetTemplatePage();
$e++;
}
}
$this->clearRecords();
return TRUE;
}
/*
*
* Magic functions.
*
*/
function __set( $name, $value ) {
$filter_function = $this->getFilterFunction( $name );
if ( $filter_function != '' ) {
if ( !is_array( $filter_function ) ) {
$filter_function = (array)$filter_function;
}
foreach( $filter_function as $function ) {
//Call function
if ( method_exists( $this, $function ) ) {
$value = $this->$function( $value );
if ( $value === FALSE ) {
return FALSE;
}
}
}
unset($function);
}
$this->data[$name] = $value;
return TRUE;
}
function __get( $name ) {
if ( isset($this->data[$name]) ) {
return $this->data[$name];
}
return FALSE;
}
public function __isset($name) {
return isset($this->data[$name]);
}
public function __unset($name) {
unset($this->data[$name]);
}
}
?>