474 lines
13 KiB
PHP
474 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* SQL Storage
|
|
*
|
|
* PHP Version 5.3
|
|
*
|
|
* @category Payment
|
|
* @package KlarnaAPI
|
|
* @author MS Dev <ms.modules@klarna.com>
|
|
* @copyright 2012 Klarna AB (http://klarna.com)
|
|
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
|
|
* @link http://integration.klarna.com/
|
|
*/
|
|
|
|
/**
|
|
* Include the {@link PCStorage} interface.
|
|
*/
|
|
require_once 'storage.intf.php';
|
|
|
|
/**
|
|
* SQL storage class for KlarnaPClass
|
|
*
|
|
* This class is an MySQL implementation of the PCStorage interface.<br>
|
|
* Config field pcURI needs to match format:
|
|
* user:passwd@addr:port/dbName.dbTable<br>
|
|
* Port can be omitted.<br>
|
|
*
|
|
* <b>Acceptable characters</b>:<br>
|
|
* Username: [A-Za-z0-9_]<br>
|
|
* Password: [A-Za-z0-9_]<br>
|
|
* Address: [A-Za-z0-9_.]<br>
|
|
* Port: [0-9]<br>
|
|
* DB name: [A-Za-z0-9_]<br>
|
|
* DB table: [A-Za-z0-9_]<br>
|
|
*
|
|
* To allow for more special characters, and to avoid having<br>
|
|
* a regular expression that is too hard to understand, you can<br>
|
|
* use an associative array:<br>
|
|
* <code>
|
|
* array(
|
|
* "user" => "myuser",
|
|
* "passwd" => "mypass",
|
|
* "dsn" => "localhost",
|
|
* "db" => "mydatabase",
|
|
* "table" => "mytable"
|
|
* );
|
|
* </code>
|
|
*
|
|
* @category Payment
|
|
* @package KlarnaAPI
|
|
* @author MS Dev <ms.modules@klarna.com>
|
|
* @copyright 2012 Klarna AB (http://klarna.com)
|
|
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
|
|
* @link http://integration.klarna.com/
|
|
*/
|
|
class SQLStorage extends PCStorage
|
|
{
|
|
|
|
/**
|
|
* Database name.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $dbName;
|
|
|
|
/**
|
|
* Database table.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $dbTable;
|
|
|
|
/**
|
|
* Database address.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $addr;
|
|
|
|
/**
|
|
* PDO DSN notation.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $dsn;
|
|
|
|
/**
|
|
* Database username.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $user;
|
|
|
|
/**
|
|
* Database password.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $passwd;
|
|
|
|
/**
|
|
* PDO DB link resource.
|
|
*
|
|
* @var PDO
|
|
*/
|
|
protected $pdo;
|
|
|
|
/**
|
|
* return the name of the storage type
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getName()
|
|
{
|
|
return "sql";
|
|
}
|
|
|
|
/**
|
|
* Splits the URI for the following formats:<br>
|
|
* user:passwd@addr/dbName.dbTable (assumes MySQL)<br>
|
|
* user:password@pdo:dsn/dbName.dbTable<br>
|
|
*
|
|
* To allow for more special characters, and to avoid having<br>
|
|
* a regular expression that is too hard to understand, you can<br>
|
|
* use an associative array:<br>
|
|
* <code>
|
|
* array(
|
|
* "user" => "myuser",
|
|
* "passwd" => "mypass",
|
|
* "dsn" => "localhost",
|
|
* "db" => "mydatabase",
|
|
* "table" => "mytable"
|
|
* );
|
|
* </code>
|
|
*
|
|
* @param string|array $uri Specified URI to database and table.
|
|
*
|
|
* @throws KlarnaException
|
|
* @return void
|
|
*/
|
|
protected function splitURI($uri)
|
|
{
|
|
/* If you want to have some characters that would make the
|
|
regexp too complex, you can use an array as input instead. */
|
|
if (is_array($uri)) {
|
|
$this->user = $uri['user'];
|
|
$this->passwd = $uri['passwd'];
|
|
$this->dsn = $uri['dsn'];
|
|
$this->dbName = $uri['db'];
|
|
$this->dbTable = $uri['table'];
|
|
|
|
return array(
|
|
$uri,
|
|
$this->user,
|
|
$this->passwd,
|
|
$this->dsn,
|
|
$this->dbName,
|
|
$this->dbTable
|
|
);
|
|
}
|
|
$pdo_rex
|
|
= '/^([\w-]+):([\w-]+)@pdo:([\w.,:;\/ \\\t=\(\){}\*-]+)\/([\w-]+)'.
|
|
'.([\w-]+)$/';
|
|
$pcuri_rex
|
|
= '/^([\w-]+):([\w-]+)@([\w\.-]+|[\w\.-]+:[\d]+|[\w\.-]+:'.
|
|
'[\w\.\/-]+|:[\w\.\/-]+)\/([\w-]+).([\w-]+)$/';
|
|
$arr = null;
|
|
if (preg_match($pdo_rex, $uri, $arr) === 1) {
|
|
/*
|
|
* [0] => user:password@pdo:dsn/dbName.dbTable
|
|
* [1] => user
|
|
* [2] => passwd
|
|
* [3] => dsn
|
|
* [4] => dbName
|
|
* [5] => dbTable
|
|
*/
|
|
if (count($arr) != 6) {
|
|
throw new Klarna_DatabaseException(
|
|
'URI is invalid! Missing field or invalid characters used!'
|
|
);
|
|
}
|
|
|
|
$this->user = $arr[1];
|
|
$this->passwd = $arr[2];
|
|
$this->dsn = $arr[3];
|
|
$this->dbName = $arr[4];
|
|
$this->dbTable = $arr[5];
|
|
} else if (preg_match($pcuri_rex, $uri, $arr) === 1) {
|
|
//user:pass@127.0.0.1:3306/dbName.dbTable
|
|
//user:pass@localhost:/tmp/mysql.sock/dbName.dbTable
|
|
/*
|
|
* [0] => user:passwd@addr/dbName.dbTable
|
|
* [1] => user
|
|
* [2] => passwd
|
|
* [3] => addr
|
|
* [4] => dbName
|
|
* [5] => dbTable
|
|
*/
|
|
if (count($arr) != 6) {
|
|
throw new Klarna_DatabaseException(
|
|
'URI is invalid! Missing field or invalid characters used!'
|
|
);
|
|
}
|
|
|
|
$this->user = $arr[1];
|
|
$this->passwd = $arr[2];
|
|
$this->addr = $arr[3];
|
|
$this->port = 3306;
|
|
if (preg_match(
|
|
'/^([0-9.]+(:([0-9]+))?)$/', $this->addr, $tmp
|
|
) === 1
|
|
) {
|
|
if (isset($tmp[3])) {
|
|
$this->port = $tmp[3];
|
|
}
|
|
}
|
|
$this->dbName = $arr[4];
|
|
$this->dbTable = $arr[5];
|
|
$this->dsn = "mysql:host={$this->addr};port={$this->port};";
|
|
} else {
|
|
throw new Klarna_DatabaseException(
|
|
'URI to SQL is not valid! ( user:passwd@addr/dbName.dbTable )'
|
|
);
|
|
}
|
|
|
|
return $arr;
|
|
}
|
|
|
|
/**
|
|
* Grabs the PDO connection to the database, specified by the URI.
|
|
*
|
|
* @param string $uri pclass uri
|
|
*
|
|
* @return void
|
|
* @throws KlarnaException
|
|
*/
|
|
protected function getConnection($uri)
|
|
{
|
|
if ($this->pdo) {
|
|
return; //Already have a connection
|
|
}
|
|
|
|
$this->splitURI($uri);
|
|
|
|
try {
|
|
$this->pdo = new PDO($this->dsn, $this->user, $this->passwd);
|
|
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
} catch (PDOException $e) {
|
|
throw new Klarna_DatabaseException('Failed to connect to database!');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initializes the DB, if the database or table is missing.
|
|
*
|
|
* @return void
|
|
* @throws KlarnaException
|
|
*/
|
|
protected function initDB()
|
|
{
|
|
try {
|
|
$this->pdo->exec("CREATE DATABASE `{$this->dbName}`");
|
|
} catch (PDOException $e) {
|
|
//SQLite does not support this...
|
|
//throw new KlarnaException(
|
|
// 'Database non-existant, failed to create it!'
|
|
//);
|
|
}
|
|
|
|
$sql = <<<SQL
|
|
CREATE TABLE IF NOT EXISTS `{$this->dbName}`.`{$this->dbTable}` (
|
|
`eid` int(10) NOT NULL,
|
|
`id` int(10) NOT NULL,
|
|
`type` int(4) NOT NULL,
|
|
`description` varchar(255) NOT NULL,
|
|
`months` int(11) NOT NULL,
|
|
`interestrate` decimal(11,2) NOT NULL,
|
|
`invoicefee` decimal(11,2) NOT NULL,
|
|
`startfee` decimal(11,2) NOT NULL,
|
|
`minamount` decimal(11,2) NOT NULL,
|
|
`country` int(11) NOT NULL,
|
|
`expire` int(11) NOT NULL
|
|
);
|
|
SQL;
|
|
try {
|
|
$this->pdo->exec($sql);
|
|
} catch (PDOException $e) {
|
|
throw new Klarna_DatabaseException(
|
|
'Table non-existant, failed to create it!'
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Connects to the DB and checks if DB and table exists.
|
|
*
|
|
* @param string|array $uri pclass uri
|
|
*
|
|
* @throws KlarnaException
|
|
* @return void
|
|
*/
|
|
protected function connect($uri)
|
|
{
|
|
$this->getConnection($uri);
|
|
$this->initDB();
|
|
}
|
|
|
|
/**
|
|
* Loads the PClasses.
|
|
*
|
|
* @param string|array $uri pclass uri
|
|
*
|
|
* @return void
|
|
* @throws KlarnaException
|
|
*/
|
|
public function load($uri)
|
|
{
|
|
$this->connect($uri);
|
|
$this->loadPClasses();
|
|
}
|
|
|
|
/**
|
|
* Loads the PClasses.
|
|
*
|
|
* @return void
|
|
* @throws KlarnaException
|
|
*/
|
|
protected function loadPClasses()
|
|
{
|
|
try {
|
|
$sth = $this->pdo->prepare(
|
|
"SELECT * FROM `{$this->dbName}`.`{$this->dbTable}`",
|
|
array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY)
|
|
);
|
|
$sth->execute();
|
|
|
|
while ($row = $sth->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) {
|
|
$this->addPClass(new KlarnaPClass($row));
|
|
}
|
|
|
|
$sth->closeCursor();
|
|
$sth = null;
|
|
} catch (PDOException $e) {
|
|
throw new Klarna_DatabaseException(
|
|
'Could not fetch PClasses from database!'
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Saves the PClasses.
|
|
*
|
|
* @param string|array $uri pclass uri
|
|
*
|
|
* @return void
|
|
* @throws KlarnaException
|
|
*/
|
|
public function save($uri)
|
|
{
|
|
$this->connect($uri);
|
|
//Only attempt to savePClasses if there are any.
|
|
if (!is_array($this->pclasses)) {
|
|
return;
|
|
}
|
|
if (count($this->pclasses) == 0) {
|
|
return;
|
|
}
|
|
$this->savePClasses();
|
|
}
|
|
|
|
/**
|
|
* Saves the PClasses.
|
|
*
|
|
* @return void
|
|
* @throws KlarnaException
|
|
*/
|
|
protected function savePClasses()
|
|
{
|
|
//Insert PClass SQL statement.
|
|
$sql = <<<SQL
|
|
INSERT INTO `{$this->dbName}`.`{$this->dbTable}`
|
|
(`eid`, `id`, `type`, `description`, `months`, `interestrate`,
|
|
`invoicefee`, `startfee`, `minamount`, `country`, `expire`)
|
|
VALUES
|
|
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
SQL;
|
|
|
|
foreach ($this->pclasses as $pclasses) {
|
|
foreach ($pclasses as $pclass) {
|
|
try {
|
|
//Remove the pclass if it exists.
|
|
$sth = $this->pdo->prepare(
|
|
"DELETE FROM `{$this->dbName}`.`{$this->dbTable}`
|
|
WHERE `id` = ? AND `eid` = ?"
|
|
);
|
|
$sth->execute(
|
|
array(
|
|
$pclass->getId(), $pclass->getEid()
|
|
)
|
|
);
|
|
|
|
$sth->closeCursor();
|
|
$sth = null;
|
|
} catch(PDOException $e) {
|
|
//Fail silently, we don't care if the removal failed.
|
|
}
|
|
|
|
try {
|
|
//Attempt to insert the PClass into the DB.
|
|
$sth = $this->pdo->prepare($sql);
|
|
$sth->execute(
|
|
array(
|
|
$pclass->getEid(),
|
|
$pclass->getId(),
|
|
$pclass->getType(),
|
|
$pclass->getDescription(),
|
|
$pclass->getMonths(),
|
|
$pclass->getInterestRate(),
|
|
$pclass->getInvoiceFee(),
|
|
$pclass->getStartFee(),
|
|
$pclass->getMinAmount(),
|
|
$pclass->getCountry(),
|
|
$pclass->getExpire()
|
|
)
|
|
);
|
|
|
|
$sth->closeCursor();
|
|
$sth = null;
|
|
} catch(PDOException $e) {
|
|
throw new Klarna_DatabaseException(
|
|
'Failed to insert PClass into database!'
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Drops the database table, to clear the PClasses.
|
|
*
|
|
* @param string|array $uri pclass uri
|
|
*
|
|
* @return void
|
|
* @throws KlarnaException
|
|
*/
|
|
public function clear($uri)
|
|
{
|
|
try {
|
|
$this->connect($uri);
|
|
unset($this->pclasses);
|
|
$this->clearTable();
|
|
} catch(Exception $e) {
|
|
throw new Klarna_DatabaseException(
|
|
$e->getMessage(), $e->getCode()
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Drops the database table, to clear the PClasses.
|
|
*
|
|
* @return void
|
|
* @throws KlarnaException
|
|
*/
|
|
protected function clearTable()
|
|
{
|
|
try {
|
|
$this->pdo->exec("DELETE FROM `{$this->dbName}`.`{$this->dbTable}`");
|
|
} catch (PDOException $e) {
|
|
throw new Klarna_DatabaseException('Could not clear the database!');
|
|
}
|
|
}
|
|
}
|