Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions app/Enum/LandingAnimationPreset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/**
* SPDX-License-Identifier: MIT
* Copyright (c) 2017-2018 Tobias Reich
* Copyright (c) 2018-2026 LycheeOrg.
*/

namespace App\Enum;

/**
* Enum LandingAnimationPreset.
*
* Defines the selectable landing page animation presets.
*/
enum LandingAnimationPreset: string
{
case NONE = 'none';
case CLASSIC_FADE = 'classic_fade';
case ZOOM_IN = 'zoom_in';
case PARALLAX_SCROLL = 'parallax_scroll';
case SLIDE_REVEAL = 'slide_reveal';
}
31 changes: 31 additions & 0 deletions app/Enum/LandingCtaPosition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/**
* SPDX-License-Identifier: MIT
* Copyright (c) 2017-2018 Tobias Reich
* Copyright (c) 2018-2026 LycheeOrg.
*/

namespace App\Enum;

/**
* Enum representing the possible positions for the landing page CTA button.
*
* Landing-scoped (deliberately not shared with WatermarkPosition, even
* though the value set is identical): landing and watermarking are
* different bounded contexts, see Feature 054 spec Design Notes.
*/
enum LandingCtaPosition: string
{
case TOP_LEFT = 'top-left';
case TOP = 'top';
case TOP_RIGHT = 'top-right';

case LEFT = 'left';
case CENTER = 'center';
case RIGHT = 'right';

case BOTTOM_LEFT = 'bottom-left';
case BOTTOM = 'bottom';
case BOTTOM_RIGHT = 'bottom-right';
}
20 changes: 20 additions & 0 deletions app/Enum/LandingFeaturedItemType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

/**
* SPDX-License-Identifier: MIT
* Copyright (c) 2017-2018 Tobias Reich
* Copyright (c) 2018-2026 LycheeOrg.
*/

namespace App\Enum;

/**
* Enum LandingFeaturedItemType.
*
* Defines whether a landing page featured item points to a photo or an album.
*/
enum LandingFeaturedItemType: string
{
case PHOTO = 'photo';
case ALBUM = 'album';
}
20 changes: 20 additions & 0 deletions app/Enum/LandingFeaturedItemsMode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

/**
* SPDX-License-Identifier: MIT
* Copyright (c) 2017-2018 Tobias Reich
* Copyright (c) 2018-2026 LycheeOrg.
*/

namespace App\Enum;

/**
* Enum LandingFeaturedItemsMode.
*
* Defines how the landing page featured-content section is populated.
*/
enum LandingFeaturedItemsMode: string
{
case AUTOMATIC = 'automatic';
case MANUAL = 'manual';
}
22 changes: 22 additions & 0 deletions app/Enum/LandingLayoutType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

/**
* SPDX-License-Identifier: MIT
* Copyright (c) 2017-2018 Tobias Reich
* Copyright (c) 2018-2026 LycheeOrg.
*/

namespace App\Enum;

/**
* Enum LandingLayoutType.
*
* Defines the selectable landing page layouts.
*/
enum LandingLayoutType: string
{
case CLASSIC = 'classic';
case PORTFOLIO = 'portfolio';
case MERIDIAN = 'meridian';
case STUDIO = 'studio';
}
21 changes: 21 additions & 0 deletions app/Enum/LandingLinkPlacement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/**
* SPDX-License-Identifier: MIT
* Copyright (c) 2017-2018 Tobias Reich
* Copyright (c) 2018-2026 LycheeOrg.
*/

namespace App\Enum;

/**
* Enum LandingLinkPlacement.
*
* Defines where an admin-managed landing page extra link is rendered.
*/
enum LandingLinkPlacement: string
{
case NAV = 'nav';
case FOOTER = 'footer';
case BOTH = 'both';
}
25 changes: 25 additions & 0 deletions app/Enum/LandingTextPosition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

/**
* SPDX-License-Identifier: MIT
* Copyright (c) 2017-2018 Tobias Reich
* Copyright (c) 2018-2026 LycheeOrg.
*/

namespace App\Enum;

/**
* Enum LandingTextPosition.
*
* Defines the placement of the landing page hero headline/subtitle/CTA.
* Deliberately not a reuse of AlbumTitlePosition: albums and the landing
* page are different bounded contexts.
*/
enum LandingTextPosition: string
{
case TOP_LEFT = 'top_left';
case TOP_RIGHT = 'top_right';
case BOTTOM_LEFT = 'bottom_left';
case BOTTOM_RIGHT = 'bottom_right';
case CENTER = 'center';
}
91 changes: 91 additions & 0 deletions app/Http/Controllers/Admin/LandingFeaturedItemController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

/**
* SPDX-License-Identifier: MIT
* Copyright (c) 2017-2018 Tobias Reich
* Copyright (c) 2018-2026 LycheeOrg.
*/

namespace App\Http\Controllers\Admin;

use App\Http\Requests\LandingFeaturedItem\DestroyLandingFeaturedItemRequest;
use App\Http\Requests\LandingFeaturedItem\IndexLandingFeaturedItemRequest;
use App\Http\Requests\LandingFeaturedItem\PatchLandingFeaturedItemRequest;
use App\Http\Requests\LandingFeaturedItem\ReorderLandingFeaturedItemRequest;
use App\Http\Requests\LandingFeaturedItem\ShowLandingFeaturedItemRequest;
use App\Http\Requests\LandingFeaturedItem\StoreLandingFeaturedItemRequest;
use App\Http\Requests\LandingFeaturedItem\UpdateLandingFeaturedItemRequest;
use App\Http\Resources\Collections\LandingFeaturedItemCollection;
use App\Http\Resources\Models\LandingFeaturedItemResource;
use App\Models\LandingFeaturedItem;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;

class LandingFeaturedItemController extends Controller
{
public function index(IndexLandingFeaturedItemRequest $request): LandingFeaturedItemCollection
{
$landing_featured_items = LandingFeaturedItem::query()->orderBy('sort_order')->orderBy('created_at')->get();

return new LandingFeaturedItemCollection($landing_featured_items);
}

public function store(StoreLandingFeaturedItemRequest $request): LandingFeaturedItemResource
{
$validated = $request->validated();

/** @var LandingFeaturedItem $landing_featured_item */
$landing_featured_item = LandingFeaturedItem::create($validated);

return new LandingFeaturedItemResource($landing_featured_item);
}

public function show(ShowLandingFeaturedItemRequest $request): LandingFeaturedItemResource
{
return new LandingFeaturedItemResource($request->landing_featured_item);
}

public function update(UpdateLandingFeaturedItemRequest $request): LandingFeaturedItemResource
{
$validated = $request->validated();
unset($validated['landing_featured_item_id']);
$request->landing_featured_item->fill($validated)->save();

return new LandingFeaturedItemResource($request->landing_featured_item);
}

public function patch(PatchLandingFeaturedItemRequest $request): LandingFeaturedItemResource
{
$validated = $request->validated();
unset($validated['landing_featured_item_id']);
$request->landing_featured_item->fill($validated)->save();

return new LandingFeaturedItemResource($request->landing_featured_item);
}

public function destroy(DestroyLandingFeaturedItemRequest $request): void
{
$request->landing_featured_item->delete();
}

public function reorder(ReorderLandingFeaturedItemRequest $request): LandingFeaturedItemCollection
{
$existing_ids = LandingFeaturedItem::query()->pluck('id')->sort()->values()->all();
$submitted_ids = collect($request->ids)->sort()->values()->all();

if ($existing_ids !== $submitted_ids) {
throw ValidationException::withMessages(['ids' => 'The submitted ids must be the complete set of existing LandingFeaturedItem ids.']);
}

DB::transaction(function () use ($request): void {
foreach ($request->ids as $index => $id) {
LandingFeaturedItem::query()->whereKey($id)->update(['sort_order' => $index]);
}
});

$landing_featured_items = LandingFeaturedItem::query()->orderBy('sort_order')->orderBy('created_at')->get();

return new LandingFeaturedItemCollection($landing_featured_items);
}
}
91 changes: 91 additions & 0 deletions app/Http/Controllers/Admin/LandingLinkController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

/**
* SPDX-License-Identifier: MIT
* Copyright (c) 2017-2018 Tobias Reich
* Copyright (c) 2018-2026 LycheeOrg.
*/

namespace App\Http\Controllers\Admin;

use App\Http\Requests\LandingLink\DestroyLandingLinkRequest;
use App\Http\Requests\LandingLink\IndexLandingLinkRequest;
use App\Http\Requests\LandingLink\PatchLandingLinkRequest;
use App\Http\Requests\LandingLink\ReorderLandingLinkRequest;
use App\Http\Requests\LandingLink\ShowLandingLinkRequest;
use App\Http\Requests\LandingLink\StoreLandingLinkRequest;
use App\Http\Requests\LandingLink\UpdateLandingLinkRequest;
use App\Http\Resources\Collections\LandingLinkCollection;
use App\Http\Resources\Models\LandingLinkResource;
use App\Models\LandingLink;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;

class LandingLinkController extends Controller
{
public function index(IndexLandingLinkRequest $request): LandingLinkCollection
{
$landing_links = LandingLink::query()->orderBy('sort_order')->orderBy('created_at')->get();

return new LandingLinkCollection($landing_links);
}

public function store(StoreLandingLinkRequest $request): LandingLinkResource
{
$validated = $request->validated();

/** @var LandingLink $landing_link */
$landing_link = LandingLink::create($validated);

return new LandingLinkResource($landing_link);
}

public function show(ShowLandingLinkRequest $request): LandingLinkResource
{
return new LandingLinkResource($request->landing_link);
}

public function update(UpdateLandingLinkRequest $request): LandingLinkResource
{
$validated = $request->validated();
unset($validated['landing_link_id']);
$request->landing_link->fill($validated)->save();

return new LandingLinkResource($request->landing_link);
}

public function patch(PatchLandingLinkRequest $request): LandingLinkResource
{
$validated = $request->validated();
unset($validated['landing_link_id']);
$request->landing_link->fill($validated)->save();

return new LandingLinkResource($request->landing_link);
}

public function destroy(DestroyLandingLinkRequest $request): void
{
$request->landing_link->delete();
}

public function reorder(ReorderLandingLinkRequest $request): LandingLinkCollection
{
$existing_ids = LandingLink::query()->pluck('id')->sort()->values()->all();
$submitted_ids = collect($request->ids)->sort()->values()->all();

if ($existing_ids !== $submitted_ids) {
throw ValidationException::withMessages(['ids' => 'The submitted ids must be the complete set of existing LandingLink ids.']);
}

DB::transaction(function () use ($request): void {
foreach ($request->ids as $index => $id) {
LandingLink::query()->whereKey($id)->update(['sort_order' => $index]);
}
});

$landing_links = LandingLink::query()->orderBy('sort_order')->orderBy('created_at')->get();

return new LandingLinkCollection($landing_links);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/**
* SPDX-License-Identifier: MIT
* Copyright (c) 2017-2018 Tobias Reich
* Copyright (c) 2018-2026 LycheeOrg.
*/

namespace App\Http\Requests\LandingFeaturedItem;

use App\Http\Requests\BaseApiRequest;
use App\Models\LandingFeaturedItem;
use App\Models\User;
use Illuminate\Support\Facades\Auth;

class DestroyLandingFeaturedItemRequest extends BaseApiRequest
{
public LandingFeaturedItem $landing_featured_item;

public function authorize(): bool
{
/** @var User|null */
$user = Auth::user();

return $user?->may_administrate === true;
}

protected function prepareForValidation(): void
{
/** @disregard */
$this->merge(['landing_featured_item_id' => $this->route('landingFeaturedItem')]);
}

public function rules(): array
{
return ['landing_featured_item_id' => ['required', 'string']];
}

protected function processValidatedValues(array $values, array $files): void
{
$this->landing_featured_item = LandingFeaturedItem::findOrFail($values['landing_featured_item_id']);
}
}
Loading
Loading