vendor and env first commit
This commit is contained in:
@@ -0,0 +1,372 @@
|
||||
<?php
|
||||
|
||||
namespace Akaunting\Setting\Drivers;
|
||||
|
||||
use Akaunting\Setting\Contracts\Driver;
|
||||
use Akaunting\Setting\Support\Arr;
|
||||
use Closure;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Support\Arr as LaravelArr;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
|
||||
class Database extends Driver
|
||||
{
|
||||
/**
|
||||
* The database connection instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connection
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The table to query from.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* The key column name to query from.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $key;
|
||||
|
||||
/**
|
||||
* The value column name to query from.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Keys which should be encrypt automatically.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $encrypted_keys;
|
||||
|
||||
/**
|
||||
* Any query constraints that should be applied.
|
||||
*
|
||||
* @var Closure|null
|
||||
*/
|
||||
protected $query_constraint;
|
||||
|
||||
/**
|
||||
* Any extra columns that should be added to the rows.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $extra_columns = [];
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param string $table
|
||||
*/
|
||||
public function __construct(Connection $connection, $table = null, $key = null, $value = null, array $encrypted_keys = [])
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->table = $table ?: 'settings';
|
||||
$this->key = $key ?: 'key';
|
||||
$this->value = $value ?: 'value';
|
||||
$this->encrypted_keys = $encrypted_keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the table to query from.
|
||||
*
|
||||
* @param string $table
|
||||
*/
|
||||
public function setTable($table)
|
||||
{
|
||||
$this->table = $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the key column name to query from.
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
public function setKey($key)
|
||||
{
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value column name to query from.
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query constraint.
|
||||
*
|
||||
* @param Closure $callback
|
||||
*/
|
||||
public function setConstraint(Closure $callback)
|
||||
{
|
||||
$this->data = [];
|
||||
$this->loaded = false;
|
||||
$this->query_constraint = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set extra columns to be added to the rows.
|
||||
*
|
||||
* @param array $columns
|
||||
*/
|
||||
public function setExtraColumns(array $columns)
|
||||
{
|
||||
$this->extra_columns = $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extra columns added to the rows.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getExtraColumns()
|
||||
{
|
||||
return $this->extra_columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function forget($key)
|
||||
{
|
||||
parent::forget($key);
|
||||
|
||||
// because the database driver cannot store empty arrays, remove empty
|
||||
// arrays to keep data consistent before and after saving
|
||||
$segments = explode('.', $key);
|
||||
array_pop($segments);
|
||||
|
||||
while ($segments) {
|
||||
$segment = implode('.', $segments);
|
||||
|
||||
// non-empty array - exit out of the loop
|
||||
if ($this->get($segment)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// remove the empty array and move on to the next segment
|
||||
$this->forget($segment);
|
||||
array_pop($segments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function write(array $data)
|
||||
{
|
||||
// Get current data
|
||||
$db_data = $this->newQuery()->get([$this->key, $this->value])->toArray();
|
||||
|
||||
$insert_data = LaravelArr::dot($data);
|
||||
$update_data = [];
|
||||
$delete_keys = [];
|
||||
|
||||
foreach ($db_data as $db_row) {
|
||||
$key = $db_row->{$this->key};
|
||||
$value = $db_row->{$this->value};
|
||||
|
||||
$is_in_insert = $is_different_in_db = $is_same_as_fallback = false;
|
||||
|
||||
if (isset($insert_data[$key])) {
|
||||
$is_in_insert = true;
|
||||
$is_different_in_db = (string) $insert_data[$key] != (string) $value;
|
||||
$is_same_as_fallback = $this->isEqualToFallback($key, $insert_data[$key]);
|
||||
}
|
||||
|
||||
if ($is_in_insert) {
|
||||
if ($is_same_as_fallback) {
|
||||
// Delete if new data is same as fallback
|
||||
$delete_keys[] = $key;
|
||||
} elseif ($is_different_in_db) {
|
||||
// Update if new data is different from db
|
||||
$update_data[$key] = $insert_data[$key];
|
||||
}
|
||||
} else {
|
||||
// Delete if current db not available in new data
|
||||
$delete_keys[] = $key;
|
||||
}
|
||||
|
||||
unset($insert_data[$key]);
|
||||
}
|
||||
|
||||
foreach ($update_data as $key => $value) {
|
||||
$value = $this->prepareValue($key, $value);
|
||||
|
||||
$this->newQuery()
|
||||
->where($this->key, '=', $key)
|
||||
->update([$this->value => $value]);
|
||||
}
|
||||
|
||||
if ($insert_data) {
|
||||
$this->newQuery(true)
|
||||
->insert($this->prepareInsertData($insert_data));
|
||||
}
|
||||
|
||||
if ($delete_keys) {
|
||||
$this->newQuery()
|
||||
->whereIn($this->key, $delete_keys)
|
||||
->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms settings data into an array ready to be insterted into the
|
||||
* database. Call array_dot on a multidimensional array before passing it
|
||||
* into this method!
|
||||
*
|
||||
* @param array $data Call array_dot on a multidimensional array before passing it into this method!
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareInsertData(array $data)
|
||||
{
|
||||
$db_data = [];
|
||||
|
||||
if ($this->getExtraColumns()) {
|
||||
foreach ($data as $key => $value) {
|
||||
$value = $this->prepareValue($key, $value);
|
||||
|
||||
// Don't insert if same as fallback
|
||||
if ($this->isEqualToFallback($key, $value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$db_data[] = array_merge(
|
||||
$this->getExtraColumns(),
|
||||
[$this->key => $key, $this->value => $value]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
foreach ($data as $key => $value) {
|
||||
$value = $this->prepareValue($key, $value);
|
||||
|
||||
// Don't insert if same as fallback
|
||||
if ($this->isEqualToFallback($key, $value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$db_data[] = [$this->key => $key, $this->value => $value];
|
||||
}
|
||||
}
|
||||
|
||||
return $db_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the provided key should be encrypted or not.
|
||||
* Also type casts the given value to a string so errors with booleans or integers are handeled.
|
||||
* Otherwise it returns the original value.
|
||||
*
|
||||
* @param string $key Key to check if it's inside the encryptedValues variable.
|
||||
* @param mixed $value Info: Encryption only supports strings.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function prepareValue(string $key, $value)
|
||||
{
|
||||
// Check if key should be encrypted
|
||||
if (in_array($key, $this->encrypted_keys)) {
|
||||
// Cast to string to avoid error when a user passes a boolean value
|
||||
return Crypt::encryptString((string) $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the provided key should be decrypted or not.
|
||||
* Otherwise it returns the original value.
|
||||
*
|
||||
* @param string $key Key to check if it's inside the encryptedValues variable.
|
||||
* @param mixed $value Info: Encryption only supports strings.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function unpackValue(string $key, $value)
|
||||
{
|
||||
// Check if key should be encrypted
|
||||
if (in_array($key, $this->encrypted_keys)) {
|
||||
// Cast to string to avoid error when a user passes a boolean value
|
||||
return Crypt::decryptString((string) $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function read()
|
||||
{
|
||||
return $this->parseReadData($this->newQuery()->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse data coming from the database.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function parseReadData($data)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
foreach ($data as $row) {
|
||||
if (is_array($row)) {
|
||||
$key = $row[$this->key];
|
||||
$value = $row[$this->value];
|
||||
} elseif (is_object($row)) {
|
||||
$key = $row->{$this->key};
|
||||
$value = $row->{$this->value};
|
||||
} else {
|
||||
$msg = 'Expected array or object, got ' . gettype($row);
|
||||
throw new \UnexpectedValueException($msg);
|
||||
}
|
||||
|
||||
// Encryption
|
||||
$value = $this->unpackValue($key, $value);
|
||||
|
||||
Arr::set($results, $key, $value);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new query builder instance.
|
||||
*
|
||||
* @param bool $insert
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
protected function newQuery($insert = false)
|
||||
{
|
||||
$query = $this->connection->table($this->table);
|
||||
|
||||
if (!$insert) {
|
||||
foreach ($this->getExtraColumns() as $key => $value) {
|
||||
$query->where($key, '=', $value);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->query_constraint !== null) {
|
||||
$callback = $this->query_constraint;
|
||||
$callback($query, $insert);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Akaunting\Setting\Drivers;
|
||||
|
||||
use Akaunting\Setting\Contracts\Driver;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
|
||||
class Json extends Driver
|
||||
{
|
||||
/**
|
||||
* @param \Illuminate\Filesystem\Filesystem $files
|
||||
* @param string $path
|
||||
*/
|
||||
public function __construct(Filesystem $files, $path = null)
|
||||
{
|
||||
$this->files = $files;
|
||||
|
||||
$this->setPath($path ?: storage_path() . '/settings.json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the path for the JSON file.
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
public function setPath($path)
|
||||
{
|
||||
// If the file does not already exist, we will attempt to create it.
|
||||
if (!$this->files->exists($path)) {
|
||||
$result = $this->files->put($path, '{}');
|
||||
if ($result === false) {
|
||||
throw new \InvalidArgumentException("Could not write to $path.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->files->isWritable($path)) {
|
||||
throw new \InvalidArgumentException("$path is not writable.");
|
||||
}
|
||||
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExtraColumns()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function read()
|
||||
{
|
||||
$contents = $this->files->get($this->path);
|
||||
|
||||
$data = json_decode($contents, true);
|
||||
|
||||
if ($data === null) {
|
||||
throw new \RuntimeException("Invalid JSON in {$this->path}");
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function write(array $data)
|
||||
{
|
||||
if ($data) {
|
||||
$contents = json_encode($data);
|
||||
} else {
|
||||
$contents = '{}';
|
||||
}
|
||||
|
||||
$this->files->put($this->path, $contents);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Akaunting\Setting\Drivers;
|
||||
|
||||
use Akaunting\Setting\Contracts\Driver;
|
||||
|
||||
class Memory extends Driver
|
||||
{
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function __construct(array $data = null)
|
||||
{
|
||||
if ($data) {
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExtraColumns()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function read()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function write(array $data)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user