Skip to content

Commit

Permalink
Files (#112)
Browse files Browse the repository at this point in the history
* FileInfo endpoint added

* FetchFile content

* More niceness

* Up to categories . .

* Project Type

* ProjectType

* Cleanup and apps list

* app info + files

* Get me a file
  • Loading branch information
annejan authored Jun 24, 2022
1 parent a6069e1 commit e2362e8
Show file tree
Hide file tree
Showing 30 changed files with 761 additions and 69 deletions.
4 changes: 2 additions & 2 deletions .env.testing
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ APP_URL=http://localhost
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=badgeware_test
DB_DATABASE=hatchery
DB_USERNAME=root
DB_PASSWORD=
DB_PASSWORD=root

BROADCAST_DRIVER=log
CACHE_DRIVER=file
Expand Down
333 changes: 333 additions & 0 deletions app/Http/Controllers/MchController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,333 @@
<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\Badge;
use App\Models\Category;
use App\Models\File;
use App\Models\Project;
use App\Models\Version;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use OpenApi\Annotations as OA;

class MchController extends Controller
{
/**
* List the available devices.
*
* @OA\Get(
* path="/mch2022/devices",
* @OA\Response(response="default",ref="#/components/responses/undocumented")
* )
*
* @return JsonResponse
*/
public function devices(): JsonResponse
{
$devices = [];
foreach (Badge::pluck('name', 'slug') as $slug => $name) {
$devices[] = [
'slug' => $slug,
'name' => $name
];
}
return response()->json(
$devices,
200,
['Content-Type' => 'application/json'],
JSON_UNESCAPED_SLASHES
);
}

/**
* Get the types of apps a device supports.
*
* @OA\Get(
* path="/mch2022/{device}/types",
* @OA\Parameter(
* name="device",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="mch2022")
* ),
* tags={"MCH2022"},
* @OA\Response(response="default",ref="#/components/responses/undocumented")
* )
*
* @param string $device
* @return JsonResponse
*/
public function types(string $device): JsonResponse
{
/** @var Badge $badge */
$badge = Badge::whereSlug($device)->firstOrFail();
return response()->json($badge->types, 200, ['Content-Type' => 'application/json'], JSON_UNESCAPED_SLASHES);
}

/**
* Get the types of apps a device supports.
*
* @OA\Get(
* path="/mch2022/{device}/{type}/categories",
* @OA\Parameter(
* name="device",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="mch2022")
* ),
* @OA\Parameter(
* name="type",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="esp32")
* ),
* tags={"MCH2022"},
* @OA\Response(response="default",ref="#/components/responses/undocumented")
* )
*
* @param string $device
* @param string $type
* @return JsonResponse
*/
public function categories(string $device, string $type): JsonResponse
{
/** @var Badge $badge */
$badge = Badge::whereSlug($device)->firstOrFail();

$count = $categories = [];
/** @var Project $project */
foreach ($badge->projects()->whereProjectType($type)->get() as $project) {
$count[$project->category_id] =
isset($count[$project->category_id]) ? $count[$project->category_id] + 1 : 1;
}
foreach ($count as $id => $apps) {
/** @var Category $category */
$category = Category::find($id);
$categories[] = [
'name' => $category->name,
'slug' => $category->slug,
'apps' => $apps,
];
}

return response()->json($categories, 200, ['Content-Type' => 'application/json'], JSON_UNESCAPED_SLASHES);
}

/**
* Get the apps from a device / type / category
*
* @OA\Get(
* path="/mch2022/{device}/{type}/{category}",
* @OA\Parameter(
* name="device",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="mch2022")
* ),
* @OA\Parameter(
* name="type",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="esp32")
* ),
* @OA\Parameter(
* name="category",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="fun")
* ),
* tags={"MCH2022"},
* @OA\Response(response="default",ref="#/components/responses/undocumented")
* )
*
* @param string $device
* @param string $type
* @param string $category
* @return JsonResponse
*/
public function apps(string $device, string $type, string $category): JsonResponse
{
/** @var Badge $badge */
$badge = Badge::whereSlug($device)->firstOrFail();
/** @var Category $category */
$categoryId = Category::whereSlug($category)->firstOrFail()->id;
$apps = [];
/** @var Project $project */
foreach ($badge->projects()->whereProjectType($type)->whereCategoryId($categoryId)->get() as $project) {
$apps[] = [
'slug' => $project->slug,
'name' => $project->name,
'author' => $project->author,
'license' => $project->license,
'description' => $project->description,
];
}
return response()->json($apps, 200, ['Content-Type' => 'application/json'], JSON_UNESCAPED_SLASHES);
}


/**
* Get the apps from a device / type / category
*
* @OA\Get(
* path="/mch2022/{device}/{type}/{category}/{app}",
* @OA\Parameter(
* name="device",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="mch2022")
* ),
* @OA\Parameter(
* name="type",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="esp32")
* ),
* @OA\Parameter(
* name="category",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="fun")
* ),
* @OA\Parameter(
* name="app",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="game_of_life")
* ),
* tags={"MCH2022"},
* @OA\Response(response="default",ref="#/components/responses/undocumented")
* )
*
* @param string $device
* @param string $type
* @param string $category
* @param string $app
* @return JsonResponse
*/
public function app(string $device, string $type, string $category, string $app): JsonResponse
{
/** @var Badge $badge */
$badge = Badge::whereSlug($device)->firstOrFail();
$categoryId = Category::whereSlug($category)->firstOrFail()->id;
/** @var Project $project */
$project = $badge->projects()
->whereProjectType($type)->whereCategoryId($categoryId)->whereSlug($app)->firstOrFail();

/** @var Version $version */
$version = $project->versions()->published()->get()->last();
$files = [];
/** @var File $file */
foreach ($version->files as $file) {
$fileData = new \stdClass();
$fileData->name = $file->name;
$fileData->url = route('mch.file', [
'device' => $badge->slug,
'type' => $project->project_type,
'category' => $category,
'app' => $project->slug,
'file' => $file->name
]);
$fileData->size = $file->size_of_content;

$files[] = $fileData;
}

return response()->json(
[
'slug' => $project->slug,
'name' => $project->name,
'author' => $project->author,
'license' => $project->license,
'description' => $project->description,
'files' => $files,
],
200,
['Content-Type' => 'application/json'],
JSON_UNESCAPED_SLASHES
);
}

/**
* Get app file content
*
* @OA\Get(
* path="/mch2022/{device}/{type}/{category}/{app}/{file}",
* @OA\Parameter(
* name="device",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="mch2022")
* ),
* @OA\Parameter(
* name="type",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="esp32")
* ),
* @OA\Parameter(
* name="category",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="fun")
* ),
* @OA\Parameter(
* name="app",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="game_of_life")
* ),
* @OA\Parameter(
* name="file",
* in="path",
* required=true,
* @OA\Schema(type="string", format="slug", example="file.py")
* ),
* tags={"MCH2022"},
* @OA\Response(response="default",ref="#/components/responses/undocumented")
* )
*
* @param string $device
* @param string $type
* @param string $category
* @param string $app
* @param string $name
* @return Response|JsonResponse
*/
public function file(
string $device,
string $type,
string $category,
string $app,
string $name
): Response|JsonResponse {
/** @var Badge $badge */
$badge = Badge::whereSlug($device)->firstOrFail();
$categoryId = Category::whereSlug($category)->firstOrFail()->id;
/** @var Project $project */
$project = $badge->projects()
->whereProjectType($type)->whereCategoryId($categoryId)->whereSlug($app)->firstOrFail();

/** @var Version|null $version */
$version = $project->versions()->published()->get()->last();

if ($version === null || empty($version->files)) {
return response()->json(['message' => 'File not found'], 404);
}

/** @var File|null $file */
$file = $version->files()->where('name', $name)->first();
if ($file === null) {
return response()->json(['message' => 'File not found'], 404);
}

return response(
$file->content,
200,
['Content-Type' => $file->mime]
);
}
}
4 changes: 2 additions & 2 deletions app/Http/Controllers/PublicController.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function index(Request $request): View
/** @var Builder $projects */
$projects = Project::whereHas(
'versions',
function ($query) {
static function ($query) {
$query->published();
}
);
Expand Down Expand Up @@ -98,7 +98,7 @@ private function returnProjectView(Request $request, $projects, string $badge =

$orderField = 'id';
$orderDirection = 'desc';
if ($request->has('order') && in_array($request->get('order'), $this->orderFields)) {
if ($request->has('order') && in_array($request->get('order'), $this->orderFields, true)) {
$orderField = $request->get('order');
if ($request->has('direction') && $request->get('direction') === 'asc') {
$orderDirection = 'asc';
Expand Down
Loading

0 comments on commit e2362e8

Please sign in to comment.