// A random string used in security hashing methods.
Configure::write('Security.salt', 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi');
// A random numeric string (digits only) used to encrypt/decrypt strings.
Configure::write('Security.cipherSeed', '76859309657453542496749683645');
* For system-wide user-defined variables, edit ''[cakephp]/app/Config/core.php'' and add the following: /**
//#######################################################
//# User-defined system strings.
//#######################################################
Configure::write('Company.Name', 'Acme Inc.'); // Company Name
Configure::write('Company.Email', 'info@acme.com'); // Company Email
Read a config variable using:
Configure::read('Company.Name')
== Database Configuration ==
Edit file ''[cakephp]/app/Config/database.php'':
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'port' => '',
'login' => 'acmeusr',
'password' => 'c4k3-rUl3Z',
'database' => 'acme_cakephp_db',
'schema' => '',
'prefix' => '',
'encoding' => 'utf8'
);
== Email Configuration ==
Edit file ''[cakephp]/app/Config/email.php'':
class EmailConfig {
public $default = array(
'transport' => 'Mail',
//'from' => Configure::read('Company.Email'),
'from' => 'info@acme.com',
'charset' => 'utf-8',
'headerCharset' => 'utf-8',
);
public $smtp = array(
'transport' => 'Smtp',
//'from' => array('site@localhost' => 'My Site'),
//'from' => array(Configure::read('Company.Email') => Configure::read('Company.Name')),
'from' => array('info@acme.com' => 'Acme Inc'),
'host' => 'localhost',
'port' => 25,
'timeout' => 30,
//'username' => 'user',
//'password' => 'secret',
'username' => null,
'password' => null,
'client' => null,
'log' => false,
'charset' => 'utf-8',
'headerCharset' => 'utf-8',
);
public $fast = array(
//'from' => 'you@localhost',
//'from' => Configure::read('Company.Email'),
'from' => 'info@acme.com',
'sender' => null,
'to' => null,
'cc' => null,
'bcc' => null,
'replyTo' => null,
'readReceipt' => null,
'returnPath' => null,
'messageId' => true,
'subject' => null,
'message' => null,
'headers' => null,
'viewRender' => null,
'template' => false,
'layout' => false,
'viewVars' => null,
'attachments' => null,
'emailFormat' => null,
'transport' => 'Smtp',
'host' => 'localhost',
'port' => 25,
'timeout' => 30,
//'username' => 'user',
//'password' => 'secret',
'username' => null,
'password' => null,
'client' => null,
'log' => true,
'charset' => 'utf-8',
'headerCharset' => 'utf-8',
);
/*
// To use this feature, you will need to have the SSL configured in your PHP install.
public $gmail = array(
'host' => 'ssl://smtp.gmail.com',
'port' => 465,
'username' => 'my@gmail.com',
'password' => 'secret',
'transport' => 'Smtp'
);
// or using TLS SMTP
public $gmail = array(
'host' => 'smtp.gmail.com',
'port' => 465,
'username' => 'my@gmail.com',
'password' => 'secret',
'transport' => 'Smtp',
'tls' => true
);
*/
}
== Setup AppController ==
Edit file ''[cakephp]/app/Controller/AppController.php'':
App::uses('Controller', 'Controller');
App::uses('SessionComponent', 'Controller/Component');
App::uses('SessionHelper', 'Controller/Component');
App::uses('AuthHelper ', 'Controller/Component');
class AppController extends Controller
{
public $components = array(
'Session',
'Auth' => array(
//'loginRedirect' => array('controller' => 'articles', 'action' => 'index'), // at login, go to Articles list
'loginRedirect' => array('controller' => 'pages', 'action' => 'display', 'home'), // at login, go to Home
//'logoutRedirect' => array('controller' => 'users', 'action' => 'login'),
'logoutRedirect' => array('controller' => 'pages', 'action' => 'display', 'home'), // at logout, go to Home
'authError' => 'You must be logged in to view this page.',
'loginError' => 'Invalid Username or Password entered, please try again.',
'authorize' => array('Controller')
),
'DebugKit.Toolbar', // see https://github.com/cakephp/debug_kit for more details
);
// only allow the login controllers only
public function beforeFilter()
{
$this->Auth->allow('login');
}
public function isAuthorized($user)
{
// Here is where we should verify the role and give access based on role
//return true;
// Admin can access every action
if (isset($user['role']) && $user['role'] === 'admin')
{
return true;
}
// Default deny
return false;
}
}
== Setup UserController ==
Edit file ''[cakephp]/app/Config/routes.php'' to include custome routes:
// ###--- Custom Routes ---###
// Let us modify the core components of CakePHP to support the UserController login module.
// First, we need to modify routes.php so that we can have a custom link for login, logout
// and the dashboard. This step is not required but I do it so that the URLs look clean.
Router::connect('/dashboard', array('controller' => 'users', 'action' => 'index'));
Router::connect('/login', array('controller' => 'users', 'action' => 'login'));
Router::connect('/logout', array('controller' => 'users', 'action' => 'logout'));
// We also need to modify the home page so that it now points to the UserController login action.
//Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home')); // default
Router::connect('/', array('controller' => 'users', 'action' => 'login'));
== Install Basic Components/Plugins ==
=== DebugKit ===
* Download ''DebugKit'' from here: https://github.com/cakephp/debug_kit
* Unpack to ''[cakephp]/app/Plugin'' directory.
* Edit ''[cakephp]/app/Config/bootstrap.php'' and uncomment the following: CakePlugin::loadAll(); // Loads all plugins at once (optional)
CakePlugin::load('DebugKit');
* Edit ''[cakephp]/app/Config/core.php'' and uncomment one of the following:
//Configure::write('debug', 0); // for production mode
Configure::write('debug', 1); // for development mode
//Configure::write('debug', 2); // for development mode (with sql dump)
* Include the toolbar component in your ''[cakephp]/app/Controller/AppController.php'': class AppController extends Controller
{
public $components = array('DebugKit.Toolbar', ...);
...
}
=== Articles ==
* Articles Component: http://book.cakephp.org/2.0/en/getting-started.html#blog-tutorial
=== Authentication ===
* Authentication Component: http://book.cakephp.org/2.0/en/tutorials-and-examples/blog-auth-example/auth.html
=== AuthorizeNetComponent ==
* Include the following file ''[cakephp/app/Controller/Component/AuthorizeNetComponent.php]'':
Use it. Call the component from the controller needing it:
"First",
"lname" => "Last",
"company" => "Acme Inc.",
"address" => "123 Fake St. Suite 0",
"city" => "City",
"state" => "ST",
"zip" => "90210",
"country" => "USA");
$shippinginfo = array("fname" => "First",
"lname" => "Last",
"company" => "Acme Inc.",
"address" => "123 Fake St. Suite 0",
"city" => "City",
"state" => "ST",
"zip" => "90210",
"country" => "USA");
$response = $this->AuthorizeNet->chargeCard('########', '##############', '4111111111111111', '01', '2010', '123', true, 110, 5, 5, "PurchaseofGoods", $billinginfo, "customeremail@example.com", 555-5555", $shippinginfo);
}
}
?>
The call to the component function chargeCard uses the following format:
$response:Array = $this->AuthorizeNet->chargeCard($loginid:String, $trankey:String, $ccnum:String, $ccexpmonth:String, $ccexpyear:String, $ccver:String, $live:Boolean, $amount:Number, $tax:Number, $shipping:Number, $desc:String, $billinginfo:Array, $email:String, $phone:String, $shippinginfo:Array);
PARAMETERS
* $loginid : Your Authorize.net Login ID
* $trankey : Your Authorize.net Transaction Key
* $ccnum : The system removes any spaces in the string to meet Authorize.net requirements
* $ccexpmonth : 2 digit month string
* $ccexpyear : 2 or 4 digit year string
* $ccver : The 3 or 4 digit card verificaton code found on the back of Visa/Mastercard and the front of AmEx
* $live : Whether to process as a live or test transaction - true : Live Transcation - false : Test Transaction
* $amount : Total amount of the transaction. This must include both tax and shipping if applicable.
* $tax : Tax amount charged (if any)
* $shipping : Shipping cost (if any)
* $desc : Description of the transaction to be logged into Authorize.net system
* $billinginfo : Associative Array containing values for customer billing details
* $email : Customer email
* $phone : Customer phone
* $billinginfo : Associative Array containing values for customer shipping details
RESPONSE
* $response : Array (1 based) containing the Payment Gateway Resonse fields
The response is an array of all the response codes from Authorize.net's system. Details on all these responses is available at [[http://developer.authorize.net/guides/AIM/]]. Here are some of the most important fields:
$response[1] = Response Code (1 = Approved, 2 = Declined, 3 = Error, 4 = Held for Review)
$response[2] = Response Subcode (Code used for Internal Transaction Details)
$response[3] = Response Reason Code (Code detailing response code)
$response[4] = Response Reason Text (Text detailing response code and response reason code)
$response[5] = Authorization Code (Authorization or approval code - 6 characters)
$response[6] = AVS Response (Address Verification Service response code - A, B, E, G, N, P, R, S, U, W, X, Y, Z)
(A, P, W, X, Y, Z are default AVS confirmation settings - Use your Authorize.net Merchant Interface to change these settings)
(B, E, G, N, R, S, U are default AVS rejection settings - Use your Authorize.net Merchant Interface to change these settings)
$response[7] = Transaction ID (Gateway assigned id number for the transaction)
$response[38] = MD5 Hash (Gateway generated MD5 has used to authenticate transaction response)
$response[39] = Card Code Response (CCV Card Code Verification response code - M = Match, N = No Match, P = No Processed, S = Should have been present, U = Issuer unable to process request)
=== TCPDF ===
* Download [[http://www.tcpdf.org|TCPDF]] and unzip.
* Move folder to ''[cakephp]/app/Vendor/tcpdf''
* Create ''[cakephp]/app/Vendor/xtcpdf.php'' (see [[http://www.martin-schenk.es/en/cakephp-2-pdf-with-tcpdf]]):
* Create ''[cakephp]app/View/Layouts/pdf/default.ctp'':
* In your Controller, for example in ''[cakephp]/app/Controller/ArticlesController.php'', create a new action:
public function create_pdf()
{
$users = $this->User->find('all');
$this->set(compact('users'));
$this->layout = '/pdf/default';
$this->render('/Pdf/my_pdf_view');
}
* Create a new view file ''[cakephp]/app/View/Pdf/my_pdf_view.ctp'':
AddPage();
$html = '
hello world
';
foreach ( $posts as $post ){
$html .= "\n
" . $post['Post']['title'];
}
$pdf->writeHTML($html, true, false, true, false, '');
$pdf->lastPage();
echo $pdf->Output(APP . 'files/pdf' . DS . 'test.pdf', 'I' /* Dest: F = File to disk, I = Inline to browser */);
?>
For example:
* In controller, generate the data and call PDF generator:
//---------------------------------------------------------------------------------------------
// description: Generate packet labels form.
// parameters :
// return :
//---------------------------------------------------------------------------------------------
public function GenFormPacketLabels($aWorkshopCode, $aContentType="attendees", $id=0)
{
$this->GenFormData($aWorkshopCode, $aContentType, $id);
$this->SetFormDimensions("PacketLabels");
}
//---------------------------------------------------------------------------------------------
// description: Generate course evaluation form.
// parameters :
// return :
//---------------------------------------------------------------------------------------------
private function GenFormData($aWorkshopCode, $aContentType="attendees", $id=0)
{
$attendees = array();
$this->set('attendees', $attendees);
// Get workshop data
if (!empty($aWorkshopCode))
{
$workshop = ClassRegistry::init('Workshop')->find('first', array(
'conditions' => array('Workshop.Code' => $aWorkshopCode),
'recursive' => 0,
));
if (!$workshop)
{
throw new NotFoundException(__('Invalid workshop'));
}
}
$this->set('workshop', $workshop);
// Generate PDF report with custom data
if ($this->request->is('post'))
{
if ($this->request->data)
{
// Get custom name tag data
$attendees = $this->GenAttendeeRec($aWorkshopCode, $this->request->data);
$this->set('attendees', $attendees);
// Set Header Response to PDF content type
$this->layout = '/pdf/default';
$this->response->type('application/pdf');
$this->render('/MyEntity/genlabels');
}
}
}
//---------------------------------------------------------------------------------------------
// description: Set form dimensions.
// parameters : $aTemplateType - Template type (string) to use: PacketLabels, MailingLabels, NameTags.
// return : void
//---------------------------------------------------------------------------------------------
private function SetFormDimensions($aTemplateType)
{
$this->set('topmargin', $this->GetAppSetting($aTemplateType.'TopMargin')); // mm
$this->set('leftmargin', $this->GetAppSetting($aTemplateType.'LeftMargin')); // mm
$this->set('rightmargin', $this->GetAppSetting($aTemplateType.'RightMargin')); // mm
$this->set('bottommargin', $this->GetAppSetting($aTemplateType.'BottomMargin')); // mm
$this->set('intercolmargin', $this->GetAppSetting($aTemplateType.'InterColMargin')); // mm
$this->set('interrowmargin', $this->GetAppSetting($aTemplateType.'InterRowMargin')); // mm
$this->set('colsperpage', $this->GetAppSetting($aTemplateType.'ColsPerPage')); // label cols
$this->set('rowsperpage', $this->GetAppSetting($aTemplateType.'RowsPerPage')); // label rows
$this->set('cellborder', $this->GetAppSetting($aTemplateType.'CellBorder')); // 0: no border
//0: no border (default), 1: frame, L: left, T: top, R: right, B: bottom
}
* Create view ''/app/View/MyEntity/genlabels.ctp'':
'',
'align' => 'C',
'stretch' => false,
'fitwidth' => true,
'cellfitalign' => '',
'border' => false,
'hpadding' => 'auto',
'vpadding' => 'auto',
'fgcolor' => array(0,0,0),
'bgcolor' => false, //array(255,255,255),
'text' => true,
'font' => 'helvetica',
'fontsize' => 8,
'stretchtext' => 4
);
//$aWorkshopName = $workshop['Workshop']['Code'] . ' - ' . $workshop['Workshop']['Name'];
$aWorkshopName = $this->Text->truncate(
$workshop['Workshop']['Code'] . ' - ' . $workshop['Workshop']['Name'],
120 /* max chars per line */ / $colsperpage /* max chars */,
array('ellipsis' => '...', 'exact' => false )
);
$aWorkshopLocation = $workshop['Workshop']['Address'];
?>
SetCreator(PDF_CREATOR);
$pdf->SetAuthor(Configure::read('Company.Name'));
$pdf->SetTitle($headertitle);
$pdf->SetSubject($headersubtitle);
$pdf->SetKeywords('');
// set default header data
$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, $headertitle, $headersubtitle);
// set header and footer fonts
$pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
$pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
$pdf->setPrintHeader(false); // do not print footer
$pdf->setPrintFooter(false); // do not print footer
// set default monospaced font
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
// set margins
//$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$pdf->SetMargins($leftmargin, $topmargin, $rightmargin);
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
// set auto page breaks
//$pdf->SetAutoPageBreak(FALSE, PDF_MARGIN_BOTTOM);
$pdf->SetAutoPageBreak(FALSE, $bottommargin);
// set image scale factor
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
// set some language-dependent strings (optional)
if (@file_exists(dirname(__FILE__).'/lang/eng.php')) {
require_once(dirname(__FILE__).'/lang/eng.php');
$pdf->setLanguageArray($l);
}
// ---------------------------------------------------------
// Add Page
// ---------------------------------------------------------
set_time_limit(0); // set execution time limit to None
// ---------------------------------------------------------
// Doc Content
$pdf->SetFont($defaultfont, 'B', 18);
$labelcount = 0;
$isLineBreak = 0;
$rowcount = 0;
foreach($attendees as $row)
{
if (($labelcount % $labelsperpage) == 0) { $pdf->AddPage(); $rowcount = 0; }
$colcount = ($labelcount % $colsperpage);
if ($colcount == 0)
{
// First cell in row
$Xoffset = $leftmargin;
$Yoffset = $topmargin + (($cellheight + $interrowmargin) * $rowcount);
$isLineBreak = 0;
}
else
{
// Any cell (except First cell) in row
$Xoffset = $leftmargin + (($cellwidth + $intercolmargin) * $colcount);
$Yoffset = $topmargin + (($cellheight + $interrowmargin) * $rowcount);
$isLineBreak = 0;
// Last cell in row
if ($colcount == ($colsperpage-1))
{
$isLineBreak = 1;
$rowcount++;
}
}
if (!empty($row['Registration']['LastName']) && !empty($row['Registration']['FirstName']))
{
$aFullName = StringUtils::nameize($row['Registration']['LastName'] . ', ' .
$row['Registration']['FirstName']); //require_once(APP . 'Lib' . DS . 'StringUtils.php');
} else {
$aFullName = "";
}
$aPacketID = $row['Registration']['PacketID'];
$aPacketID = ( ($aPacketID > 0) ? (substr($aPacketID, 0, 4) . '-' . substr($aPacketID, 4, 4)) : 0);
$pdf->SetFont($defaultfont, 'B', 18);
//$aPacketLabel = "\n" . $aFullName . "\n" . $aPacketID . "\n" . $labelcount; // with counter (debug)
$aPacketLabel = "\n" . $aFullName . "\n" . $aPacketID;
// Barcode (print in X,Y coordinates of next cell)
$x = $pdf->GetX(); // save X pos
$y = $pdf->GetY(); // save Y pos
$Xoffsetbarcode = $Xoffset + (($cellwidth - 50 /* barcode width */) / 2);
$Yoffsetbarcode = $Yoffset + (($cellheight - 15 /* barcode height */) / 2) + 18 /* offset from ctr */;
$pdf->write1DBarcode($aPacketID, 'C128', $Xoffsetbarcode, $Yoffsetbarcode,
50 /* width */, 15 /* height */, 0.4 /* bar resolution */, $barcodestyle, 'N');
// Workshop name
$pdf->SetXY($Xoffset, $Yoffset);
$pdf->SetFont($defaultfont, '', 8);
$pdf->Write($height, $aWorkshopName, '', 0, 'L', 0 /*$isnewline*/, $stretch,
$isfirstline, $isfirstblock, $heightmax);
// Cell
$pdf->SetXY($x, $y); // Reset X,Y so wrapping cell wraps around the barcode's cell.
$pdf->SetFont($defaultfont, 'B', 22);
$pdf->MultiCell($cellwidth, $cellheight, $aPacketLabel, $cellborder, 'C' /* align */,
$cellfill, $isLineBreak, $Xoffset, $Yoffset, true /* reset height */, 'M');
if ($isLineBreak) { $pdf->Ln(1); }
$labelcount++;
}
//$pdf->SetFont($defaultfont, '', 8);
//date_default_timezone_set('America/New_York');
//$pdf->Write($height, 'Generated: ' . date("Y-m-d H:i:s"), '', $isbgfilled, 'L',
true /* newline */, $stretch, $isfirstline, $isfirstblock, $heightmax);
// Close and output PDF document
ob_end_clean(); // Clean (erase) the output buffer and turn off output buffering
ob_start(); // Turn on output buffering, to avoid errors
$pdf->Output($workshop['Workshop']['Code'] . '-' . 'PacketLabels.pdf', 'I' /* Inline file dest */);
//ob_end_flush(); // Turn off output buffering
// ---------------------
// End
// ---------------------
?>
=== StringUtils ===
* Include this file in ''[cakephp]/app/Lib/StringUtils.php'':
* Create a View to include graph (Eg: ''[cakephp]/app/View/MyEntity/graphview.ctp''):
Values(1, 4, 8, 9, 16, 25, 27);
$graph->Render('LineGraph');
?>
* To include graph in a PDF, edit a View (using TCPDF) to include graph (Eg: ''[cakephp]/app/View/MyEntity/pdfgraphview.ctp''):
App::import('Vendor','xtcpdf');
$pdf = new XTCPDF('L' /* L=Letter, P=Portrait */, PDF_UNIT, 'Letter' /* Page Size */, true, 'UTF-8', false);
$pdf->AddPage();
//------------------------------
// Graph (using SVGGraph)
//------------------------------
//require_once 'svggraph/SVGGraph.php';
App::import('Vendor', 'xsvggraph');
$graph = new XSVGGraph(500, 400);
$graph->Values(1, 4, 8, 9, 16, 25, 27);
$output = $graph->fetch('LineGraph');
// Feed it to TCPDF (Since fetch without options generates the XML declaration and doctype).
// This should generate $output of the format:
//
// Feed it like this:
$pdf->ImageSVG('@' . $output, $x=15, $y=30, $w='', $h='',
$link='http://www.tcpdf.org', $align='', $palign='', $border=1, $fitonpage=false);
// Of course you can also save the output in a file, and then provide the path to the file:
//$pdf->ImageSVG($file='images/file.svg', $x=15, $y=30, $w='', $h='',
// $link='', $align='', $palign='', $border=0, $fitonpage=false);
$pdf->lastPage();
echo $pdf->Output(APP . 'files/pdf' . DS . 'articles.pdf', 'I' /* Dest: F = File saved to disk, I = Inline to browser */);
=== PHPExcel ===
* Download a copy of PhpExcel helper and component for CakePHP 2.x: [[https://github.com/segy/PhpExcel]].
* Copy files to respective folders in CakePHP app.
* Get PHPExcel updates from [[https://github.com/PHPOffice/PHPExcel]], and update helper files in ''[app]/vendor/PhpExcel''.
* See documentation:
* [[https://github.com/segy/PhpExcel/blob/master/View/Helper/PhpExcelHelper.php|PhpExcelHelper]]
* [[http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2009/05/07/4606.aspx|Use PHP to create Open XML Spreadsheet reports]].
In PhpExcel helper, edit function ''createdWorksheet()'' to look like this:
public function createWorksheet() {
// load vendor classes
App::import('Vendor', 'PHPExcel'); // <-- Check class name
$this->_xls = new PHPExcel();
$this->_row = 1;
return $this;
}
In controller, add references to helper:
class MyController extends AppController
{
...
public $helpers = array('Html', 'Form', 'Session', ..., 'PhpExcel');
...
}
In controller, add action to generate data:
...
function actionGetData($id)
{
$data = ClassRegistry::init('Customer')->find('all', array(
'conditions' => array('Customer.id' => $id),
));
$this->set('data', $data);
// Create a view that does not display any html header code except for the Excel data.
// To do this, set the layout to be 'ajax', which just happens to contain no html outside the main content.
$this->layout = 'ajax';
}
Create view. Eg: actiongetdata
// create new empty worksheet and set default font
$this->PhpExcel->createWorksheet()->setDefaultFont('Calibri', 12);
// define table cells
$table = array(
array('label' => __('User'), 'filter' => true),
array('label' => __('Type'), 'filter' => true),
array('label' => __('Date')),
array('label' => __('Description'), 'width' => 50, 'wrap' => true),
array('label' => __('Modified'))
);
// add heading with different font and bold text
$this->PhpExcel->addTableHeader($table, array('name' => 'Cambria', 'bold' => true));
// add data
foreach ($data as $d) {
$this->PhpExcel->addTableRow(array(
$d['User']['name'],
$d['Type']['name'],
$d['User']['date'],
$d['User']['description'],
$d['User']['modified']
));
}
// close table
$this->PhpExcel->addTableFooter();
// Save to Excel file
ob_end_clean(); // remove all output (very important, otherwise data is garbage)
this->PhpExcel->output('MyExcelFile.xlsx');
== Delete Cached Models ==
After updating a model, clear the cache to see the changes on the site.
$ rm -f /app/tmp/cache/models/cake_model_*
$ rm -f /app/tmp/cache/persistent/cake_core_*