├── .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 | [](https://packagist.org/packages/hackerESQ/laravel-settings)
4 | [](https://packagist.org/packages/hackerESQ/laravel-settings)
5 | [](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 |
--------------------------------------------------------------------------------