Apply strict_types and extensive type declarations throughout the API and models, improving type safety and error handling. Key changes: add declare(strict_types=1) to many files; convert properties, method parameters and return values to typed signatures (PDO, arrays, ints, strings, bools, nullables); switch exception handling to Throwable in index and Router; improve Router, controllers and model method signatures and nullability handling; refine file/image serving security checks and headers in ImageController; strengthen Database typing and initialization methods; return explicit types from BaseModel CRUD helpers and counting; update Media/Cast/Adult/Game/Console/Settings controllers and models to use typed methods, better validation, and clearer update/create return types. Also add AGENTS.md (agent skills index), update README with Swagger/OpenAPI usage instructions, and add /.windsurf to .gitignore. These changes aim to harden runtime correctness, make intended contracts explicit, and prepare the codebase for easier maintenance and static analysis.
363 lines
8.9 KiB
Markdown
363 lines
8.9 KiB
Markdown
# Kyoo Backend
|
|
|
|
A RESTful API backend for media management, supporting movies, TV series, music albums, games, and cast information.
|
|
|
|
## Features
|
|
|
|
- **Media Management**: CRUD operations for movies, TV series, music albums, and games
|
|
- **Cast Management**: Manage actors, directors, and other staff with filmography tracking
|
|
- **Image Handling**: Automatic processing and storage of posters, banners, and cast photos
|
|
- **Search & Filtering**: Advanced search with pagination support
|
|
- **API Logging**: Built-in request/response logging for debugging
|
|
- **Docker Support**: Easy deployment with Docker Compose
|
|
- **Auto Documentation**: Self-documenting API endpoint
|
|
|
|
## Tech Stack
|
|
|
|
- **PHP 8.2** with Apache
|
|
- **MariaDB 10.11**
|
|
- **Docker & Docker Compose**
|
|
- **phpMyAdmin** for database management
|
|
|
|
## Quick Start
|
|
|
|
### Prerequisites
|
|
|
|
- Docker installed
|
|
- Docker Compose installed
|
|
|
|
### Installation
|
|
|
|
1. Clone the repository:
|
|
```bash
|
|
git clone <repository-url>
|
|
cd kyoobackend
|
|
```
|
|
|
|
2. Start the services:
|
|
```bash
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
3. Access the API:
|
|
- API Base URL: `http://localhost:6400/api`
|
|
- phpMyAdmin: `http://localhost:6402`
|
|
|
|
### Database Credentials
|
|
|
|
- **Host**: `mariadb` (within Docker) or `localhost:6401` (from host)
|
|
- **Database**: `kyoo`
|
|
- **User**: `kyoo_user`
|
|
- **Password**: `kyoo_password`
|
|
- **Root Password**: `root_password`
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
kyoobackend/
|
|
├── api/
|
|
│ ├── controllers/ # Request handlers
|
|
│ │ ├── MediaController.php
|
|
│ │ ├── CastController.php
|
|
│ │ ├── ImageController.php
|
|
│ │ └── SettingsController.php
|
|
│ ├── models/ # Data models
|
|
│ │ ├── Media.php
|
|
│ │ ├── Cast.php
|
|
│ │ ├── Game.php
|
|
│ │ ├── Series.php
|
|
│ │ ├── Music.php
|
|
│ │ └── ...
|
|
│ ├── services/ # Business logic
|
|
│ │ ├── ApiLogger.php
|
|
│ │ ├── ImageHandler.php
|
|
│ │ └── DocumentationService.php
|
|
│ ├── config.php # Configuration
|
|
│ ├── database.php # Database connection
|
|
│ ├── Router.php # API routing
|
|
│ └── index.php # Entry point
|
|
├── docker-compose.yml # Docker configuration
|
|
├── Dockerfile # PHP container build
|
|
└── php-custom.ini # PHP configuration
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
### Root
|
|
- `GET /api` - API information and available endpoints
|
|
|
|
### Documentation
|
|
- `GET /api/docs` - Auto-generated API documentation
|
|
|
|
### Media
|
|
- `GET /api/media` - Get all media (with pagination and filtering)
|
|
- `GET /api/media/:id` - Get specific media item
|
|
- `POST /api/media` - Create new media
|
|
- `PUT /api/media/:id` - Update media
|
|
- `DELETE /api/media/:id` - Delete media
|
|
|
|
### Series Episodes
|
|
- `GET /api/media/:id/episodes` - Get all episodes for a series
|
|
- `GET /api/media/:id/episodes/:episodeId` - Get specific episode
|
|
- `POST /api/media/:id/episodes` - Add episode to series
|
|
- `PUT /api/media/:id/episodes/:episodeId` - Update episode
|
|
- `DELETE /api/media/:id/episodes/:episodeId` - Delete episode
|
|
|
|
### Music Tracks
|
|
- `GET /api/media/:id/tracks` - Get all tracks for an album
|
|
- `GET /api/media/:id/tracks/:trackId` - Get specific track
|
|
- `POST /api/media/:id/tracks` - Add track to album
|
|
- `PUT /api/media/:id/tracks/:trackId` - Update track
|
|
- `DELETE /api/media/:id/tracks/:trackId` - Delete track
|
|
|
|
### Cast
|
|
- `GET /api/cast` - Get all cast members (with search)
|
|
- `GET /api/cast/:id` - Get specific cast member with filmography
|
|
- `GET /api/cast/:id/media` - Get all media for a cast member
|
|
- `POST /api/cast` - Create new cast member
|
|
- `PUT /api/cast/:id` - Update cast member
|
|
- `DELETE /api/cast/:id` - Delete cast member
|
|
|
|
### Adult Cast
|
|
- `GET /api/cast/adult` - Get all adult cast members (with filters)
|
|
- `GET /api/cast/adult/:id` - Get specific adult cast member
|
|
- `POST /api/cast/adult` - Create new adult cast member
|
|
- `PUT /api/cast/adult/:id` - Update adult cast member
|
|
- `DELETE /api/cast/adult/:id` - Delete adult cast member
|
|
|
|
### Images
|
|
- `GET /api/images/*` - Serve images directly
|
|
|
|
### Settings
|
|
- `GET /api/settings` - Get application settings
|
|
- `PUT /api/settings` - Update settings
|
|
|
|
## Query Parameters
|
|
|
|
### Media List
|
|
- `page` - Page number (default: 1)
|
|
- `limit` - Items per page (default: 20)
|
|
- `category` - Filter by category (e.g., "movie", "tv", "music", "game")
|
|
- `type` - Filter by type (e.g., "Movie", "TV", "Album", "Game")
|
|
- `search` - Search in title and description
|
|
|
|
### Cast List
|
|
- `page` - Page number (default: 1)
|
|
- `limit` - Items per page (default: 20)
|
|
- `search` - Search by name
|
|
|
|
### Adult Cast List
|
|
- `page` - Page number (default: 1)
|
|
- `limit` - Items per page (default: 20)
|
|
- `search` - Search by name
|
|
- `ethnicity` - Filter by ethnicity
|
|
- `hair_color` - Filter by hair color
|
|
|
|
### Series Episodes
|
|
- `season` - Filter by season number
|
|
|
|
## Data Models
|
|
|
|
### Media
|
|
```json
|
|
{
|
|
"id": 1,
|
|
"title": "Movie Title",
|
|
"cleanname": "movie-title",
|
|
"year": 2024,
|
|
"poster": "/images/movies/poster_xxx.webp",
|
|
"banner": "/images/movies/banner_xxx.webp",
|
|
"description": "Description text",
|
|
"rating": 8.5,
|
|
"category": "movie",
|
|
"type": "Movie",
|
|
"status": "released",
|
|
"aspectRatio": "16:9",
|
|
"runtime": 120,
|
|
"director": "Director Name",
|
|
"writer": "Writer Name",
|
|
"source": "netflix",
|
|
"releaseDate": "2024-01-01",
|
|
"genres": ["Action", "Drama"],
|
|
"tags": ["tag1", "tag2"],
|
|
"studios": ["Studio1"],
|
|
"staff": [
|
|
{
|
|
"id": 1,
|
|
"name": "Actor Name",
|
|
"role": "Actor",
|
|
"characterName": "Character",
|
|
"characterImage": "/images/characters/char_xxx.webp"
|
|
}
|
|
],
|
|
"createdAt": "2024-01-01 00:00:00",
|
|
"updatedAt": "2024-01-01 00:00:00"
|
|
}
|
|
```
|
|
|
|
### Cast
|
|
```json
|
|
{
|
|
"id": 1,
|
|
"name": "Actor Name",
|
|
"cleanname": "actor-name",
|
|
"photo": "/images/cast/photo_xxx.webp",
|
|
"bio": "Biography text",
|
|
"birthDate": "1990-01-01",
|
|
"birthPlace": "City, Country",
|
|
"occupations": ["Actor", "Director"],
|
|
"filmography": [
|
|
{
|
|
"id": 1,
|
|
"title": "Movie Title",
|
|
"year": 2024,
|
|
"poster": "/images/movies/poster_xxx.webp",
|
|
"category": "movie",
|
|
"type": "Movie",
|
|
"role": "Actor",
|
|
"characterName": "Character"
|
|
}
|
|
],
|
|
"createdAt": "2024-01-01 00:00:00",
|
|
"updatedAt": "2024-01-01 00:00:00"
|
|
}
|
|
```
|
|
|
|
## Response Format
|
|
|
|
All responses follow this structure:
|
|
|
|
### Success
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": { ... }
|
|
}
|
|
```
|
|
|
|
### Error
|
|
```json
|
|
{
|
|
"success": false,
|
|
"error": "Error message"
|
|
}
|
|
```
|
|
|
|
### Paginated List
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"items": [ ... ],
|
|
"total": 100,
|
|
"page": 1,
|
|
"limit": 20,
|
|
"totalPages": 5
|
|
}
|
|
}
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Environment variables can be set in `docker-compose.yml` or as system environment variables:
|
|
|
|
- `DB_HOST` - Database host (default: `mariadb`)
|
|
- `DB_NAME` - Database name (default: `kyoo`)
|
|
- `DB_USER` - Database user (default: `kyoo_user`)
|
|
- `DB_PASS` - Database password (default: `kyoo_password`)
|
|
- `API_LOGGING_ENABLED` - Enable API logging (default: `false`)
|
|
|
|
## Docker Commands
|
|
|
|
### Start services
|
|
```bash
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
### Stop services
|
|
```bash
|
|
docker-compose down
|
|
```
|
|
|
|
### View logs
|
|
```bash
|
|
# All logs
|
|
docker-compose logs
|
|
|
|
# Specific service
|
|
docker-compose logs php
|
|
docker-compose logs mariadb
|
|
```
|
|
|
|
### Reset database
|
|
```bash
|
|
docker-compose down -v
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
## Development
|
|
|
|
The API files are mounted as volumes, so changes are immediately reflected without rebuilding.
|
|
|
|
### API Logging
|
|
|
|
Logs are written to:
|
|
- API requests/responses: `/var/www/html/logs/api.log`
|
|
- PHP errors: `/var/www/html/logs/php_error.log`
|
|
|
|
Enable logging by setting `API_LOGGING_ENABLED=true`.
|
|
|
|
## Troubleshooting
|
|
|
|
### PHP container won't start
|
|
```bash
|
|
docker-compose logs php
|
|
```
|
|
|
|
### Database connection errors
|
|
Check if MariaDB is running:
|
|
```bash
|
|
docker-compose ps
|
|
```
|
|
|
|
### Tables not created
|
|
Tables are auto-created on first API call. Check logs:
|
|
```bash
|
|
docker-compose logs php
|
|
```
|
|
|
|
## Swagger/OpenAPI Documentation
|
|
|
|
A Swagger/OpenAPI specification file is included at `swagger.json` in the project root. This file can be used with Swagger UI to interactively test the API.
|
|
|
|
### Using Swagger UI
|
|
|
|
#### Option 1: Online Swagger Editor
|
|
1. Go to [https://editor.swagger.io](https://editor.swagger.io)
|
|
2. Import the `swagger.json` file
|
|
3. Click "Try it out" to test endpoints
|
|
|
|
#### Option 2: Docker with Swagger UI
|
|
```bash
|
|
docker run -p 8080:8080 -e SWAGGER_JSON=/swagger/swagger.json -v $(pwd):/swagger swaggerapi/swagger-ui
|
|
```
|
|
Then access at: http://localhost:8080
|
|
|
|
#### Option 3: Local Swagger UI
|
|
1. Download Swagger UI from [https://github.com/swagger-api/swagger-ui](https://github.com/swagger-api/swagger-ui)
|
|
2. Extract and open `dist/index.html`
|
|
3. Modify the URL to point to your `swagger.json` file
|
|
|
|
### API Endpoints Covered
|
|
- Root endpoints (API info, auto-docs)
|
|
- Media CRUD operations
|
|
- Series episodes CRUD operations
|
|
- Music tracks CRUD operations
|
|
- Cast CRUD operations
|
|
- Adult cast CRUD operations
|
|
- Settings operations
|
|
|
|
## License
|
|
|
|
[Add your license here]
|