# Product Updates Code Standards

**Last Updated**: 2025-11-20  
**Status**: Production Ready ✅

## Overview

This document defines coding conventions, naming patterns, file organization, and best practices for the Product Updates CMS system. Follow these standards to maintain code quality and consistency.

## PHP Standards

### Code Style

**Indentation**: 4 spaces (no tabs)

**Line Length**: Maximum 120 characters (soft limit)

**Braces**: Opening brace on same line for functions/classes, new line for control structures

```php
// Functions
function exampleFunction($param) {
    // Code
}

// Control structures
if ($condition) {
    // Code
} else {
    // Code
}
```

### Naming Conventions

**Functions**: camelCase

```php
function findWritableDataFile() { }
function sanitizeHtmlInput($html) { }
```

**Variables**: camelCase

```php
$updatesData = [];
$currentMonthSlug = '';
$featureImage = '';
```

**Constants**: UPPER_SNAKE_CASE

```php
define('ADMIN_VERSION', '2025.11.19.3');
define('PRODUCT_UPDATES_AUTO_REGENERATE_DISABLED', true);
```

**Arrays**: Descriptive names, plural for collections

```php
$allMonths = [];
$bigFeatures = [];
$imageDirectories = [];
```

### File Organization

**Structure**:

- Functions at top of file
- Configuration constants
- Main logic
- HTML output

**Includes**:

- Always use `require_once` for critical includes
- Use `include` for optional includes
- Use absolute paths when possible

### Error Handling

**Pattern**:

```php
try {
    // Operation
} catch (Exception $e) {
    error_log('[Product Updates] Error: ' . $e->getMessage());
    // User-friendly error
    return false;
}
```

**Never Use**:

- `@` operator to suppress errors
- Empty catch blocks
- Silent failures

### Input Sanitization

**Always Sanitize**:

```php
// Text input
$title = sanitizeInput($_POST['title'] ?? '');

// HTML input
$description = sanitizeHtmlInput($_POST['description'] ?? '');

// Output
echo htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
```

**Functions**:

- `sanitizeInput()` - Plain text
- `sanitizeHtmlInput()` - HTML content (admin)
- `sanitizeHtmlOutput()` - HTML output (public)

### File Operations

**Atomic Writes**:

```php
$temp_file = $file . '.tmp';
file_put_contents($temp_file, $data, LOCK_EX);
// Verify integrity
if (file_get_contents($temp_file) === $data) {
    rename($temp_file, $file); // Atomic
}
```

**Directory Creation**:

```php
if (!is_dir($dir)) {
    if (!mkdir($dir, 0755, true)) {
        error_log('[Product Updates] Failed to create directory: ' . $dir);
        return false;
    }
}
```

## JavaScript Standards

### Code Style

**Indentation**: 2 spaces

**Line Length**: Maximum 100 characters

**Variables**: camelCase

```javascript
const updatesData = {};
let currentMonthSlug = "";
const featureImage = "";
```

**Functions**: camelCase

```javascript
function findWritableDataFile() {}
function sanitizeHtmlInput(html) {}
```

### Alpine.js Patterns

**Data Initialization**:

```javascript
x-data="{
    isOpen: false,
    items: [],
    searchQuery: ''
}"
```

**Methods**:

```javascript
x-init="init()"
@click="toggleModal()"
x-show="isOpen"
```

**Best Practices**:

- Use `$root` for parent scope access
- Avoid global variables
- Use Alpine.js reactivity properly

### Error Handling

**Pattern**:

```javascript
try {
  const response = await fetch(url);
  const data = await response.json();
  if (!data.success) {
    throw new Error(data.message);
  }
  return data;
} catch (error) {
  console.error("Error:", error);
  showToast("error", "Error", error.message);
  return null;
}
```

**Never Use**:

- `console.log()` in production code
- `console.error()` in production code
- `console.warn()` in production code
- Use structured logger if logging needed

## CSS Standards

### Naming Conventions

**Classes**: kebab-case

```css
.admin-container {
}
.feature-card {
}
.month-list-item {
}
```

**Variables**: kebab-case

```css
:root {
  --ordio-blue: #4d8ef3;
  --gray-800: #1f2937;
  --border-radius: 0.5rem;
}
```

### Organization

**Structure**:

- Reset/normalize
- Variables
- Base styles
- Component styles
- Utility classes

**Responsive Design**:

- Mobile-first approach
- Use Tailwind CSS utilities when possible
- Custom CSS for complex components

## File Naming

### PHP Files

**Pattern**: `kebab-case.php`

```
produkt-updates-upload.php
serve-produkt-updates-image.php
produkt-updates-diagnostics.php
```

### JavaScript Files

**Pattern**: `kebab-case.js`

```
produkt-updates-admin.js
image-upload-handler.js
```

### CSS Files

**Pattern**: `kebab-case.css`

```
produkt-updates-admin.css
produkt-updates-public.css
```

## Documentation Standards

### Function Documentation

**Pattern**:

```php
/**
 * Brief description
 *
 * Longer description if needed
 *
 * @param string $param Parameter description
 * @return string Return description
 */
function exampleFunction($param) {
    // Implementation
}
```

### Inline Comments

**When to Comment**:

- Complex logic
- Non-obvious code
- Workarounds
- TODO items

**Pattern**:

```php
// Check if directory exists and is writable
if (is_dir($dir) && is_writable($dir)) {
    // Use this location
    return $dir;
}
```

## Security Standards

### Input Validation

**Always Validate**:

- Required fields
- Data types
- Formats (email, URL, date)
- File uploads (type, size, dimensions)

**Pattern**:

```php
// Validate required
if (empty($title)) {
    return ['error' => 'Title is required'];
}

// Validate type
if (!is_string($title)) {
    return ['error' => 'Invalid title type'];
}

// Validate format
if (!preg_match('/^[a-z0-9\-]+$/', $slug)) {
    return ['error' => 'Invalid slug format'];
}
```

### Output Escaping

**Always Escape**:

- HTML output: `htmlspecialchars($text, ENT_QUOTES, 'UTF-8')`
- HTML attributes: `htmlspecialchars($value, ENT_QUOTES, 'UTF-8')`
- URLs: `urlencode($url)`
- JSON: `json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)`

### File Upload Security

**Required Checks**:

- MIME type validation
- File extension validation
- File size limits
- Dimension limits
- Image integrity check

**Pattern**:

```php
// Check MIME type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $file['tmp_name']);
if (!in_array($mime_type, $allowed_types)) {
    return ['error' => 'Invalid file type'];
}

// Check dimensions
$image_info = getimagesize($file['tmp_name']);
if ($image_info[0] > 4000 || $image_info[1] > 4000) {
    return ['error' => 'Image too large'];
}
```

## Performance Standards

### Database Queries

**Not Applicable**: System uses JSON files, not database

### File Operations

**Best Practices**:

- Load JSON once per request
- Cache processed data in memory
- Use atomic writes
- Minimize file system operations

### Image Optimization

**Required**:

- Resize to max 1920x1920px
- Compress (JPEG: 85, PNG: 6)
- Convert to WebP when possible
- Lazy load below-fold images

### Code Optimization

**Best Practices**:

- Avoid unnecessary loops
- Use efficient data structures
- Minimize external API calls
- Profile performance-critical code

## Testing Standards

### Test Coverage

**Required Tests**:

- All CRUD operations
- Image upload and optimization
- Path resolution logic
- Error handling
- Edge cases

### Test Endpoints

**Use Test Endpoints**:

- Comprehensive test: `/v2/admin/produkt-updates/comprehensive-production-test.php`
- Storage health: `/v2/api/produkt-updates-storage-health.php`
- Diagnostics: `/v2/api/produkt-updates-diagnostics.php`

## Related Documentation

- [Development Guide](./PRODUCT_UPDATES_DEVELOPMENT_GUIDE.md) - Development procedures
- [Testing](./PRODUCT_UPDATES_TESTING.md) - Testing standards
- [Troubleshooting](./PRODUCT_UPDATES_TROUBLESHOOTING.md) - Common issues
