From 234e3f4ca5950e1a6021131e68debd2784b7fbc9 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 28 Jun 2018 22:14:50 +0200 Subject: [PATCH] Implement link type controller. --- app/Api/V1/Controllers/LinkTypeController.php | 197 ++++++++++++++++++ app/Http/Controllers/Admin/LinkController.php | 2 +- app/Models/LinkType.php | 4 +- .../LinkType/LinkTypeRepository.php | 14 +- .../LinkType/LinkTypeRepositoryInterface.php | 9 +- routes/api.php | 26 +++ 6 files changed, 247 insertions(+), 5 deletions(-) create mode 100644 app/Api/V1/Controllers/LinkTypeController.php diff --git a/app/Api/V1/Controllers/LinkTypeController.php b/app/Api/V1/Controllers/LinkTypeController.php new file mode 100644 index 0000000000..31215cd5a3 --- /dev/null +++ b/app/Api/V1/Controllers/LinkTypeController.php @@ -0,0 +1,197 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Controllers; + +use FireflyIII\Api\V1\Requests\LinkTypeRequest; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\LinkType; +use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; +use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\Transformers\LinkTypeTransformer; +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 LinkTypeController + */ +class LinkTypeController extends Controller +{ + /** @var LinkTypeRepositoryInterface */ + private $repository; + + /** @var UserRepositoryInterface */ + private $userRepository; + + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @var User $user */ + $user = auth()->user(); + $this->repository = app(LinkTypeRepositoryInterface::class); + $this->userRepository = app(UserRepositoryInterface::class); + $this->repository->setUser($user); + + return $next($request); + } + ); + } + + /** + * Delete the resource. + * + * @param LinkType $linkType + * + * @return JsonResponse + * @throws FireflyException + */ + public function delete(LinkType $linkType): JsonResponse + { + if ($linkType->editable === false) { + throw new FireflyException(sprintf('You cannot delete this link type (#%d, "%s")', $linkType->id, $linkType->name)); + } + $this->repository->destroy($linkType, null); + + return response()->json([], 204); + } + + /** + * List all of them. + * + * @param Request $request + * + * @return JsonResponse] + */ + public function index(Request $request): JsonResponse + { + // create some objects: + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + + // get list of accounts. Count it and split it. + $collection = $this->repository->get(); + $count = $collection->count(); + $linkTypes = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + + // make paginator: + $paginator = new LengthAwarePaginator($linkTypes, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.link_types.index') . $this->buildParams()); + + // present to user. + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new FractalCollection($linkTypes, new LinkTypeTransformer($this->parameters), 'link_types'); + $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 LinkType $linkType + * + * @return JsonResponse + */ + public function show(Request $request, LinkType $linkType): JsonResponse + { + $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($linkType, new LinkTypeTransformer($this->parameters), 'link_types'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } + + /** + * Store new object. + * + * @param LinkTypeRequest $request + * + * @return JsonResponse + * @throws FireflyException + */ + public function store(LinkTypeRequest $request): JsonResponse + { + if (!$this->userRepository->hasRole(auth()->user(), 'owner')) { + throw new FireflyException('You need the "owner"-role to do this.'); + } + $data = $request->getAll(); + // if currency ID is 0, find the currency by the code: + $linkType = $this->repository->store($data); + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $resource = new Item($linkType, new LinkTypeTransformer($this->parameters), 'link_types'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } + + /** + * @param LinkTypeRequest $request + * @param LinkType $linkType + * + * @return JsonResponse + * @throws FireflyException + */ + public function update(LinkTypeRequest $request, LinkType $linkType): JsonResponse + { + if ($linkType->editable === false) { + throw new FireflyException(sprintf('You cannot edit this link type (#%d, "%s")', $linkType->id, $linkType->name)); + } + if (!$this->userRepository->hasRole(auth()->user(), 'owner')) { + throw new FireflyException('You need the "owner"-role to do this.'); + } + + $data = $request->getAll(); + $this->repository->update($linkType, $data); + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $resource = new Item($linkType, new LinkTypeTransformer($this->parameters), 'link_types'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Admin/LinkController.php b/app/Http/Controllers/Admin/LinkController.php index be3be8fdb4..5884596fa0 100644 --- a/app/Http/Controllers/Admin/LinkController.php +++ b/app/Http/Controllers/Admin/LinkController.php @@ -112,7 +112,7 @@ class LinkController extends Controller public function destroy(Request $request, LinkTypeRepositoryInterface $repository, LinkType $linkType) { $name = $linkType->name; - $moveTo = $repository->find((int)$request->get('move_link_type_before_delete')); + $moveTo = $repository->findNull((int)$request->get('move_link_type_before_delete')); $repository->destroy($linkType, $moveTo); $request->session()->flash('success', (string)trans('firefly.deleted_link_type', ['name' => $name])); diff --git a/app/Models/LinkType.php b/app/Models/LinkType.php index a39fc05041..b9caaf05b7 100644 --- a/app/Models/LinkType.php +++ b/app/Models/LinkType.php @@ -24,6 +24,7 @@ namespace FireflyIII\Models; use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** @@ -34,12 +35,13 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property bool $editable * @property Carbon $created_at * @property Carbon $updated_at - * @property int $id + * @property int $id * Class LinkType * */ class LinkType extends Model { + use SoftDeletes; /** * The attributes that should be casted to native types. * diff --git a/app/Repositories/LinkType/LinkTypeRepository.php b/app/Repositories/LinkType/LinkTypeRepository.php index 76fa74d748..a7c79b891a 100644 --- a/app/Repositories/LinkType/LinkTypeRepository.php +++ b/app/Repositories/LinkType/LinkTypeRepository.php @@ -57,9 +57,9 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface * @return bool * @throws \Exception */ - public function destroy(LinkType $linkType, LinkType $moveTo): bool + public function destroy(LinkType $linkType, LinkType $moveTo = null): bool { - if (null !== $moveTo->id) { + if (null !== $moveTo) { TransactionJournalLink::where('link_type_id', $linkType->id)->update(['link_type_id' => $moveTo->id]); } $linkType->delete(); @@ -125,6 +125,16 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface return $count + $opposingCount > 0; } + /** + * @param int $id + * + * @return LinkType|null + */ + public function findNull(int $id): ?LinkType + { + return LinkType::find($id); + } + /** * See if such a link already exists (and get it). * diff --git a/app/Repositories/LinkType/LinkTypeRepositoryInterface.php b/app/Repositories/LinkType/LinkTypeRepositoryInterface.php index a0c8d2c636..9aa8c03757 100644 --- a/app/Repositories/LinkType/LinkTypeRepositoryInterface.php +++ b/app/Repositories/LinkType/LinkTypeRepositoryInterface.php @@ -45,7 +45,7 @@ interface LinkTypeRepositoryInterface * * @return bool */ - public function destroy(LinkType $linkType, LinkType $moveTo): bool; + public function destroy(LinkType $linkType, LinkType $moveTo = null): bool; /** * @param TransactionJournalLink $link @@ -62,6 +62,13 @@ interface LinkTypeRepositoryInterface */ public function find(int $id): LinkType; + /** + * @param int $id + * + * @return LinkType|null + */ + public function findNull(int $id): ?LinkType; + /** * Find link type by name. * diff --git a/routes/api.php b/routes/api.php index bdf9a3637e..ba748dbc0e 100644 --- a/routes/api.php +++ b/routes/api.php @@ -156,6 +156,32 @@ Route::group( } ); +Route::group( + ['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'link_types', 'as' => 'api.v1.link_types.'], + function () { + + // Link Type API routes: + Route::get('', ['uses' => 'LinkTypeController@index', 'as' => 'index']); + Route::post('', ['uses' => 'LinkTypeController@store', 'as' => 'store']); + Route::get('{linkType}', ['uses' => 'LinkTypeController@show', 'as' => 'show']); + Route::put('{linkType}', ['uses' => 'LinkTypeController@update', 'as' => 'update']); + Route::delete('{linkType}', ['uses' => 'LinkTypeController@delete', 'as' => 'delete']); + } +); + +Route::group( + ['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'piggy_banks', 'as' => 'api.v1.piggy_banks.'], + function () { + + // Piggy Bank API routes: + Route::get('', ['uses' => 'PiggyBankController@index', 'as' => 'index']); + Route::post('', ['uses' => 'PiggyBankController@store', 'as' => 'store']); + Route::get('{piggyBank}', ['uses' => 'PiggyBankController@show', 'as' => 'show']); + Route::put('{piggyBank}', ['uses' => 'PiggyBankController@update', 'as' => 'update']); + Route::delete('{piggyBank}', ['uses' => 'PiggyBankController@delete', 'as' => 'delete']); + } +); + Route::group( ['middleware' => ['auth:api', 'bindings'], 'namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'currencies', 'as' => 'api.v1.currencies.'], function () {