<?php

defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
require_once("includes/phpqrcode/qrlib.php");


/*
Plugin Name: SEPA Girocode
Plugin URI:  http://www.halli-online.de/sepa-girocode/
Description: Create EPC-Codes (in Germany known as Girocode) for money transfer | Girocode-Barcode für SEPA-Überweisungen erstellen
Version:     0.3
Author:      Michael Hallmann
Author URI:  http://www.halli-online.de/
License:     GPL2
License URI: https://www.gnu.org/licenses/gpl-2.0.html

SEPA Girocode 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 2 of the License, or
any later version.
 
SEPA Girocode 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 SEPA Girocode. If not, see https://www.gnu.org/licenses/gpl-2.0.html.
*/


class sepa_girocode_class {
  
private $data = array();

function __construct() {
	$this->data['iban'] = "";
	$this->data['bic'] = "";
	$this->data['beneficiary'] = "";
	$this->data['purpose'] = "";
	$this->data['amount'] = 0;
	$this->data['isclickable'] = 0;
	$this->data['purposecode'] = '';
	$this->data['reference'] = '';
	$this->data['dimension'] = 150;

}

public function getValidAtts() {
	return $this->data;
}

public function __get( $property) {
	if (array_key_exists($property, $this->data)) 
		return $this->data["$property"];
	else
		throw new Exception( 'Can\'t get property ' . $property);
}


public function __set( $property, $value ) {
	if (! array_key_exists($property, $this->data)) {
		throw new Exception( 'Can\'t set property ' . $property);
	}

	
	$value = trim($value);

	switch( $property) {
		case "bic":
			$this->data["$property"] = strtoupper( substr( $value, 0, 11 ) );
			break;
		case "iban":
			$this->data["$property"] = strtoupper( $value );
			break;
		case "amount":
			$this->data["$property"] = floatval($value);
			break;
		case "purpose":
			$this->data["$property"] = substr($value, 0, 140);
			break;
		case "beneficiary":
			$this->data["$property"] = substr( $value, 0, 70 );
			break;
		case "reference":
			$this->data["$property"] = substr( $value, 0, 35 );
			break;
		case "purposecode":
			$this->data["$property"] = strtoupper(substr( $value, 0, 4 ));
			break;
		case "isclickable":
			$this->data["$property"] = floatval($value);
			break;
		default:
			$this->data["$property"] = $value;
    }
	
	return true;
}

public function getGoogleUrl() {
	// https://developers.google.com/chart/infographics/docs/qr_codes
	// this function is currently not in use
	$nl = chr(13) . chr(10);

	$url  = "https://chart.googleapis.com/chart?";
	$url .= "cht=qr&";
	$url .= "chs=150x150&";
	$url .= "chld=M|4&";
	$url .= "chl=";

	return $url . urlencode( $this->getQrPayload() );
}


public function getQrPayload() {
	$nl = chr(13) . chr(10);
	
	$qrdata  = "BCD" . $nl;  // Service Tag
	$qrdata .= "001" . $nl; // Version
	$qrdata .= "1" . $nl;  // Char Set UTF-8
	$qrdata .= "SCT" . $nl;  // Id-Code
	$qrdata .= $this->bic . $nl;  // BIC, blank if not used
	$qrdata .= $this->beneficiary . $nl; // name of beneficiary
	$qrdata .= $this->iban . $nl;  // IBAN of beneficiary
	$qrdata .= "EUR" . $this->amount . $nl; // amount in EUR
	$qrdata .= $this->purposecode . $nl;  // purpose code
	$qrdata .= $this->reference . $nl;  // remittance (reference), beginning with RF
	// one can use either purpose or reference, reference overrules purpose
	if ($this->reference == "") {
		$qrdata .= $this->purpose . $nl;  // remittance (text), unstructured
	} else  {
		$qrdata .= "" . $nl;  
	}

	$qrdata .= "nvc:trash@halli-online.de";  // information (beneficiary to originator information)

	return $qrdata;
}

public function renderQrCode() {
	$outerFrame = 1; 
	$pixelPerPoint = 8; 
	 
	// generating frame 
	$payload = $this->getQrPayload();
	$frame = QRcode::text($payload, false, QR_ECLEVEL_M); 
	 
	// rendering frame with GD2 (that should be function by real impl.!!!) 
	$h = count($frame); 
	$w = strlen($frame[0]); 
	$imgW = $w + 2*$outerFrame; 
	$imgH = $h + 2*$outerFrame; 
	 
	$base_image = imagecreate($imgW, $imgH); 
	 
	$col[0] = imagecolorallocate($base_image,255,255,255); // BG, white  
	$col[1] = imagecolorallocate($base_image,0,0,0);     // FG, black
	
	imagefill($base_image, 0, 0, $col[0]); 

	for($y=0; $y<$h; $y++) { 
		for($x=0; $x<$w; $x++) { 
			if ($frame[$y][$x] == '1') { 
				imagesetpixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]);  
			} 
		} 
	} 
	 
	// saving to file 
	//$target_image = imagecreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint); 
	$target_image = imagecreatefrompng(plugin_dir_path( __FILE__ ) . "images/girocode.png");

	imagecopyresized( 
		$target_image,  
		$base_image,  
		25, 25, 0, 0,  
		$imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH 
	); 
	imagedestroy($base_image); 
	
	ob_start ( );
	imagepng ( $target_image );
	$tmp = ob_get_contents ( );
	ob_end_clean ( );
	
	imagedestroy($target_image);
	
	return $tmp;
}


public function QrPngWithHeader() {
		
			
		$image = imagecreatefromstring($this->renderQrCode());
		if (! $image)  die("Fehler in getQrPng");
		header('Content-Type: image/png');
		imagepng($image);
		imagedestroy($image);  
		return true;
		exit;
}

public function getTransientKey() { 
	return "sgc_" . md5($this->getQrPayload());
}

public function getQrDiv() {
	$key = $this->getTransientKey();
	$img_src = "index.php?sepa-girocode=show-code&key=" . $key;
	$click_url = "index.php?sepa-girocode=get-codefile&key=" . $key;
	$width_height = $this->dimension;
	$output = "";
	$a = "";
	$ae = "";
	
	if ($this->isclickable == 1) {
		$a = "<a href='$click_url' target='_blank'>";
		$ae = "</a>";
	}
	
	
	$output .= "<div>$a<img src='$img_src' width='$width_height' height='$width_height'></img>$ae</div>";

	return $output;
}

}  // end class


function sepa_girocode_activate() {
	// nothing to do
}

function sepa_girocode_deactivate() {
	global $wpdb;
	// delete all transients
	$result = $wpdb->get_results("SELECT * FROM $wpdb->options WHERE option_name LIKE '_transient_sgc_%'");
	foreach ($result as $transient) {
		delete_transient(trim(substr($transient->option_name, 11, 999)));
	}
}

	
	
	
function sepa_girocode_shortcode( $atts ) {
	
	$sgc = new sepa_girocode_class();
		
	foreach ($atts as $k => $v) {
		if (array_key_exists($k, $sgc->getValidAtts())) {
			$sgc->$k = $v;
		} else {
			throw new Exception( 'Can\'t set parameter ' . $k);
		}
	}

	$key =  $sgc->getTransientKey();

	if ( false === ( $value = get_transient($key) ) ) {
		$tmp = set_transient($key, 
					  $sgc,
					  YEAR_IN_SECONDS);
		if (!$tmp) die ("Konnte Transient nicht setzen! KEY = " . $key);
	}

	return $sgc->getQrDiv();
}	



function sepa_girocode_parse_request($wp) {
	// only process requests with "halli-girocode=show-code"
	

	if (array_key_exists('sepa-girocode', $wp->query_vars) && $wp->query_vars['sepa-girocode'] == 'show-code') {
		
		$key = $wp->query_vars['key'];
		if ( false === ( $sgc = get_transient($key) ) ) {
			die("Kein Transient gefunden!");
		}
		
		$sgc->QrPngWithHeader();
		exit;

	}
	

	
	if (array_key_exists('sepa-girocode', $wp->query_vars) && $wp->query_vars['sepa-girocode'] == 'get-codefile') {
		$key = $wp->query_vars['key'];
		$sgc = get_transient($key);
		header("Content-Type: application/octet-stream");
		header("Content-Disposition: attachment; filename=\"$key.girocode\"");
		echo $sgc->getQrPayload();
		
		exit;
	}
	
}




function sepa_girocode_query_vars($vars) {
	$vars[] = 'sepa-girocode';
	$vars[] = 'key';
	return $vars;
}


register_activation_hook( __FILE__, 'sepa_girocode_activate' );
register_deactivation_hook( __FILE__, 'sepa_girocode_deactivate' );

add_shortcode( 'girocode', 'sepa_girocode_shortcode' );
add_action('parse_request', 'sepa_girocode_parse_request');
add_filter('query_vars', 'sepa_girocode_query_vars');

?>