├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── config └── settings.php ├── database └── migrations │ ├── 2020_04_01_100000_create_settings_table.php │ └── 2020_04_01_100001_update_settings_table.php ├── phpunit.xml.dist ├── src ├── Controllers │ └── SettingController.example.php ├── Facades │ └── Settings.php ├── Settings.php └── SettingsServiceProvider.php └── tests └── SettingsTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .phpunit.result.cache 3 | build/report.junit.xml 4 | composer.lock 5 | /vendor -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 hackerESQ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Settings 2 | 3 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/hackerESQ/laravel-settings.svg?style=flat-square)](https://packagist.org/packages/hackerESQ/laravel-settings) 4 | [![Total Downloads](https://img.shields.io/packagist/dt/hackerESQ/laravel-settings.svg?style=flat-square)](https://packagist.org/packages/hackerESQ/laravel-settings) 5 | [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md) 6 | 7 | Super simple key/value settings for Laravel that natively supports [encryption](#encryption) and [multi-tenancy](#multi-tenancy). 8 | 9 | * [Installation](#installation) 10 | * [Usage](#usage) 11 | * [Set new setting](#set-new-setting) 12 | * [Get all settings](#get-all-settings) 13 | * [Get single setting](#get-single-setting) 14 | * [Get certain setting (via array)](#get-certain-settings) 15 | * [Check if a setting is set](#check-if-a-setting-is-set) 16 | * [Encryption](#encryption) 17 | * [Multi-tenancy](#multi-tenancy) 18 | * [Casting](#casting) 19 | * [Disable cache](#disable-cache) 20 | * [Hidden settings](#hidden-settings) 21 | * [Customize table name](#customize-table-name) 22 | 23 | 24 | ## Installation 25 | This package can be used in Laravel 8.0+. 26 | 27 | You can install the package via composer: 28 | 29 | ``` bash 30 | composer require hackeresq/laravel-settings 31 | ``` 32 | 33 | Since Laravel 5.5+, service providers and aliases will automatically get registered and you can skip this step. To use this package with older versions, please use release < 2.0. 34 | 35 | You can publish [the migration](https://github.com/hackerESQ/settings/blob/master/database/migrations/create_settings_table.php) and [config](https://github.com/hackerESQ/settings/blob/master/config/settings.php) files, then migrate the new settings table all in one go, using: 36 | 37 | ```bash 38 | php artisan vendor:publish --provider="HackerESQ\Settings\SettingsServiceProvider" --tag=migrations && php artisan vendor:publish --provider="HackerESQ\Settings\SettingsServiceProvider" --tag=config && php artisan migrate 39 | ``` 40 | 41 | Success! laravel-settings is now installed! 42 | 43 | ## Usage 44 | 45 | Settings can be accessed using the easy-to-remember Facade, `Settings`. 46 | 47 | ### Set new setting 48 | You can set new settings using the "set" method, which accepts an associative array of one or more key/value pairs. For security reasons, this will first check to see if such a setting key is "fillable," which is a configuration option in the [config/settings.php](https://github.com/hackerESQ/settings/blob/master/config/settings.php) file. 49 | 50 | If such a key exists in the config, it will update the key to the new value passed. If the key does not exist in the fillable config, it will disregard the change. So, if this is a fresh install, do not expect the following to work: 51 | 52 | ```php 53 | Settings::set(['firm_name'=>'new']); 54 | ``` 55 | 56 | It will not set the new setting until you have either set the fillable fields in the config, or you have opted to force the setting. If you wish to force set a new setting, you should use the `force()` method before calling the `set()` method: 57 | 58 | ```php 59 | Settings::force()->set(['firm_name'=>'new']); 60 | ``` 61 | 62 | As of version 3.0.4, the global override for forcing settings has been removed from the config file for this package. Instead, you can use a wildcard for the fillable property, like this: 63 | 64 | ```php 65 | 'fillable' => ['*'] 66 | ``` 67 | 68 | This is more in line with standard Laravel syntax (e.g. for models). 69 | 70 | ### Get all settings 71 | If no parameters are passed to the "get" method, it will return an array of all settings: 72 | 73 | ```php 74 | Settings::get(); 75 | ``` 76 | 77 | You can optionally hide specific settings using the `hidden` config as described [below](#hidden-settings). 78 | 79 | ### Get single setting 80 | You can return a single setting by passing a single setting key: 81 | 82 | ```php 83 | Settings::get('firm_name'); 84 | ``` 85 | 86 | ### Get certain settings 87 | You can also return a list of specified settings by passing an array of setting keys: 88 | 89 | ```php 90 | Settings::get(['firm_name','contact_types']); 91 | ``` 92 | 93 | ### Check if a setting is set 94 | Sometimes you can't know if a setting has been set or not (i.e. boolean settings that will return false if the setting does not exist, but also if the setting has been set to false). 95 | 96 | ```php 97 | Settings::has(['dark_theme']); 98 | ``` 99 | 100 | ## Encryption 101 | 102 | You can define keys that should be encrypted automatically within the [config/settings.php](https://github.com/hackerESQ/settings/blob/master/config/settings.php) file. To do so, add the keys as such: 103 | 104 | ```php 105 | 'encrypt' => [ 106 | 'twitter_client_id', 107 | 'twitter_client_secret', 108 | ], 109 | ``` 110 | 111 | ## Multi-tenancy 112 | This package can be used in a multi-tenant environment. The [set](#set-new-setting), [get](#get-all-settings), and [has](#check-if-a-setting-is-set) methods all read an internal 'tenant' attribute that can be set with the `tenant()` method. You can set the 'tenant' attribute by calling the `tenant()` method first, like this: 113 | 114 | ```php 115 | Settings::tenant('tenant_name')->set(['firm_name'=>'foo bar']); 116 | 117 | // returns true (i.e. successfully set `firm name`) 118 | 119 | ``` 120 | 121 | ```php 122 | Settings::tenant('tenant_name')->get('firm_name'); 123 | 124 | // returns 'foo bar' 125 | 126 | ``` 127 | 128 | ```php 129 | Settings::tenant('tenant_name')->has('firm_name'); 130 | 131 | // returns true 132 | 133 | ``` 134 | 135 | The 'tenant' attribute passed can be any alphanumeric string. The 'tenant' attribute can also be left blank to have, for example, settings saved to a so-called "central" tenant. Note: the 'tenant' attribute is not strictly typed, and will be passed to the database query as a string. 136 | 137 | ## Casting 138 | You can cast settings to native PHP types using the `cast` option in the settings.php config. Here's an example of an array being cast to JSON and back to a native PHP array: 139 | 140 | 141 | ```php 142 | // settings.php 143 | 144 | 'cast' => [ 145 | 'array_of_values' => 'json' 146 | ] 147 | ``` 148 | 149 | Which allows you to do the following: 150 | 151 | ```php 152 | Settings::set(['array_of_values' => ['one', 'two', 'three']]); 153 | 154 | return Settings::get('array_of_values'); 155 | 156 | // returns a PHP array: ['one', 'two', 'three'] 157 | ``` 158 | 159 | ## Disable cache 160 | Depending on your use case, you may like to disable the cache (enabled by default). Disable the cache by modifying the [config/settings.php](https://github.com/hackerESQ/settings/blob/master/config/settings.php) file as such: 161 | 162 | ```php 163 | 'cache' => false 164 | ``` 165 | 166 | ## Hidden settings 167 | 168 | You may wish to hide specific settings (like API keys or other sensitive user data) from inadvertent disclosure. You can set these settings in the [config/settings.php](https://github.com/hackerESQ/settings/blob/master/config/settings.php) file. To do so, add the keys as such: 169 | 170 | ```php 171 | 'hidden' => [ 172 | 'twitter_client_secret', 173 | 'super_secret_password', 174 | ], 175 | ``` 176 | 177 | Once these are set, they must be specifically requested using the `get()` method. In other words, this acts like the `$hidden` attribute on Laravel Eloquent models. 178 | 179 | In addition to hiding specific settings, you can opt to hide ALL the settings (unless specifically requested, of course). To do this, you can use a wildcard: 180 | 181 | ```php 182 | 'hidden' => ['*'], 183 | ``` 184 | 185 | ## Customize table name 186 | 187 | For some cases, it may be necessary to customize the name of the table where settings are stored. By default, the migrations that come with this package create a 'settings' table. If, for some reason, it becomes necessary to change the default table, you can set the 'table' option in the [config/settings.php](https://github.com/hackerESQ/settings/blob/master/config/settings.php) file, like this: 188 | 189 | ```php 190 | 'table' => 'user_options_table', 191 | ``` 192 | 193 | This configuration option is not included in the base config file as this is an edge case that is not commonly encountered; but nonetheless a nice convenience to have when it does come up. 194 | 195 | ## Finally 196 | ### Testing 197 | You can run tests with the `composer test` command. 198 | 199 | ### Contributing 200 | Feel free to create a fork and submit a pull request if you would like to contribute. 201 | 202 | ### Bug reports 203 | Raise an issue on GitHub if you notice something broken. 204 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hackeresq/laravel-settings", 3 | "description": "Super simple key/value settings for Laravel 8+", 4 | "keywords": [ 5 | "settings", 6 | "laravel", 7 | "key", 8 | "value" 9 | ], 10 | "license": "MIT", 11 | "minimum-stability": "stable", 12 | "autoload": { 13 | "psr-4": { 14 | "HackerESQ\\Settings\\": "src/" 15 | } 16 | }, 17 | "autoload-dev": { 18 | "psr-4": { 19 | "HackerESQ\\Settings\\Tests\\": "tests" 20 | } 21 | }, 22 | "require": { 23 | "php" : ">=8.0", 24 | "laravel/framework": "^8.0|^9.0|^10.0", 25 | "doctrine/dbal": "^3.0" 26 | }, 27 | "require-dev": { 28 | "phpunit/phpunit": "^7.0|^8.0|^9.0", 29 | "orchestra/testbench": "^6.11" 30 | }, 31 | "scripts": { 32 | "test": "vendor/bin/phpunit" 33 | }, 34 | "extra": { 35 | "laravel": { 36 | "providers": [ 37 | "HackerESQ\\Settings\\SettingsServiceProvider" 38 | ], 39 | "aliases": { 40 | "Settings": "HackerESQ\\Settings\\Facades\\Settings" 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /config/settings.php: -------------------------------------------------------------------------------- 1 | [], 17 | 18 | 19 | /* 20 | |-------------------------------------------------------------------------- 21 | | Keys for fillable settings 22 | |-------------------------------------------------------------------------- 23 | | 24 | | This option defines which settings are considered "safe" and should be 25 | | written to the database. You can use ["*"] to make all settings 26 | | fillable. This is unadvisable as any settings will be filled. 27 | | 28 | */ 29 | 30 | 'fillable' => [], 31 | 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | Cache settings 36 | |-------------------------------------------------------------------------- 37 | | 38 | | This option controls whether key/values are cached or pulled directly 39 | | from the database. If this setting is true, cache is enabled. 40 | | If this setting is false, caching is disabled. 41 | | 42 | */ 43 | 44 | 'cache' => true, 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Hidden settings 49 | |-------------------------------------------------------------------------- 50 | | 51 | | This option controls the settings that are hidden when using the get() 52 | | method without any specific settings. This protects sensitive data 53 | | like API keys or other high-value user data. You can use ["*"] 54 | | to make all settings hidden unless specifically requested. 55 | | 56 | */ 57 | 58 | 'hidden' => [], 59 | 60 | /* 61 | |-------------------------------------------------------------------------- 62 | | Keys to cast 63 | |-------------------------------------------------------------------------- 64 | | 65 | | This option controls the settings that are cast to native types 66 | | by default. Currently you can choose 'json' or 'boolean' - 67 | | in future, other types will be made available. 68 | | 69 | */ 70 | 71 | 'cast' => [], 72 | 73 | ]; -------------------------------------------------------------------------------- /database/migrations/2020_04_01_100000_create_settings_table.php: -------------------------------------------------------------------------------- 1 | string('key')->unique()->index(); 19 | $table->text('value')->nullable(); 20 | $table->primary('key'); 21 | }); 22 | } 23 | } 24 | 25 | 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('settings'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2020_04_01_100001_update_settings_table.php: -------------------------------------------------------------------------------- 1 | string('key')->index()->change(); 19 | $table->string('tenant')->nullable(); 20 | $table->dropPrimary('key'); 21 | $table->dropUnique('settings_key_unique'); 22 | 23 | $table->primary(['key', 'tenant']); 24 | $table->unique(['key', 'tenant']); 25 | 26 | }); 27 | 28 | } 29 | 30 | 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | // 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | src/ 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | tests 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Controllers/SettingController.example.php: -------------------------------------------------------------------------------- 1 | validate($request, [ 21 | 'firm_name'=>'string', 22 | ]); 23 | 24 | Settings::set( $request->all() ); 25 | 26 | return array("message"=>"success"); 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Facades/Settings.php: -------------------------------------------------------------------------------- 1 | tenant = $tenant; 22 | 23 | return $this; 24 | } 25 | 26 | /** 27 | * Should we force? 28 | * @param bool $force (optional) 29 | * @return Settings $this 30 | */ 31 | public function force(bool $force = true) 32 | { 33 | $this->force = $force; 34 | 35 | return $this; 36 | } 37 | 38 | /** 39 | * Get settings from the database 40 | * @return array 41 | */ 42 | private function resolveDB() 43 | { 44 | return DB::table(config('settings.table', 'settings')) 45 | ->where('tenant', $this->tenant) 46 | ->pluck('value', 'key') 47 | ->toArray(); 48 | } 49 | 50 | /** 51 | * Get settings from the cache 52 | * @return array 53 | */ 54 | private function resolveCache() 55 | { 56 | if (config('settings.cache', true)) { 57 | return Cache::rememberForever('settings' . $this->tenant, function () { 58 | return $this->resolveDB(); 59 | }); 60 | } 61 | 62 | return $this->resolveDB(); 63 | } 64 | 65 | /** 66 | * Decrypt any settings that need to be decrypted 67 | * @param array $settings 68 | * @return array 69 | */ 70 | private function decryptHandler(array $settings) 71 | { 72 | // DO WE NEED TO DECRYPT ANYTHING? 73 | foreach ($settings as $key => $value) { 74 | if (in_array($key, config('settings.encrypt', [])) && !empty($value)) { 75 | Arr::set($settings, $key, decrypt($value)); 76 | } 77 | } 78 | return $settings; 79 | } 80 | 81 | /** 82 | * Encrypt any settings that need to be encrypted 83 | * @param array $settings 84 | * @return array 85 | */ 86 | private function encryptHandler(array $settings) 87 | { 88 | // DO WE NEED TO ENCRYPT ANYTHING? 89 | foreach ($settings as $key => $value) { 90 | if (in_array($key, config('settings.encrypt', [])) && !empty($value)) { 91 | Arr::set($settings, $key, encrypt($value)); 92 | } 93 | } 94 | return $settings; 95 | } 96 | 97 | /** 98 | * Upsert into the database 99 | * @param string $key 100 | * @param string $value 101 | * @return void 102 | */ 103 | private function upsert(string $key, $value) 104 | { 105 | DB::table(config('settings.table', 'settings'))->updateOrInsert( 106 | [ 107 | 'key' => $key, 108 | 'tenant' => $this->tenant 109 | ], 110 | [ 111 | 'key' => $key, 112 | 'value' => $value, 113 | 'tenant' => $this->tenant 114 | ] 115 | ); 116 | } 117 | 118 | /** 119 | * Get value of settings by key 120 | * @param string|array $key (optional) 121 | * @param string|array $default (optional) 122 | * @return mixed string 123 | */ 124 | public function get(string|array $key = NULL, string|array $default = NULL) 125 | { 126 | $settings = $this->getCasts($this->decryptHandler($this->resolveCache())); 127 | 128 | // no key passed, assuming get all settings 129 | if (is_null($key)) { 130 | // are we hiding everything? 131 | return (config('settings.hidden', []) == ['*']) 132 | ? [] // then return nothing. 133 | : array_merge( 134 | $default ?? [], 135 | Arr::except($settings, config('settings.hidden', [])) 136 | ); 137 | } 138 | 139 | // array of keys passed, return those settings only 140 | if (is_array($key)) { 141 | foreach ($key as $key) { 142 | $result[$key] = $settings[$key] ?? $default[$key] ?? NULL; 143 | } 144 | return $result; 145 | } 146 | 147 | // single key passed, return that setting only 148 | if (array_key_exists($key, $settings)) { 149 | return $settings[$key]; 150 | } 151 | 152 | // else return only default 153 | return $default; 154 | } 155 | 156 | /** 157 | * Check if a given key exists 158 | * @param string|array $needle 159 | * @return boolean 160 | */ 161 | public function has(mixed $needle) 162 | { 163 | $settings = $this->decryptHandler($this->resolveCache()); 164 | 165 | if (is_array($needle)) { 166 | foreach ($needle as $item) { 167 | if (!array_key_exists($item, $settings)) return false; 168 | } 169 | return true; 170 | } 171 | return array_key_exists($needle, $settings); 172 | } 173 | 174 | /** 175 | * Set value of setting 176 | * @param array $changes 177 | * @return boolean 178 | */ 179 | public function set(array $changes) 180 | { 181 | $changes = $this->setCasts($this->encryptHandler($changes)); 182 | 183 | // Extracts only fillable key/values from array using fillable config 184 | if (config('settings.fillable', []) != ['*'] && !$this->force) { 185 | $changes = Arr::only($changes, config('settings.fillable', [])); 186 | } 187 | 188 | foreach ($changes as $key => $value) { 189 | $this->upsert($key, $value); 190 | } 191 | 192 | // reset cache 193 | if (config('settings.cache', true)) { 194 | Cache::forget('settings' . $this->tenant); 195 | } 196 | 197 | return true; 198 | } 199 | 200 | /** 201 | * Casts database values to type 202 | * @param array $settings 203 | * @return array 204 | */ 205 | public function getCasts(array $settings) 206 | { 207 | foreach(config('settings.cast', []) as $castable => $cast_to) { 208 | if (!isset($settings[$castable])) { 209 | continue; 210 | } 211 | 212 | // cast JSON 213 | if ($cast_to == 'json') { 214 | $settings[$castable] = json_decode($settings[$castable], true); 215 | } 216 | 217 | // cast BOOLEAN 218 | if ($cast_to == 'boolean') { 219 | $settings[$castable] = $settings[$castable] == 1 ? true : false; 220 | } 221 | 222 | // cast INT 223 | if ($cast_to == 'integer') { 224 | $settings[$castable] = (int) $settings[$castable]; 225 | } 226 | } 227 | 228 | return $settings; 229 | } 230 | 231 | /** 232 | * Casts native values to string 233 | * @param array $settings 234 | * @return array 235 | */ 236 | public function setCasts(array $settings) 237 | { 238 | foreach(config('settings.cast', []) as $castable => $cast_to) { 239 | if (!isset($settings[$castable])) { 240 | continue; 241 | } 242 | 243 | // cast JSON 244 | if ($cast_to == 'json') { 245 | $settings[$castable] = json_encode($settings[$castable]); 246 | } 247 | 248 | // cast BOOLEAN 249 | if ($cast_to == 'boolean') { 250 | $settings[$castable] = $settings[$castable] == true ? 1 : 0; 251 | } 252 | } 253 | 254 | return $settings; 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /src/SettingsServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 23 | __DIR__ . '/../config/settings.php' => config_path('settings.php'), 24 | ], 'config'); 25 | 26 | 27 | /** 28 | * Publish settings migration 29 | */ 30 | $this->publishes([ 31 | __DIR__.'/../database/migrations/2020_04_01_100000_create_settings_table.php' => $this->app->databasePath()."/migrations/2020_04_01_100000_create_settings_table.php", 32 | __DIR__.'/../database/migrations/2020_04_01_100001_update_settings_table.php' => $this->app->databasePath()."/migrations/2020_04_01_100001_update_settings_table.php", 33 | ], 'migrations'); 34 | 35 | } 36 | 37 | /** 38 | * Register services. 39 | * 40 | * @return void 41 | */ 42 | public function register () { 43 | 44 | // bind 'settings' to the class named 'settings' in the IOC container 45 | $this->app->singleton('settings', function ($app) { 46 | return new \HackerESQ\Settings\Settings ($app); 47 | }); 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /tests/SettingsTest.php: -------------------------------------------------------------------------------- 1 | set('app.debug', env('APP_DEBUG', true)); 24 | $app['config']->set('database.default', 'testing'); 25 | $app['config']->set('database.connections.testing', [ 26 | 'driver' => 'sqlite', 27 | 'database' => ':memory:', 28 | ]); 29 | 30 | // package specific 31 | $app['config']->set('settings.encrypt', []); 32 | $app['config']->set('settings.fillable', []); 33 | $app['config']->set('settings.cache', true); 34 | $app['config']->set('settings.hidden', []); 35 | $app['config']->set('settings.cast', []); 36 | } 37 | 38 | /** 39 | * Define database migrations. 40 | * 41 | * @return void 42 | */ 43 | protected function defineDatabaseMigrations() 44 | { 45 | $this->loadMigrationsFrom([ 46 | '--database' => 'testing', 47 | '--path' => realpath(__DIR__ . '/../database/migrations') 48 | ]); 49 | } 50 | 51 | /** 52 | * Get package providers. 53 | * 54 | * @param \Illuminate\Foundation\Application $app 55 | * @return array 56 | */ 57 | protected function getPackageProviders($app) 58 | { 59 | return [\HackerESQ\Settings\SettingsServiceProvider::class]; 60 | } 61 | 62 | /** 63 | * Get package aliases. 64 | * 65 | * @param \Illuminate\Foundation\Application $app 66 | * 67 | * @return array 68 | */ 69 | protected function getPackageAliases($app) 70 | { 71 | return [ 72 | 'Settings' => 'HackerESQ\Settings\Facades\Settings', 73 | ]; 74 | } 75 | 76 | /** @test */ 77 | public function it_can_set_and_get_settings() 78 | { 79 | $this->app['config']->set('settings.fillable', ['key']); 80 | 81 | $result = Settings::set(['key' => 'value']); 82 | 83 | $this->assertTrue($result); 84 | 85 | $result = Settings::get('key'); 86 | 87 | $this->assertEquals($result, 'value'); 88 | } 89 | 90 | /** @test */ 91 | public function it_can_force_set_settings() 92 | { 93 | $result = Settings::force()->set(['forced' => 'value']); 94 | 95 | $this->assertTrue($result); 96 | 97 | $result = Settings::get('forced'); 98 | 99 | $this->assertEquals($result, 'value'); 100 | } 101 | 102 | /** @test */ 103 | public function it_can_get_one_setting() 104 | { 105 | $this->app['config']->set('settings.fillable', ['foo']); 106 | 107 | Settings::set(['foo' => 'value']); 108 | 109 | $result = Settings::get('foo'); 110 | 111 | $this->assertEquals('value', $result, json_encode($result)); 112 | } 113 | 114 | /** @test */ 115 | public function it_can_get_many_settings() 116 | { 117 | $this->app['config']->set('settings.fillable', ['foo', 'bar']); 118 | 119 | Settings::set(['foo' => 'value']); 120 | Settings::set(['bar' => 'value']); 121 | 122 | $result = Settings::get(); 123 | 124 | $this->assertArrayHasKey('foo', $result, json_encode($result)); 125 | $this->assertArrayHasKey('bar', $result, json_encode($result)); 126 | } 127 | 128 | /** @test */ 129 | public function it_can_get_array_of_settings() 130 | { 131 | $this->app['config']->set('settings.fillable', ['foo', 'bar']); 132 | 133 | Settings::set(['foo' => 'value']); 134 | Settings::set(['bar' => 'value']); 135 | 136 | $result = Settings::get(['foo', 'bar']); 137 | 138 | $this->assertArrayHasKey('foo', $result, json_encode($result)); 139 | $this->assertArrayHasKey('bar', $result, json_encode($result)); 140 | } 141 | 142 | /** @test */ 143 | public function it_can_set_many_settings() 144 | { 145 | $this->app['config']->set('settings.fillable', ['foo', 'bar']); 146 | 147 | Settings::set([ 148 | 'foo' => 'value', 149 | 'bar' => 'value' 150 | ]); 151 | 152 | $result = Settings::get(); 153 | 154 | $this->assertArrayHasKey('foo', $result, json_encode($result)); 155 | $this->assertArrayHasKey('bar', $result, json_encode($result)); 156 | } 157 | 158 | /** @test */ 159 | public function it_can_return_has_settings() 160 | { 161 | $this->app['config']->set('settings.fillable', ['foo', 'bar']); 162 | 163 | Settings::set([ 164 | 'foo' => 'value', 165 | 'bar' => 'value', 166 | ]); 167 | 168 | $result = Settings::has('foo'); 169 | 170 | $this->assertTrue($result, json_encode($result)); 171 | 172 | $result = Settings::has(['foo', 'bar']); 173 | 174 | $this->assertTrue($result, json_encode($result)); 175 | 176 | $result = Settings::has('not_here'); 177 | 178 | $this->assertFalse($result, json_encode($result)); 179 | } 180 | 181 | /** @test */ 182 | public function it_can_encrypt_settings() 183 | { 184 | $this->app['config']->set('settings.fillable', ['foo', 'bar']); 185 | $this->app['config']->set('settings.encrypt', ['foo']); 186 | 187 | Settings::set([ 188 | 'foo' => 'value', 189 | 'bar' => 'value' 190 | ]); 191 | 192 | // should be encrypted 193 | $result = DB::table('settings')->select('value')->where('key', 'foo')->first(); 194 | $this->assertNotEquals('value', $result->value, json_encode($result)); 195 | 196 | // should NOT be encrypted 197 | $result = DB::table('settings')->select('value')->where('key', 'bar')->first(); 198 | $this->assertEquals('value', $result->value, json_encode($result)); 199 | } 200 | 201 | /** @test */ 202 | public function it_can_hide_settings() 203 | { 204 | $this->app['config']->set('settings.fillable', ['foo', 'bar']); 205 | $this->app['config']->set('settings.hidden', ['foo']); 206 | 207 | Settings::set([ 208 | 'foo' => 'value', 209 | 'bar' => 'value' 210 | ]); 211 | 212 | $result = Settings::get(); 213 | $this->assertArrayNotHasKey('foo', $result, json_encode($result)); 214 | $this->assertArrayHasKey('bar', $result, json_encode($result)); 215 | } 216 | 217 | /** @test */ 218 | public function it_can_hide_all_settings() 219 | { 220 | $this->app['config']->set('settings.fillable', ['foo', 'bar']); 221 | $this->app['config']->set('settings.hidden', ['*']); 222 | 223 | Settings::set([ 224 | 'foo' => 'value', 225 | 'bar' => 'value' 226 | ]); 227 | 228 | $result = Settings::get(); 229 | $this->assertArrayNotHasKey('foo', $result, json_encode($result)); 230 | $this->assertArrayNotHasKey('bar', $result, json_encode($result)); 231 | } 232 | 233 | /** @test */ 234 | public function it_can_prevent_fill_settings() 235 | { 236 | $this->app['config']->set('settings.fillable', []); 237 | 238 | Settings::set([ 239 | 'foo' => 'value', 240 | 'bar' => 'value' 241 | ]); 242 | 243 | $result = Settings::get(); 244 | 245 | $this->assertArrayNotHasKey('foo', $result, json_encode($result)); 246 | $this->assertArrayNotHasKey('bar', $result, json_encode($result)); 247 | } 248 | 249 | /** @test */ 250 | public function it_can_fill_settings() 251 | { 252 | $this->app['config']->set('settings.fillable', ['*']); 253 | 254 | Settings::set([ 255 | 'foo' => 'value', 256 | 'bar' => 'value' 257 | ]); 258 | 259 | $result = Settings::get(); 260 | 261 | $this->assertArrayHasKey('foo', $result, json_encode($result)); 262 | $this->assertArrayHasKey('bar', $result, json_encode($result)); 263 | } 264 | 265 | /** @test */ 266 | public function it_can_set_and_get_tenant_settings() 267 | { 268 | $this->app['config']->set('settings.fillable', ['*']); 269 | 270 | Settings::tenant('test')->set(['foo' => 'bar']); 271 | 272 | $tenant = Settings::tenant('test')->get(); 273 | 274 | $this->assertArrayHasKey('foo', $tenant, json_encode($tenant)); 275 | 276 | $no_tenant = Settings::tenant()->get(); 277 | 278 | $this->assertArrayNotHasKey('foo', $no_tenant, json_encode($no_tenant)); 279 | } 280 | 281 | /** @test */ 282 | public function it_can_return_default_string_settings() 283 | { 284 | $settings = Settings::get('baz', 'test'); 285 | 286 | $this->assertEquals('test', $settings, json_encode($settings)); 287 | } 288 | 289 | /** @test */ 290 | public function it_can_return_default_array_settings() 291 | { 292 | $this->app['config']->set('settings.fillable', ['foo', 'bar']); 293 | 294 | Settings::set([ 295 | 'foo' => 'bar', 296 | 'bar' => 'baz' 297 | ]); 298 | 299 | $settings = Settings::get(['foo', 'bar', 'not_set'], ['not_set' => 'test']); 300 | 301 | $this->assertEquals('test', $settings['not_set'], json_encode($settings)); 302 | } 303 | 304 | /** @test */ 305 | public function it_can_return_default_all_settings() 306 | { 307 | $settings = Settings::get(['not_set'], ['not_set' => 'test']); 308 | 309 | $this->assertEquals('test', $settings['not_set'], json_encode($settings)); 310 | } 311 | 312 | /** @test */ 313 | public function it_casts_arrays() 314 | { 315 | $this->app['config']->set('settings.fillable', ['*']); 316 | $this->app['config']->set('settings.cast', ['array' => 'json']); 317 | 318 | Settings::set(['array' => ['test', 'one', 'two']]); 319 | 320 | $settings = Settings::get('array'); 321 | 322 | $this->assertIsArray($settings); 323 | } 324 | 325 | /** @test */ 326 | public function it_casts_booleans() 327 | { 328 | $this->app['config']->set('settings.fillable', ['*']); 329 | $this->app['config']->set('settings.cast', ['boolean' => 'boolean']); 330 | 331 | Settings::set(['boolean' => true]); 332 | 333 | $settings = Settings::get('boolean'); 334 | 335 | $this->assertEquals($settings, true); 336 | } 337 | } 338 | --------------------------------------------------------------------------------