From 0502f2a4a53483299d1a073c17af9d9371b90619 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 30 Jun 2018 18:10:54 +0200 Subject: [PATCH] Implement rule group API. --- .../V1/Controllers/RuleGroupController.php | 81 ++++++++++++++++--- app/Api/V1/Requests/RuleGroupRequest.php | 79 ++++++++++++++++++ app/Models/RuleGroup.php | 2 + app/Transformers/RuleGroupTransformer.php | 6 +- routes/api.php | 13 +++ 5 files changed, 169 insertions(+), 12 deletions(-) create mode 100644 app/Api/V1/Requests/RuleGroupRequest.php diff --git a/app/Api/V1/Controllers/RuleGroupController.php b/app/Api/V1/Controllers/RuleGroupController.php index 3c1cec83e4..6c4196375f 100644 --- a/app/Api/V1/Controllers/RuleGroupController.php +++ b/app/Api/V1/Controllers/RuleGroupController.php @@ -23,13 +23,26 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers; +use FireflyIII\Api\V1\Requests\RuleGroupRequest; +use FireflyIII\Models\RuleGroup; +use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; +use FireflyIII\Transformers\RuleGroupTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Pagination\LengthAwarePaginator; +use League\Fractal\Manager; +use League\Fractal\Pagination\IlluminatePaginatorAdapter; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\Serializer\JsonApiSerializer; class RuleGroupController extends Controller { + /** @var RuleGroupRepositoryInterface */ + private $ruleGroupRepository; + public function __construct() { parent::__construct(); @@ -38,7 +51,9 @@ class RuleGroupController extends Controller /** @var User $user */ $user = auth()->user(); - // todo add local repositories. + $this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class); + $this->ruleGroupRepository->setUser($user); + return $next($request); } ); @@ -67,34 +82,71 @@ class RuleGroupController extends Controller */ public function index(Request $request): JsonResponse { - // todo implement. + // create some objects: + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + // types to get, page size: + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + + // get list of budgets. Count it and split it. + $collection = $this->ruleGroupRepository->get(); + $count = $collection->count(); + $ruleGroups = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + + // make paginator: + $paginator = new LengthAwarePaginator($ruleGroups, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.rule_groups.index') . $this->buildParams()); + + // present to user. + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new FractalCollection($ruleGroups, new RuleGroupTransformer($this->parameters), 'rule_groups'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); } /** * List single resource. * - * @param Request $request - * @param string $object + * @param Request $request + * @param RuleGroup $ruleGroup * * @return JsonResponse */ - public function show(Request $request, string $object): JsonResponse + public function show(Request $request, RuleGroup $ruleGroup): JsonResponse { - // todo implement me. + $manager = new Manager(); + // add include parameter: + $include = $request->get('include') ?? ''; + $manager->parseIncludes($include); + + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); } /** * Store new object. * - * @param Request $request + * @param RuleGroupRequest $request * * @return JsonResponse */ - public function store(Request $request): JsonResponse + public function store(RuleGroupRequest $request): JsonResponse { - // todo replace code and replace request object. + $ruleGroup = $this->ruleGroupRepository->store($request->getAll()); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); } @@ -104,9 +156,16 @@ class RuleGroupController extends Controller * * @return JsonResponse */ - public function update(Request $request, string $object): JsonResponse + public function update(RuleGroupRequest $request, RuleGroup $ruleGroup): JsonResponse { - // todo replace code and replace request object. + $ruleGroup = $this->ruleGroupRepository->update($ruleGroup, $request->getAll()); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); } } \ No newline at end of file diff --git a/app/Api/V1/Requests/RuleGroupRequest.php b/app/Api/V1/Requests/RuleGroupRequest.php new file mode 100644 index 0000000000..a8b88601e4 --- /dev/null +++ b/app/Api/V1/Requests/RuleGroupRequest.php @@ -0,0 +1,79 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Requests; + +use FireflyIII\Models\RuleGroup; + + +/** + * + * Class RuleGroupRequest + */ +class RuleGroupRequest extends Request +{ + /** + * @return bool + */ + public function authorize(): bool + { + // Only allow authenticated users + return auth()->check(); + } + + /** + * @return array + */ + public function getAll(): array + { + return [ + 'title' => $this->string('title'), + 'description' => $this->string('description'), + 'active' => $this->boolean('active'), + ]; + } + + /** + * @return array + */ + public function rules(): array + { + $rules = [ + 'title' => 'required|between:1,100|uniqueObjectForUser:rule_groups,title', + 'description' => 'between:1,5000|nullable', + 'active' => 'required|boolean', + ]; + switch ($this->method()) { + default: + break; + case 'PUT': + case 'PATCH': + /** @var RuleGroup $ruleGroup */ + $ruleGroup = $this->route()->parameter('ruleGroup'); + $rules['title'] = 'required|between:1,100|uniqueObjectForUser:rule_groups,title,' . $ruleGroup->id; + break; + } + + return $rules; + } +} \ No newline at end of file diff --git a/app/Models/RuleGroup.php b/app/Models/RuleGroup.php index 6c607e49e0..142ec71bda 100644 --- a/app/Models/RuleGroup.php +++ b/app/Models/RuleGroup.php @@ -26,6 +26,7 @@ use Carbon\Carbon; use FireflyIII\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Support\Collection; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** @@ -39,6 +40,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property string $text * @property int $id * @property int $order + * @property Collection $rules */ class RuleGroup extends Model { diff --git a/app/Transformers/RuleGroupTransformer.php b/app/Transformers/RuleGroupTransformer.php index 5cbd579a54..d749f09945 100644 --- a/app/Transformers/RuleGroupTransformer.php +++ b/app/Transformers/RuleGroupTransformer.php @@ -23,8 +23,8 @@ declare(strict_types=1); namespace FireflyIII\Transformers; - use FireflyIII\Models\RuleGroup; +use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Item; use League\Fractal\TransformerAbstract; use Symfony\Component\HttpFoundation\ParameterBag; @@ -62,6 +62,10 @@ class RuleGroupTransformer extends TransformerAbstract $this->parameters = $parameters; } + public function includeRules(RuleGroup $ruleGroup): FractalCollection + { + return $this->collection($ruleGroup->rules, new RuleTransformer($this->parameters), 'rules'); + } /** * Include the user. diff --git a/routes/api.php b/routes/api.php index f7f967d3d9..8083a43212 100644 --- a/routes/api.php +++ b/routes/api.php @@ -219,6 +219,19 @@ Route::group( } ); +Route::group( + ['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'rule_groups', 'as' => 'api.v1.rule_groups.'], + function () { + + // Rules API routes: + Route::get('', ['uses' => 'RuleGroupController@index', 'as' => 'index']); + Route::post('', ['uses' => 'RuleGroupController@store', 'as' => 'store']); + Route::get('{ruleGroup}', ['uses' => 'RuleGroupController@show', 'as' => 'show']); + Route::put('{ruleGroup}', ['uses' => 'RuleGroupController@update', 'as' => 'update']); + Route::delete('{ruleGroup}', ['uses' => 'RuleGroupController@delete', 'as' => 'delete']); + } +); + Route::group( ['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'currencies', 'as' => 'api.v1.currencies.'], function () {