Skip to content

Commit

Permalink
Merge pull request #6 from kg-bot/improved_filtering
Browse files Browse the repository at this point in the history
Added where, limit and page methods
  • Loading branch information
kg-bot committed Oct 9, 2020
2 parents e3bf93a + 76fea8b commit b2954b5
Show file tree
Hide file tree
Showing 3 changed files with 279 additions and 147 deletions.
111 changes: 39 additions & 72 deletions src/Builders/Builder.php
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
<?php
/**
* Created by PhpStorm.
* User: nts
* Date: 31.3.18.
* Time: 17.00
*/


namespace Rackbeat\Builders;

use Psr\Http\Message\ResponseInterface;
use Rackbeat\Traits\ApiFiltering;
use Rackbeat\Utils\Model;
use Rackbeat\Utils\Request;


class Builder
{
use ApiFiltering;

protected $entity;
/** @var Model */
protected $model;
Expand All @@ -34,67 +33,43 @@ public function __construct( Request $request ) {
* @throws \Rackbeat\Exceptions\RackbeatRequestException
*/
public function get( $filters = [] ) {
$filters[] = [ 'limit', '=', 1000 ];

$urlFilters = $this->parseFilters( $filters );

return $this->request->handleWithExceptions( function () use ( $urlFilters ) {

$response = $this->request->client->get( "{$this->entity}{$urlFilters}" );
$response = $this->request->client->get( "{$this->entity}{$urlFilters}" );
$fetchedItems = $this->getResponse( $response );

return $this->populateModelsFromResponse( $fetchedItems->first() );
} );
}

$responseData = json_decode( (string) $response->getBody() );
$fetchedItems = collect( $responseData );
$items = collect( [] );
$pages = $responseData->pages;

foreach ( $fetchedItems->first() as $index => $item ) {

/**
* @param $response
*
* @return \Illuminate\Support\Collection|Model
*/
protected function populateModelsFromResponse( $response ) {
$items = collect();
if ( is_iterable( $response ) ) {
foreach ( $response as $index => $item ) {
/** @var Model $model */
$modelClass = $this->getModelClass( $item );
$model = new $modelClass( $this->request, $item );

$items->push( $model );
}
} else {
$modelClass = $this->getModelClass( $response );

return $items;
} );
}

protected function parseFilters( $filters = [] ) {

$limit = array_search( 'limit', array_column( $filters, 0 ) );
if ( $limit !== false && $limit !== ( count( $filters ) - 1 ) ) {

unset( $filters[ count( $filters ) - 1 ] );
return new $modelClass( $this->request, $response );
}

$urlFilters = '';

if ( count( $filters ) > 0 ) {

$filters = array_unique( $filters, SORT_REGULAR );

$i = 1;

$urlFilters .= '?';

foreach ( $filters as $filter ) {

$sign = ! empty( $filter[2] ) ? $filter[1] : '=';
$value = $filter[2] ?? $filter[1];

$urlFilters .= $filter[0] . $sign . urlencode( $value );

if ( count( $filters ) > $i ) {

$urlFilters .= '&';
}

$i++;
}
}
return $items;

return $urlFilters;
}

/**
Expand All @@ -107,16 +82,12 @@ protected function parseFilters( $filters = [] ) {
*/
public function all( $filters = [] ) {
$page = 1;
$this->limit( 1000 );

$items = collect();

$response = function ( $filters, $page ) {

/**
* Default filters, limit must be always set last otherwise it will not work
*/
$filters[] = [ 'page', '=', $page ];
$filters[] = [ 'limit', '=', 1000 ];
$this->page( $page );

$urlFilters = $this->parseFilters( $filters );

Expand All @@ -125,17 +96,9 @@ public function all( $filters = [] ) {
$response = $this->request->client->get( "{$this->entity}{$urlFilters}" );

$responseData = json_decode( (string) $response->getBody() );
$fetchedItems = collect( $responseData );
$items = collect( [] );
$fetchedItems = $this->getResponse( $response );
$pages = $responseData->pages;

foreach ( $fetchedItems->first() as $index => $item ) {
/** @var Model $model */
$modelClass = $this->getModelClass( $item );
$model = new $modelClass( $this->request, $item );

$items->push( $model );
}
$items = $this->populateModelsFromResponse( $fetchedItems->first() );

return (object) [

Expand Down Expand Up @@ -171,15 +134,16 @@ public function all( $filters = [] ) {
* @throws \Rackbeat\Exceptions\RackbeatRequestException
*/
public function find( $id, $filters = [] ) {
unset( $this->wheres['limit'], $this->wheres['page'] );

$urlFilters = $this->parseFilters( $filters );
$id = rawurlencode( rawurlencode( $id ) );

return $this->request->handleWithExceptions( function () use ( $id, $urlFilters ) {
$response = $this->request->client->get( "{$this->entity}/{$id}{$urlFilters}" );
$responseData = collect( json_decode( (string) $response->getBody() ) );
$modelClass = $this->getModelClass( $responseData->first() );
$responseData = $this->getResponse( $response );

return new $modelClass( $this->request, $responseData->first() );
return $this->populateModelsFromResponse( $responseData->first() );
} );
}

Expand All @@ -195,13 +159,12 @@ public function find( $id, $filters = [] ) {
public function create( $data ) {
return $this->request->handleWithExceptions( function () use ( $data ) {

$response = $this->request->client->post( "{$this->entity}", [
$response = $this->request->client->post( $this->entity, [
'json' => $data,
] );
$responseData = collect( json_decode( (string) $response->getBody() ) );
$modelClass = $this->getModelClass( $responseData->first() );
$responseData = $this->getResponse( $response );

return new $modelClass( $this->request, $responseData->first() );
return $this->populateModelsFromResponse( $responseData->first() );
} );
}

Expand All @@ -218,4 +181,8 @@ public function setEntity( $new_entity ) {
protected function getModelClass( $item ) {
return $this->model;
}

protected function getResponse( ResponseInterface $response ) {
return collect( json_decode( (string) $response->getBody() ) );
}
}
172 changes: 172 additions & 0 deletions src/Traits/ApiFiltering.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<?php


namespace Rackbeat\Traits;


trait ApiFiltering
{

/** @var int[] */
protected $wheres = [
'limit' => 1000,
'page' => 1
];

/**
* @param array $filters
*
* @return string
*/
protected function parseFilters( $filters = [] ) {

foreach ( $filters as $filter ) {
call_user_func_array( [ $this, 'where' ], array_values( $filter ) );
}


$urlFilters = '';

if ( count( $this->wheres ) > 0 ) {
$i = 1;

$urlFilters .= '?';

foreach ( $this->wheres as $key => $filter ) {

if ( ! is_array( $filter ) ) {
$sign = '=';
$value = $filter;
} else {
[ $sign, $value ] = $filter;
}

$urlFilters .= $key . $sign . urlencode( $value );

if ( count( $this->wheres ) > $i ) {

$urlFilters .= '&';
}

$i++;
}
}

return $urlFilters;
}

/**
* Search for resources that only match your criteria, this method can be used in multiple ways
* Example 1:
* ->where('name', 'Test')
*
* Example 2:
* ->where('name', '=', 'Test')
*
* Example 3:
* ->where('is_active')
*
* If you use third example it will be sent as `is_active=true`
*
* @param string $key
* @param string|null $operator
* @param mixed $value
*
* @return $this
*/
public function where( string $key, string $operator = null, $value = null ): self {
if ( func_num_args() === 1 ) {
$value = true;

$operator = '=';
}

if ( func_num_args() === 2 ) {
$value = $operator;

$operator = '=';
}

$this->wheres[ $key ] = [ $operator, $value ];

return $this;
}

/**
* How many resources we should load (max 1000, min 1)
*
* @param int $limit
*
* @return $this
*/
public function limit( $limit = 1000 ): self {
$this->wheres['limit'] = $limit;

return $this;
}

/**
* @param int $page
*
* @return $this
*/
public function page( $page = 1 ): self {
$this->wheres['page'] = $page;

return $this;
}

/**
* Set the return fields that you want
*
* @param array $fields
*
* @return $this
*/
public function fields( array $fields = [] ): self {
$this->wheres['fields'] = implode( ',', $fields );

return $this;
}

/**
* What should be expanded (loaded) in relation to requested resource (only field_values for now)
*
* @param string $expand
*
* @return $this
*/
public function expand( string $expand = 'field_values' ): self {
$this->wheres['expand'] = $expand;

return $this;
}

/**
* Search for exact field match, if you need to use starting_with match use ->field($id, $value)
*
* @param int $id
* @param $value
*
* @return $this
*/
public function fieldEq( int $id, $value ): self {
$this->wheres[ 'field_eq[' . $id . ']' ] = $value;

return $this;
}

/**
* Search by field, this is not equal search so it can return more field, use ->fieldEq($id, $value) if you want to search for exact field
*
* @param int $id
* @param $value
*
* @return $this
*/
public function field( int $id, $value ): self {
$this->wheres[ 'field[' . $id . ']' ] = $value;

return $this;
}
}
Loading

0 comments on commit b2954b5

Please sign in to comment.