diff --git a/.env.example b/.env.example index cbd8c108..cc352568 100644 --- a/.env.example +++ b/.env.example @@ -35,9 +35,11 @@ SESSION_DRIVER=database SESSION_LIFETIME=120 QUEUE_DRIVER=sync +REDIS_CLIENT=phpredis REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 +REDIS_CACHE_DB=0 MAIL_DRIVER=mailgun MAIL_HOST=smtp.mailtrap.io diff --git a/CHANGELOG.md b/CHANGELOG.md index 6968343a..b6c1b30d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,22 @@ The complete changelog for the Costs to Expect REST API, our changelog follows the format defined at https://keepachangelog.com/en/1.0.0/ -## [v2.13.4] - 2020-06-19 +## [v2.11.5] - 2020-06-24 +### Added +- We have added a documentation page; the documentation page links to the API documentation and includes a couple of examples. + +### Changed +- We have updated the example ENV file. +- We have renamed a couple of our helper conversion/validation classes and moved them to a new namespace. +- We have made a minor content tweak on the landing page; the documentation button is in another section. +- We have updated and relocated our validation classes; the validation classes are now part of the `App\Request\Validate` namespace. +- We have reworked our summary controllers; we have removed some code duplication and added additional error checking. + +### Fixed +- Incorrectly assuming the result will be an array with at least one value. +- We have fixed an error in the changelog; we jump a couple of minor versions. + +## [v2.11.4] - 2020-06-19 ### Changed - We have switched to Redis for our cache. diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php index 5e322ad0..847d3771 100644 --- a/app/Http/Controllers/CategoryController.php +++ b/app/Http/Controllers/CategoryController.php @@ -15,7 +15,7 @@ use App\Utilities\Pagination as UtilityPagination; use App\Models\Category; use App\Models\Transformers\Category as CategoryTransformer; -use App\Validators\Fields\Category as CategoryValidator; +use App\Request\Validate\Category as CategoryValidator; use Exception; use Illuminate\Database\QueryException; use Illuminate\Http\JsonResponse; diff --git a/app/Http/Controllers/ItemCategoryController.php b/app/Http/Controllers/ItemCategoryController.php index e86c1955..8b675fa1 100644 --- a/app/Http/Controllers/ItemCategoryController.php +++ b/app/Http/Controllers/ItemCategoryController.php @@ -12,7 +12,7 @@ use App\Models\ItemCategory; use App\Models\Transformers\ItemCategory as ItemCategoryTransformer; use App\Response\Header\Headers; -use App\Validators\Fields\ItemCategory as ItemCategoryValidator; +use App\Request\Validate\ItemCategory as ItemCategoryValidator; use Exception; use Illuminate\Database\QueryException; use Illuminate\Http\JsonResponse; diff --git a/app/Http/Controllers/ItemPartialTransferController.php b/app/Http/Controllers/ItemPartialTransferController.php index 8a263536..71784942 100644 --- a/app/Http/Controllers/ItemPartialTransferController.php +++ b/app/Http/Controllers/ItemPartialTransferController.php @@ -13,7 +13,7 @@ use App\Request\Parameter; use App\Request\Route; use App\Utilities\Pagination as UtilityPagination; -use App\Validators\Fields\ItemPartialTransfer as ItemPartialTransferValidator; +use App\Request\Validate\ItemPartialTransfer as ItemPartialTransferValidator; use Exception; use Illuminate\Database\QueryException; use Illuminate\Http\JsonResponse; diff --git a/app/Http/Controllers/ItemSubcategoryController.php b/app/Http/Controllers/ItemSubcategoryController.php index 9a05d5d7..f804df65 100644 --- a/app/Http/Controllers/ItemSubcategoryController.php +++ b/app/Http/Controllers/ItemSubcategoryController.php @@ -12,7 +12,7 @@ use App\Models\ItemSubcategory; use App\Models\Subcategory; use App\Models\Transformers\ItemSubcategory as ItemSubcategoryTransformer; -use App\Validators\Fields\ItemSubcategory as ItemSubcategoryValidator; +use App\Request\Validate\ItemSubcategory as ItemSubcategoryValidator; use Exception; use Illuminate\Database\QueryException; use Illuminate\Http\JsonResponse; diff --git a/app/Http/Controllers/ItemTransferController.php b/app/Http/Controllers/ItemTransferController.php index 7ede5a56..b2e480ec 100644 --- a/app/Http/Controllers/ItemTransferController.php +++ b/app/Http/Controllers/ItemTransferController.php @@ -13,7 +13,7 @@ use App\Request\Parameter; use App\Request\Route; use App\Utilities\Pagination as UtilityPagination; -use App\Validators\Fields\ItemTransfer as ItemTransferValidator; +use App\Request\Validate\ItemTransfer as ItemTransferValidator; use Exception; use Illuminate\Database\QueryException; use Illuminate\Http\JsonResponse; diff --git a/app/Http/Controllers/RequestController.php b/app/Http/Controllers/RequestController.php index e68dab86..c1329864 100644 --- a/app/Http/Controllers/RequestController.php +++ b/app/Http/Controllers/RequestController.php @@ -12,7 +12,7 @@ use App\Models\Transformers\RequestErrorLog as RequestErrorLogTransformer; use App\Models\Transformers\RequestLog as RequestLogTransformer; use App\Utilities\Pagination as UtilityPagination; -use App\Validators\Fields\RequestErrorLog as RequestErrorLogValidator; +use App\Request\Validate\RequestErrorLog as RequestErrorLogValidator; use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\Config; diff --git a/app/Http/Controllers/ResourceController.php b/app/Http/Controllers/ResourceController.php index 08e88d58..2596a28e 100644 --- a/app/Http/Controllers/ResourceController.php +++ b/app/Http/Controllers/ResourceController.php @@ -14,7 +14,7 @@ use App\Utilities\Pagination as UtilityPagination; use App\Models\Resource; use App\Models\Transformers\Resource as ResourceTransformer; -use App\Validators\Fields\Resource as ResourceValidator; +use App\Request\Validate\Resource as ResourceValidator; use Exception; use Illuminate\Database\QueryException; use Illuminate\Http\JsonResponse; diff --git a/app/Http/Controllers/ResourceTypeController.php b/app/Http/Controllers/ResourceTypeController.php index 329ed2a2..2b557a53 100644 --- a/app/Http/Controllers/ResourceTypeController.php +++ b/app/Http/Controllers/ResourceTypeController.php @@ -18,7 +18,7 @@ use App\Utilities\Pagination as UtilityPagination; use App\Models\ResourceType; use App\Models\Transformers\ResourceType as ResourceTypeTransformer; -use App\Validators\Fields\ResourceType as ResourceTypeValidator; +use App\Request\Validate\ResourceType as ResourceTypeValidator; use Exception; use Illuminate\Database\QueryException; use Illuminate\Http\JsonResponse; diff --git a/app/Http/Controllers/SubcategoryController.php b/app/Http/Controllers/SubcategoryController.php index 8029a738..1b5aef11 100644 --- a/app/Http/Controllers/SubcategoryController.php +++ b/app/Http/Controllers/SubcategoryController.php @@ -14,7 +14,7 @@ use App\Utilities\Pagination as UtilityPagination; use App\Models\Subcategory; use App\Models\Transformers\Subcategory as SubcategoryTransformer; -use App\Validators\Fields\Subcategory as SubcategoryValidator; +use App\Request\Validate\Subcategory as SubcategoryValidator; use Exception; use Illuminate\Database\QueryException; use Illuminate\Http\JsonResponse; diff --git a/app/Http/Controllers/Summary/ItemController.php b/app/Http/Controllers/Summary/ItemController.php index 956a9739..d6f08094 100644 --- a/app/Http/Controllers/Summary/ItemController.php +++ b/app/Http/Controllers/Summary/ItemController.php @@ -4,16 +4,16 @@ use App\Http\Controllers\Controller; use App\Item\Factory; -use App\Option\Get; -use App\Response\Cache; -use App\Request\Parameter; -use App\Request\Route; use App\Models\Transformers\Summary\ItemCategory as ItemCategoryTransformer; use App\Models\Transformers\Summary\ItemMonth as ItemMonthTransformer; use App\Models\Transformers\Summary\ItemSubcategory as ItemSubcategoryTransformer; use App\Models\Transformers\Summary\ItemYear as ItemYearTransformer; +use App\Option\Get; +use App\Request\Parameter; +use App\Request\Route; +use App\Request\Validate\Boolean; +use App\Response\Cache; use App\Response\Header\Headers; -use App\Utilities\General; use Illuminate\Http\JsonResponse; /** @@ -49,8 +49,8 @@ public function index(string $resource_type_id, string $resource_id): JsonRespon $parameters = Parameter\Request::fetch( $item_interface->collectionParametersKeys(), - (int) $resource_type_id, - (int) $resource_id + (int)$resource_type_id, + (int)$resource_id ); $years = false; @@ -62,44 +62,40 @@ public function index(string $resource_type_id, string $resource_id): JsonRespon $category = null; $subcategory = null; - if ( - array_key_exists('years', $parameters) === true && - General::booleanValue($parameters['years']) === true - ) { + if (array_key_exists('years', $parameters) === true && + Boolean::convertedValue($parameters['years']) === true) { $years = true; } - if ( - array_key_exists('months', $parameters) === true && - General::booleanValue($parameters['months']) === true - ) { + if (array_key_exists('months', $parameters) === true && + Boolean::convertedValue($parameters['months']) === true) { $months = true; } if (array_key_exists('categories', $parameters) === true && - General::booleanValue($parameters['categories']) === true) { + Boolean::convertedValue($parameters['categories']) === true) { $categories = true; } if (array_key_exists('subcategories', $parameters) === true && - General::booleanValue($parameters['subcategories']) === true) { + Boolean::convertedValue($parameters['subcategories']) === true) { $subcategories = true; } if (array_key_exists('year', $parameters) === true) { - $year = (int) $parameters['year']; + $year = (int)$parameters['year']; } if (array_key_exists('month', $parameters) === true) { - $month = (int) $parameters['month']; + $month = (int)$parameters['month']; } if (array_key_exists('category', $parameters) === true) { - $category = (int) $parameters['category']; + $category = (int)$parameters['category']; } if (array_key_exists('subcategory', $parameters) === true) { - $subcategory = (int) $parameters['subcategory']; + $subcategory = (int)$parameters['subcategory']; } unset( @@ -123,11 +119,13 @@ public function index(string $resource_type_id, string $resource_id): JsonRespon if ($years === true) { return $this->yearsSummary( - (int) $resource_type_id, - (int) $resource_id, + (int)$resource_type_id, + (int)$resource_id, $parameters ); - } else if ( + } + + if ( $year !== null && $category === null && $subcategory === null && @@ -135,36 +133,40 @@ public function index(string $resource_type_id, string $resource_id): JsonRespon ) { if ($months === true) { return $this->monthsSummary( - (int) $resource_type_id, - (int) $resource_id, + (int)$resource_type_id, + (int)$resource_id, $year, $parameters ); - } else if ($month !== null) { + } + + if ($month !== null) { return $this->monthSummary( - (int) $resource_type_id, - (int) $resource_id, + (int)$resource_type_id, + (int)$resource_id, $year, $month, $parameters ); - } else { - return $this->yearSummary( - (int) $resource_type_id, - (int) $resource_id, - $year, - $parameters - ); } + + return $this->yearSummary( + (int)$resource_type_id, + (int)$resource_id, + $year, + $parameters + ); } if ($categories === true) { return $this->categoriesSummary( - (int) $resource_type_id, - (int) $resource_id, + (int)$resource_type_id, + (int)$resource_id, $parameters ); - } else if ( + } + + if ( $category !== null && $year === null && $month === null && @@ -172,27 +174,29 @@ public function index(string $resource_type_id, string $resource_id): JsonRespon ) { if ($subcategories === true) { return $this->subcategoriesSummary( - (int) $resource_type_id, - (int) $resource_id, + (int)$resource_type_id, + (int)$resource_id, $category, $parameters ); - } else if ($subcategory !== null) { + } + + if ($subcategory !== null) { return $this->subcategorySummary( - (int) $resource_type_id, - (int) $resource_id, + (int)$resource_type_id, + (int)$resource_id, $category, $subcategory, $parameters ); - } else { - return $this->categorySummary( - (int) $resource_type_id, - (int) $resource_id, - $category, - $parameters - ); } + + return $this->categorySummary( + (int)$resource_type_id, + (int)$resource_id, + $category, + $parameters + ); } if ( @@ -204,8 +208,8 @@ public function index(string $resource_type_id, string $resource_id): JsonRespon count($filter_parameters) > 0 ) { return $this->filteredSummary( - (int) $resource_type_id, - (int) $resource_id, + (int)$resource_type_id, + (int)$resource_id, $category, $subcategory, $year, @@ -217,14 +221,14 @@ public function index(string $resource_type_id, string $resource_id): JsonRespon } return $this->tcoSummary( - (int) $resource_type_id, - (int) $resource_id, + (int)$resource_type_id, + (int)$resource_id, $parameters ); } /** - * Return the total summary for a resource, total cost of ownership + * Return the annualised summary for a resource * * @param int $resource_type_id * @param int $resource_id @@ -232,12 +236,11 @@ public function index(string $resource_type_id, string $resource_id): JsonRespon * * @return JsonResponse */ - private function tcoSummary( + private function yearsSummary( int $resource_type_id, int $resource_id, array $parameters - ): JsonResponse - { + ): JsonResponse { $cache_control = new Cache\Control($this->user_id); $cache_control->setTtlOneWeek(); @@ -246,52 +249,74 @@ private function tcoSummary( if ($cache_control->cacheable() === false || $cache_summary->valid() === false) { - $summary = $this->model->summary( + $summary = $this->model->yearsSummary( $resource_type_id, $resource_id, $parameters ); - $collection = [ - 'total' => number_format($summary[0]['total'], 2, '.', '') - ]; + $collection = array_map( + static function ($year) { + return (new ItemYearTransformer($year))->toArray(); + }, + $summary + ); - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); + } - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } - } + return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); + } - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + private function assignContentToCache( + array $summary, + array $collection, + Cache\Control $cache_control, + Cache\Summary $cache_summary + ): \App\Response\Cache\Summary { + $headers = new Headers(); + $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> + addETag($collection)-> + addParameters(Parameter\Request::xHeader())-> + addFilters(Parameter\Filter::xHeader())-> + addSearch(Parameter\Search::xHeader()); + + if (array_key_exists(0, $summary)) { + if (array_key_exists('last_updated', $summary[0]) === true) { + $headers->addLastUpdated($summary[0]['last_updated']); + } + if (array_key_exists('total_count', $summary[0]) === true) { + $headers->addTotalCount((int)$summary[0]['total_count']); + } } - return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); + $cache_summary->create($collection, $headers->headers()); + $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + + return $cache_summary; } /** - * Return the annualised summary for a resource + * Return the monthly summary for a specific year * * @param int $resource_type_id * @param int $resource_id + * @param int $year * @param array $parameters * * @return JsonResponse */ - private function yearsSummary( + private function monthsSummary( int $resource_type_id, int $resource_id, + int $year, array $parameters - ): JsonResponse - { + ): JsonResponse { $cache_control = new Cache\Control($this->user_id); $cache_control->setTtlOneWeek(); @@ -300,57 +325,49 @@ private function yearsSummary( if ($cache_control->cacheable() === false || $cache_summary->valid() === false) { - $summary = $this->model->yearsSummary( + $summary = $this->model->monthsSummary( $resource_type_id, $resource_id, + $year, $parameters ); $collection = array_map( - static function ($year) { - return (new ItemYearTransformer($year))->toArray(); + static function ($month) { + return (new ItemMonthTransformer($month))->toArray(); }, $summary ); - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } - } - - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); } /** - * Return the total cost for a specific year + * Return the month summary for a specific year and month * - * @param int $resource_type_id, + * @param int $resource_type_id * @param int $resource_id * @param int $year + * @param int $month * @param array $parameters * * @return JsonResponse */ - private function yearSummary( + private function monthSummary( int $resource_type_id, int $resource_id, int $year, + int $month, array $parameters - ): JsonResponse - { + ): JsonResponse { $cache_control = new Cache\Control($this->user_id); $cache_control->setTtlOneWeek(); @@ -359,53 +376,46 @@ private function yearSummary( if ($cache_control->cacheable() === false || $cache_summary->valid() === false) { - $summary = $this->model->yearSummary( + $summary = $this->model->monthSummary( $resource_type_id, $resource_id, $year, + $month, $parameters ); - $collection = (new ItemYearTransformer($summary[0]))->toArray(); - - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - + $collection = []; if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } + $collection = (new ItemMonthTransformer($summary[0]))->toArray(); } - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); } /** - * Return the monthly summary for a specific year + * Return the total cost for a specific year * - * @param int $resource_type_id + * @param int $resource_type_id , * @param int $resource_id * @param int $year * @param array $parameters * * @return JsonResponse */ - private function monthsSummary( + private function yearSummary( int $resource_type_id, int $resource_id, int $year, array $parameters - ): JsonResponse - { + ): JsonResponse { $cache_control = new Cache\Control($this->user_id); $cache_control->setTtlOneWeek(); @@ -414,60 +424,43 @@ private function monthsSummary( if ($cache_control->cacheable() === false || $cache_summary->valid() === false) { - $summary = $this->model->monthsSummary( + $summary = $this->model->yearSummary( $resource_type_id, $resource_id, $year, $parameters ); - $collection = array_map( - static function ($month) { - return (new ItemMonthTransformer($month))->toArray(); - }, - $summary - ); - - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - + $collection = []; if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } + $collection = (new ItemYearTransformer($summary[0]))->toArray(); } - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); } /** - * Return the month summary for a specific year and month + * Return the categories summary for a resource * * @param int $resource_type_id * @param int $resource_id - * @param int $year - * @param int $month * @param array $parameters * * @return JsonResponse */ - private function monthSummary( + private function categoriesSummary( int $resource_type_id, int $resource_id, - int $year, - int $month, array $parameters - ): JsonResponse - { + ): JsonResponse { $cache_control = new Cache\Control($this->user_id); $cache_control->setTtlOneWeek(); @@ -475,53 +468,46 @@ private function monthSummary( $cache_summary->setFromCache($cache_control->get(request()->getRequestUri())); if ($cache_control->cacheable() === false || $cache_summary->valid() === false) { - - $summary = $this->model->monthSummary( + $summary = $this->model->categoriesSummary( $resource_type_id, $resource_id, - $year, - $month, $parameters ); - $collection = (new ItemMonthTransformer($summary[0]))->toArray(); - - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } - } + $collection = array_map( + static function ($category) { + return (new ItemCategoryTransformer($category))->toArray(); + }, + $summary + ); - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); } /** - * Return the categories summary for a resource + * Return the subcategories summary for a category * * @param int $resource_type_id * @param int $resource_id + * @param int $category_id * @param array $parameters * * @return JsonResponse */ - private function categoriesSummary( + private function subcategoriesSummary( int $resource_type_id, int $resource_id, + int $category_id, array $parameters - ): JsonResponse - { + ): JsonResponse { $cache_control = new Cache\Control($this->user_id); $cache_control->setTtlOneWeek(); @@ -529,67 +515,50 @@ private function categoriesSummary( $cache_summary->setFromCache($cache_control->get(request()->getRequestUri())); if ($cache_control->cacheable() === false || $cache_summary->valid() === false) { - $summary = $this->model->categoriesSummary( + + $summary = $this->model->subCategoriesSummary( $resource_type_id, $resource_id, + $category_id, $parameters ); $collection = array_map( - static function ($category) { - return (new ItemCategoryTransformer($category))->toArray(); + static function ($subcategory) { + return (new ItemSubcategoryTransformer($subcategory))->toArray(); }, $summary ); - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } - } - - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); } /** - * Return a filtered summary + * Return the subcategories summary for a category * * @param int $resource_type_id * @param int $resource_id - * @param int|null $category_id - * @param int|null $subcategory_id - * @param int|null $year - * @param int|null $month + * @param int $category_id + * @param int $subcategory_id * @param array $parameters - * @param array $search_parameters - * @param array $filter_parameters * * @return JsonResponse */ - private function filteredSummary( + private function subcategorySummary( int $resource_type_id, int $resource_id, - int $category_id = null, - int $subcategory_id = null, - int $year = null, - int $month = null, - array $parameters = [], - array $search_parameters = [], - array $filter_parameters = [] - ): JsonResponse - { + int $category_id, + int $subcategory_id, + array $parameters + ): JsonResponse { $cache_control = new Cache\Control($this->user_id); $cache_control->setTtlOneWeek(); @@ -598,38 +567,25 @@ private function filteredSummary( if ($cache_control->cacheable() === false || $cache_summary->valid() === false) { - $summary = $this->model->filteredSummary( + $summary = $this->model->subCategorySummary( $resource_type_id, $resource_id, $category_id, $subcategory_id, - $year, - $month, - $parameters, - $search_parameters, - $filter_parameters + $parameters ); - $collection = [ - 'total' => number_format($summary[0]['total'], 2, '.', '') - ]; - - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - + $collection = []; if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } + $collection = (new ItemSubcategoryTransformer($summary[0]))->toArray(); } - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); @@ -650,8 +606,7 @@ private function categorySummary( int $resource_id, int $category_id, array $parameters - ): JsonResponse - { + ): JsonResponse { $cache_control = new Cache\Control($this->user_id); $cache_control->setTtlOneWeek(); @@ -667,46 +622,48 @@ private function categorySummary( $parameters ); - $collection = (new ItemCategoryTransformer($summary[0]))->toArray(); - - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - + $collection = []; if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } + $collection = (new ItemCategoryTransformer($summary[0]))->toArray(); } - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); } /** - * Return the subcategories summary for a category + * Return a filtered summary * * @param int $resource_type_id * @param int $resource_id - * @param int $category_id + * @param int|null $category_id + * @param int|null $subcategory_id + * @param int|null $year + * @param int|null $month * @param array $parameters + * @param array $search_parameters + * @param array $filter_parameters * * @return JsonResponse */ - private function subcategoriesSummary( + private function filteredSummary( int $resource_type_id, int $resource_id, - int $category_id, - array $parameters - ): JsonResponse - { + int $category_id = null, + int $subcategory_id = null, + int $year = null, + int $month = null, + array $parameters = [], + array $search_parameters = [], + array $filter_parameters = [] + ): JsonResponse { $cache_control = new Cache\Control($this->user_id); $cache_control->setTtlOneWeek(); @@ -715,60 +672,52 @@ private function subcategoriesSummary( if ($cache_control->cacheable() === false || $cache_summary->valid() === false) { - $summary = $this->model->subCategoriesSummary( + $summary = $this->model->filteredSummary( $resource_type_id, $resource_id, $category_id, - $parameters - ); - - $collection = array_map( - static function ($subcategory) { - return (new ItemSubcategoryTransformer($subcategory))->toArray(); - }, - $summary + $subcategory_id, + $year, + $month, + $parameters, + $search_parameters, + $filter_parameters ); - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } + $total = '0.00'; + if (array_key_exists(0, $summary) && array_key_exists('total', $summary[0])) { + $total = number_format($summary[0]['total'], 2, '.', ''); } - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $collection = [ + 'total' => $total + ]; + + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); } /** - * Return the subcategories summary for a category + * Return the total summary for a resource, total cost of ownership * * @param int $resource_type_id * @param int $resource_id - * @param int $category_id - * @param int $subcategory_id * @param array $parameters * * @return JsonResponse */ - private function subcategorySummary( + private function tcoSummary( int $resource_type_id, int $resource_id, - int $category_id, - int $subcategory_id, array $parameters - ): JsonResponse - { + ): JsonResponse { $cache_control = new Cache\Control($this->user_id); $cache_control->setTtlOneWeek(); @@ -777,32 +726,27 @@ private function subcategorySummary( if ($cache_control->cacheable() === false || $cache_summary->valid() === false) { - $summary = $this->model->subCategorySummary( + $summary = $this->model->summary( $resource_type_id, $resource_id, - $category_id, - $subcategory_id, $parameters ); - $collection = (new ItemSubcategoryTransformer($summary[0]))->toArray(); - - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } + $total = '0.00'; + if (array_key_exists(0, $summary) && array_key_exists('total', $summary[0])) { + $total = number_format($summary[0]['total'], 2, '.', ''); } - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $collection = [ + 'total' => $total + ]; + + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); @@ -816,7 +760,7 @@ private function subcategorySummary( * * @return JsonResponse */ - public function optionsIndex(string $resource_type_id, string $resource_id) + public function optionsIndex(string $resource_type_id, string $resource_id): JsonResponse { Route\Validate::resource( $resource_type_id, @@ -832,13 +776,9 @@ public function optionsIndex(string $resource_type_id, string $resource_id) $this->permitted_resource_types ); - $get = Get::init()-> - setParameters($item_interface->collectionParametersConfig())-> - setSearchable($item_interface->searchParametersConfig())-> - setFilterable($item_interface->filterParametersConfig())-> - setDescription('route-descriptions.summary_GET_resource-type_resource_items')-> - setAuthenticationStatus($permissions['view'])-> - option(); + $get = Get::init()->setParameters($item_interface->collectionParametersConfig())->setSearchable($item_interface->searchParametersConfig()) + ->setFilterable($item_interface->filterParametersConfig())->setDescription('route-descriptions.summary_GET_resource-type_resource_items') + ->setAuthenticationStatus($permissions['view'])->option(); return $this->optionsResponse($get, 200); } diff --git a/app/Http/Controllers/Summary/ResourceTypeItemController.php b/app/Http/Controllers/Summary/ResourceTypeItemController.php index ece562dc..2b3b90c9 100644 --- a/app/Http/Controllers/Summary/ResourceTypeItemController.php +++ b/app/Http/Controllers/Summary/ResourceTypeItemController.php @@ -8,13 +8,13 @@ use App\Response\Cache; use App\Request\Parameter; use App\Request\Route; +use App\Request\Validate\Boolean; use App\Models\Transformers\Summary\ResourceTypeItemCategory as ResourceTypeItemCategoryTransformer; use App\Models\Transformers\Summary\ResourceTypeItemMonth as ResourceTypeItemMonthTransformer; use App\Models\Transformers\Summary\ResourceTypeItemResource as ResourceTypeItemResourceTransformer; use App\Models\Transformers\Summary\ResourceTypeItemSubcategory as ResourceTypeItemSubcategoryTransformer; use App\Models\Transformers\Summary\ResourceTypeItemYear as ResourceTypeItemYearTransformer; use App\Response\Header\Headers; -use App\Utilities\General; use Illuminate\Http\JsonResponse; /** @@ -60,34 +60,28 @@ public function index(string $resource_type_id): JsonResponse $category = null; $subcategory = null; - if ( - array_key_exists('resources', $parameters) === true && - General::booleanValue($parameters['resources']) === true - ) { + if (array_key_exists('resources', $parameters) === true && + Boolean::convertedValue($parameters['resources']) === true) { $resources = true; } - if ( - array_key_exists('years', $parameters) === true && - General::booleanValue($parameters['years']) === true - ) { + if (array_key_exists('years', $parameters) === true && + Boolean::convertedValue($parameters['years']) === true) { $years = true; } - if ( - array_key_exists('months', $parameters) === true && - General::booleanValue($parameters['months']) === true - ) { + if (array_key_exists('months', $parameters) === true && + Boolean::convertedValue($parameters['months']) === true) { $months = true; } if (array_key_exists('categories', $parameters) === true && - General::booleanValue($parameters['categories']) === true) { + Boolean::convertedValue($parameters['categories']) === true) { $categories = true; } if (array_key_exists('subcategories', $parameters) === true && - General::booleanValue($parameters['subcategories']) === true) { + Boolean::convertedValue($parameters['subcategories']) === true) { $subcategories = true; } @@ -132,7 +126,9 @@ public function index(string $resource_type_id): JsonResponse $resource_type_id, $parameters ); - } else if ( + } + + if ( $year !== null && $category === null && $subcategory === null && @@ -144,22 +140,22 @@ public function index(string $resource_type_id): JsonResponse $year, $parameters ); - } else { - if ($month !== null) { - return $this->monthSummary( - $resource_type_id, - $year, - $month, - $parameters - ); - } else { - return $this->yearSummary( - $resource_type_id, - $year, - $parameters - ); - } } + + if ($month !== null) { + return $this->monthSummary( + $resource_type_id, + $year, + $month, + $parameters + ); + } + + return $this->yearSummary( + $resource_type_id, + $year, + $parameters + ); } if ($categories === true) { @@ -167,7 +163,9 @@ public function index(string $resource_type_id): JsonResponse $resource_type_id, $parameters ); - } else if ( + } + + if ( $category !== null && $year === null && $month === null && @@ -179,22 +177,22 @@ public function index(string $resource_type_id): JsonResponse $category, $parameters ); - } else { - if ($subcategory !== null) { - return $this->subcategorySummary( - $resource_type_id, - $category, - $subcategory, - $parameters - ); - } else { - return $this->categorySummary( - $resource_type_id, - $category, - $parameters - ); - } } + + if ($subcategory !== null) { + return $this->subcategorySummary( + $resource_type_id, + $category, + $subcategory, + $parameters + ); + } + + return $this->categorySummary( + $resource_type_id, + $category, + $parameters + ); } if ($resources === true) { @@ -230,6 +228,35 @@ public function index(string $resource_type_id): JsonResponse ); } + private function assignContentToCache( + array $summary, + array $collection, + Cache\Control $cache_control, + Cache\Summary $cache_summary + ): \App\Response\Cache\Summary { + $headers = new Headers(); + $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> + addETag($collection)-> + addParameters(Parameter\Request::xHeader())-> + addFilters(Parameter\Filter::xHeader())-> + addSearch(Parameter\Search::xHeader()); + + + if (array_key_exists(0, $summary)) { + if (array_key_exists('last_updated', $summary[0]) === true) { + $headers->addLastUpdated($summary[0]['last_updated']); + } + if (array_key_exists('total_count', $summary[0]) === true) { + $headers->addTotalCount((int)$summary[0]['total_count']); + } + } + + $cache_summary->create($collection, $headers->headers()); + $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + + return $cache_summary; + } + /** * Return the total summary for all the resources in the resource type * @@ -256,31 +283,21 @@ private function summary( $parameters ); + $total = '0.00'; + if (array_key_exists(0, $summary) && array_key_exists('total', $summary[0])) { + $total = number_format($summary[0]['total'], 2, '.', ''); + } + $collection = [ - 'total' => number_format( - $summary[0]['total'], - 2, - '.', - '' - ) + 'total' => $total ]; - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } - } - - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); @@ -320,22 +337,12 @@ static function ($resource) { $summary ); - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } - } - - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); @@ -375,22 +382,12 @@ static function ($year) { $summary ); - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } - } - - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); @@ -426,24 +423,17 @@ private function yearSummary( $parameters ); - $collection = (new ResourceTypeItemYearTransformer($summary[0]))->toArray(); - - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - + $collection = []; if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } + $collection = (new ResourceTypeItemYearTransformer($summary[0]))->toArray(); } - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); @@ -486,22 +476,12 @@ static function ($month) { $summary ); - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } - } - - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); @@ -540,24 +520,17 @@ private function monthSummary( $parameters ); - $collection = (new ResourceTypeItemMonthTransformer($summary[0]))->toArray(); - - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - + $collection = []; if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } + $collection = (new ResourceTypeItemMonthTransformer($summary[0]))->toArray(); } - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); @@ -597,22 +570,12 @@ static function ($category) { $summary ); - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } - } - - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); @@ -648,24 +611,17 @@ private function categorySummary( $parameters ); - $collection = (new ResourceTypeItemCategoryTransformer($summary[0]))->toArray(); - - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - + $collection = []; if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } + $collection = (new ResourceTypeItemCategoryTransformer($summary[0]))->toArray(); } - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); @@ -715,28 +671,21 @@ private function filteredSummary( $filter_parameters ); + $total = '0.00'; + if (array_key_exists(0, $summary) && array_key_exists('total', $summary[0])) { + $total = number_format($summary[0]['total'], 2, '.', ''); + } + $collection = [ - 'total' => number_format($summary[0]['total'], 2, '.', '') + 'total' => $total ]; - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addFilters(Parameter\Filter::xHeader())-> - addSearch(Parameter\Search::xHeader())-> - addParameters(Parameter\Request::xHeader()); - - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } - } - - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); @@ -779,22 +728,12 @@ static function ($category) { $summary ); - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addParameters(Parameter\Request::xHeader()); - - if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } - } - - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); @@ -833,24 +772,17 @@ private function subcategorySummary( $parameters ); - $collection = (new ResourceTypeItemSubcategoryTransformer($summary[0]))->toArray(); - - $headers = new Headers(); - $headers->addCacheControl($cache_control->visibility(), $cache_control->ttl())-> - addETag($collection)-> - addSearch(Parameter\Search::xHeader()); - + $collection = []; if (array_key_exists(0, $summary)) { - if (array_key_exists('last_updated', $summary[0]) === true) { - $headers->addLastUpdated($summary[0]['last_updated']); - } - if (array_key_exists('total_count', $summary[0]) === true) { - $headers->addTotalCount((int) $summary[0]['total_count']); - } + $collection = (new ResourceTypeItemSubcategoryTransformer($summary[0]))->toArray(); } - $cache_summary->create($collection, $headers->headers()); - $cache_control->put(request()->getRequestUri(), $cache_summary->content()); + $this->assignContentToCache( + $summary, + $collection, + $cache_control, + $cache_summary + ); } return response()->json($cache_summary->collection(), 200, $cache_summary->headers()); diff --git a/app/Item/AbstractItem.php b/app/Item/AbstractItem.php index da62c4fc..badddd53 100644 --- a/app/Item/AbstractItem.php +++ b/app/Item/AbstractItem.php @@ -5,7 +5,7 @@ use App\Interfaces\Item\IModel; use App\Models\Transformers\Transformer; -use App\Validators\Fields\Validator; +use App\Request\Validate\Validator; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Config; diff --git a/app/Item/AllocatedExpense.php b/app/Item/AllocatedExpense.php index 59ae8933..71c17f03 100644 --- a/app/Item/AllocatedExpense.php +++ b/app/Item/AllocatedExpense.php @@ -6,8 +6,8 @@ use App\Interfaces\Item\IModel; use App\Models\Item\AllocatedExpense as ItemModel; use App\Models\Transformers\Transformer; -use App\Validators\Fields\ItemType\AllocatedExpense as ItemTypeAllocatedExpenseValidator; -use App\Validators\Fields\Validator; +use App\Request\Validate\ItemType\AllocatedExpense as ItemTypeAllocatedExpenseValidator; +use App\Request\Validate\Validator; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Config; diff --git a/app/Item/SimpleExpense.php b/app/Item/SimpleExpense.php index 0a288a9a..1f774e17 100644 --- a/app/Item/SimpleExpense.php +++ b/app/Item/SimpleExpense.php @@ -6,8 +6,8 @@ use App\Interfaces\Item\IModel; use App\Models\Item\SimpleExpense as ItemModel; use App\Models\Transformers\Transformer; -use App\Validators\Fields\ItemType\SimpleExpense as ItemTypeSimpleExpenseValidator; -use App\Validators\Fields\Validator; +use App\Request\Validate\ItemType\SimpleExpense as ItemTypeSimpleExpenseValidator; +use App\Request\Validate\Validator; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Config; diff --git a/app/Item/SimpleItem.php b/app/Item/SimpleItem.php index 0fb987d1..6135fcce 100644 --- a/app/Item/SimpleItem.php +++ b/app/Item/SimpleItem.php @@ -6,8 +6,8 @@ use App\Interfaces\Item\IModel; use App\Models\Item\SimpleItem as ItemModel; use App\Models\Transformers\Transformer; -use App\Validators\Fields\ItemType\SimpleItem as ItemTypeSimpleItemValidator; -use App\Validators\Fields\Validator; +use App\Request\Validate\ItemType\SimpleItem as ItemTypeSimpleItemValidator; +use App\Request\Validate\Validator; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Config; diff --git a/app/Models/Item/AllocatedExpense.php b/app/Models/Item/AllocatedExpense.php index 89909e62..f1300aa4 100644 --- a/app/Models/Item/AllocatedExpense.php +++ b/app/Models/Item/AllocatedExpense.php @@ -4,7 +4,7 @@ namespace App\Models\Item; use App\Interfaces\Item\IModel; -use App\Utilities\General; +use App\Request\Validate\Boolean; use App\Utilities\Model as ModelUtility; use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Database\Eloquent\Model; @@ -77,7 +77,7 @@ public function single( if ( array_key_exists('include-categories', $parameters) === true && - General::booleanValue($parameters['include-categories']) === true + Boolean::convertedValue($parameters['include-categories']) === true ) { $result->leftJoin('item_category', 'item.id', 'item_category.item_id')-> leftJoin('category', 'item_category.category_id', 'category.id'); @@ -89,7 +89,7 @@ public function single( if ( array_key_exists('include-subcategories', $parameters) === true && - General::booleanValue($parameters['include-subcategories']) === true + Boolean::convertedValue($parameters['include-subcategories']) === true ) { $result->leftJoin('item_sub_category', 'item_category.id', 'item_sub_category.item_category_id')-> leftJoin('sub_category', 'item_sub_category.sub_category_id', 'sub_category.id'); @@ -250,7 +250,7 @@ public function totalCount( if ( array_key_exists('include-unpublished', $parameters) === false || - General::booleanValue($parameters['include-unpublished']) === false + Boolean::convertedValue($parameters['include-unpublished']) === false ) { $collection->where(function ($collection) { $collection->whereNull('item_type_allocated_expense.publish_after')->orWhereRaw('item_type_allocated_expense.publish_after < NOW()'); @@ -308,7 +308,7 @@ public function paginatedCollection( if ( array_key_exists('include-categories', $parameters) === true && - General::booleanValue($parameters['include-categories']) === true + Boolean::convertedValue($parameters['include-categories']) === true ) { $collection->leftJoin('item_category', 'item.id', 'item_category.item_id')-> leftJoin('category', 'item_category.category_id', 'category.id'); @@ -327,7 +327,7 @@ public function paginatedCollection( if ( array_key_exists('include-subcategories', $parameters) === true && - General::booleanValue($parameters['include-subcategories']) === true + Boolean::convertedValue($parameters['include-subcategories']) === true ) { $collection->leftJoin('item_sub_category', 'item_category.id', 'item_sub_category.item_category_id')-> leftJoin('sub_category', 'item_sub_category.sub_category_id', 'sub_category.id'); @@ -381,7 +381,7 @@ public function paginatedCollection( if ( array_key_exists('include-unpublished', $parameters) === false || - General::booleanValue($parameters['include-unpublished']) === false + Boolean::convertedValue($parameters['include-unpublished']) === false ) { $collection->where(function ($collection) { $collection->whereNull('item_type_allocated_expense.publish_after')->orWhereRaw('item_type_allocated_expense.publish_after < NOW()'); diff --git a/app/Models/Item/SimpleExpense.php b/app/Models/Item/SimpleExpense.php index de578d1a..82b1aff6 100644 --- a/app/Models/Item/SimpleExpense.php +++ b/app/Models/Item/SimpleExpense.php @@ -4,7 +4,7 @@ namespace App\Models\Item; use App\Interfaces\Item\IModel; -use App\Utilities\General; +use App\Request\Validate\Boolean; use App\Utilities\Model as ModelUtility; use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Database\Eloquent\Model; @@ -86,7 +86,7 @@ public function single( if ( array_key_exists('include-categories', $parameters) === true && - General::booleanValue($parameters['include-categories']) === true + Boolean::convertedValue($parameters['include-categories']) === true ) { $result->leftJoin('item_category', 'item.id', 'item_category.item_id')-> leftJoin('category', 'item_category.category_id', 'category.id'); @@ -98,7 +98,7 @@ public function single( if ( array_key_exists('include-subcategories', $parameters) === true && - General::booleanValue($parameters['include-subcategories']) === true + Boolean::convertedValue($parameters['include-subcategories']) === true ) { $result->leftJoin('item_sub_category', 'item_category.id', 'item_sub_category.item_category_id')-> leftJoin('sub_category', 'item_sub_category.sub_category_id', 'sub_category.id'); @@ -222,7 +222,7 @@ public function paginatedCollection( if ( array_key_exists('include-categories', $parameters) === true && - General::booleanValue($parameters['include-categories']) === true + Boolean::convertedValue($parameters['include-categories']) === true ) { $collection->leftJoin('item_category', 'item.id', 'item_category.item_id')-> leftJoin('category', 'item_category.category_id', 'category.id'); @@ -241,7 +241,7 @@ public function paginatedCollection( if ( array_key_exists('include-subcategories', $parameters) === true && - General::booleanValue($parameters['include-subcategories']) === true + Boolean::convertedValue($parameters['include-subcategories']) === true ) { $collection->leftJoin('item_sub_category', 'item_category.id', 'item_sub_category.item_category_id')-> leftJoin('sub_category', 'item_sub_category.sub_category_id', 'sub_category.id'); diff --git a/app/Models/ResourceTypeItem.php b/app/Models/ResourceTypeItem.php index 96f702cf..2af2f51f 100644 --- a/app/Models/ResourceTypeItem.php +++ b/app/Models/ResourceTypeItem.php @@ -3,7 +3,7 @@ namespace App\Models; -use App\Utilities\General; +use App\Request\Validate\Boolean; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Query\Builder as QueryBuilder; @@ -133,7 +133,7 @@ public function paginatedCollection( if ( array_key_exists('include-categories', $parameters_collection) === true && - General::booleanValue($parameters_collection['include-categories']) === true + Boolean::convertedValue($parameters_collection['include-categories']) === true ) { $collection->join('item_category', 'item.id', 'item_category.item_id')-> join('category', 'item_category.category_id', 'category.id'); @@ -151,7 +151,7 @@ public function paginatedCollection( if ( array_key_exists('include-subcategories', $parameters_collection) === true && - General::booleanValue($parameters_collection['include-subcategories']) === true + Boolean::convertedValue($parameters_collection['include-subcategories']) === true ) { $collection->join('item_sub_category', 'item_category.id', 'item_sub_category.item_category_id')-> join('sub_category', 'item_sub_category.sub_category_id', 'sub_category.id'); diff --git a/app/Models/ResourceTypeItem/AllocatedExpense.php b/app/Models/ResourceTypeItem/AllocatedExpense.php index fb49aa6d..76857b9d 100644 --- a/app/Models/ResourceTypeItem/AllocatedExpense.php +++ b/app/Models/ResourceTypeItem/AllocatedExpense.php @@ -4,7 +4,7 @@ namespace App\Models\ResourceTypeItem; use App\Interfaces\ResourceTypeItem\IModel; -use App\Utilities\General; +use App\Request\Validate\Boolean; use App\Utilities\Model as ModelUtility; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; @@ -148,7 +148,7 @@ public function paginatedCollection( if ( array_key_exists('include-categories', $parameters_collection) === true && - General::booleanValue($parameters_collection['include-categories']) === true + Boolean::convertedValue($parameters_collection['include-categories']) === true ) { $collection->leftJoin('item_category', 'item.id', 'item_category.item_id')-> leftJoin('category', 'item_category.category_id', 'category.id'); @@ -167,7 +167,7 @@ public function paginatedCollection( if ( array_key_exists('include-subcategories', $parameters_collection) === true && - General::booleanValue($parameters_collection['include-subcategories']) === true + Boolean::convertedValue($parameters_collection['include-subcategories']) === true ) { $collection->leftJoin('item_sub_category', 'item_category.id', 'item_sub_category.item_category_id')-> leftJoin('sub_category', 'item_sub_category.sub_category_id', 'sub_category.id'); diff --git a/app/Models/ResourceTypeItem/SimpleExpense.php b/app/Models/ResourceTypeItem/SimpleExpense.php index 093bb3b8..28c0aade 100644 --- a/app/Models/ResourceTypeItem/SimpleExpense.php +++ b/app/Models/ResourceTypeItem/SimpleExpense.php @@ -4,7 +4,7 @@ namespace App\Models\ResourceTypeItem; use App\Interfaces\ResourceTypeItem\IModel; -use App\Utilities\General; +use App\Request\Validate\Boolean; use App\Utilities\Model as ModelUtility; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Query\Builder as QueryBuilder; @@ -123,7 +123,7 @@ public function paginatedCollection( if ( array_key_exists('include-categories', $parameters_collection) === true && - General::booleanValue($parameters_collection['include-categories']) === true + Boolean::convertedValue($parameters_collection['include-categories']) === true ) { $collection->leftJoin('item_category', 'item.id', 'item_category.item_id')-> leftJoin('category', 'item_category.category_id', 'category.id'); @@ -142,7 +142,7 @@ public function paginatedCollection( if ( array_key_exists('include-subcategories', $parameters_collection) === true && - General::booleanValue($parameters_collection['include-subcategories']) === true + Boolean::convertedValue($parameters_collection['include-subcategories']) === true ) { $collection->leftJoin('item_sub_category', 'item_category.id', 'item_sub_category.item_category_id')-> leftJoin('sub_category', 'item_sub_category.sub_category_id', 'sub_category.id'); diff --git a/app/Request/Parameter/Request.php b/app/Request/Parameter/Request.php index 50056128..17538d57 100644 --- a/app/Request/Parameter/Request.php +++ b/app/Request/Parameter/Request.php @@ -8,7 +8,7 @@ use App\Models\Category; use App\Models\ResourceType; use App\Models\Subcategory; -use App\Utilities\General; +use App\Request\Validate\Boolean; /** * Fetch any GET parameters attached to the URI and validate them, silently @@ -42,7 +42,7 @@ private static function find(array $parameter_names = []): void case 'include-resources'; case 'include-categories': case 'include-subcategories'; - self::$parameters[$parameter] = General::booleanValue($request_parameters[$parameter]); + self::$parameters[$parameter] = Boolean::convertedValue($request_parameters[$parameter]); break; default: @@ -79,7 +79,10 @@ private static function validate(?int $resource_type_id, ?int $resource_id): voi case 'include-unpublished': if ( array_key_exists($key, self::$parameters) === true && - General::booleanValue(self::$parameters[$key]) === false + ( + Boolean::isConvertible(self::$parameters[$key]) === false || + Boolean::convertedValue(self::$parameters[$key]) === false + ) ) { unset(self::$parameters[$key]); } @@ -127,7 +130,7 @@ private static function validate(?int $resource_type_id, ?int $resource_id): voi case 'years': if ( array_key_exists($key, self::$parameters) === true && - General::isBooleanValue(self::$parameters[$key]) === false + Boolean::isConvertible(self::$parameters[$key]) === false ) { unset(self::$parameters[$key]); } diff --git a/app/Utilities/General.php b/app/Request/Validate/Boolean.php similarity index 51% rename from app/Utilities/General.php rename to app/Request/Validate/Boolean.php index 2996201f..fac9b89a 100644 --- a/app/Utilities/General.php +++ b/app/Request/Validate/Boolean.php @@ -1,42 +1,41 @@ * @copyright Dean Blackborough 2018-2020 * @license https://github.com/costs-to-expect/api/blob/master/LICENSE */ -class General +class Boolean { /** - * Checks a value and see if a boolean is returned after a call to - * filter_var($value, FILTER_VALIDATE_BOOLEAN) + * Converts the provided value to a boolean, valid options are 1, true, + * "true" and "off". We look for the positive values are return anything + * else as FALSE * * @param $value * * @return bool */ - public static function booleanValue($value): bool + public static function convertedValue($value): bool { return filter_var($value, FILTER_VALIDATE_BOOLEAN) === true; } /** - * Check to see if a value is a valid boolean, uses filter_var so true, 1, - * "true" and "on" are all valid positive boolean values, off values - * are false, 0, "false" and "off" + * Check to see if the provided value can be turned into a boolean, + * we use filter_var s0 true, 1, "true" and "on" are all valid positive + * boolean values, valid false values are false, 0, "false" and "off" * * @param mixed $value Value to check to see if it is a possible boolean * * @return bool */ - public static function isBooleanValue($value): bool + public static function isConvertible($value): bool { $filtered = filter_var($value, FILTER_VALIDATE_BOOLEAN,FILTER_NULL_ON_FAILURE); diff --git a/app/Validators/Fields/Category.php b/app/Request/Validate/Category.php similarity index 71% rename from app/Validators/Fields/Category.php rename to app/Request/Validate/Category.php index 8f2c3371..e92e1e8d 100644 --- a/app/Validators/Fields/Category.php +++ b/app/Request/Validate/Category.php @@ -1,10 +1,9 @@ requiredIndexes(['resource_type_id'], $options); return ValidatorFacade::make( request()->all(), - $this->createRules(intval($options['resource_type_id'])), + $this->createRules((int) $options['resource_type_id']), $this->translateMessages('api.category.validation.POST.messages') ); } /** + * Return a valid validator object for a update (PATCH) request + * * @param array $options * - * @return Validator + * @return \Illuminate\Contracts\Validation\Validator|null */ - public function update(array $options = []): Validator + public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator { return ValidatorFacade::make( request()->all(), diff --git a/app/Validators/Fields/ItemCategory.php b/app/Request/Validate/ItemCategory.php similarity index 68% rename from app/Validators/Fields/ItemCategory.php rename to app/Request/Validate/ItemCategory.php index 9e375266..356ff7e4 100644 --- a/app/Validators/Fields/ItemCategory.php +++ b/app/Request/Validate/ItemCategory.php @@ -1,10 +1,9 @@ hash->category()->decode(request()->input('category_id')); $category_id = null; @@ -39,13 +38,8 @@ public function create(array $options = []): Validator ); } - /** - * @param array $options - * - * @return Validator - */ - public function update(array $options = []): Validator + public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator { - // TODO: Implement update() method. + return null; } } diff --git a/app/Validators/Fields/ItemPartialTransfer.php b/app/Request/Validate/ItemPartialTransfer.php similarity index 76% rename from app/Validators/Fields/ItemPartialTransfer.php rename to app/Request/Validate/ItemPartialTransfer.php index b6dfcec0..96c761ed 100644 --- a/app/Validators/Fields/ItemPartialTransfer.php +++ b/app/Request/Validate/ItemPartialTransfer.php @@ -1,10 +1,9 @@ requiredIndexes([ 'resource_type_id', @@ -53,7 +52,7 @@ public function create(array $options = []): Validator [ 'resource_id' => [ 'required', - Rule::exists('resource', 'id')->where(function ($query) use ($options) + Rule::exists('resource', 'id')->where(static function ($query) use ($options) { $query->where('resource_type_id', '=', $options['resource_type_id'])-> where('id', '!=', $options['existing_resource_id']); @@ -66,13 +65,8 @@ public function create(array $options = []): Validator ); } - /** - * @param array $options - * - * @return Validator - */ - public function update(array $options = []): \Illuminate\Contracts\Validation\Validator + public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator { - // TODO: Implement update() method. + return null; } } diff --git a/app/Validators/Fields/ItemSubcategory.php b/app/Request/Validate/ItemSubcategory.php similarity index 66% rename from app/Validators/Fields/ItemSubcategory.php rename to app/Request/Validate/ItemSubcategory.php index d949ce4d..2a7b1b64 100644 --- a/app/Validators/Fields/ItemSubcategory.php +++ b/app/Request/Validate/ItemSubcategory.php @@ -1,10 +1,9 @@ category_id = $category_id; - return array_merge( [ 'subcategory_id' => [ @@ -41,13 +34,13 @@ private function createRules(int $category_id): array } /** - * Return the validator object for the create request + * Return a valid validator object for a create (POST) request * * @param array $options * - * @return Validator + * @return \Illuminate\Contracts\Validation\Validator */ - public function create(array $options = []): Validator + public function create(array $options = []): \Illuminate\Contracts\Validation\Validator { $this->requiredIndexes(['category_id'], $options); @@ -59,17 +52,13 @@ public function create(array $options = []): Validator return ValidatorFacade::make( ['subcategory_id' => $subcategory_id], - self::createRules(intval($options['category_id'])), + $this->createRules(), $this->translateMessages('api.item-subcategory.validation.POST.messages') ); } - /** - * @param array $options - * @return Validator - */ - public function update(array $options = []): Validator + public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator { - // TODO: Implement update() method. + return null; } } diff --git a/app/Validators/Fields/ItemTransfer.php b/app/Request/Validate/ItemTransfer.php similarity index 72% rename from app/Validators/Fields/ItemTransfer.php rename to app/Request/Validate/ItemTransfer.php index b59ae82a..c5d84c31 100644 --- a/app/Validators/Fields/ItemTransfer.php +++ b/app/Request/Validate/ItemTransfer.php @@ -1,10 +1,9 @@ requiredIndexes(['resource_type_id', 'existing_resource_id'], $options); @@ -45,7 +44,7 @@ public function create(array $options = []): Validator [ 'resource_id' => [ 'required', - Rule::exists('resource', 'id')->where(function ($query) use ($options) + Rule::exists('resource', 'id')->where(static function ($query) use ($options) { $query->where('resource_type_id', '=', $options['resource_type_id'])-> where('id', '!=', $options['existing_resource_id']); @@ -56,13 +55,8 @@ public function create(array $options = []): Validator ); } - /** - * @param array $options - * - * @return Validator - */ - public function update(array $options = []): \Illuminate\Contracts\Validation\Validator + public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator { - // TODO: Implement update() method. + return null; } } diff --git a/app/Request/Validate/ItemType/AllocatedExpense.php b/app/Request/Validate/ItemType/AllocatedExpense.php new file mode 100644 index 00000000..98c96be8 --- /dev/null +++ b/app/Request/Validate/ItemType/AllocatedExpense.php @@ -0,0 +1,47 @@ + + * @copyright Dean Blackborough 2018-2020 + * @license https://github.com/costs-to-expect/api/blob/master/LICENSE + */ +class AllocatedExpense extends BaseValidator +{ + public function __construct() + { + $this->item = new \App\Item\AllocatedExpense(); + + parent::__construct(); + } + + /** + * Return the validator object for the create request + * + * @param array $options + * + * @return \Illuminate\Contracts\Validation\Validator + */ + public function create(array $options = []): \Illuminate\Contracts\Validation\Validator + { + return $this->createItemValidator(); + } + + /** + * Return a valid validator object for a update (PATCH) request + * + * @param array $options + * + * @return \Illuminate\Contracts\Validation\Validator|null + */ + public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator + { + return $this->updateItemValidator(); + } +} diff --git a/app/Request/Validate/ItemType/SimpleExpense.php b/app/Request/Validate/ItemType/SimpleExpense.php new file mode 100644 index 00000000..54c3dc42 --- /dev/null +++ b/app/Request/Validate/ItemType/SimpleExpense.php @@ -0,0 +1,47 @@ + + * @copyright Dean Blackborough 2018-2020 + * @license https://github.com/costs-to-expect/api/blob/master/LICENSE + */ +class SimpleExpense extends BaseValidator +{ + public function __construct() + { + $this->item = new \App\Item\SimpleExpense(); + + parent::__construct(); + } + + /** + * Return the validator object for the create request + * + * @param array $options + * + * @return \Illuminate\Contracts\Validation\Validator + */ + public function create(array $options = []): \Illuminate\Contracts\Validation\Validator + { + return $this->createItemValidator(); + } + + /** + * Return a valid validator object for a update (PATCH) request + * + * @param array $options + * + * @return \Illuminate\Contracts\Validation\Validator|null + */ + public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator + { + return $this->updateItemValidator(); + } +} diff --git a/app/Request/Validate/ItemType/SimpleItem.php b/app/Request/Validate/ItemType/SimpleItem.php new file mode 100644 index 00000000..ef55e404 --- /dev/null +++ b/app/Request/Validate/ItemType/SimpleItem.php @@ -0,0 +1,47 @@ + + * @copyright Dean Blackborough 2018-2020 + * @license https://github.com/costs-to-expect/api/blob/master/LICENSE + */ +class SimpleItem extends BaseValidator +{ + public function __construct() + { + $this->item = new \App\Item\SimpleItem(); + + parent::__construct(); + } + + /** + * Return the validator object for the create request + * + * @param array $options + * + * @return \Illuminate\Contracts\Validation\Validator + */ + public function create(array $options = []): \Illuminate\Contracts\Validation\Validator + { + return $this->createItemValidator(); + } + + /** + * Return a valid validator object for a update (PATCH) request + * + * @param array $options + * + * @return \Illuminate\Contracts\Validation\Validator|null + */ + public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator + { + return $this->updateItemValidator(); + } +} diff --git a/app/Validators/Fields/RequestErrorLog.php b/app/Request/Validate/RequestErrorLog.php similarity index 65% rename from app/Validators/Fields/RequestErrorLog.php rename to app/Request/Validate/RequestErrorLog.php index c5790adc..5328bc8b 100644 --- a/app/Validators/Fields/RequestErrorLog.php +++ b/app/Request/Validate/RequestErrorLog.php @@ -1,10 +1,9 @@ all(), @@ -34,8 +33,8 @@ public function create(array $options = []): Validator ); } - public function update(array $options = []): Validator + public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator { - // TODO: Implement update() method. + return null; } } diff --git a/app/Validators/Fields/Resource.php b/app/Request/Validate/Resource.php similarity index 71% rename from app/Validators/Fields/Resource.php rename to app/Request/Validate/Resource.php index 04ce520e..91f8d27c 100644 --- a/app/Validators/Fields/Resource.php +++ b/app/Request/Validate/Resource.php @@ -1,10 +1,9 @@ requiredIndexes(['resource_type_id'], $options); return ValidatorFacade::make( request()->all(), - self::createRules(intval($options['resource_type_id'])), + $this->createRules((int) $options['resource_type_id']), $this->translateMessages('api.resource.validation.POST.messages') ); } /** + * Return a valid validator object for a update (PATCH) request + * * @param array $options - * @return Validator + * + * @return \Illuminate\Contracts\Validation\Validator|null */ - public function update(array $options = []): Validator + public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator { return ValidatorFacade::make( request()->all(), diff --git a/app/Validators/Fields/ResourceType.php b/app/Request/Validate/ResourceType.php similarity index 75% rename from app/Validators/Fields/ResourceType.php rename to app/Request/Validate/ResourceType.php index a91b1bed..3ac6bae0 100644 --- a/app/Validators/Fields/ResourceType.php +++ b/app/Request/Validate/ResourceType.php @@ -1,11 +1,10 @@ hash->itemType()->decode(request()->input('item_type_id')); + $item_type_id = null; if (count($decode) === 1) { $item_type_id = $decode[0]; @@ -98,11 +104,13 @@ public function create(array $options = []): Validator } /** + * Return a valid validator object for a update (PATCH) request + * * @param array $options * - * @return Validator + * @return \Illuminate\Contracts\Validation\Validator|null */ - public function update(array $options = []): Validator + public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator { return ValidatorFacade::make( request()->all(), diff --git a/app/Validators/Fields/Subcategory.php b/app/Request/Validate/Subcategory.php similarity index 67% rename from app/Validators/Fields/Subcategory.php rename to app/Request/Validate/Subcategory.php index 1471331f..b6e07498 100644 --- a/app/Validators/Fields/Subcategory.php +++ b/app/Request/Validate/Subcategory.php @@ -1,15 +1,15 @@ * @copyright Dean Blackborough 2018-2020 @@ -40,7 +40,7 @@ private function createRules(int $category_id): array } /** - * Create the validation rules for the update request + * Create the validation rules for the update (PATCH) request * * @param integer $category_id * @param integer $subcategory_id @@ -62,38 +62,47 @@ private function updateRules(int $category_id, int $subcategory_id): array ); } + /** + * Any fields which can't be defined via the configuration files because + * the validation rules are dynamic + * + * @return array|string[] + */ public function dynamicDefinedFields(): array { return ['name']; } /** - * Return the validator object for the create request + * Return a valid validator object for a create (POST) request * * @param array $options * - * @return Validator + * @return \Illuminate\Contracts\Validation\Validator */ - public function create(array $options = []): Validator + public function create(array $options = []): \Illuminate\Contracts\Validation\Validator { $this->requiredIndexes(['category_id'], $options); return ValidatorFacade::make( request()->all(), - self::createRules(intval($options['category_id'])), + $this->createRules((int) $options['category_id']), $this->translateMessages('api.subcategory.validation.POST.messages') ); } /** + * Return a valid validator object for a update (PATCH) request + * * @param array $options - * @return Validator + * + * @return \Illuminate\Contracts\Validation\Validator|null */ - public function update(array $options = []): Validator + public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator { return ValidatorFacade::make( request()->all(), - $this->updateRules($options['category_id'], $options['subcategory_id']), + $this->updateRules((int) $options['category_id'], (int) $options['subcategory_id']), $this->translateMessages('api.subcategory.validation.PATCH.messages') ); } diff --git a/app/Validators/Fields/Validator.php b/app/Request/Validate/Validator.php similarity index 61% rename from app/Validators/Fields/Validator.php rename to app/Request/Validate/Validator.php index 9be57ced..491efd75 100644 --- a/app/Validators/Fields/Validator.php +++ b/app/Request/Validate/Validator.php @@ -1,14 +1,13 @@ $custom_message) { $messages[$key] = trans($custom_message); - }; + } return $messages; } - protected function requiredIndexes(array $required = [], array $provided = []) + /** + * Check to ensure we have all the required indexes, check the required + * keys against the provided keys + * + * @param array $required + * @param array $provided + */ + protected function requiredIndexes( + array $required = [], + array $provided = [] + ): void { foreach ($provided as $key => $value) { - if (in_array($key, $required) === false) { + if (in_array($key, $required, true) === false) { abort(500, 'Indexes missing in options array for validator'); } } } /** - * Return the validator object for the create request + * Return a valid validator object for a create (POST) request + * + * @param array $options + * + * @return \Illuminate\Contracts\Validation\Validator + */ + abstract public function create(array $options = []): \Illuminate\Contracts\Validation\Validator; + + /** + * Return a valid validator object for a update (PATCH) request * * @param array $options * + * @return \Illuminate\Contracts\Validation\Validator|null + */ + abstract public function update(array $options = []): ?\Illuminate\Contracts\Validation\Validator; + + /** * @return \Illuminate\Contracts\Validation\Validator */ - public function create(array $options = []): \Illuminate\Contracts\Validation\Validator + protected function createItemValidator(): \Illuminate\Contracts\Validation\Validator { $messages = []; foreach ($this->item->validationPostableFieldMessages() as $key => $custom_message) { $messages[$key] = trans($custom_message); - }; + } return ValidatorFacade::make( request()->all(), @@ -80,18 +100,14 @@ public function create(array $options = []): \Illuminate\Contracts\Validation\Va } /** - * Return the validator object for the update request - * - * @param array $options - * * @return \Illuminate\Contracts\Validation\Validator */ - public function update(array $options = []): \Illuminate\Contracts\Validation\Validator + public function updateItemValidator(): ?\Illuminate\Contracts\Validation\Validator { $messages = []; foreach ($this->item->validationPatchableFieldMessages() as $key => $custom_message) { $messages[$key] = trans($custom_message); - }; + } return ValidatorFacade::make( request()->all(), diff --git a/app/Utilities/Pagination.php b/app/Utilities/Pagination.php index de700ad3..dc85cc11 100644 --- a/app/Utilities/Pagination.php +++ b/app/Utilities/Pagination.php @@ -3,6 +3,8 @@ namespace App\Utilities; +use App\Request\Validate\Boolean; + use Illuminate\Support\Facades\Config; /** @@ -247,7 +249,12 @@ private static function render(): array self::$offset = (int) request()->query('offset', 0); self::$limit = (int) request()->query('limit', self::$limit); if (self::$allow_override === true) { - self::$collection = General::booleanValue(request()->query('collection', false)); + + self::$collection = false; + + if (Boolean::convertedValue(request()->query('collection')) === true) { + self::$collection = true; + } } $uris = [ diff --git a/app/Validators/Fields/ItemType/AllocatedExpense.php b/app/Validators/Fields/ItemType/AllocatedExpense.php deleted file mode 100644 index 290e71a0..00000000 --- a/app/Validators/Fields/ItemType/AllocatedExpense.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright Dean Blackborough 2018-2020 - * @license https://github.com/costs-to-expect/api/blob/master/LICENSE - */ -class AllocatedExpense extends BaseValidator -{ - public function __construct() - { - $this->item = new \App\Item\AllocatedExpense(); - - parent::__construct(); - } -} diff --git a/app/Validators/Fields/ItemType/SimpleExpense.php b/app/Validators/Fields/ItemType/SimpleExpense.php deleted file mode 100644 index 263932b7..00000000 --- a/app/Validators/Fields/ItemType/SimpleExpense.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright Dean Blackborough 2018-2020 - * @license https://github.com/costs-to-expect/api/blob/master/LICENSE - */ -class SimpleExpense extends BaseValidator -{ - public function __construct() - { - $this->item = new \App\Item\SimpleExpense(); - - parent::__construct(); - } -} diff --git a/app/Validators/Fields/ItemType/SimpleItem.php b/app/Validators/Fields/ItemType/SimpleItem.php deleted file mode 100644 index 96bdfb06..00000000 --- a/app/Validators/Fields/ItemType/SimpleItem.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright Dean Blackborough 2018-2020 - * @license https://github.com/costs-to-expect/api/blob/master/LICENSE - */ -class SimpleItem extends BaseValidator -{ - public function __construct() - { - $this->item = new \App\Item\SimpleItem(); - - parent::__construct(); - } -} diff --git a/config/api/app/version.php b/config/api/app/version.php index cbf5e980..79dbd743 100644 --- a/config/api/app/version.php +++ b/config/api/app/version.php @@ -3,9 +3,9 @@ declare(strict_types=1); return [ - 'version'=> '2.11.4', + 'version'=> 'v2.11.5', 'prefix' => 'v2', - 'release_date' => '2020-06-19', + 'release_date' => '2020-06-24', 'changelog' => [ 'api' => '/v2/changelog', 'markdown' => 'https://github.com/costs-to-expect/api/blob/master/CHANGELOG.md' diff --git a/public/package.json b/public/package.json index 1a9c21be..f9b9cbfb 100644 --- a/public/package.json +++ b/public/package.json @@ -5,7 +5,6 @@ "dependencies": { "bootstrap": "^4.3", "jquery": "^3.5.1", - "open-iconic": "^1.1.1", "popper.js": "^1.16" }, "main": "index.php", diff --git a/public/yarn.lock b/public/yarn.lock index 456262d8..24c5fe84 100644 --- a/public/yarn.lock +++ b/public/yarn.lock @@ -12,11 +12,6 @@ jquery@^3.5.1: resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5" integrity sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg== -open-iconic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/open-iconic/-/open-iconic-1.1.1.tgz#9dcfc8c7cd3c61cdb4a236b1a347894c97adc0c6" - integrity sha1-nc/Ix808Yc20ojaxo0eJTJetwMY= - popper.js@^1.16: version "1.16.0" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.0.tgz#2e1816bcbbaa518ea6c2e15a466f4cb9c6e2fbb3" diff --git a/resources/views/documentation.blade.php b/resources/views/documentation.blade.php new file mode 100644 index 00000000..5f7bccaa --- /dev/null +++ b/resources/views/documentation.blade.php @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Costs to Expect API: Documentation + + + + + + + +
+
+
+

Our App is in the alpha stage, the beta is coming soon.

+
+
+
+
+ +
+
+ + +
+
+
+
+ Icon +
+
+ Welcome to Costs to Expect +
+
+

Documentation

+
+ +
+
+
+
+ +
+
+ + @if ($maintenance === true) + + + @endif + +

Docs and examples

+ +

The documentation for the Costs to Expects API is + available as a Postman collection.

+ +

Our documentation is + available at https://postman.costs-to-expect.com.

+ +

We will ensure that all our docs are always be up to date; + the docs will always refer to the released live version + of the API.

+ +

In addition to the published documentation, we include + some documentation within our API, in the form of + OPTIONS requests.

+ +

The root collection of the API details all the available + routes and the endpoints for each route. An OPTIONS + endpoint exists for each route; in addition to the + supported routes, the OPTIONS response shows the + supported fields and parameters.

+ +

Structure

+ +

In the Costs to Expect API, we have three base levels + of hierarchy, resource type, resource, and item.

+ +
    +
  • Items are the individual expense or items we a tracking.
  • +
  • Resources are the names for the buckets, lists or trackers.
  • +
  • Resource types are for grouping and where we define the kind of thing we are tracking or forecasting.
  • +
+ +

The resources in a resource type all use the same + tracking or forecasting method. The categories and + subcategories defined for a resource type belong to + all the resources.

+ +

Examples

+ +

We have included a couple of examples below to give + you an idea of the typical responses the API will return.

+ +

Resource types

+ +
Request
+ +
curl --location --request GET 'https://api.costs-to-expect.com/v2/resource-types?limit=25&offset=0'
+ +
Response
+ +
[
+  {
+    "id": "d185Q15grY",
+    "name": "Blackborough boys",
+    "description": "The Blackborough children, Jack and Niall",
+    "created": "2018-09-06 22:04:23",
+    "public": true,
+    "item_type": {
+      "id": "OqZwKX16bW",
+      "name": "allocated-expense",
+      "description": "Expenses with an allocation rate"
+    },
+    "resources": {
+      "count": 2
+    }
+  }
+]
+ +
Headers
+ +
Cache-Control: max-age=604800, public
+Content-Length: 335
+Content-Type: application/json
+Content-Encoding: gzip
+Content-Language: en
+ETag: "2a03c7fc4044c27aa801410c050fadb4"
+Vary: Accept-Encoding
+X-Powered-By: PHP/7.4.5
+Content-Security-Policy: default-src 'none'
+Strict-Transport-Security: max-age=31536000;
+Referrer-Policy: strict-origin-when-cross-origin
+X-Content-Type-Options: nosniff
+X-Count: 1
+X-Total-Count: 1
+X-Offset: 0
+X-Limit: 10
+X-Link-Previous:
+X-Link-Next:
+X-RateLimit-Limit: 300
+X-RateLimit-Remaining: 299
+Date: Mon, 22 Jun 2020 14:40:57 GMT
+ +

Items for a resource

+ +
Request
+ +
curl --location --request GET 'https://api.costs-to-expect.com/v2/resource-types/d185Q15grY/resources/kw8gLq31VB/items?limit=25&offset=0'
+ +
Response
+ +
[
+  {
+    "id": "K13qM2K3OV",
+    "name": "Pocket money",
+    "description": null,
+    "total": "3.90",
+    "percentage": 100,
+    "actualised_total": "3.90",
+    "effective_date": "2020-05-25",
+    "created": "2020-05-25 18:01:00",
+    "updated": "2020-05-25 18:01:00"
+  },
+  {
+    "id": "akzpAXBD8g",
+    "name": "Share of shopping",
+    "description": null,
+    "total": "156.91",
+    "percentage": 20,
+    "actualised_total": "31.38",
+    "effective_date": "2020-05-24",
+    "created": "2020-05-24 12:52:00",
+    "updated": "2020-05-24 12:52:00"
+  }
+]
+ +
Headers
+ +
Cache-Control: max-age=604800, private
+Content-Length: 790
+Content-Type: application/json
+Content-Encoding: gzip
+Content-Language: en
+ETag: "c3b0623f7dc47c6a48bd18c8fcbf3618"
+Vary: Accept-Encoding
+X-Powered-By: PHP/7.4.5
+Content-Security-Policy: default-src 'none'
+Strict-Transport-Security: max-age=31536000;
+Referrer-Policy: strict-origin-when-cross-origin
+X-Content-Type-Options: nosniff
+X-Count: 10
+X-Total-Count: 1694
+X-Offset: 0
+X-Limit: 10
+X-Link-Previous:
+X-Link-Next: /v2/resource-types/d185Q15grY/resources/kw8gLq31VB/items?offset=10&limit=10
+X-RateLimit-Limit: 300
+X-RateLimit-Remaining: 299
+Date: Sun, Mon, 22 Jun 2020 14:46:03 GMT
+
+
+ +
+
+
+

+ Copyright © Dean Blackborough 2018 - {{ date('Y') }}
+ Our App | + Our Website | + Our Blog | + Status +

+

Latest release: {{ $version }} ({{ date('jS M Y', strtotime($date)) }})

+

All code maintained by Dean Blackborough and released under the MIT license.

+
+
+
+
+
+ + + + + diff --git a/resources/views/welcome.blade.php b/resources/views/welcome.blade.php index 7aea4be9..572bfc81 100644 --- a/resources/views/welcome.blade.php +++ b/resources/views/welcome.blade.php @@ -7,7 +7,6 @@ - @@ -57,12 +56,13 @@ function gtag(){dataLayer.push(arguments);} @@ -86,12 +86,13 @@ function gtag(){dataLayer.push(arguments);} @@ -148,6 +149,11 @@ function gtag(){dataLayer.push(arguments);}

Access API View our API on Github +

+ +

The documentation for the API is available as a Postman collection.

+ +

Documentation

@@ -205,67 +211,36 @@ function gtag(){dataLayer.push(arguments);}
-

Latest feature release [v2.11.0]

+

Latest release {{ $version }}

The latest release of the Costs to Expect API is {{ $version }}; we released it on the {{ date('jS M Y', strtotime($date)) }}.

-

The combined changelog below shows all the fixes and improvements we have made to the - API since the last feature release.

+

The changelog below shows all the fixes and improvements we have made, to view + the entire changelog please check here.

Added

Changed

Fixed

- -

Removed

- - diff --git a/routes/web.php b/routes/web.php index c49f47ef..8ea60909 100644 --- a/routes/web.php +++ b/routes/web.php @@ -15,4 +15,14 @@ ] ); +Route::view( + 'documentation', + 'documentation', + [ + 'maintenance' => app()->isDownForMaintenance(), + 'version' => $version['version'], + 'date' => $version['release_date'] + ] +); +