# Gallery Package - Cursor Rules

## Project Overview

This is the **bongo/gallery** package, part of the Bongo CMS Laravel monorepo. It provides gallery management functionality allowing administrators to create custom image galleries from within the admin panel.

**Package Type:** Laravel CMS Package
**Namespace:** `Bongo\Gallery`
**Dependencies:**
- `bongo/framework` ^3.0 (base functionality)
- `bongo/image` ^3.0 (image management)
- PHP 8.2+
- Laravel 10+

## Key Architecture Patterns

### Service Provider (AbstractServiceProvider Pattern)

The `GalleryServiceProvider` extends `Bongo\Framework\Providers\AbstractServiceProvider`, which provides automatic bootstrapping:

```php
class GalleryServiceProvider extends AbstractServiceProvider
{
    protected string $module = 'gallery';

    public function boot(): void
    {
        parent::boot();
        AliasLoader::getInstance()->alias('Gallery', Gallery::class);
    }
}
```

The `AbstractServiceProvider` automatically registers:
- **Config**: `src/Config/gallery.php` → `config('gallery.*')`
- **Routes**: Files in `src/Routes/` with appropriate middleware
- **Views**: `src/Views/gallery/` → `view('gallery::*')`
- **Migrations**: `src/Migrations/`
- **Translations**: `src/Translations/` → `trans('gallery::*')`

### Route Organization

Routes are automatically registered by `AbstractServiceProvider`:

1. **api.php** → Routes prefixed with `api.gallery.*` with `auth:sanctum` middleware
   - `/api/galleries/{id}` - Image CRUD operations for a gallery

2. **backend.php** → Routes prefixed with `backend.gallery.*` with `auth` + `employee` middleware
   - `/admin/galleries` - Admin CRUD operations
   - `/admin/galleries/datatable` - DataTable JSON endpoint

3. **frontend.php** → Routes prefixed with `frontend.gallery.*`
   - `/galleries/preview/{uuid}` - Gallery preview (requires auth + developer middleware)

### Model Architecture

The `Gallery` model extends `AbstractModel` and uses multiple traits:

```php
class Gallery extends AbstractModel implements Imageable
{
    use SoftDeletes;        // Laravel soft deletes
    use HasKey;             // Unique key field from framework
    use HasImages;          // Polymorphic image relationship from bongo/image
    use HasStatus;          // Status field (pending/active/inactive)
    use HasUUID;            // UUID field generation

    public const PENDING = 'pending';
    public const ACTIVE = 'active';
    public const INACTIVE = 'inactive';
}
```

**Key Relationships:**
- `images()` - Polymorphic many-to-many with `Image` model (via `imageables` pivot table with `sort_order`)

## Directory Structure

```
src/
├── Config/
│   └── gallery.php                    # Configuration (prefix: 'galleries')
├── Events/
│   ├── GalleryDeleted.php             # Event dispatched on deletion
│   └── GalleryUpdated.php             # Event dispatched on update
├── Http/
│   ├── Controllers/
│   │   ├── Api/
│   │   │   └── GalleryController.php  # Image upload/update/delete API
│   │   ├── Backend/
│   │   │   ├── GalleryController.php  # Admin CRUD operations
│   │   │   └── GalleryDatatableController.php  # DataTable JSON endpoint
│   │   └── Frontend/
│   │       └── GalleryController.php  # Gallery preview for developers
│   └── Requests/
│       └── UpdateGalleryRequest.php   # Form validation (name required)
├── Migrations/
│   └── 2021_01_01_000001_create_galleries_table.php
├── Models/
│   └── Gallery.php                    # Main model
├── Routes/
│   ├── api.php                        # API routes (image management)
│   ├── backend.php                    # Admin routes
│   └── frontend.php                   # Frontend routes (preview)
├── Seeders/
│   └── PackageSeeder.php              # Seeds package metadata
├── Translations/
│   └── en/
│       └── backend.php                # Backend translation keys
├── Views/
│   ├── backend/
│   │   ├── index.blade.php            # Gallery list view
│   │   ├── create.blade.php           # Create form
│   │   ├── edit.blade.php             # Edit form
│   │   ├── show.blade.php             # Gallery detail view
│   │   └── partials/
│   │       └── form/
│   │           └── details.blade.php  # Form partial
│   └── frontend/
│       ├── preview.blade.php          # Gallery preview
│       └── partials/
│           └── gallery.blade.php      # Gallery display partial
└── GalleryServiceProvider.php
```

## Coding Conventions

### PHP Standards
- **PHP Version:** 8.2+
- **Type Declarations:** Always use strict types with `declare(strict_types=1);`
- **Return Types:** Always specify return types on methods
- **Property Types:** Always type-hint properties
- **Nullable Types:** Use `?Type` or explicit null unions

### Controller Patterns

#### Backend Controllers (Admin)
```php
class GalleryController extends AbstractController
{
    // Index - returns view with DataTable
    public function index(): View

    // Create - creates empty gallery and redirects to edit
    public function create(): RedirectResponse

    // Show - displays gallery details
    public function show(Gallery $gallery): View

    // Edit - displays edit form
    public function edit(Gallery $gallery): View

    // Update - validates and updates gallery
    public function update(UpdateGalleryRequest $request, Gallery $gallery): RedirectResponse

    // Destroy - soft deletes gallery
    public function destroy(Gallery $gallery): RedirectResponse
}
```

#### API Controllers
```php
class GalleryController extends AbstractApiController
{
    // Return JSON responses
    public function index(int $id): JsonResponse
    public function store(StoreImageRequest $request, int $id): JsonResponse
    public function update(UpdateImageRequest $request, int $id): JsonResponse
    public function destroy(Request $request, int $id): JsonResponse
}
```

#### DataTable Controllers
```php
class GalleryDatatableController extends AbstractDatatableController
{
    protected function getBaseQuery(): Builder
    {
        return $this->gallery->newQuery();
    }
}
```

### Naming Conventions
- **Models:** Singular PascalCase (`Gallery`)
- **Tables:** Plural snake_case (`galleries`)
- **Controllers:** Singular with suffix (`GalleryController`)
- **Routes:** Lowercase plural (`galleries`)
- **Views:** Lowercase singular namespace (`gallery::backend.index`)
- **Config:** Lowercase singular (`gallery.prefix`)

### Event Dispatching
Always dispatch events for significant model changes:
```php
$gallery->update($request->all());
event(new GalleryUpdated($gallery));
```

### Flash Messages
Use framework helper methods on redirect responses:
```php
return redirect()
    ->route('backend.gallery.show', $gallery->id)
    ->success(trans('gallery::backend.update_success'));

return back()->error(trans('gallery::backend.delete_failed'));
```

### Translation Keys
Structure: `{module}::{context}.{key}`
```php
trans('gallery::backend.store_success')
trans('gallery::backend.delete_failed')
```

## Common Tasks

### Adding a New Field to Gallery

1. **Create migration:**
```bash
cd /path/to/cms/gallery
php artisan make:migration add_field_to_galleries_table
```

2. **Update model:**
```php
// Add to $fillable array in Gallery.php
protected $fillable = [
    'name',
    'status',
    'new_field',
];
```

3. **Update validation:**
```php
// Update UpdateGalleryRequest.php
public function rules(): array
{
    return [
        'name' => 'required',
        'new_field' => 'nullable|string',
    ];
}
```

4. **Update views:**
- Add form field to `src/Views/backend/partials/form/details.blade.php`
- Display in `src/Views/backend/show.blade.php`

### Creating a New Controller Method

1. Add method to appropriate controller
2. Add route to appropriate route file
3. Add translation keys if needed
4. Test the endpoint

### Adding a New Event

1. Create event class in `src/Events/`
2. Dispatch in controller or model observer
3. Create listener if needed (register in service provider)

## Testing

Run tests from package root:
```bash
vendor/bin/phpunit
```

## Code Style

Fix code style with Laravel Pint:
```bash
# Check style
vendor/bin/pint --test

# Fix style
vendor/bin/pint
```

## Framework Integration Points

### From bongo/framework:
- `AbstractServiceProvider` - Base service provider with auto-registration
- `AbstractController` - Base controller with helper methods
- `AbstractApiController` - Base API controller
- `AbstractDatatableController` - Base DataTable controller
- `AbstractModel` - Base model with audit fields
- `HasKey` - Trait for unique key field
- `HasStatus` - Trait for status field management
- `HasUUID` - Trait for UUID generation
- `File::generateName()` - Unique filename generation

### From bongo/image:
- `Imageable` interface - Contract for models with images
- `HasImages` trait - Polymorphic image relationships
- `Image` model - Image entity
- `StoreImageRequest` - Image upload validation
- `UpdateImageRequest` - Image update validation

## Configuration

**Config file:** `src/Config/gallery.php`

```php
return [
    'prefix' => 'galleries',  // URL prefix for all routes
];
```

Access via: `config('gallery.prefix')`

## Database Schema

**Table:** `galleries`

| Column | Type | Description |
|--------|------|-------------|
| id | increments | Primary key |
| uuid | uuid | Unique identifier for public URLs |
| name | string | Gallery name |
| key | string | Unique key for programmatic access |
| status | enum | pending/active/inactive |
| created_by | unsigned int | User ID who created |
| updated_by | unsigned int | User ID who last updated |
| deleted_by | unsigned int | User ID who deleted |
| created_at | timestamp | Creation timestamp |
| updated_at | timestamp | Last update timestamp |
| deleted_at | timestamp | Soft delete timestamp |

**Pivot Table:** `imageables` (polymorphic relationship)

| Column | Type | Description |
|--------|------|-------------|
| image_id | unsigned int | Foreign key to images table |
| imageable_id | unsigned int | Foreign key to galleries table |
| imageable_type | string | 'Bongo\Gallery\Models\Gallery' |
| sort_order | int | Order of images in gallery |

## Key Features

1. **Gallery CRUD:** Create, read, update, delete galleries via admin panel
2. **Image Upload:** Upload images via API with file handling and dimension detection
3. **Image Management:** Update image titles and sort order within galleries
4. **Image Deletion:** Delete images with file system cleanup
5. **File Renaming:** Rename image files with database content replacement across multiple tables
6. **DataTables:** Server-side DataTable support for gallery listing
7. **Preview:** Developer-only gallery preview functionality
8. **Soft Deletes:** Galleries can be soft deleted and restored
9. **Events:** GalleryUpdated and GalleryDeleted events for integration
10. **Status Management:** Pending/Active/Inactive status workflow

## Important Notes

- The API controller handles image operations (upload/update/delete), not gallery CRUD
- Backend controller handles gallery CRUD operations
- Image file renaming updates content in pages, posts, projects, and categories tables
- Preview route requires authentication and developer role
- Images are stored in `config('image.public_path').'uploads/'`
- The `Gallery` facade is aliased in the service provider
- All routes use the configurable prefix from `gallery.prefix` config
