src/Controller/Shop/Shoppingcart.php
<?php
/*
HCSF - A multilingual CMS and Shopsystem
Copyright (C) 2014 Marcus Haase - mail@marcus.haase.name
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace HaaseIT\HCSF\Controller\Shop;
use HaaseIT\Toolbox\Tools;
class Shoppingcart extends Base
{
/**
* @var \HaaseIT\Toolbox\Textcat
*/
private $textcats;
/**
* @var array
*/
private $imagestosend = [];
/**
* Shoppingcart constructor.
* @param \Zend\ServiceManager\ServiceManager $serviceManager
*/
public function __construct(\Zend\ServiceManager\ServiceManager $serviceManager)
{
parent::__construct($serviceManager);
$this->textcats = $this->serviceManager->get('textcats');
}
/**
*
*/
public function preparePage()
{
$this->P = new \HaaseIT\HCSF\CorePage($this->serviceManager);
$this->P->cb_pagetype = 'contentnosubnav';
if ($this->config->getShop('show_pricesonlytologgedin') && !$this->helperCustomer->getUserData()) {
$this->P->oPayload->cl_html = $this->textcats->T('denied_notloggedin');
} else {
$this->P->cb_customcontenttemplate = 'shop/shoppingcart';
// Check if there is a message to display above the shoppingcart
$this->P->oPayload->cl_html = $this->getNotification();
// Display the shoppingcart
if (isset($_SESSION['cart']) && count($_SESSION['cart']) >= 1) {
$aErr = [];
if (filter_input(INPUT_POST, 'doCheckout') === 'yes') {
$aErr = $this->validateCheckout($aErr);
if (count($aErr) === 0) {
$this->helper->redirectToPage($this->doCheckout());
}
}
$aShoppingcart = $this->helperShop->buildShoppingCartTable($_SESSION['cart'], false, '', $aErr);
$this->P->cb_customdata = $aShoppingcart;
} else {
$this->P->oPayload->cl_html .= $this->textcats->T('shoppingcart_empty');
}
}
}
/**
* @param array $aErr
* @return array
*/
private function validateCheckout($aErr = [])
{
$aErr = $this->helperCustomer->validateCustomerForm($this->config->getLang(), $aErr, true);
if (!$this->helperCustomer->getUserData() && filter_input(INPUT_POST, 'tos') !== 'y') {
$aErr['tos'] = true;
}
if (!$this->helperCustomer->getUserData() && filter_input(INPUT_POST, 'cancellationdisclaimer') !== 'y') {
$aErr['cancellationdisclaimer'] = true;
}
$postpaymentmethod = filter_input(INPUT_POST, 'paymentmethod');
if (
$postpaymentmethod === null
|| in_array($postpaymentmethod, $this->config->getShop('paymentmethods'), true) === false
) {
$aErr['paymentmethod'] = true;
}
return $aErr;
}
/**
* @param $aV
* @return array
*/
private function getItemImage($aV)
{
// base64 encode img and prepare for db
// image/png image/jpeg image/gif
// data:{mimetype};base64,XXXX
$aImagesToSend = [];
$base64Img = false;
$binImg = false;
if ($this->config->getShop('email_orderconfirmation_embed_itemimages_method') === 'glide') {
$sPathToImage = '/'.$this->config->getCore('directory_images').'/'.$this->config->getShop('directory_images_items').'/';
$sImageroot = PATH_BASEDIR.$this->config->getCore('directory_glide_master');
if (
is_file($sImageroot.substr($sPathToImage.$aV['img'], strlen($this->config->getCore('directory_images')) + 1))
&& $aImgInfo = getimagesize($sImageroot.substr($sPathToImage.$aV['img'], strlen($this->config->getCore('directory_images')) + 1))
) {
$glideserver = \League\Glide\ServerFactory::create([
'source' => $sImageroot,
'cache' => PATH_GLIDECACHE,
'max_image_size' => $this->config->getCore('glide_max_imagesize'),
]);
$glideserver->setBaseUrl('/'.$this->config->getCore('directory_images').'/');
$base64Img = $glideserver->getImageAsBase64($sPathToImage.$aV['img'], $this->config->getShop('email_orderconfirmation_embed_itemimages_glideparams'));
$TMP = explode(',', $base64Img);
$binImg = base64_decode($TMP[1]);
unset($TMP);
}
} else {
$sPathToImage =
PATH_DOCROOT.$this->config->getCore('directory_images').'/'
.$this->config->getShop('directory_images_items').'/'
.$this->config->getShop('directory_images_items_email').'/';
if ($aImgInfo = getimagesize($sPathToImage.$aV['img'])) {
$binImg = file_get_contents($sPathToImage.$aV['img']);
$base64Img = 'data:'.$aImgInfo['mime'].';base64,';
$base64Img .= base64_encode($binImg);
}
}
if ($this->config->getShop('email_orderconfirmation_embed_itemimages')) {
$aImagesToSend['binimg'] = $binImg;
}
if (!empty($base64Img)) {
$aImagesToSend['base64img'] = $base64Img;
}
return $aImagesToSend;
}
/**
* @return array
*/
private function prepareDataOrder()
{
$cartpricesums = $_SESSION['cartpricesums'];
return [
'o_custno' => filter_var(trim(Tools::getFormfield('custno')), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_email' => filter_var(trim(Tools::getFormfield('email')), FILTER_SANITIZE_EMAIL),
'o_corpname' => filter_var(trim(Tools::getFormfield('corpname')), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_name' => filter_var(trim(Tools::getFormfield('name')), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_street' => filter_var(trim(Tools::getFormfield('street')), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_zip' => filter_var(trim(Tools::getFormfield('zip')), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_town' => filter_var(trim(Tools::getFormfield('town')), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_phone' => filter_var(trim(Tools::getFormfield('phone')), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_cellphone' => filter_var(trim(Tools::getFormfield('cellphone')), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_fax' => filter_var(trim(Tools::getFormfield('fax')), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_country' => filter_var(trim(Tools::getFormfield('country')), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_group' => trim($this->helperCustomer->getUserData('cust_group')),
'o_remarks' => filter_var(trim(Tools::getFormfield('remarks')), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_tos' => (filter_input(INPUT_POST, 'tos') === 'y' || $this->helperCustomer->getUserData()) ? 'y' : 'n',
'o_cancellationdisclaimer' => (filter_input(INPUT_POST, 'cancellationdisclaimer') === 'y' || $this->helperCustomer->getUserData()) ? 'y' : 'n',
'o_paymentmethod' => filter_var(trim(Tools::getFormfield('paymentmethod')), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_sumvoll' => $cartpricesums['sumvoll'],
'o_sumerm' => $cartpricesums['sumerm'],
'o_sumnettoall' => $cartpricesums['sumnettoall'],
'o_taxvoll' => $cartpricesums['taxvoll'],
'o_taxerm' => $cartpricesums['taxerm'],
'o_sumbruttoall' => $cartpricesums['sumbruttoall'],
'o_mindermenge' => isset($cartpricesums['mindergebuehr']) ? $cartpricesums['mindergebuehr'] : '',
'o_shippingcost' => $this->helperShop->getShippingcost(),
'o_orderdate' => date('Y-m-d'),
'o_ordertimestamp' => time(),
'o_authed' => $this->helperCustomer->getUserData() ? 'y' : 'n',
'o_sessiondata' => serialize($_SESSION),
'o_postdata' => serialize($_POST),
'o_remote_address' => filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_ordercompleted' => 'n',
'o_paymentcompleted' => 'n',
'o_srv_hostname' => filter_input(INPUT_SERVER, 'SERVER_NAME', FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW),
'o_vatfull' => $this->config->getShop('vat')['full'],
'o_vatreduced' => $this->config->getShop('vat')['reduced'],
];
}
/**
* @param int $orderid
* @param string $cartkey
* @param array $values
* @return array
*/
private function buildOrderItemRow($orderid, $cartkey, array $values)
{
return [
'oi_o_id' => $orderid,
'oi_cartkey' => $cartkey,
'oi_amount' => $values['amount'],
'oi_price_netto_list' => $values['price']['netto_list'],
'oi_price_netto_use' => $values['price']['netto_use'],
'oi_price_brutto_use' => $values['price']['brutto_use'],
'oi_price_netto_sale' => isset($values['price']['netto_sale']) ? $values['price']['netto_sale'] : '',
'oi_price_netto_rebated' => isset($values['price']['netto_rebated']) ? $values['price']['netto_rebated'] : '',
'oi_vat' => $this->config->getShop('vat')[$values['vat']],
'oi_rg' => $values['rg'],
'oi_rg_rebate' => isset(
$this->config->getShop('rebate_groups')[$values['rg']][trim($this->helperCustomer->getUserData('cust_group'))]
)
? $this->config->getShop('rebate_groups')[$values['rg']][trim($this->helperCustomer->getUserData('cust_group'))]
: '',
'oi_itemname' => $values['name'],
'oi_img' => $this->imagestosend[$values['img']]['base64img'],
];
}
private function writeCheckoutToDB()
{
/** @var \Doctrine\DBAL\Connection $dbal */
$dbal = $this->serviceManager->get('dbal');
try {
$dbal->beginTransaction();
$aDataOrder = $this->prepareDataOrder();
$iInsertID = $this->helper->autoInsert($dbal, 'orders', $aDataOrder);
foreach ($_SESSION['cart'] as $sK => $aV) {
$this->imagestosend[$aV['img']] = $this->getItemImage($aV);
$this->helper->autoInsert(
$dbal,
'orders_items',
$this->buildOrderItemRow($iInsertID, $sK, $aV)
);
}
$dbal->commit();
return $iInsertID;
} catch (\Exception $e) {
// If something raised an exception in our transaction block of statements,
// roll back any work performed in the transaction
print '<p>Unable to complete transaction!</p>';
error_log($e);
$dbal->rollBack();
}
}
private function doCheckout()
{
$iInsertID = $this->writeCheckoutToDB();
$sMailbody_us = $this->buildOrderMailBody(false, $iInsertID);
$sMailbody_they = $this->buildOrderMailBody(true, $iInsertID);
// write to file
$this->writeCheckoutToFile($sMailbody_us);
// Send Mails
$this->sendCheckoutMails($iInsertID, $sMailbody_us, $sMailbody_they);
unset($_SESSION['cart'], $_SESSION['cartpricesums'], $_SESSION['sondercart']);
$postpaymentmethod = filter_input(INPUT_POST, 'paymentmethod');
if ($postpaymentmethod !== null) {
if (
$postpaymentmethod === 'paypal'
&& $this->config->getShop('paypal_interactive')
) {
return '/_misc/paypal.html?id='.$iInsertID;
} elseif ($postpaymentmethod === 'sofortueberweisung') {
return '/_misc/sofortueberweisung.html?id='.$iInsertID;
}
}
return '/_misc/checkedout.html?id='.$iInsertID;
}
/**
* @param int $iInsertID
* @param string $sMailbody_us
* @param string $sMailbody_they
*/
private function sendCheckoutMails($iInsertID, $sMailbody_us, $sMailbody_they)
{
$aFilesToSend = [];
if (
!empty($this->config->getShop('email_orderconfirmation_attachment_cancellationform_'.$this->config->getLang()))
&& file_exists(
PATH_DOCROOT.$this->config->getCore('directory_emailattachments')
.'/'.$this->config->getShop('email_orderconfirmation_attachment_cancellationform_'
.$this->config->getLang())
)
) {
$aFilesToSend[] =
PATH_DOCROOT.$this->config->getCore('directory_emailattachments').'/'
.$this->config->getShop('email_orderconfirmation_attachment_cancellationform_'.$this->config->getLang());
}
$this->helper->mailWrapper(
filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL),
$this->textcats->T('shoppingcart_mail_subject').' '.$iInsertID,
$sMailbody_they,
$this->imagestosend,
$aFilesToSend
);
$this->helper->mailWrapper(
$this->config->getCore('email_sender'),
'Bestellung im Webshop Nr: '.$iInsertID,
$sMailbody_us,
$this->imagestosend
);
}
/**
* @param string $sMailbody_us
*/
private function writeCheckoutToFile($sMailbody_us)
{
$fp = fopen(PATH_LOGS.'shoplog_'.date('Y-m-d').'.html', 'a');
// Write $somecontent to our opened file.
fwrite($fp, $sMailbody_us."\n\n-------------------------------------------------------------------------\n\n");
fclose($fp);
}
/**
* @param string $field
* @return string
*/
private function getPostValue($field)
{
$postvalue = filter_input(INPUT_POST, $field);
return (!empty($postvalue) ? $postvalue : '');
}
/**
* @param bool $bCust
* @param int $iId
* @return mixed
*/
private function buildOrderMailBody($bCust = true, $iId)
{
$aM = [
'customdata' => $this->helperShop->buildShoppingCartTable($_SESSION['cart'], true),
'currency' => $this->config->getShop('waehrungssymbol'),
];
if (!empty($this->config->getShop('custom_order_fields'))) {
$aM['custom_order_fields'] = $this->config->getShop('custom_order_fields');
}
$postcustno = trim(filter_input(INPUT_POST, 'custno', FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW));
$postcountry = trim(filter_input(INPUT_POST, 'country', FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW));
$postpaymentmethod = filter_input(INPUT_POST, 'paymentmethod', FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
$serverservername = filter_input(INPUT_SERVER, 'SERVER_NAME', FILTER_SANITIZE_URL);
$aData = [
'customerversion' => $bCust,
'datetime' => date('d.m.Y - H:i'),
'custno' => $postcustno !== null && strlen($postcustno) >= $this->config->getCustomer('minimum_length_custno') ? $postcustno : '',
'corpname' => $this->getPostValue('corpname'),
'name' => $this->getPostValue('name'),
'street' => $this->getPostValue('street'),
'zip' => $this->getPostValue('zip'),
'town' => $this->getPostValue('town'),
'phone' => $this->getPostValue('phone'),
'cellphone' => $this->getPostValue('cellphone'),
'fax' => $this->getPostValue('fax'),
'email' => $this->getPostValue('email'),
'country' => !empty($postcountry) ?
(
isset(
$this->config->getCountries('countries_'.$this->config->getLang())[$postcountry]
)
? $this->config->getCountries('countries_'.$this->config->getLang())[$postcountry]
: $postcountry)
: '',
'remarks' => $this->getPostValue('remarks'),
'tos' => $this->getPostValue('tos'),
'cancellationdisclaimer' => $this->getPostValue('cancellationdisclaimer'),
'paymentmethod' => $this->getPostValue('paymentmethod'),
'shippingcost' => empty($_SESSION['shippingcost']) ? false : $_SESSION['shippingcost'],
'paypallink' => $postpaymentmethod === 'paypal' ? $serverservername.'/_misc/paypal.html?id='.$iId : '',
'sofortueberweisunglink' => $postpaymentmethod === 'sofortueberweisung' ? $serverservername.'/_misc/sofortueberweisung.html?id='.$iId : '',
'SESSION' => !$bCust ? Tools::debug($_SESSION, '$_SESSION', true, true) : '',
'POST' => !$bCust ? Tools::debug($_POST, '$_POST', true, true) : '',
'orderid' => $iId,
];
$aM['customdata']['mail'] = $aData;
return $this->serviceManager->get('twig')->render('shop/mail-order-html.twig', $aM);
}
/**
* @return string
*/
private function getNotification()
{
$return = '';
$getmsg = filter_input(INPUT_GET, 'msg');
$getcartkey = filter_input(INPUT_GET, 'cartkey', FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
$getamount = filter_input(INPUT_GET, 'amount', FILTER_SANITIZE_NUMBER_INT);
if (!empty($getmsg)) {
if (
($getmsg === 'updated' && !empty($getcartkey) && !empty($getamount))
|| ($getmsg === 'removed' && !empty($getcartkey))
) {
$return .= $this->textcats->T('shoppingcart_msg_'.$getmsg.'_1').' ';
if (!empty($this->config->getShop('custom_order_fields')) && mb_strpos($getcartkey, '|') !== false) {
$mCartkeys = explode('|', $getcartkey);
foreach ($mCartkeys as $sKey => $sValue) {
if ($sKey == 0) {
$return .= $sValue.', ';
} else {
$TMP = explode(':', $sValue);
$return .= $this->textcats->T('shoppingcart_item_'.$TMP[0]).' '.$TMP[1].', ';
unset($TMP);
}
}
$return = Tools::cutStringend($return, 2);
} else {
$return .= $getcartkey;
}
$return.= ' '.$this->textcats->T('shoppingcart_msg_'.$getmsg.'_2');
if ($getmsg === 'updated') {
$return .= ' '.$getamount;
}
$return .= '<br><br>';
}
}
return $return;
}
}