Skip to content

Commit

Permalink
Merge pull request #304 from alleyinteractive/http-client-cond
Browse files Browse the repository at this point in the history
Adding Conditionable Method Chaining
  • Loading branch information
srtfisher authored Jul 29, 2022
2 parents f359103 + c17ae40 commit b8ad5b3
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/mantle/database/query/class-builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@
use Mantle\Database\Pagination\Paginator;
use Mantle\Support\Collection;
use Mantle\Support\Str;
use Mantle\Support\Traits\Conditionable;

use function Mantle\Support\Helpers\collect;

/**
* Builder Query Builder
*/
abstract class Builder {
use Conditionable;

/**
* Model to build on.
*
Expand Down
39 changes: 38 additions & 1 deletion src/mantle/http-client/class-pending-request.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
namespace Mantle\Http_Client;

use Mantle\Support\Pipeline;
use Mantle\Support\Traits\Conditionable;

use function Mantle\Support\Helpers\tap;

/**
* Pending Request to be made with the Http Client.
*/
class Pending_Request {
use Conditionable;

/**
* Base URL for the request.
*
Expand Down Expand Up @@ -259,12 +262,46 @@ public function with_headers( array $headers ) {
*
* @param string $key Header key.
* @param mixed $value Header value.
* @param bool $replace Replace the existing header, defaults to false.
* @return static
*/
public function with_header( string $key, $value ) {
public function with_header( string $key, $value, bool $replace = false ) {
if ( $replace && isset( $this->options['headers'][ $key ] ) ) {
unset( $this->options['headers'][ $key ] );
}

return $this->with_headers( [ $key => $value ] );
}

/**
* Retrieve the headers for the request.
*
* @return array
*/
public function headers(): array {
return $this->options['headers'] ?? [];
}

/**
* Clear the headers for the request.
*
* @return static
*/
public function clear_headers() {
$this->options['headers'] = [];
return $this;
}

/**
* Retrieve a specific header for the request.
*
* @param string $key Header key.
* @return mixed
*/
public function header( string $key ) {
return $this->headers()[ $key ] ?? null;
}

/**
* Specify the basic authentication username and password for the request.
*
Expand Down
67 changes: 67 additions & 0 deletions src/mantle/support/class-higher-order-when-proxy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
/**
* Higher_Order_When_Proxy class file
*
* @package Mantle
*/

namespace Mantle\Support;

/**
* Higher Order When Proxy
*
* Allow a higher-order proxy that can be used conditionally.
*/
class Higher_Order_When_Proxy {

/**
* The target being conditionally operated on.
*
* @var mixed
*/
protected $target;

/**
* The condition for proxying.
*
* @var bool
*/
protected $condition;

/**
* Create a new proxy instance.
*
* @param mixed $target
* @param bool $condition
* @return void
*/
public function __construct( $target, $condition ) {
$this->target = $target;
$this->condition = $condition;
}

/**
* Proxy accessing an attribute onto the target.
*
* @param string $key
* @return mixed
*/
public function __get( $key ) {
return $this->condition
? $this->target->{$key}
: $this->target;
}

/**
* Proxy a method call on the target.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call( $method, $parameters ) {
return $this->condition
? $this->target->{$method}( ...$parameters )
: $this->target;
}
}
74 changes: 74 additions & 0 deletions src/mantle/support/traits/trait-conditionable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
/**
* Conditionable trait file.
*
* phpcs:disable Squiz.Commenting.FunctionComment
*
* @package Mantle
*/

namespace Mantle\Support\Traits;

use Closure;
use Mantle\Support\Higher_Order_When_Proxy;

/**
* Allow a class to conditionally invoke a method fluently.
*
* A method can use the trait to invoke a method conditionally upon itself.
*/
trait Conditionable {
/**
* Apply the callback if the given "value" is (or resolves to) truthy.
*
* @template TWhenParameter
* @template TWhenReturnType
*
* @param (\Closure($this): TWhenParameter)|TWhenParameter $value
* @param (callable($this, TWhenParameter): TWhenReturnType)|null $callback
* @param (callable($this, TWhenParameter): TWhenReturnType)|null $default
* @return static|TWhenReturnType
*/
public function when( $value, callable $callback = null, callable $default = null ) {
$value = $value instanceof Closure ? $value( $this ) : $value;

if ( func_num_args() === 1 ) {
return new Higher_Order_When_Proxy( $this, $value );
}

if ( $value ) {
return $callback( $this, $value ) ?? $this;
} elseif ( $default ) {
return $default( $this, $value ) ?? $this;
}

return $this;
}

/**
* Apply the callback if the given "value" is (or resolves to) falsy.
*
* @template TUnlessParameter
* @template TUnlessReturnType
*
* @param (\Closure( $this): TUnlessParameter)|TUnlessParameter $value
* @param (callable( $this, TUnlessParameter): TUnlessReturnType)|null $callback
* @param (callable( $this, TUnlessParameter): TUnlessReturnType)|null $default
* @return $this|TUnlessReturnType
*/
public function unless( $value, callable $callback = null, callable $default = null ) {
$value = $value instanceof Closure ? $value( $this ) : $value;

if ( func_num_args() === 1 ) {
return new Higher_Order_When_Proxy( $this, ! $value );
}

if ( ! $value ) {
return $callback( $this, $value ) ?? $this;
} elseif ( $default ) {
return $default( $this, $value ) ?? $this;
}

return $this;
}
}
2 changes: 2 additions & 0 deletions src/mantle/support/traits/trait-enumerates-values.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
* @property-read Higher_Order_Collection_Proxy $until
*/
trait Enumerates_Values {
use Conditionable;

/**
* The methods that can be proxied.
*
Expand Down
40 changes: 40 additions & 0 deletions tests/http-client/test-http-client.php
Original file line number Diff line number Diff line change
Expand Up @@ -399,4 +399,44 @@ public function test_pool_forward_base_url() {
&& 'POST' === $request->method()
);
}

public function test_conditionable_when_request() {
$request = $this->http_factory
->with_header( 'X-Foo', 'Bar' )
->when( true, fn ( Pending_Request $request ) => $request->with_header( 'X-Foo', 'Baz', true ) );

$this->assertEquals( 'Baz', $request->header( 'X-Foo' ) );

$request = $this->http_factory
->with_header( 'X-Foo', 'Bar' )
->when( true )->with_header( 'X-Foo', 'Baz', true );

$this->assertEquals( 'Baz', $request->header( 'X-Foo' ) );

$request = $this->http_factory
->with_header( 'X-Foo', 'Bar' )
->when( false, fn ( Pending_Request $request ) => $request->with_header( 'X-Foo', 'Baz', true ) );

$this->assertEquals( 'Bar', $request->header( 'X-Foo' ) );
}

public function test_conditionable_unless_request() {
$request = $this->http_factory
->with_header( 'X-Foo', 'Bar' )
->unless( false, fn ( Pending_Request $request ) => $request->with_header( 'X-Foo', 'Baz', true ) );

$this->assertEquals( 'Baz', $request->header( 'X-Foo' ) );

$request = $this->http_factory
->with_header( 'X-Foo', 'Bar' )
->unless( false )->with_header( 'X-Foo', 'Baz', true );

$this->assertEquals( 'Baz', $request->header( 'X-Foo' ) );

$request = $this->http_factory
->with_header( 'X-Foo', 'Bar' )
->unless( true, fn ( Pending_Request $request ) => $request->with_header( 'X-Foo', 'Baz', true ) );

$this->assertEquals( 'Bar', $request->header( 'X-Foo' ) );
}
}

0 comments on commit b8ad5b3

Please sign in to comment.