Skip to content

Commit

Permalink
merge master with conflicts
Browse files Browse the repository at this point in the history
* composer.json
* src/HasEnums.php
* tests/TestCase.php
  • Loading branch information
Gummibeer committed Aug 5, 2019
2 parents fe434e8 + bf3f884 commit 0a94736
Show file tree
Hide file tree
Showing 21 changed files with 906 additions and 6 deletions.
4 changes: 4 additions & 0 deletions .styleci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ preset: laravel
disabled:
- single_class_element_per_statement
- self_accessor

finder:
exclude:
- "tests/stubs"
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[![Build Status](https://img.shields.io/travis/spatie/laravel-enum/master.svg?style=flat-square)](https://travis-ci.org/spatie/laravel-enum)
[![Quality Score](https://img.shields.io/scrutinizer/g/spatie/laravel-enum.svg?style=flat-square)](https://scrutinizer-ci.com/g/spatie/laravel-enum)
[![Code Coverage](https://img.shields.io/coveralls/github/spatie/laravel-enum.svg?style=flat-square)](https://coveralls.io/github/spatie/laravel-enum)
[![StyleCI](https://github.styleci.io/repos/180570906/shield?branch=master)](https://github.styleci.io/repos/180570906)
[![Total Downloads](https://img.shields.io/packagist/dt/spatie/laravel-enum.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-enum)

This package provides extended support for our [spatie/enum](https://github.com/spatie/enum) package in Laravel.
Expand Down Expand Up @@ -77,6 +78,32 @@ By using the `$casts` property you can cast your `status` attribute to `int` or
- [ ] Validation [#5](https://github.com/spatie/laravel-enum/issues/5)
- [ ] Request Transformation [#7](https://github.com/spatie/laravel-enum/pull/7)

### Scopes

The `HasEnums` trait also provides some useful scopes to query your database.
These scopes will also take the optional mapping you provided into account.

```php
Post::whereEnum('status', StatusEnum::DRAFT());

Post::whereNotEnum('status', StatusEnum::PUBLISHED());
```

You may provide multiple enums as an array:

```php
Post::whereEnum('status', [StatusEnum::DRAFT(), StatusEnum::ARCHIVED()]);

Post::whereNotEnum('status', [StatusEnum::PUBLISHED()]);
```

You may also provide textual input:

```php
Post::whereEnum('status', 'archived');
Post::whereEnum('status', 'legacy archived value');
```

### Testing

``` bash
Expand Down
9 changes: 9 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
],
"require": {
"php": "^7.2",
"illuminate/console": "^5.8",
"illuminate/support": "^5.8",
"spatie/enum": "^2.3"
},
"require-dev": {
Expand All @@ -45,5 +47,12 @@
},
"config": {
"sort-packages": true
},
"extra": {
"laravel": {
"providers": [
"Spatie\\Enum\\Laravel\\EnumServiceProvider"
]
}
}
}
1 change: 1 addition & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
cacheResult="false"
processIsolation="false"
stopOnFailure="false">
<testsuites>
Expand Down
98 changes: 98 additions & 0 deletions src/Commands/MakeEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

namespace Spatie\Enum\Laravel\Commands;

use Illuminate\Support\Str;
use Illuminate\Console\GeneratorCommand;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;

class MakeEnum extends GeneratorCommand
{
protected $name = 'make:enum';
protected $description = 'Create a new enum';

protected function getStub()
{
return __DIR__.'/../../stubs/enum.stub';
}

protected function getDefaultNamespace($rootNamespace)
{
return $rootNamespace.'\Enums';
}

protected function replaceClass($stub, $name)
{
$stub = parent::replaceClass($stub, $name);

$stub = str_replace('DummyDocBlock', $this->getDocBlock(), $stub);
$stub = str_replace('DummyValueMapConst', $this->getValueMapConst(), $stub);

return $stub;
}

protected function getDocBlock(): string
{
$methods = array_merge($this->option('method'), $this->option('value'));

if (! empty($methods)) {
$docBlock = PHP_EOL.'/**';
$docBlock .= implode('', array_map(function ($method) {
return PHP_EOL.' * @method static self '.$this->formatValueToMethod($method).'()';
}, $methods));
$docBlock .= PHP_EOL.' */';
}

return $docBlock ?? '';
}

protected function getValueMapConst(): string
{
$values = $this->option('value');

if (! empty($values)) {
$tab = str_repeat(' ', 4);
$constant = $tab.'const MAP_VALUE = [';

foreach ($values as $value) {
$constant .= PHP_EOL.$tab.$tab.'\''.$this->formatValueToMethod($value).'\' => \''.$value.'\',';
}

$constant .= PHP_EOL.$tab.'];';
}

return $constant ?? '';
}

protected function formatValueToMethod(string $value): string
{
switch ($this->option('formatter')) {
case 'const':
return strtoupper(Str::snake($value));
case 'snake':
return Str::snake($value);
case 'studly':
return Str::studly($value);
case 'camel':
default:
return Str::camel($value);
}
}

protected function getArguments()
{
return [
['name', InputArgument::REQUIRED, 'The name of the enum'],
];
}

protected function getOptions()
{
return [
['method', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The method name that should be added to the enum'],
['value', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The value that should be added to the enum'],
['formatter', null, InputOption::VALUE_REQUIRED, 'The formatter to use for the value to method conversion (snake, const, studly, camel)', 'camel'],
];
}
}
18 changes: 18 additions & 0 deletions src/EnumServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Spatie\Enum\Laravel;

use Illuminate\Support\ServiceProvider;
use Spatie\Enum\Laravel\Commands\MakeEnum;

class EnumServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('command.make:enum', MakeEnum::class);

$this->commands([
'command.make:enum',
]);
}
}
13 changes: 13 additions & 0 deletions src/Exceptions/NoSuchEnumField.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Spatie\Enum\Laravel\Exceptions;

use InvalidArgumentException;

final class NoSuchEnumField extends InvalidArgumentException
{
public static function make(string $field, string $model): NoSuchEnumField
{
return new self("No enum field {$field} registered on model {$model}");
}
}
136 changes: 130 additions & 6 deletions src/HasEnums.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use Spatie\Enum\Enumerable;
use InvalidArgumentException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Spatie\Enum\Laravel\Exceptions\NoSuchEnumField;
use Spatie\Enum\Laravel\Exceptions\InvalidEnumError;

/**
Expand All @@ -29,8 +31,88 @@ public function getAttribute($key)
}

/**
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param string $key
* @param int|string|Enumerable $value
* @param int|string|\Spatie\Enum\Enumerable|int[]|string[]|\Spatie\Enum\Enumerable[] $enumerables
*
* @see \Illuminate\Database\Eloquent\Builder::whereIn()
*/
public function scopeWhereEnum(
Builder $builder,
string $key,
$enumerables
): void {
$this->buildEnumScope(
$builder,
'whereIn',
$key,
$enumerables
);
}

/**
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param string $key
* @param int|string|\Spatie\Enum\Enumerable|int[]|string[]|\Spatie\Enum\Enumerable[] $enumerables
*
* @see \Illuminate\Database\Eloquent\Builder::orWhereIn()
*/
public function scopeOrWhereEnum(
Builder $builder,
string $key,
$enumerables
): void {
$this->buildEnumScope(
$builder,
'orWhereIn',
$key,
$enumerables
);
}

/**
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param string $key
* @param int|string|\Spatie\Enum\Enumerable|int[]|string[]|\Spatie\Enum\Enumerable[] $enumerables
*
* @see \Illuminate\Database\Eloquent\Builder::whereNotIn()
*/
public function scopeWhereNotEnum(
Builder $builder,
string $key,
$enumerables
): void {
$this->buildEnumScope(
$builder,
'whereNotIn',
$key,
$enumerables
);
}

/**
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param string $key
* @param int|string|\Spatie\Enum\Enumerable|int[]|string[]|\Spatie\Enum\Enumerable[] $enumerables
*
* @see \Illuminate\Database\Eloquent\Builder::orWhereNotIn()
*/
public function scopeOrWhereNotEnum(
Builder $builder,
string $key,
$enumerables
): void {
$this->buildEnumScope(
$builder,
'orWhereNotIn',
$key,
$enumerables
);
}

/**
* @param string $key
* @param int|string|\Spatie\Enum\Enumerable $value
*
* @return $this
*/
Expand All @@ -46,17 +128,29 @@ protected function setEnumAttribute(string $key, $value)
throw InvalidEnumError::make(static::class, $key, $enumClass, get_class($value));
}

$this->attributes[$key] = $this->hasCast($key, ['int', 'integer'])
? $value->getIndex()
: $value->getValue();
$this->attributes[$key] = $this->getStoredValue($key, $value);

return $this;
}

/**
* @param string $key
* @param \Spatie\Enum\Enumerable $enum
*
* @return int|string
*/
protected function getStoredValue(string $key, Enumerable $enum)
{
return $this->hasCast($key, ['int', 'integer'])
? $enum->getIndex()
: $enum->getValue();
}

/**
* @param string $key
* @param int|string $value
* @return Enumerable
*
* @return \Spatie\Enum\Enumerable
*/
protected function getEnumAttribute(string $key, $value): Enumerable
{
Expand Down Expand Up @@ -85,13 +179,43 @@ protected function getEnumClass(string $key): string
* @param string $class
* @param int|string $value
*
* @return Enumerable
* @return \Spatie\Enum\Enumerable
*/
protected function asEnum(string $class, $value): Enumerable
{
if ($value instanceof Enumerable) {
return $value;
}

return forward_static_call(
$class.'::make',
$value
);
}

/**
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param string $method
* @param string $key
* @param int|string|\Spatie\Enum\Enumerable|int[]|string[]|\Spatie\Enum\Enumerable[] $enumerables
*/
protected function buildEnumScope(
Builder $builder,
string $method,
string $key,
$enumerables
): void {
if (! $this->isEnumAttribute($key)) {
throw NoSuchEnumField::make($key, get_class($this));
}

$enumerables = is_array($enumerables) ? $enumerables : [$enumerables];

$builder->$method(
$key,
array_map(function ($value) use ($key) {
return $this->getStoredValue($key, $this->getEnumAttribute($key, $value));
}, $enumerables)
);
}
}
10 changes: 10 additions & 0 deletions stubs/enum.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace DummyNamespace;

use Spatie\Enum\Enum;
DummyDocBlock
final class DummyClass extends Enum
{
DummyValueMapConst
}

0 comments on commit 0a94736

Please sign in to comment.