Browse Source

Without share.

master
Alexander Demidov 5 years ago
commit
b3c03162f1
  1. 3
      .gitignore
  2. 22
      LICENSE
  3. 111
      README.md
  4. 33
      composer.json
  5. 18
      phpunit.xml
  6. 143
      src/Cache.php
  7. 14
      src/Facades/Settings.php
  8. 169
      src/Settings.php
  9. 62
      src/SettingsServiceProvider.php
  10. 33
      src/config/settings.php
  11. 33
      src/database/migrations/2015_04_13_020453_create_settings_table.php
  12. 34
      src/database/migrations/2015_12_15_020453_alter_settings_table.php
  13. 20
      src/helpers.php
  14. 73
      tests/CacheTest.php
  15. 123
      tests/SettingsTest.php
  16. 7
      tests/bootstrap.php

3
.gitignore

@ -0,0 +1,3 @@
/.idea
/vendor
composer.lock

22
LICENSE

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Efriandika Pratama
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

111
README.md

@ -0,0 +1,111 @@
[![Latest Stable Version](https://poser.pugx.org/efriandika/laravel-settings/v/stable.svg)](https://packagist.org/packages/efriandika/laravel-settings)
[![Total Downloads](https://poser.pugx.org/efriandika/laravel-settings/downloads.svg)](https://packagist.org/packages/efriandika/laravel-settings)
[![Latest Unstable Version](https://poser.pugx.org/efriandika/laravel-settings/v/unstable.svg)](https://packagist.org/packages/efriandika/laravel-settings)
[![License](https://poser.pugx.org/efriandika/laravel-settings/license.svg)](https://packagist.org/packages/efriandika/laravel-settings)
# Laravel-Settings
Laravel 5.1.x Persistent Settings (Database + Cache)
### Attention: for update to v1.2.0
Re-Publish new migration file
$ php artisan vendor:publish --provider="Efriandika\LaravelSettings\SettingsServiceProvider" --force
And run
$ php artisan migrate
## How to Install
Require this package with composer ([Packagist](https://packagist.org/packages/efriandika/laravel-settings)) using the following command:
composer require efriandika/laravel-settings
or modify your `composer.json`:
"require": {
"efriandika/laravel-settings": "1.*"
}
then run `composer update`:
After updating composer, Register the ServiceProvider to the `providers` array in `config/app.php`
'Efriandika\LaravelSettings\SettingsServiceProvider',
Add an alias for the facade to `aliases` array in your `config/app.php`
'Settings' => Efriandika\LaravelSettings\Facades\Settings::class,
Publish the config and migration files now (Attention: This command will not work if you don't follow previous instruction):
$ php artisan vendor:publish --provider="Efriandika\LaravelSettings\SettingsServiceProvider" --force
Change `config/settings.php` according to your needs. If you change `db_table`, don't forget to change the table's name
in the migration file as well.
Create the `settings` table.
$ php artisan migrate
## How to Use it?
Set a value
Settings::set('key', 'value');
Get a value
$value = Settings::get('key');
Get a value with Default Value.
$value = Settings::get('key', 'Default Value');
> Note: If key is not found (null) in cache or settings table, it will return default value
Get a value via an helper
$value = settings('key');
$value = settings('key', 'default value');
Forget a value
Settings::forget('key');
Forget all values
Settings::flush();
## Fallback to Laravel Config (available in v1.2.0)
How to activate?
// Change your config/settings.php
'fallback' => true
Example
/*
* If the value with key => mail.host is not found in cache or DB of Larave Settings
* it will return same value as config::get('mail.host');
*/
Settings::get('mail.host');
> Note: It will work if default value in laravel setting is not set
### Changelogs
v1.2.0 - Dec 16th, 2015
* Bugs fix
* Adding Feature: Fallback Value
### To Do
-
### License
The Laravel 5 Persistent Settings is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)

33
composer.json

@ -0,0 +1,33 @@
{
"name": "efriandika/laravel-settings",
"description": "Laravel 5 Persistent Settings",
"keywords": [
"laravel",
"settings",
"persistent"
],
"license": "MIT",
"authors": [
{
"name": "Efriandika Pratama",
"email": "efriandika@gmail.com"
}
],
"require": {
"php": ">=5.5.9",
"illuminate/support": "5.*"
},
"require-dev": {
"phpunit/phpunit": "4.6.*",
"illuminate/database": ">=5.1 <6.0",
"illuminate/events": ">=4.1 <6.0"
},
"autoload": {
"files": [
"src/helpers.php"
],
"psr-4": {
"Efriandika\\LaravelSettings\\": "src/"
}
}
}

18
phpunit.xml

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="tests/bootstrap.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites>
<testsuite name="Package Test Suite">
<directory suffix=".php">./tests/</directory>
</testsuite>
</testsuites>
</phpunit>

143
src/Cache.php

@ -0,0 +1,143 @@
<?php namespace Efriandika\LaravelSettings;
/**
* Class Cache
* @package Efriandika\LaravelSettings
*/
class Cache
{
/**
* Path to cache file
*
* @var string
*/
protected $cacheFile;
/**
* Cached Settings
*
* @var array
*/
protected $settings;
/**
* Constructor
*
* @param string $cacheFile
*/
public function __construct($cacheFile)
{
$this->cacheFile = $cacheFile;
$this->checkCacheFile();
$this->settings = $this->getAll();
}
/**
* Sets a value
*
* @param $key
* @param $value
*
* @return mixed
*/
public function set($key, $value)
{
$this->settings[$key] = $value;
$this->store();
return $value;
}
/**
* Gets a value
*
* @param $key
* @param null $default
*
* @return mixed
*/
public function get($key, $default = null)
{
return (array_key_exists($key, $this->settings) ? $this->settings[$key] : $default);
}
/**
* Checks if $key is cached
*
* @param $key
*
* @return bool
*/
public function hasKey($key)
{
return array_key_exists($key, $this->settings);
}
/**
* Gets all cached settings
*
* @return array
*/
public function getAll()
{
$values = json_decode(file_get_contents($this->cacheFile), true);
foreach ($values as $key => $value) {
$values[$key] = unserialize($value);
}
return $values;
}
/**
* Stores all settings to the cache file
*
* @return void
*/
private function store()
{
$settings = [];
foreach ($this->settings as $key => $value) {
$settings[$key] = serialize($value);
}
file_put_contents($this->cacheFile, json_encode($settings));
}
/**
* Removes a value
*
* @return void
*/
public function forget($key)
{
if (array_key_exists($key, $this->settings)) {
unset($this->settings[$key]);
}
$this->store();
}
/**
* Removes all values
*
* @return void
*/
public function flush()
{
file_put_contents($this->cacheFile, json_encode([]));
// fixed the set after immediately the flush, should be returned empty
$this->settings = [];
}
/**
* Checks if the cache file exists and creates it if not
*
* @return void
*/
private function checkCacheFile()
{
if (!file_exists($this->cacheFile)) {
$this->flush();
}
}
}

14
src/Facades/Settings.php

@ -0,0 +1,14 @@
<?php namespace Efriandika\LaravelSettings\Facades;
use Illuminate\Support\Facades\Facade;
class Settings extends Facade {
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor() { return 'settings'; }
}

169
src/Settings.php

@ -0,0 +1,169 @@
<?php namespace Efriandika\LaravelSettings;
use Illuminate\Database\DatabaseManager;
use Illuminate\Support\Facades\Config;
/**
* Class Settings
* @package Efriandika\LaravelSettings
*/
class Settings
{
/**
* Registry config
*
* @var array
*/
protected $config;
/**
* Database manager instance
*
* @var \Illuminate\Database\DatabaseManager
*/
protected $database;
/**
* Cache
*
* @var \Efriandika\LaravelSettings\Cache
*/
protected $cache;
/**
* Constructor
*
* @param DatabaseManager $database
*/
public function __construct(DatabaseManager $database, Cache $cache, $config = array ())
{
$this->database = $database;
$this->config = $config;
$this->cache = $cache;
}
/**
* Gets a value
*
* @param string $key
* @param string $default
*
* @return mixed
*/
public function get($key, $default = null)
{
$value = $this->fetch($key);
if(!is_null($value))
return $value;
else if($default != null)
return $default;
else if($this->config['fallback'])
return Config::get($key, null);
else
return $default;
}
/**
* @param $key
*
* @return mixed|null
*/
private function fetch($key)
{
if ($this->cache->hasKey($key)) {
return $this->cache->get($key);
}
$row = $this->database->table($this->config['db_table'])->where('setting_key', $key)->first(['setting_value']);
return (!is_null($row)) ? $this->cache->set($key, unserialize($row->setting_value)) : null;
}
/**
* Checks if setting exists
*
* @param $key
*
* @return bool
*/
public function hasKey($key)
{
if ($this->cache->hasKey($key)) {
return true;
}
$row = $this->database->table($this->config['db_table'])->where('setting_key', $key)->first(['setting_value']);
return (count($row) > 0);
}
/**
* Store value into registry
*
* @param string $key
* @param mixed $value
*
* @return mixed
*/
public function set($key, $value)
{
$value = serialize($value);
$setting = $this->database->table($this->config['db_table'])->where('setting_key', $key)->first();
if (is_null($setting)) {
$this->database->table($this->config['db_table'])
->insert(['setting_key' => $key, 'setting_value' => $value]);
} else {
$this->database->table($this->config['db_table'])
->where('setting_key', $key)
->update(['setting_value' => $value]);
}
$this->cache->set($key, unserialize($value));
return $value;
}
/**
* Remove a setting
*
* @param string $key
*
* @return void
*/
public function forget($key)
{
$this->database->table($this->config['db_table'])->where('setting_key', $key)->delete();
$this->cache->forget($key);
}
/**
* Remove all settings
*
* @return bool
*/
public function flush()
{
$this->cache->flush();
return $this->database->table($this->config['db_table'])->delete();
}
/**
* Fetch all values
*
* @return mixed
*/
public function getAll()
{
return $this->cache->getAll();
}
}

62
src/SettingsServiceProvider.php

@ -0,0 +1,62 @@
<?php namespace Efriandika\LaravelSettings;
use Illuminate\Support\ServiceProvider;
class SettingsServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = false;
/**
* Bootstrap the application events.
*
* @return void
*/
public function boot()
{
$this->publishes([
__DIR__ . '/config/settings.php' => config_path('settings.php')
]);
$this->publishes([
__DIR__ . '/database/migrations/' => base_path('/database/migrations')
]);
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->mergeConfigFrom(
__DIR__ . '/config/settings.php', 'settings'
);
$this->app['settings'] = function ($app) {
$config = $app->config->get('settings', [
'cache_file' => storage_path('settings.json'),
'db_table' => 'settings'
]);
return new Settings($app['db'], new Cache($config['cache_file']), $config);
};
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return array ('settings');
}
}

33
src/config/settings.php

@ -0,0 +1,33 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Cache Filename
|--------------------------------------------------------------------------
|
| Cache configuration path
|
*/
'cache_file' => storage_path('settings.json'),
/*
|--------------------------------------------------------------------------
| Table name to store settings
|--------------------------------------------------------------------------
|
| Info: If you change this table name, dont forget to update your settings migrations file.
|
*/
'db_table' => 'settings',
/*
|--------------------------------------------------------------------------
| Fallback setting
|--------------------------------------------------------------------------
|
| Return Laravel config if the value with particular key is not found in cache or DB.
| It will work if default value in laravel setting is not set, and this value is set to true
|
*/
'fallback' => true
];

33
src/database/migrations/2015_04_13_020453_create_settings_table.php

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateSettingsTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('settings', function(Blueprint $table)
{
$table->string('key', 100)->index()->unique('key');
$table->text('value', 65535)->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('settings');
}
}

34
src/database/migrations/2015_12_15_020453_alter_settings_table.php

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
class AlterSettingsTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function ($table) {
$table->renameColumn('key', 'setting_key');
$table->renameColumn('value', 'setting_value');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function ($table) {
$table->renameColumn('setting_key', 'key');
$table->renameColumn('setting_value', 'value');
});
}
}

20
src/helpers.php

@ -0,0 +1,20 @@
<?php
use Efriandika\LaravelSettings\Facades\Settings;
if (!function_exists('settings'))
{
/**
* @param string|null $key
* @param null $default
* @return mixed|\Efriandika\LaravelSettings\Facades\Settings
*/
function settings($key = null, $default = null)
{
if (is_null($key)) {
return app('settings');
}
return Settings::get($key, $default);
}
}

73
tests/CacheTest.php

@ -0,0 +1,73 @@
<?php
use Efriandika\LaravelSettings\Cache;
class CacheTest extends PHPUnit_Framework_TestCase
{
protected $cache;
protected $cacheFile;
protected function setUp()
{
$this->cacheFile = storage_path('settings.json');
$this->cache = new Cache($this->cacheFile);
}
public function testSet()
{
$this->cache->set('key', 'value');
$contents = file_get_contents($this->cacheFile);
$this->assertEquals('{"key":"s:5:\"value\";"}', $contents);
}
public function testSetArray()
{
$set = ['value' => 1, 'value2' => 2];
$this->cache->set('key', $set);
$contents = file_get_contents($this->cacheFile);
$this->assertEquals('{"key":"a:2:{s:5:\"value\";i:1;s:6:\"value2\";i:2;}"}', $contents);
$this->assertEquals($this->cache->get('key'), $set);
}
public function testGet()
{
$this->cache->set('key', 'value');
$this->assertEquals('value', $this->cache->get('key'));
}
public function testGetAll()
{
$this->cache->set('key', 'value');
$this->cache->set('key2', 'value2');
$this->assertEquals(['key' => 'value', 'key2' => 'value2'], $this->cache->getAll());
}
public function testFlush()
{
$this->cache->set('key', 'value');
$this->cache->flush();
$this->assertEquals([], $this->cache->getAll());
}
public function testHasKey()
{
$this->cache->set('key', 'value');
$this->assertTrue($this->cache->hasKey('key'));
}
public function testForget()
{
$this->cache->set('key', 'value');
$this->cache->forget('key');
$this->assertNull($this->cache->get('key'));
}
protected function tearDown()
{
@unlink(storage_path('settings.json'));
}
}

123
tests/SettingsTest.php

@ -0,0 +1,123 @@
<?php
use Illuminate\Container\Container;
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Events\Dispatcher;
use Efriandika\LaravelSettings\Settings;
use Efriandika\LaravelSettings\Cache;
class SettingsTest extends PHPUnit_Framework_TestCase
{
protected $settings;
protected $db;
protected $config;
protected function setUp()
{
$this->db = $this->initDb();
$this->config = [
'db_table' => 'settings',
'cache_file' => storage_path('settings.json'),
];
$this->settings = new Settings($this->db, new Cache($this->config['cache_file']), $this->config);
}
public function testSet()
{
$this->settings->set('key', 'value');
$setting = $this->db->table($this->config['db_table'])->where('key', 'key')->first(['value']);
$this->assertEquals('value', unserialize($setting['value']));
}
public function testSetArray()
{
$set = ['valuekey' => 'value'];
$this->settings->set('key', $set);
$setting = $this->db->table($this->config['db_table'])->where('key', 'key')->first(['value']);
$this->assertEquals($set, unserialize($setting['value']));
$this->assertEquals($set, $this->settings->get('key'));
}
public function testGet()
{
$this->settings->set('key', 'value');
$this->assertEquals('value', $this->settings->get('key'));
}
public function testGetAll()
{
$this->settings->set('key', 'value');
$this->settings->set('key2', 'value2');
$this->assertEquals('value', $this->settings->get('key'));
$this->assertEquals('value2', $this->settings->get('key2'));
$this->assertEquals(['key' => 'value', 'key2' => 'value2'], $this->settings->getAll());
}
public function testFlush()
{
$this->settings->set('key', 'value');
$this->settings->flush();
$this->assertEquals([], $this->settings->getAll());
}
public function testHasKey()
{
$this->settings->set('key', 'value');
$this->assertTrue($this->settings->hasKey('key'));
$this->assertFalse($this->settings->hasKey('key2'));
}
public function testHasKeyWithoutCache()
{
$this->settings->set('key', 'value');
$this->assertTrue($this->settings->hasKey('key'));
$this->assertFalse($this->settings->hasKey('key2'));
@unlink(storage_path('settings.json'));
$this->assertTrue($this->settings->hasKey('key'));
$this->assertFalse($this->settings->hasKey('key2'));
}
public function testForget()
{
$this->settings->set('key', 'value');
$this->settings->forget('key');
$this->assertNull($this->settings->get('key'));
}
protected function tearDown()
{
Capsule::schema()->drop('settings');
@unlink(storage_path('settings.json'));
}
private function initDb()
{
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'sqlite',
'host' => 'localhost',
'database' => ':memory:',
'prefix' => '',
]);
$capsule->setEventDispatcher(new Dispatcher(new Container));
$capsule->setAsGlobal();
$capsule->bootEloquent();
Capsule::schema()->create('settings', function ($table) {
$table->string('key', 100)->index()->unique('key');
$table->text('value', 65535)->nullable();
});
return $capsule->getDatabaseManager();
}
}

7
tests/bootstrap.php

@ -0,0 +1,7 @@
<?php
require dirname(__DIR__) . '/vendor/autoload.php';
function storage_path($filename) {
return dirname(__DIR__) . '/tests/' . $filename;
}
Loading…
Cancel
Save