API for object groups.

This commit is contained in:
James Cole
2020-06-20 16:28:23 +02:00
parent c40f6f2864
commit 1a154a8d45
11 changed files with 416 additions and 2 deletions

View File

@@ -0,0 +1,196 @@
<?php
/**
* GroupController.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\ObjectGroupUpdateRequest;
use FireflyIII\Models\Account;
use FireflyIII\Models\ObjectGroup;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Transformers\ObjectGroupTransformer;
use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection;
use League\Fractal\Resource\Item;
/**
* Class GroupController.
*
*/
class ObjectGroupController extends Controller
{
private ObjectGroupRepositoryInterface $repository;
/**
* ObjectGroupController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(ObjectGroupRepositoryInterface::class);
$this->repository->setUser($user);
return $next($request);
}
);
}
/**
* Remove the specified resource from storage.
*
* @param ObjectGroup $objectGroup
*
* @codeCoverageIgnore
* @return JsonResponse
*/
public function delete(ObjectGroup $objectGroup): JsonResponse
{
$this->repository->destroy($objectGroup);
return response()->json([], 204);
}
/**
* Display a listing of the resource.
*
* @param Request $request
*
* @codeCoverageIgnore
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
$manager = $this->getManager();
// types to get, page size:
$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();
$objectGroups = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($objectGroups, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.object-groups.index') . $this->buildParams());
/** @var ObjectGroupTransformer $transformer */
$transformer = app(ObjectGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($objectGroups, $transformer, 'object_groups');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* List all piggies under the object group.
*
* @param ObjectGroup $objectGroup
*
* @return JsonResponse
* @codeCoverageIgnore
*
*/
public function piggyBanks(ObjectGroup $objectGroup): JsonResponse
{
// create some objects:
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of piggy banks. Count it and split it.
$collection = $this->repository->getPiggyBanks($objectGroup);
$count = $collection->count();
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.object-groups.piggy_banks', [$objectGroup->id]) . $this->buildParams());
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* Show single instance.
*
* @param ObjectGroup $objectGroup
*
* @return JsonResponse
*/
public function show(ObjectGroup $objectGroup): JsonResponse
{
$manager = $this->getManager();
/** @var ObjectGroupTransformer $transformer */
$transformer = app(ObjectGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($objectGroup, $transformer, 'object_groups');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* Update object.
*
* @param ObjectGroupUpdateRequest $request
* @param Account $account
*
* @return JsonResponse
*/
public function update(ObjectGroupUpdateRequest $request, ObjectGroup $objectGroup): JsonResponse
{
$data = $request->getUpdateData();
$this->repository->update($objectGroup, $data);
$this->repository->sort();
$manager = $this->getManager();
/** @var ObjectGroupTransformer $transformer */
$transformer = app(ObjectGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($objectGroup, $transformer, 'object_groups');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* ObjectGroupUpdateRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
/**
* Class AccountObjectGroupUpdateRequestUpdateRequest
*
* @codeCoverageIgnore
*/
class ObjectGroupUpdateRequest extends Request
{
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* @return array
*/
public function getUpdateData(): array
{
return [
'title' => $this->string('title'),
'order' => $this->integer('order'),
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$objectGroup = $this->route()->parameter('objectGroup');
return [
'title' => sprintf('min:1|uniqueObjectGroup:%d', $objectGroup->id),
'order' => 'numeric',
];
}
}

View File

@@ -4,7 +4,9 @@ declare(strict_types=1);
namespace FireflyIII\Models;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
@@ -33,6 +35,19 @@ class ObjectGroup extends Model
{
protected $fillable = ['title', 'order', 'user_id'];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'user_id' => 'integer',
'deleted_at' => 'datetime',
];
/**
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
*/
@@ -61,4 +76,13 @@ class ObjectGroup extends Model
}
throw new NotFoundHttpException;
}
/**
* @return BelongsTo
* @codeCoverageIgnore
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}

View File

@@ -107,6 +107,12 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface
public function update(ObjectGroup $objectGroup, array $data): ObjectGroup
{
$objectGroup->title = $data['title'];
if (isset($data['order'])) {
$order = 0 === $data['order'] ? 1 : $data['order'];
$objectGroup->order = $order;
}
$objectGroup->save();
return $objectGroup;
@@ -128,4 +134,11 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface
$this->user = $user;
}
/**
* @inheritDoc
*/
public function getPiggyBanks(ObjectGroup $objectGroup): Collection
{
return $objectGroup->piggyBanks;
}
}

View File

@@ -28,6 +28,13 @@ interface ObjectGroupRepositoryInterface
*/
public function deleteEmpty(): void;
/**
* @param ObjectGroup $objectGroup
*
* @return Collection
*/
public function getPiggyBanks(ObjectGroup $objectGroup): Collection;
/**
* Sort
*/

View File

@@ -0,0 +1,81 @@
<?php
/**
* ObjectGroupTransformer.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Transformers;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\ObjectGroup;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use Log;
/**
* Class AccountTransformer
*/
class ObjectGroupTransformer extends AbstractTransformer
{
protected ObjectGroupRepositoryInterface $repository;
/**
*
* AccountTransformer constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
$this->repository = app(ObjectGroupRepositoryInterface::class);
}
/**
* Transform the account.
*
* @param ObjectGroup $objectGroup
*
* @return array
*/
public function transform(ObjectGroup $objectGroup): array
{
$this->repository->setUser($objectGroup->user);
return [
'id' => (int) $objectGroup->id,
'created_at' => $objectGroup->created_at->toAtomString(),
'updated_at' => $objectGroup->updated_at->toAtomString(),
'title' => $objectGroup->title,
'order' => $objectGroup->order,
'links' => [
[
'rel' => 'self',
'uri' => '/groups/' . $objectGroup->id,
],
],
];
}
}

View File

@@ -85,7 +85,7 @@ class PiggyBankTransformer extends AbstractTransformer
$notes = '' === $notes ? null : $notes;
$objectGroupId = null;
$objectGroupOrder = 0;
$objectGroupOrder = null;
$objectGroupTitle = null;
/** @var ObjectGroup $objectGroup */
$objectGroup = $piggyBank->objectGroups->first();

View File

@@ -144,7 +144,7 @@ return [
'encryption' => null === env('USE_ENCRYPTION') || true === env('USE_ENCRYPTION'),
'version' => '5.3.0',
'api_version' => '1.1.0',
'api_version' => '1.2.0',
'db_version' => 14,
'maxUploadSize' => 15242880,
'send_error_message' => env('SEND_ERROR_MESSAGE', true),

View File

@@ -1684,5 +1684,6 @@ return [
'update_object_group' => 'Update group',
'updated_object_group' => 'Succesfully updated group ":title"',
'deleted_object_group' => 'Succesfully deleted group ":title"',
'object_group' => 'Group',
];

View File

@@ -36,6 +36,12 @@
<td style="width:40%;">{{ 'account'|_ }}</td>
<td><a href="{{ route('accounts.show', piggyBank.account_id) }}">{{ piggyBank.account.name }}</a></td>
</tr>
{% if piggy.object_group_title %}
<tr>
<td style="width:40%;">{{ 'object_group'|_ }}</td>
<td>{{ piggy.object_group_title }}</a></td>
</tr>
{% endif %}
<tr>
<td>{{ 'target_amount'|_ }}</td>
<td>

View File

@@ -54,6 +54,21 @@ Route::group(
}
);
Route::group(
['namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'groups',
'as' => 'api.v1.object-groups.',],
static function () {
// Accounts API routes:
Route::get('', ['uses' => 'ObjectGroupController@index', 'as' => 'index']);
Route::get('{objectGroup}', ['uses' => 'ObjectGroupController@show', 'as' => 'show']);
Route::put('{objectGroup}', ['uses' => 'ObjectGroupController@update', 'as' => 'update']);
Route::delete('{objectGroup}', ['uses' => 'ObjectGroupController@delete', 'as' => 'delete']);
Route::get('{objectGroup}/piggy_banks', ['uses' => 'ObjectGroupController@piggyBanks', 'as' => 'piggy_banks']);
}
);
Route::group(
['namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'attachments',
'as' => 'api.v1.attachments.',],