diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..088996b --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/build/ +/vendor/ +composer.lock +composer.phar \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ecb3cbc --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Yarob Al-Taay + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b10a07a --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +#STILL IN DEVELOPMENTgit + +# Laravel Model Settings + +Add settings feature to Eloquent models in Laravel 5. + + +## Background + +This has been developed to simplify adding "settings" feature to any eloquent model on your laravel project. Settings WILL be stored in `json` format, which has it's pros and cons! + +## Installation +To install the package via Composer: + +```shell +$ composer require yarob/laravel-model-settings +``` +Then, update `config/app.php` by adding an entry for the service provider. + +```php +'providers' => [ + // ... + Yarob\LaravelModelSettings\ServiceProvider::class, +]; +``` +Finally, via terminal, publish the default configuration file: + +```shell +php artisan vendor:publish --provider="Yarob\LaravelModelSettings\ServiceProvider" +``` +## Updating your Eloquent Models + +Your models should use the `hasSettings` trait. +You must also add `settings` to your `fillable` array, and then cast `settings` to `json` as shown in the example below + +```php +use Yarob\LaravelModelSettings\HasSettings; + +class User extends Model +{ + use hasSettings; + + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = [ + 'name', 'email', 'settings' + ]; + + + /** + * The attributes that should be casted. + * + * @var array + */ + protected $casts = [ + 'settings' =>'json', + ]; + +} +``` + +Your model and database must have column named `settings` in the database to store the settings values. You can add this manually via a migration on the intended model. The column should be text and big enough to store all settings after json encoded. + +## Usage + +Better demonstrated in example + +```php +$user = $user = App\User::first(); + +$user->settings()->save(array( + 'address' => 'London', + 'phone_number' => '0123456789' + )); + +dd($user->settings); +``` +## Configuration + +Configuration was made to be as flexible as possible. You can add the allowed settings keys per Model basis. + +Global configuration can be set in the `app/config/model-settings.php` file. By default, `phone_number` and `address` settings keys have been added to `User` model. But feel free to change that. + +If a configuration isn't set, then the package defaults from +`vendor/yarob/laravel-model-settings/resources/config/model-settings.php` are used. +Here is an example configuration: + +```php +return [ + 'User' => [ + 'phone_number', + 'address', + ], +]; +``` + + + +## Copyright and License + +[laravel-model-settings](https://github.com/EazyServer/laravel-model-settings) +was written by [Yarob Al-Taay](https://twitter.com/TheEpicVoyage) and is released under the +[MIT License](LICENSE.md). + +Copyright (c) 2017 Yarob Al-Taay \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..64b924b --- /dev/null +++ b/composer.json @@ -0,0 +1,18 @@ +{ + "name": "yarob/laravel-model-settings", + "description": "Laravel 5.0+ package to manage eloquent settings in JSON format", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Yarob Al-Taay", + "email": "yarob83@gmail.com" + } + ], + "require": {}, + "autoload": { + "psr-4": { + "Yarob\\LaravelModelSettings\\": "src" + } + } +} diff --git a/resources/config/model-settings.php b/resources/config/model-settings.php new file mode 100644 index 0000000..a0c34e9 --- /dev/null +++ b/resources/config/model-settings.php @@ -0,0 +1,19 @@ + [ + 'phone_number', + 'address', + ], + + /** + * You can add more Models with allowed keys settings below, + * as per the example above + */ +]; diff --git a/src/HasSettings.php b/src/HasSettings.php new file mode 100644 index 0000000..90007ea --- /dev/null +++ b/src/HasSettings.php @@ -0,0 +1,56 @@ +hasSettingsService = $modelSettingsService; + $this->events = $events; + } + + /** + * @param \Illuminate\Database\Eloquent\Model $model + * @return boolean|null + */ + public function saving(Model $model) + { + return $this->saveSettings($model, 'saving'); + } + + /** + * @param \Illuminate\Database\Eloquent\Model $model + * @param string $event + * @return boolean|null + */ + protected function saveSettings(Model $model, $event) + { + // If the "saving-settings" event returns a value, abort + if ($this->fireSavingSettingsEvent($model, $event) !== null) { + return; + } + $wasSaved = $this->hasSettingsService->save($model); + + $this->fireSettingsSavedEvent($model, $wasSaved); + } + + /** + * Fire the namespaced validating event. + * + * @param \Illuminate\Database\Eloquent\Model $model + * @param string $event + * @return mixed + */ + protected function fireSavingSettingsEvent(Model $model, $event) + { + return $this->events->until('eloquent.saving-settings: ' . get_class($model), [$model, $event]); + } + + /** + * Fire the namespaced post-validation event. + * + * @param \Illuminate\Database\Eloquent\Model $model + * @param string $status + * @return void + */ + protected function fireSettingsSavedEvent(Model $model, $status) + { + $this->events->fire('eloquent.settings-saved: ' . get_class($model), [$model, $status]); + } +} diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php new file mode 100644 index 0000000..d8c90e6 --- /dev/null +++ b/src/ServiceProvider.php @@ -0,0 +1,43 @@ +publishes([ + __DIR__ . '/../resources/config/model-settings.php' => config_path('model-settings.php'), + ], 'config'); + } + + /** + * Register the service provider. + * + * @return void + */ + public function register() + { + $this->mergeConfigFrom(__DIR__ . '/../resources/config/model-settings.php', 'model-settings'); + + $this->app->singleton(HasSettingsObserver::class, function ($app) { + return new HasSettingsObserver(new ModelSettingsService(), $app['events']); + }); + } +} \ No newline at end of file diff --git a/src/Services/ModelSettingsService.php b/src/Services/ModelSettingsService.php new file mode 100644 index 0000000..93c00d6 --- /dev/null +++ b/src/Services/ModelSettingsService.php @@ -0,0 +1,82 @@ +model = $model; + } + } + + /** + * Save settings for current model. + * + * @param null $settings + * @return bool + * @throws ErrorException + * @internal param Model $model + */ + public function save($settings=null) + { + if(!empty($settings) and !empty($this->model)) + { + if (!Schema::hasColumn($this->model->getTable(), 'settings')) { + throw new ErrorException('"settings" column seems to be missing on "'.class_basename($this->model).'" table on database!'); + } + else + { + $allowedSettingsKeys = $this->getConfiguration(); + $oldSettings = is_array($this->model->settings)?$this->model->settings:array(); + + $settings = array_merge( + $oldSettings, + array_only( + $settings, + $allowedSettingsKeys + ) + ); + + return $this->model->update(compact('settings')); + } + } + } + + /** + * Get Model settings configuration for the current model, + * + * @return array + */ + public function getConfiguration() + { + static $defaultConfig = null; + + if ($defaultConfig === null) { + $defaultConfig = app('config')->get('model-settings'); + } + + return $defaultConfig[class_basename($this->model)]; + } + +}