Skip to content
This repository has been archived by the owner on Mar 4, 2024. It is now read-only.

Commit

Permalink
Merge pull request #26 from DarkGhostHunter/master
Browse files Browse the repository at this point in the history
New trait and updated dependency.
  • Loading branch information
DarkGhostHunter committed Jun 30, 2020
2 parents 9e9280d + 04a8210 commit ddcbb8d
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 9 deletions.
5 changes: 3 additions & 2 deletions README.md
Expand Up @@ -26,7 +26,7 @@ This package doesn't use any Service Provider.

## Usage

Just check any of these traits. Each one and other classes contains an brief explanation on how to use in the first lines.
Just check any of these traits. Each one and other classes contains a brief explanation on how to use in the first lines.

If you want to use one, [just do it](https://www.php.net/manual/en/language.oop5.traits.php).

Expand Down Expand Up @@ -56,6 +56,7 @@ Just remember to **change the namespace** if you're copy-pasting them!

### Traits for everything

* [`Comparable`](src/Comparable.php): Allows a class or its properties to be compared to a list of values.
* [`ConditionCalls`](src/ConditionCalls.php): Allows an object instance to execute `when` and `unless` logic.
* [`EnumerableStates`](src/EnumerableStates.php): Allows a class instance to have a single allowed state.
* [`FiresItself`](src/FiresItself.php): Allows an Event to be fired conveniently.
Expand All @@ -75,7 +76,7 @@ Just remember to **change the namespace** if you're copy-pasting them!

### Models

* [`ConditionFill'](src/Eloquent/ConditionFill.php): Fills an attribute if a given condition is truthy or falsy.
* [`ConditionFill`](src/Eloquent/ConditionFill.php): Fills an attribute if a given condition is truthy or falsy.
* [`DefaultColumns`](src/Eloquent/DefaultColumns.php): Adds a `DefaultColumns` Global Scope to the Model selecting only given default columns, unless overrun manually in the query.
* [`EncryptsJson`](src/Eloquent/EncryptsJson.php): Encrypts and decrypts the JSON representation of a Model.
* [`FillsAttributes`](src/Eloquent/FillsAttributes.php): Automatically fills the Model with values by each method name, like `fillFooAttribute()`.
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -23,7 +23,7 @@
"php": "^7.2.15",
"ext-json": "*",
"illuminate/support": "^7.0",
"guzzlehttp/guzzle": "^6.5"
"guzzlehttp/guzzle": "^6.5 || ^7.0"
},
"require-dev": {
"orchestra/testbench": "^5.2"
Expand Down
117 changes: 117 additions & 0 deletions src/Comparable.php
@@ -0,0 +1,117 @@
<?php
/**
* Comparable
*
* This trait allows an instance to be compared to a list of items and check if the comparison
* returns true or false. By default, it checks the current object is an instance of the them.
*
* For example, you can check if the object is an instance of a given interface.
*
* $this->isAnyOf([Renderable::class, Htmlable::class]);
*
* You can also create your own comparison with a callback that accepts the current object,
* the item being compared to, and its key.
*
* $this->isAnyOf([1, 2, 3], function ($comparable, $compared, $key) {
* return $comparable->timesSaved() === $comparable;
* });
*
* Alternatively, you can use the `isNoneOf` method to check if none of the comparisons is
* successful, using the same syntax.
*
* $this->isNoneOf([Renderable::class, Htmlable::class]);
*
* $this->isNoneOf([1, 2, 3], function ($comparable, $compared, $key) {
* return $comparable->timesSaved() === $comparable;
* });
*
* Finally, you can get the array key of the compared item if is successful, otherwise it
* will return `false`:
*
* $result = $this->whichOf(['foo' => 'bar', 'baz' => 'quz'], function ($comparable, $compared) {
* return $comparable->name === $compared;
* });
*
* echo $result; // "foo"
*
* ---
* MIT License
*
* Copyright (c) Italo Israel Baeza Cabrera
*
* 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.
*
* Laravel is a Trademark of Taylor Otwell. Copyright © 2011-2020 Laravel LLC.
*
* @link https://github.com/DarkGhostHunter/Laratraits
*/

namespace DarkGhostHunter\Laratraits;

trait Comparable
{
/**
* Returns if any of the compared items comparison returns truthy.
*
* @param iterable $comparables
* @param null|callable $callback
* @param bool $returnKey
* @return bool
*/
public function isAnyOf(iterable $comparables, callable $callback = null, bool $returnKey = false)
{
$callback = $callback ?? static function ($compared, $comparable) {
return $compared instanceof $comparable;
};

$comparables = is_iterable($comparables) ? $comparables : [$comparables];

foreach ($comparables as $key => $comparable) {
if ($result = $callback($this, $comparable, $key)) {
return $returnKey ? $key : $result;
}
}

return false;
}

/**
* Returns if none of the compared items comparison returns truthy.
*
* @param mixed $comparables
* @param null|callable $callback
* @return bool
*/
public function isNoneOf($comparables, callable $callback = null)
{
return $this->isAnyOf($comparables, $callback) === false;
}

/**
* Returns which key of the compared items returns successful comparison.
*
* @param mixed $comparables
* @param null|callable $callback
* @return bool|int|string
*/
public function whichOf($comparables, callable $callback = null)
{
return $this->isAnyOf($comparables, $callback, true);
}
}
8 changes: 2 additions & 6 deletions src/ConditionCalls.php
Expand Up @@ -78,9 +78,7 @@ public function when($value, callable $callback, callable $default = null)
{
if ($result = value($value)) {
$callback($this, $result);
}

if ($default) {
} elseif ($default) {
$default($this, $result);
}

Expand All @@ -99,9 +97,7 @@ public function unless($value, callable $callback, callable $default = null)
{
if (! $result = value($value)) {
$callback($this, $result);
}

if ($default) {
} elseif ($default) {
$default($this, $result);
}

Expand Down
109 changes: 109 additions & 0 deletions tests/ComparableTest.php
@@ -0,0 +1,109 @@
<?php

namespace Tests;

use Exception;
use Illuminate\Support\Fluent;
use PHPUnit\Framework\TestCase;
use DarkGhostHunter\Laratraits\Comparable;

class ComparableTest extends TestCase
{
/** @var \DarkGhostHunter\Laratraits\Comparable */
protected $compared;

protected function setUp() : void
{
parent::setUp();

$this->compared = new class([
'foo' => 'bar',
'baz' => 'quz',
'qux' => 'quuz'
]) extends Fluent
{
use Comparable;
};
}

public function test_is_instance_of()
{
$this->assertTrue($this->compared->isAnyOf([Exception::class, Fluent::class]));
$this->assertFalse($this->compared->isAnyOf([Exception::class]));
}

public function test_is_from_callback()
{
$result = $this->compared->isAnyOf(['foo', 'bar', 'quz'], static function ($compared, $comparable) {
return $compared->foo === $comparable ? $comparable : null;
});

$this->assertSame('bar', $result);

$result = $this->compared->isAnyOf(['foo', 'quuz', 'quz'], static function ($compared, $comparable) {
return $compared->foo === $comparable ? $comparable : null;
});

$this->assertFalse($result);
}

public function test_returns_key()
{
$this->assertSame(1, $this->compared->isAnyOf([Exception::class, Fluent::class], null, true));
$this->assertFalse($this->compared->isAnyOf([Exception::class], null, true));

$result = $this->compared->isAnyOf(['foo', 'bar', 'quz'], static function ($compared, $comparable) {
return $compared->foo === $comparable ? $comparable : null;
}, true);

$this->assertSame(1, $result);

$result = $this->compared->isAnyOf(['foo', 'quuz', 'quz'], static function ($compared, $comparable) {
return $compared->foo === $comparable ? $comparable : null;
}, true);

$this->assertFalse($result);
}

public function test_none_of_instance_of()
{
$this->assertFalse($this->compared->isNoneOf([Exception::class, Fluent::class]));
$this->assertTrue($this->compared->isNoneOf([Exception::class]));
}

public function test_none_from_callback()
{
$result = $this->compared->isNoneOf(['foo', 'bar', 'quz'], static function ($compared, $comparable) {
return $compared->foo === $comparable ? $comparable : null;
});

$this->assertFalse($result);

$result = $this->compared->isNoneOf(['foo', 'quuz', 'quz'], static function ($compared, $comparable) {
return $compared->foo === $comparable ? $comparable : null;
});

$this->assertTrue($result);
}

public function test_which_key()
{
$this->assertSame(1, $this->compared->whichOf([Exception::class, Fluent::class]));
$this->assertFalse($this->compared->whichOf([Exception::class]));
}

public function test_which_key_from_callback()
{
$result = $this->compared->whichOf(['foo', 'bar', 'quz'], static function ($compared, $comparable) {
return $compared->foo === $comparable ? $comparable : null;
});

$this->assertSame(1, $result);

$result = $this->compared->whichOf(['foo', 'quuz', 'quz'], static function ($compared, $comparable) {
return $compared->foo === $comparable ? $comparable : null;
});

$this->assertFalse($result);
}
}
22 changes: 22 additions & 0 deletions tests/ConditionCallTest.php
Expand Up @@ -51,6 +51,17 @@ public function test_does_not_calls_callable_when_falsy()
$this->assertSame('bar', $this->object->foo);
}

public function test_doesnt_calls_default_when_thrughy()
{
$this->object->when('qux', function ($instance, $value) {
$instance->foo = $value;
}, function ($instance, $value) {
$instance->foo = $value . ' quz';
});

$this->assertSame('qux', $this->object->foo);
}

public function test_calls_default_when_falsy()
{
$this->object->when('', function ($instance, $value) {
Expand Down Expand Up @@ -80,6 +91,17 @@ public function test_does_not_calls_callable_unless_truthy()
$this->assertSame('bar', $this->object->foo);
}

public function test_doesnt_calls_default_when_falsy()
{
$this->object->unless(false, function ($instance, $value) {
$instance->foo = $value;
}, function ($instance, $value) {
$instance->foo = $value . ' qux';
});

$this->assertFalse($this->object->foo);
}

public function test_calls_default_unless_truthy()
{
$this->object->unless('quz', function ($instance, $value) {
Expand Down

0 comments on commit ddcbb8d

Please sign in to comment.