# نکات پیاده‌سازی — تسک ۰۴: ماژول بلاگ

## نگاشت فیلدهای Request → Response (مهم!)

در Drupal نام فیلدهای **ارسالی** با نام فیلدهای **دریافتی** متفاوت است:

| فیلد در Request | فیلد در Response | توضیح |
|----------------|-----------------|-------|
| `label` | `title` | عنوان مقاله |
| `description` (string) | `body: {value, format}` | متن مقاله — در response به object تبدیل می‌شود |
| `field_image: [{target_id}]` | `images: [{url, fid, filename, filemime, filesize}]` | تصاویر — ID ارسال، object دریافت |
| — | `author` | نام نویسنده (computed از realname کاربر) |
| — | `uuid` | شناسه یکتا |
| — | `status` | وضعیت انتشار (string: "1") |
| — | `created` / `changed` | Unix timestamp به صورت string |

## فرمت واقعی Response بلاگ (از سرور Drupal — endpoint 93)
```json
{
  "uuid": "95f6acb0-3331-4141-801e-004e8460edac",
  "title": "روش های خانگی محافظت از پوست در تابستان",
  "status": "1",
  "body": {
    "value": "متن کامل مقاله...",
    "format": "full_html"
  },
  "created": "1763536163",
  "changed": "1763537699",
  "author": "single doctor",
  "images": [
    {
      "url": "https://domain.com/sites/default/files/blog/image.png",
      "fid": "97",
      "filename": "image.png",
      "filemime": "image/png",
      "filesize": 320787
    }
  ],
  "tag": [
    {
      "uuid": "24926497-fc2d-47d7-82ae-26cbbc4d6468",
      "id": "2501",
      "name": "مجله"
    },
    {
      "uuid": "6c6a488b-1051-43a2-887b-0ec7a05e52d5",
      "id": "2500",
      "name": "سلامتی"
    }
  ]
}
```

> **نکات مهم response:**
> - `body` یک **object** است با کلیدهای `value` و `format` — نه string ساده!
> - `format` معمولاً `"full_html"` یا `"basic_html"` است
> - `author` از `realname` کاربر نویسنده computed می‌شود
> - `created` و `changed` به صورت **string** برگردانده می‌شوند (نه integer)
> - `status` به صورت string `"1"` برگردانده می‌شود (نه boolean)
> - `images` و `tag` ممکن است آرایه خالی `[]` باشند
> - response دارای `id` نیست — فقط `uuid`

## فرمت Request ایجاد/ویرایش بلاگ

### POST /api/v1/blog/
```json
{
  "label": "عنوان مقاله",
  "description": "متن کامل مقاله...",
  "field_image": [
    { "target_id": 97 },
    { "target_id": 98 }
  ]
}
```

### PATCH /api/v1/blog/{uuid}
```json
{
  "label": "عنوان ویرایش‌شده",
  "description": "متن ویرایش‌شده"
}
```

## آپلود تصویر بلاگ (endpoint 99)
قبل از ایجاد بلاگ، تصویر باید آپلود شود و `fid` آن در `field_image` استفاده شود:

```
POST /file/upload/blog/blog/field_image
Headers:
  Content-Type: application/octet-stream
  Content-Disposition: file; filename="image.png"
  X-CSRF-Token: {token}
  Authorization: Bearer {token}
Response → fid که در field_image استفاده می‌شود
```

## تولید Slug
- از عنوان فارسی slug تولید کن
- پکیج `cocur/slugify` را نصب کن:
  ```bash
  ddev composer require cocur/slugify
  ```
- اگر slug تکراری بود، عدد به انتهای آن اضافه کن: `rahnamai-diabet-2`

## بلاگ‌های برتر (Top Blogs)
- endpoint: `GET /api/v1/blogs/top` (نیاز به auth دارد)
- پاسخ: آرایه مستقیم (نه object با pagination) از بلاگ‌هایی که `is_top = 1` هستند
- فرمت هر آیتم دقیقاً مشابه response معمولی بلاگ است

## لیست بلاگ‌ها با فیلتر
```
GET /api/v1/blogs?page=1&limit=10&title=نشانه&tag=3637
```
- `title`: جستجو در عنوان
- `tag`: فیلتر بر اساس ID تگ

## Pagination
```php
$offset = ($page - 1) * $limit;
// در Repository با limit/offset
```

## مجوزها
```
POST   → احراز هویت الزامی (ROLE_DOCTOR یا ROLE_ADMIN)
PATCH  → احراز هویت الزامی (owner یا ROLE_ADMIN)
DELETE → احراز هویت الزامی (owner یا ROLE_ADMIN)
GET    → عمومی (بدون auth)
GET /api/v1/blogs/top → احراز هویت الزامی
```

## بهینه‌سازی
- view_count با یک query atomic آپدیت کن تا race condition نباشد:
  ```php
  $this->em->createQuery('UPDATE Blog b SET b.viewCount = b.viewCount + 1 WHERE b.id = :id')
      ->setParameter('id', $blog->getId())
      ->execute();
  ```
