-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 64ff01e
Showing
8 changed files
with
349 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# IDE generated files # | ||
###################### | ||
.idea | ||
|
||
# OS generated files # | ||
###################### | ||
.DS_Store | ||
.DS_Store? | ||
._* | ||
.Spotlight-V100 | ||
.Trashes | ||
ehthumbs.db | ||
Thumbs.db |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
"name": "korridor/laravel-computed-attributes", | ||
"description": "Laravel package that adds computed attributes to eloquent models.", | ||
"keywords": ["laravel", "model", "eloquent", "computed", "attribute", "caching", "performance"], | ||
"homepage": "https://github.com/korridor/laravel-computed-attributes", | ||
"license": "MIT", | ||
"authors": [ | ||
{ | ||
"name": "korridor", | ||
"email": "26689068+korridor@users.noreply.github.com" | ||
} | ||
], | ||
"minimum-stability": "stable", | ||
"require": { | ||
"php": "^7.1|^7.2|^7.3", | ||
"illuminate/support": "^5.6|^5.7|^5.8|^6", | ||
"illuminate/database": "^5.6|^5.7|^5.8|^6", | ||
"illuminate/console": "^5.6|^5.7|^5.8|^6" | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"Korridor\\LaravelComputedAttributes\\": "src" | ||
} | ||
}, | ||
"extra": { | ||
"laravel": { | ||
"providers": [ | ||
"Korridor\\LaravelComputedAttributes\\LaravelComputedAttributesServiceProvider" | ||
] | ||
} | ||
}, | ||
"config": { | ||
"sort-packages": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
The MIT License (MIT) | ||
===================== | ||
|
||
Copyright © `2019` `korridor` | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Laravel computed attributes | ||
|
||
Warning: This package is still under heavy development. | ||
|
||
## Installation | ||
|
||
You can install the package via composer with following command: | ||
|
||
```bash | ||
composer require korridor/laravel-computed-attributes | ||
``` | ||
|
||
## License | ||
|
||
This package is licensed under the MIT License (MIT). Please see [license file](license.md) for more information. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<?php | ||
|
||
namespace Korridor\LaravelComputedAttributes; | ||
|
||
use Str; | ||
|
||
trait ComputedAttributes | ||
{ | ||
/** | ||
* @param string $attributeName | ||
* @return mixed | ||
*/ | ||
public function getComputedAttributeValue(string $attributeName) | ||
{ | ||
$functionName = 'get'.Str::studly($attributeName).'Computed'; | ||
$value = $this->{$functionName}(); | ||
|
||
return $value; | ||
} | ||
|
||
/** | ||
* @param string $attributeName | ||
*/ | ||
public function setComputedAttributeValue(string $attributeName) | ||
{ | ||
$computed = $this->getComputedAttributeValue($attributeName); | ||
$this->{$attributeName} = $computed; | ||
} | ||
|
||
/** | ||
* @return array | ||
*/ | ||
public function getComputedAttributeConfiguration() | ||
{ | ||
if (isset($this->computed)) { | ||
return $this->computed; | ||
} else { | ||
return []; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
<?php | ||
|
||
namespace Korridor\LaravelComputedAttributes\Console; | ||
|
||
use Composer\Autoload\ClassMapGenerator; | ||
use Illuminate\Console\Command; | ||
use Illuminate\Database\Eloquent\Model; | ||
use Korridor\LaravelComputedAttributes\ComputedAttributes; | ||
use ReflectionClass; | ||
use ReflectionException; | ||
|
||
/** | ||
* Class GenerateComputedAttributes. | ||
*/ | ||
class GenerateComputedAttributes extends Command | ||
{ | ||
/** | ||
* The name and signature of the console command. | ||
* | ||
* @var string | ||
*/ | ||
protected $signature = 'computed-attributes:generate '. | ||
'{modelsAttributes? : List of models and optionally their attributes (example: "FullModel;PartModel:attribute_1,attribute_2" or "OtherNamespace\OtherModel")} '. | ||
'{--chunkSize=100 : Size of the model chunk}'; | ||
|
||
/** | ||
* The console command description. | ||
* | ||
* @var string | ||
*/ | ||
protected $description = ''; | ||
|
||
/** | ||
* Create a new command instance. | ||
*/ | ||
public function __construct() | ||
{ | ||
parent::__construct(); | ||
} | ||
|
||
/** | ||
* Execute the console command. | ||
* | ||
* @return bool | ||
* @throws ReflectionException | ||
*/ | ||
public function handle() | ||
{ | ||
$modelsWithAttributes = $this->argument('modelsAttributes'); | ||
$modelPath = app_path('Models'); | ||
$modelNamespace = 'App\\Models\\'; | ||
$chunkSizeRaw = $this->option('chunkSize'); | ||
if (preg_match('/^\d+$/', $chunkSizeRaw)) { | ||
$chunkSize = intval($chunkSizeRaw); | ||
if ($chunkSize < 1) { | ||
$this->error('Option chunkSize needs to be greater than zero'); | ||
|
||
return false; | ||
} | ||
} else { | ||
$this->error('Option chunkSize needs to be an integer'); | ||
|
||
return false; | ||
} | ||
|
||
// Get all models with trait | ||
$classmap = ClassMapGenerator::createMap($modelPath); | ||
$models = []; | ||
foreach ($classmap as $class => $filepath) { | ||
$reflection = new ReflectionClass($class); | ||
$traits = $reflection->getTraitNames(); | ||
foreach ($traits as $trait) { | ||
if ('Korridor\\LaravelComputedAttributes\\ComputedAttributes' === $trait) { | ||
array_push($models, $class); | ||
} | ||
} | ||
} | ||
|
||
// Get all class/attribute combinations | ||
$modelAttributesToProcess = []; | ||
if (null === $modelsWithAttributes) { | ||
$this->info('Start calculating for all models with trait...'); | ||
foreach ($models as $model) { | ||
/** @var Model|ComputedAttributes $modelInstance */ | ||
$modelInstance = new $model(); | ||
$attributes = $modelInstance->getComputedAttributeConfiguration(); | ||
array_push($modelAttributesToProcess, [ | ||
'model' => $model, | ||
'modelInstance' => $modelInstance, | ||
'attributes' => $attributes, | ||
]); | ||
} | ||
} else { | ||
$this->info('Start calculating for given models...'); | ||
$modelsInAttribute = explode(';', $modelsWithAttributes); | ||
foreach ($modelsInAttribute as $modelInAttribute) { | ||
$modelInAttributeExploded = explode(':', $modelInAttribute); | ||
if (1 !== sizeof($modelInAttributeExploded) && 2 !== sizeof($modelInAttributeExploded)) { | ||
$this->error('Parsing error'); | ||
|
||
return false; | ||
} | ||
$model = $modelNamespace.$modelInAttributeExploded[0]; | ||
if (in_array($model, $models)) { | ||
/** @var Model|ComputedAttributes $modelInstance */ | ||
$modelInstance = new $model(); | ||
} else { | ||
$this->error('Model "'.$model.'" not found'); | ||
|
||
return false; | ||
} | ||
$attributes = $modelInstance->getComputedAttributeConfiguration(); | ||
if (2 === sizeof($modelInAttributeExploded)) { | ||
$attributeWhitelistItems = explode(',', $modelInAttributeExploded[1]); | ||
foreach ($attributeWhitelistItems as $attributeWhitelistItem) { | ||
if (in_array($attributeWhitelistItem, $attributes)) { | ||
} else { | ||
$this->error('Attribute "'.$attributeWhitelistItem.'" does not exist in model '.$model); | ||
|
||
return false; | ||
} | ||
} | ||
} | ||
array_push($modelAttributesToProcess, [ | ||
'model' => $model, | ||
'modelInstance' => $modelInstance, | ||
'attributes' => $attributes, | ||
]); | ||
} | ||
} | ||
|
||
// Calculate | ||
foreach ($modelAttributesToProcess as $modelAttributeToProcess) { | ||
$this->info('Start calculating for following attributes of model "'.$modelAttributeToProcess['model'].'":'); | ||
/** @var Model|ComputedAttributes $modelInstance */ | ||
$modelInstance = $modelAttributeToProcess['modelInstance']; | ||
$attributes = $modelAttributeToProcess['attributes']; | ||
$this->info('['.implode(',', $attributes).']'); | ||
if (sizeof($attributes) > 0) { | ||
$modelInstance->chunk($chunkSize, function ($modelResults) use ($attributes) { | ||
/* @var Model|ComputedAttributes $modelInstance */ | ||
foreach ($modelResults as $modelResult) { | ||
foreach ($attributes as $attribute) { | ||
$modelResult->setComputedAttributeValue($attribute); | ||
} | ||
$modelResult->save(); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
|
||
namespace Korridor\LaravelComputedAttributes; | ||
|
||
use Illuminate\Support\ServiceProvider; | ||
use Korridor\LaravelComputedAttributes\Console\GenerateComputedAttributes; | ||
|
||
/** | ||
* Class LaravelComputedAttributesServiceProvider. | ||
*/ | ||
class LaravelComputedAttributesServiceProvider extends ServiceProvider | ||
{ | ||
/** | ||
* Register services. | ||
*/ | ||
public function register() | ||
{ | ||
} | ||
|
||
/** | ||
* Bootstrap services. | ||
*/ | ||
public function boot() | ||
{ | ||
if ($this->app->runningInConsole()) { | ||
$this->commands([ | ||
Console\GenerateComputedAttributes::class, | ||
]); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?php | ||
|
||
use Illuminate\Database\Eloquent\Model; | ||
use Korridor\LaravelComputedAttributes\ComputedAttributes; | ||
|
||
class Post extends Model | ||
{ | ||
use ComputedAttributes; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $computed = [ | ||
'complex_calculation', | ||
]; | ||
|
||
/** | ||
* @return int | ||
*/ | ||
public function getComplexCalculationComputed() | ||
{ | ||
return 1 + 2; | ||
} | ||
|
||
/** | ||
* Boot function from laravel. | ||
*/ | ||
protected static function boot() | ||
{ | ||
static::saving(function (Post $model) { | ||
$model->setComputedAttributeValue('complex_calculation'); | ||
}); | ||
parent::boot(); | ||
} | ||
} |