لاگ تغییرات

تاریخچه نسخه‌های دیوان قانون

v4.9.1

فعلی


رفع باگ‌های ویرایشگر صفحات

**رفع مودال باز نمی‌شد/بسته نمی‌شد**: کلاس hidden Tailwind با display:flex تداخل داشت. به modal-hidden با !important تغییر یافت.
**رفع URL دوگانه**: تابع peUrl() هنگام URLهایی که已经有 query string داشتند، ? دوگانه تولید می‌کرد (?page=faq?XTransformPort=8000). حالا به‌درستی & اضافه می‌کند.
**رفع خطای «صفحه یافت نشد»** هنگام ایجاد صفحه جدید: redirect URL اصلاح شد.

فایل‌های تغییر یافته

php-cms/resources/views/admin/pages.php — رفع modal CSS + peUrl() URL construction
php-cms/public/update.php — v4.9.1
php-cms/resources/views/layouts/app.php — نسخه ۴.۹.۱

---

v4.9.0



نمایش ساختار کامل صفحه در ویرایشگر

**مشکل قبلی:** ویرایشگر فقط بلوک‌های سفارشی را نشان می‌داد — بلوک‌های پیش‌فرض سایت (هدر، هیرو، آمار و...) نمایش داده نمی‌شدند. کاربر نمی‌توانست ببیند بلوک جدیدش کجا قرار می‌گیرد.

**رفع:** ویرایشگر حالا **ساختار کامل صفحه** را نشان می‌دهد:
**بلوک‌های سیستمی (🔒)**: بخش‌های پیش‌فرض سایت (هدر، فوتر، هیرو، آمار و...) به‌صورت خاکستری و فقط‌خواندنی نمایش داده می‌شوند
**منطقه سفارشی (سبز)**: جایی که بلوک‌های شما قرار می‌گیرند — کاملاً مشخص است کجا در صفحه هستند

برای هر صفحه، بلوک‌های سیستمی متفاوت است:
**صفحه اصلی**: هدر، هیرو، آمار، قانون روز، دسته‌بندی‌ها، قوانین جدید، پربازدید، آمار AI، مواد پربازدید، فوتر
**درباره ما**: هدر، بلوک سفارشی، هیرو، مأموریت، آمار، قابلیت‌ها، چطور کار می‌کند، هشدار، تماس توسعه‌دهنده، فوتر
**تماس با ما**: هدر، بنر، کارت‌های اطلاعات، فرم تماس، فوتر
**صفحه قانون**: هدر، بلوک سفارشی، هدر قانون، مقدمه، کنترل فونت، فهرست مواد، مواد، چتبات، مرتبط، نظرات، فوتر

ایجاد صفحات جدید

دکمه «صفحه جدید» در بالای ویرایشگر
وارد کردن عنوان + آدرس (slug) صفحه
صفحه در آدرس /page/{slug} قابل دسترس می‌شود
صفحات سفارشی با علامت ✦ در تب‌ها متمایز می‌شوند

ویرایش عنوان و آدرس صفحات سفارشی

برای صفحات سفارشی، دکمه «ویرایش عنوان/آدرس» و «حذف صفحه» نمایش داده می‌شود
تغییر آدرس (slug) → تمام بلوک‌های صفحه هم به‌روزرسانی می‌شوند

فایل‌های تغییر یافته

php-cms/resources/views/admin/pages.php — بازنویسی کامل با system blocks + new/rename/delete page
php-cms/resources/views/custom-page.php ← **جدید** — رندر صفحات سفارشی
php-cms/app/routes_admin.php — مسیر /admin/pages/manage برای create/rename/delete
php-cms/public/index.php — مسیر /page/{slug} برای صفحات سفارشی
php-cms/public/update.php — v4.9.0
php-cms/resources/views/layouts/app.php — نسخه ۴.۹.۰

---


---

v4.8.0



رفع بلوک‌های صفحه اصلی + صفحه قانون

**مشکل:** بلوک‌هایی که در ویرایشگر برای صفحه «home» اضافه می‌شدند نمایش داده نمی‌شدند — چون home.php و law-detail.php متد PageBlocks::render() را فراخوانی نمی‌کردند.

**رفع:**
home.phpPageBlocks::render('home') اضافه شد (در بالای صفحه، قبل از Hero)
law-detail.phpPageBlocks::render('law-detail') اضافه شد (در بالای صفحه، قبل از هدر قانون)

بازنویسی کامل ویرایشگر صفحات

**مشکل قبلی:**
ویرایشگر خودکار لود نمی‌شد
بلوک‌های اضافه‌شده نمایش داده نمی‌شدند (به‌خاطر مشکل URL fetch)
رابط کاربری شلوغ و نامناسب بود

**رفع:**
**رفع مشکل fetch URLs**: تابع peUrl() اضافه شد که به‌صورت خودکار XTransformPort را به URLهای fetch اضافه می‌کند (در محیط sandbox لازم، در production بی‌تأثیر)
**۶ صفحه قابل ویرایش**: اصلی، درباره ما، تماس با ما، صفحه قانون، جستجو، دسته‌بندی‌ها
**۸ نوع بلوک**: متن، عنوان، ویدیو، تصویر، نقل‌قول، هشدار، کارت اطلاعات، HTML دلخواه
**انتخابگر نوع بلوک بصری**: به‌جای dropdown، گرید از کارت‌های نوع (هر کدام با آیکون)
**پیش‌نمایش زنده**: هر بلوک پیش‌نمایش خودش را نشان می‌دهد (متن، ویدیو، تصویر و...)
**ویرایش inline**: روی ✏️ بزنید → فرم ویرایش در همان کارت باز می‌شود
**دکمه‌های همیشه قابل دیدن**: ↑↓ 👁️ ✏️ 🗑 روی هر بلوک
**نوار زبان صفحه**: تب‌های بالای صفحه برای جابه‌جایی بین صفحات
**Toast notifications**: پیام موفقیت/خطا به‌صورت浮动

تست‌ها

| Test | Result |
|------|--------|
| Homepage renders PageBlocks | ✓ PageBlocks::render('home') |
| Law detail renders PageBlocks | ✓ PageBlocks::render('law-detail') |
| Page editor auto-loads blocks | ✓ |
| Add block via UI | ✓ (3 blocks after add) |
| Delete block via UI | ✓ (2 blocks after delete) |
| Inline edit toggles | ✓ |
| 6 page tabs visible | ✓ |
| 8 block type buttons | ✓ |
| Fetch URLs work with XTransformPort | ✓ peUrl() helper |

فایل‌های تغییر یافته

php-cms/resources/views/home.php — افزودن PageBlocks::render('home')
php-cms/resources/views/law-detail.php — افزودن PageBlocks::render('law-detail')
php-cms/resources/views/admin/pages.php — **بازنویسی کامل** با peUrl() fix + UI بهبودیافته
php-cms/public/update.php — v4.8.0
php-cms/resources/views/layouts/app.php — نسخه ۴.۸.۰
php-cms/CHANGELOG.md — لاگ v4.8.0

---

v4.7.0



رفع شمارش مواد در پنل ادمین

پنل ادمین (داشبورد) از COUNT(*) استفاده می‌کرد که شامل ردیف‌های تکراری بود.
حالا از Settings::liveArticleCount() (DISTINCT) استفاده می‌کند — همان روش صفحه اصلی.

ویرایشگر صفحات زنده (Live Editor)

**بازنویسی کامل** ویرایشگر صفحات به‌صورت زنده (inline):

#### ویرایش مستقیم (بدون مودال)
هر بلوک یک کارت است با: پیش‌نمایش زنده + فرم ویرایش inline
روی دکمه ✏️ بزنید → فرم ویرایش باز می‌شود (در همان کارت، نه در مودال)
تغییر عنوان/محتوا → پیش‌نمایش بلافاصله به‌روزرسانی می‌شود
روی 💾 بزنید → ذخیره + رفرش

#### حذف همیشه قابل دسترس
دکمه 🗑 روی هر بلوک همیشه قابل دیدن است
با کلیک روی 🗑 → بلوک بلافاصله حذف می‌شود (بدون نیاز به باز کردن مودال)

#### دکمه‌های کنترل
↑ ↓ : جابه‌جایی بالا/پایین (با drag-reorder در سرور)
👁️/🚫 : فعال/غیرفعال‌کردن بلوک
✏️ : ویرایش inline
🗑 : حذف

#### نوع بلوک جدید: کارت اطلاعات (info_card)
مناسب برای اطلاعات تماس (ایمیل، ساعت، تلفن، آدرس)
محتوا به‌صورت JSON: {"icon":"mail","icon_color":"primary","subtitle":"...","content":"...","link_url":"...","link_text":"..."}
آیکون‌های موجود: mail, clock, phone, location, flag, ai, info
رنگ‌های قابل انتخاب: primary, amber, rose, emerald, sky, violet, gold
پشتیبانی از gradient background

صفحه تماس با ما اکنون قابل ویرایش

۴ بلوک پیش‌فرض برای صفحه تماس ایجاد می‌شود (ایمیل، ساعت، گزارش خطا، هوش مصنوعی)
همه از نوع info_card — قابل ویرایش از پنل ادمین
کد HTML hardcoded در contact.php با PageBlocks::render('contact') جایگزین شد
ایمیل (mailto:)، لینک‌های داخلی (/search) و لینک‌های خارجی همگی پشتیبانی می‌شوند

نتایج تست

| Test | Result |
|------|--------|
| Admin dashboard article count | ✓ Uses Settings::liveArticleCount() |
| Page editor shows 4 contact blocks | ✓ پست الکترونیک، ساعات، گزارش، AI |
| Each block has edit + delete buttons | ✓ Always visible |
| Inline edit form toggles | ✓ ✏️ button opens form inline |
| Contact page renders info cards | ✓ 4 cards from DB |
| Email mailto link works | ✓ mailto:info@divan.qanun |
| Hours display correctly | ✓ "۹:۰۰ تا ۱۷:۰۰" |
| Page selector tabs (about/contact) | ✓ |

فایل‌های تغییر یافته

php-cms/app/Helpers/PageBlocks.php — اضافه شدن renderInfoCard() + رفع لینک‌های mailto/tel
php-cms/app/routes_admin.php — رفع شمارش مواد در داشبورد ادمین
php-cms/public/update.php — v4.7.0 + seed بلوک‌های پیش‌فرض صفحه تماس
php-cms/resources/views/admin/pages.php — **بازنویسی کامل** به ویرایشگر زنده
php-cms/resources/views/contact.php — جایگزینی HTML hardcoded با PageBlocks::render
php-cms/resources/views/layouts/app.php — نسخه ۴.۷.۰

---

v4.6.0



رفع تب‌بندی تنظیمات (تک‌ردیفه)

تنظیمات به ۶ تب تقلیل یافت (تب «مدیریت مواد» حذف شد — کاربر اعلام کرد لازم نیست)
تب‌ها حالا در یک ردیف افقی با اسکرول نازک (thin scrollbar) قرار دارند — دیگر دو ردیفه نیست
flex-wrap: nowrap + overflow-x: auto + flex-shrink: 0 روی هر تب

حذف متن «حساب تست» از فرم ورود

متن حساب تست: admin@divan.qanun / admin123 از صفحه لاگین حذف شد.

کپچای ریاضی (Anti-Spam)

**کلاس جدید App\Helpers\Captcha** — کپچای ریاضی سبک بدون وابستگی خارجی:
سؤال: ۳ + ۷ = ? (با ارقام فارسی)
پاسخ در $_SESSION['captcha_answer'] ذخیره می‌شود
پس از ۵ تلاش ناموفق، کپچا regenerate می‌شود (ضد brute-force)
پشتیبانی از ارقام فارسی و انگلیسی
متد Captcha::field('captcha') برای رندر خودکار

به ۳ فرم اضافه شد:
**لاگین**: /login
**ثبت نام**: /register
**تماس با ما**: /contact

بازطراحی صفحه «درباره ما»

طراحی تمیزتر با فضای سفاداری بیشتر (padding اضافه‌تر)
۹ کارت قابلیت به‌جای ۱۲ (حذف قابلیت‌های تکراری/کم‌اهمیت)
کارت‌های feature با hover-lift effect + shadow نرم
استت‌پیل‌های gradient (به‌جای کارت‌های تیره)
بخش‌های مجزا با backgroundهای متناوب (میکروفون سفید/خاکستری)
بدون overflow افقی

ویرایشگر منوی هدر (WordPress-like)

**قبل:** فیلد متنی با فرمت عنوان|/مسیر در هر خط.
**بعد:** ویرایشگر ساختاریافته با کارت آیتم‌ها:
هر آیتم: عنوان + URL + زیرمنوها
دکمه افزودن/حذف/جابه‌جایی بالا/پایین
زیرمنوها (submenu) برای هر آیتم
ذخیره به‌صورت JSON در header_menu_json
پشتیبانی از لینک‌های خارجی (https://...)
رندر dropdown در دسکتاپ، رندر flat در موبایل

ویرایشگر ستون‌های فوتر (WordPress-like)

**قبل:** ستون‌های ثابت «دسترسی سریع» و «منابع» در فایل کد.
**بعد:** ویرایشگر ساختاریافته:
هر ستون: عنوان + لیست لینک‌ها
افزودن/حذف ستون + افزودن/حذف/جابه‌جایی لینک
ذخیره به‌صورت JSON در footer_columns_json
رندر خودکار در فوتر (با برند سایت به‌عنوان ستون اول)
پشتیبانی از لینک‌های خارجی

ویرایشگر صفحات (CMS) — جدید!

**جدول جدید page_blocks** + کلاس App\Helpers\PageBlocks:
مدیر می‌تواند برای هر صفحه (about, contact, home, law-detail) بلوک‌های محتوای سفارشی اضافه کند
انواع بلوک:
- text — متن (HTML مجاز، sanitized)
- html — کد HTML دلخواه (با احتیاط)
- video — ویدیو از YouTube/Aparat (auto-embed)
- image — تصویر از URL
- heading — عنوان بزرگ
- quote — نقل‌قول (سبک استایل)
- warning — هشدار (پس‌زمینه زرد)
هر بلوک: id, page_key, block_type, title, content, sort_order, is_active
رندر خودکار در بالای صفحه (با PageBlocks::render('about'))

#### مسیرهای ادمین
GET /admin/pages — لیست همه بلوک‌ها (گروه‌بندی بر اساس صفحه)
POST /admin/pages/save — ایجاد/ویرایش بلوک
POST /admin/pages/delete — حذف بلوک
POST /admin/pages/reorder — تغییر ترتیب با drag-reorder

#### رابط کاربری
مودال ایجاد/ویرایش بلوک با فرم کامل
دکمه‌های جابه‌جایی بالا/پایین
نشانگر نوع بلوک (pill رنگی)
پیش‌نمایش محتوای بلوک
راهنمای کلیدهای صفحه معتبر (about, contact, home, law-detail)
افزودن به نوار ناوبری ادمین: «ویرایشگر صفحات»

پشتیبانی از ویدیو

YouTube: youtube.com/watch?v=ID یا youtu.be/ID → auto-embed iframe
Aparat: aparat.com/v/HASH → auto-embed
URLهای نامشخص → لینک قابل‌کلیک

نتایج تست

| Test | Result |
|------|--------|
| Settings tabs single-row | ✓ flex-wrap: nowrap |
| 6 tabs (not 7) | ✓ removed «مدیریت مواد» |
| Login has no demo text | ✓ |
| Captcha renders on login | ✓ |
| Captcha renders on register | ✓ |
| Captcha renders on contact | ✓ |
| About page less crowded | ✓ 9 features (was 12) |
| Header menu editor renders | ✓ items + submenus |
| Footer column editor renders | ✓ columns + links |
| Add header item dynamically | ✓ addHeaderItem() works |
| Page editor /admin/pages works | ✓ renders + saves |
| Create video block → renders on /about | ✓ iframe with youtube embed |

فایل‌های تغییر یافته

php-cms/app/Helpers/Captcha.php ← **جدید** — کپچای ریاضی
php-cms/app/Helpers/PageBlocks.php ← **جدید** — رندر بلوک‌های صفحه
php-cms/app/Helpers/Settings.php — اضافه شدن متدهای JSON برای هدر/فوتر + ثابت‌های پیش‌فرض
php-cms/app/routes_admin.php — ۴ مسیر جدید برای ویرایشگر صفحات + ذخیره‌سازی JSON هدر/فوتر
php-cms/public/index.php — اعتبارسنجی کپچا در login/register/contact
php-cms/public/update.php — migration v4.6.0 (جدول page_blocks) + تنظیمات پیش‌فرض JSON
php-cms/resources/views/admin/settings.php — رفع CSS تب‌ها + حذف تب articles + ویرایشگر ساختاریافته هدر/فوتر
php-cms/resources/views/admin/pages.php ← **جدید** — رابط کاربری ویرایشگر صفحات
php-cms/resources/views/auth/login.php — حذف متن دمو + افزودن کپچا
php-cms/resources/views/auth/register.php — افزودن کپچا
php-cms/resources/views/contact.php — افزودن کپچا
php-cms/resources/views/about.php — بازطراحی کامل + رندر بلوک‌های CMS
php-cms/resources/views/layouts/app.php — هدر با dropdown زیرمنوها + فوتر با ستون‌های سفارشی + لینک ویرایشگر صفحات
php-cms/resources/views/layouts/admin.php — افزودن لینک «ویرایشگر صفحات» به نوار ناوبری
php-cms/CHANGELOG.md — لاگ v4.6.0

---

v4.5.0



رفع پین فهرست مواد (TOC Pin)

**مشکل قبلی:** وقتی روی دکمه «پین فهرست» کلیک می‌کردید، خود لیست مواد هم باز می‌شد که فضای زیادی می‌گرفت.
**رفع:** حالا فقط نوار عنوان «فهرست مواد» پین می‌شود. کاربر روی عنوان کلیک می‌کند تا لیست مواد باز شود.

رفع شمارش مواد در صفحه تنظیمات

**مشکل قبلی:** در ویجت «آمار هوش مصنوعی» در صفحه تنظیمات، تعداد کل مواد از COUNT(*) استفاده می‌شد که شامل ردیف‌های تکراری هم بود.
**رفع:** حالا از COUNT(DISTINCT CONCAT(law_id, '-', number)) استفاده می‌شود (همان روش صفحه اصلی).

صفحه تنظیمات با تب‌بندی کامل (Tabs)

**مشکل قبلی:** همه تنظیمات در یک صفحه بلند به‌صورت پشت سر هم بود که خواندن و پیدا کردن تنظیمات خاص را سخت می‌کرد.
**راه‌حل:** صفحه تنظیمات به ۷ تب مجزا تقسیم شد:
1. **عمومی** — نام سایت، توضیحات، رنگ‌ها، حالت نگهداری
2. **آمار صفحه اصلی** — انتخاب بلوک‌های آماری + اعداد تقریبی
3. **مدیریت مواد** — حذف مواد تکراری + آمار مواد یکتا (با badge وقتی تکراری وجود دارد)
4. **هوش مصنوعی** — فعال‌سازی، ارائه‌دهنده، کلید API، تست اتصال
5. **سئو و گوگل** — Google Search Console، Google Analytics، OpenGraph
6. **هیدر و فوتر** ← جدید
7. **پشتیبان‌گیری** — دانلود فایل دیتابیس

ویژگی‌ها:
تب فعال در localStorage ذخیره می‌شود (بعد از ذخیره و رفرش، همان تب باز می‌شود)
دکمه ذخیره sticky در پایین صفحه (همیشه قابل دسترس)
آیکون هشدار قرمز در تب «مدیریت مواد» وقتی ردیف تکراری وجود دارد
رابط کاربری با انیمیشن fadeIn هنگام تغییر تب
کاملاً responsive (در موبایل افقی اسکرول می‌شود)

سفارشی‌سازی کامل هیدر و فوتر (جدید)

#### منوی هیدر قابل تنظیم
ادمین می‌تواند آیتم‌های منوی هیدر را اضافه/حذف/مرتب کند
فرمت ساده: هر خط یک آیتم با فرمت عنوان|/مسیر (مثلاً دسته‌بندی|/categories)
پشتیبانی از مسیرهای خارجی (مثل https://example.com/blog)
لینک‌های خارجی با target="_blank" باز می‌شوند
هم در منوی دسکتاپ و هم در کشوی موبایل اعمال می‌شود

#### فوتر قابل تنظیم
**متن کپی‌رایت**: قابل تغییر (پیش‌فرض: «ساخته شده با ❤️ برای آگاهی حقوقی شهروندان»)
**اعتبار طراح**: نمایش/عدم نمایش نام طراح و برنامه‌نویس در فوتر
- نقش طراح: «طراح و برنامه‌نویس» (قابل تغییر)
- نام طراح: «حامد بنائی» (پیش‌فرض)
- لینک بله: https://ble.ir/irsalam
- لینک تلگرام: https://t.me/irsalam
لینک‌ها با آیکون تلگرام/بله نمایش داده می‌شوند
هم در دسکتاپ و هم در موبایل به‌صورت واکنش‌گرا

کلاس App\Helpers\Settings — متدهای جدید

headerMenuItems() : array — پارس کردن متن به آرایه آیتم‌های منو
footerCopyright() : string — متن کپی‌رایت
showDesignerCredit() : bool — آیا اعتبار طراح نمایش داده شود
designerName(), designerRole(), designerBale(), designerTelegram() — اطلاعات طراح
ثابت DEFAULT_HEADER_MENU — منوی پیش‌فرض

صفحه «درباره ما» کامل و جامع

صفحه /about بازنویسی کامل شد:
**بنر هیرو** با نام سایت و شعار
**بیانیه مأموریت** — توضیح چرایی و چگونگی
**۴ کارت آماری**: تعداد قوانین، مواد، دسته‌بندی‌ها، برچسب‌ها (لایو از دیتابیس)
**۱۲ کارت قابلیت**: جستجوی هوشمند، تفسیر هوش مصنوعی، چتبات پرسش‌پاسخ، شاخص سختی، ذخیره و یادداشت، دنبال کردن، خط زمانی، مقایسه، گزارش اشتباهات، ارجاع، اشتراک‌گذاری، سئو
**بخش «چطور کار می‌کند»** با ۳ مرحله
**زیرساخت فنی** — PHP 8.5 + FrankenPHP، MySQL/SQLite، Tailwind، GLM-4
**هشدار حقوقی** — این اطلاعات جایگزین مشاوره حقوقی نیست
**CTA تماس با توسعه‌دهنده** در پایین صفحه:
- دکمه «ارتباط در بله» → لینک بله طراح
- دکمه «ارتباط در تلگرام» → لینک تلگرام طراح
- دکمه «فرم تماس» → صفحه تماس
- نام طراح: «حامد بنائی — طراح و برنامه‌نویس»
**SEO کامل** — title، description، canonical، JSON-LD AboutPage schema

تنظیمات جدید (اضافه شده به update.php)

header_menu_items (textarea)
footer_copyright_text (text)
footer_show_designer (checkbox 0/1)
footer_designer_name (text)
footer_designer_role (text)
footer_designer_bale (URL)
footer_designer_telegram (URL)

نتایج تست

| Test | Result |
|------|--------|
| TOC pin: list NOT auto-open | ✓ toc_open: false after pin |
| TOC pin: header sticky | ✓ position: sticky |
| Click pinned header opens list | ✓ toc_open: true |
| Settings page tabbed | ✓ 7 tabs all work |
| Active tab persists in localStorage | ✓ |
| Dedupe badge on «مدیریت مواد» tab | ✓ (when dupArticles > 0) |
| Header menu customizable | ✓ Renders 3+ items |
| Footer designer credit | ✓ Shows حامد بنائی + Bale + Telegram |
| About page comprehensive | ✓ 12 features + 3 steps + contact CTA |
| Save settings persists | ✓ verified via DB query |

فایل‌های تغییر یافته

php-cms/app/Helpers/Settings.php — added 7 new methods for header/footer
php-cms/app/routes_admin.php — added 7 new settings keys + footer_show_designer checkbox handling
php-cms/resources/views/admin/settings.php — **بازنویسی کامل** با ۷ تب
php-cms/resources/views/layouts/app.php — منوی هدر سفارشی + فوتر سفارشی با اعتبار طراح
php-cms/resources/views/law-detail.php — رفع پین TOC (فقط هدر پین می‌شود، نه لیست)
php-cms/resources/views/about.php — **بازنویسی کامل** با ۱۲ قابلیت + CTA تماس با توسعه‌دهنده
php-cms/public/update.php — migration v4.5.0 + ۷ تنظیمات جدید
php-cms/CHANGELOG.md — لاگ v4.5.0

---

v4.4.0



رفع باگ بحرانی شمارش مواد در MySQL

**علت باگ:** کوئری COUNT(DISTINCT law_id || '-' || number) در SQLite درست کار می‌کرد (concat) اما در MySQL || عملگر OR منطقی است، بنابراین به‌جای تعداد واقعی مواد، ۱ یا ۲ برمی‌گرداشت.

**راه‌حل:** همه کوئری‌های || به CONCAT(law_id, '-', number) تغییر یافتند که در هر دو SQLite و MySQL درست کار می‌کند. ۴ مکان اصلاح شد:
Settings::liveArticleCount() — آمار صفحه اصلی
routes_admin.php — dedupe detection (قبل و بعد از حذف)
admin/settings.php — نمایش تعداد مواد یکتا

دکمه‌های اکشن آیکون-فقط در موبایل + Tooltip

دکمه‌های ذخیره/دنبال/مقایسه/چاپ/اشتراک در موبایل فقط آیکون هستند (متن با hidden sm:inline پنهان می‌شود)
وقتی کاربر روی دکمه هاور می‌شود یا کلیک می‌کند، یک Tooltip شناور بالای دکمه ظاهر می‌شود و نام آن را نشان می‌دهد (در موبایل ۲ ثانیه نمایش داده می‌شود)
در دسکتاپ همچنان آیکون + متن نمایش داده می‌شود
هر دکمه data-tooltip attribute دارد که نام فارسی آن را نگه می‌دارد

کنترل اندازه فونت مواد (A- A A+)

۳ دکمه در بالای فهرست مواد اضافه شد: A- (کوچک‌کردن)، A (پیش‌فرض)، A+ (بزرگ‌کردن)
۵ سطح اندازه: خیلی کوچک، کوچک، پیش‌فرض، بزرگ، خیلی بزرگ
انتخاب کاربر در localStorage ذخیره می‌شود و در بازدیدهای بعدی حفظ می‌شود
همزمان با تغییر اندازه فونت، line-height هم بهینه می‌شود
از CSS variables (--article-content-size, --article-line-height) استفاده می‌کند

پین کردن فهرست مواد در موبایل (Sticky TOC)

دکمه «پین فهرست» در موبایل اضافه شد (کنار کنترل فونت)
وقتی کاربر کلیک کند:
- فهرست مواد (<details>) باز می‌شود
- به position: sticky; top: 56px تبدیل می‌شود (زیر هدر سایت)
- هنگام اسکرول، بالای صفحه می‌ماند
- برچسب دکمه به «حذف پین» تغییر می‌کند
- Toast پیام موفقیت نمایش داده می‌شود
با کلیک مجدد، پین حذف می‌شود
فقط در موبایل قابل مشاهده است (در دسکتاپ فهرست از قبل sticky است)

سیستم سئوی کامل (SEO)

**کلاس App\Helpers\SEO** اضافه شد — تمام متادیتای سئو را در یک نقطه متمرکز می‌کند
متدها: setTitle, setDescription, setCanonical, setOgImage, setJsonLd, setRobots
اسکیماهای JSON-LD آماده: websiteSchema, breadcrumbSchema, legislationSchema
رندر خودکار همه تگ‌های متا با SEO::renderHead()

#### متا تگ‌های استاندارد
<title> بهینه برای هر صفحه (قانون، دسته‌بندی، برچسب، صفحه اصلی)
<meta name="description"> با truncation هوشمند به ۱۶۰ کاراکتر
<meta name="robots"> با directives مناسب
<link rel="canonical"> برای جلوگیری از duplicate content
<meta name="author"> و <meta name="keywords">

#### OpenGraph (Facebook، WhatsApp، Telegram)
og:type, og:site_name, og:title, og:description, og:url, og:locale
og:image با ابعاد ۱۲۰۰×۶۳۰ پیکسل (از تنظیمات قابل تنظیم)

#### Twitter Card
twitter:card, twitter:title, twitter:description, twitter:image, twitter:site

#### JSON-LD Structured Data
**WebSite schema** در صفحه اصلی (با SearchAction برای جستجوی سایت)
**BreadcrumbList** در صفحه هر قانون (مسیر: خانه > دسته‌بندی > قانون)
**Legislation schema** در صفحه هر قانون (با datePublished, description, about)

#### robots.txt
مسیر /robots.txt اضافه شد
Disallow برای مسیرهای ادمین، API، autocomplete، query stringها
Sitemap: به نقشه سایت اشاره می‌کند

#### sitemap.xml
مسیر /sitemap.xml اضافه شد
شامل:
- صفحه اصلی (priority 1.0)
- صفحات استاتیک (categories, timeline, compare, tags, about, contact)
- همه قوانین منتشرشده (priority 0.8)
- **URLهای مستقیم هر ماده قانونی**: /law/{slug}/article/{N} (priority 0.5)
- همه دسته‌بندی‌ها (priority 0.6)
- همه برچسب‌ها (priority 0.4)
هر URL دارای <lastmod>, <changefreq>, <priority>

#### URLهای دوستدار سئو برای مواد قانونی
مسیر جدید: /law/{slug}/article/{N} (مثلاً /law/mandatory-vehicle-insurance-law/article/1)
این مسیر با **301 Moved Permanently** به /law/{slug}#article-N تغییر مسیر می‌دهد
مزیت: موتورهای جستجو هر ماده را به‌عنوان یک URL مجزا ایندکس می‌کنند
وقتی کاربر روی لینک کلیک کند، به همان ماده خاص اسکرول می‌شود

#### ادغام Google Search Console
در /admin/settings → بخش «تنظیمات سئو و گوگل»:
- فیلد Google Search Console verification — کد تأیید مالکیت
- فیلد Google Analytics 4 — شناسه اندازه‌گیری (G-XXXXXXXX)
- فیلد OpenGraph default image — تصویر پیش‌فرض برای اشتراک‌گذاری
- فیلد Twitter handle — @username
- فیلد Keywords — کلمات کلیدی پیش‌فرض
نمایش لینک‌های /robots.txt و /sitemap.xml برای ثبت در Search Console

#### Google Analytics 4
وقتی شناسه G-XXXXXXXX وارد شد، اسکریپت gtag.js به‌صورت خودکار در همه صفحات اضافه می‌شود
anonymize_ip: true برای رعایت حریم خصوصی کاربران (GDPR)

نتایج تست

| Test | Result |
|------|--------|
| Article count in MySQL | ✓ CONCAT() works |
| Mobile action buttons (icon-only at 375px) | ✓ 5 labels hidden |
| Tooltip on click | ✓ Shows for 2s |
| Font-size A+ | 15.2px → 16.8px ✓ |
| TOC sticky position after pin | static → sticky ✓ |
| Title on law page | <title>قانون ... · دیوان قانون</title> ✓ |
| Canonical URL | <link rel="canonical"> ✓ |
| JSON-LD BreadcrumbList | ✓ ۳ levels (خانه/دسته/قانون) |
| JSON-LD Legislation | ✓ With datePublished |
| robots.txt | ✓ 200 OK with sitemap link |
| sitemap.xml | ✓ 630 URLs (laws + articles + categories + tags) |
| Article deep-link /law/slug/article/N | ✓ 301 redirect to #article-N |
| Google Search Console meta | ✓ Renders when set |
| Google Analytics script | ✓ Loads gtag.js when GA ID set |

فایل‌های تغییر یافته

php-cms/app/Helpers/SEO.php ← **جدید** — کلاس کامل سئو
php-cms/app/Helpers/Settings.php ← اصلاح || به CONCAT
php-cms/app/routes_admin.php ← اصلاح || + اضافه شدن SEO settings keys
php-cms/public/index.php ← robots.txt, sitemap.xml, /law/slug/article/N route
php-cms/public/update.php ← migration v4.4.0
php-cms/resources/views/layouts/app.phpSEO::renderHead() + نسخه ۴.۴.۰
php-cms/resources/views/home.php ← SEO title + JSON-LD WebSite schema
php-cms/resources/views/law-detail.php ← SEO title + canonical + JSON-LD + tooltip + font-size + TOC pin
php-cms/resources/views/partials/article-card.php ← CSS variables for font-size
php-cms/resources/views/admin/settings.php ← بخش جدید «تنظیمات سئو و گوگل»
php-cms/Caddyfile ← rewrite rule برای route صحیح
php-cms/CHANGELOG.md ← لاگ v4.4.0

---

v4.3.0



رفع مشکل شمارش مواد قانونی

**تعداد مواد قانونی حالا با COUNT(DISTINCT law_id, number) محاسبه می‌شود** — نه COUNT(*).
مشکل قبلی: وقتی یک قانون را چند بار ایمپورت می‌کردید، ردیف‌های تکراری برای همان شماره ماده ساخته می‌شد و آمار صفحه اصلی را بیشتر از واقعیت نشان می‌داد (مثلاً ۸٬۰۰۰+ به‌جای ۳٬۰۰۰ واقعی).
حالا آمار صفحه اصلی و /api/stats همیشه تعداد مواد یکتا را نشان می‌دهند.
روش جدید: App\Helpers\Settings::liveStat($key) — یک نقطه مرکزی برای همه آمار زنده.

ابزار حذف مواد تکراری (Dedupe)

در صفحه /admin/settings بخش جدید «مدیریت مواد قانونی» اضافه شد:
- نمایش سه عدد: کل ردیف‌های مواد، مواد یکتا (DISTINCT)، ردیف‌های تکراری
- اگر ردیف تکراری وجود داشته باشد، دکمه «حذف مواد تکراری» فعال می‌شود
- با کلیک روی دکمه، ردیف‌های تکراری حذف و جدیدترین نسخه هر ماده نگه داشته می‌شود
- نمایش پیام موفقیت با تعداد ردیف‌های حذف‌شده
این ابزار برای پاکسازی دیتابیس کافی است (نیازی به SQL دستی نیست).

بهبودهای ویو موبایل (Mobile-First)

طراحی موبایل کامل بازنویسی شد تا تمرکز روی محتوای قانونی باشد و عناصر اضافه حذف شوند:

#### صفحه جزئیات قانون (Law Detail)
**عنوان قانون**: text-xl sm:text-2xl md:text-4xl (۲۰px در موبایل، ۳۶px در دسکتاپ)
**breadcrumb**: text-[10px] sm:text-xs (فشرده در موبایل)
**padding هدر**: py-5 sm:py-8 (کمتر در موبایل)
**خلاصه قانون**: text-sm sm:text-base leading-6 sm:leading-7 (فونت کوچک‌تر در موبایل)
**badge دسته‌بندی و قانون منتخب**: کوچک‌تر در موبایل (px-2 sm:px-2.5)
**متادیتای هدر**: مخفی شدن در موبایل (با hidden sm:inline-flex):
- شماره قانون ($law['number'])
- تعداد بازدید
- تعداد نظرات
**متادیتای باقی‌مانده در موبایل**: تاریخ تصویب، تعداد مواد، سختی قانون، زمان مطالعه

#### کارت ماده قانونی (article-card)
**badge شماره ماده**: w-10 h-10 sm:w-12 sm:h-12 md:w-14 md:h-14
- موبایل: ۴۰×۴۰ پیکسل (قبلاً ۴۸×۴۸)
- دسکتاپ: ۵۶×۵۶ پیکسل
- rounded-lg در موبایل، rounded-xl در دسکتاپ
**padding کارت**: p-4 sm:p-5 md:p-6 (۱۶px در موبایل، قبلاً ۲۰px)
**عنوان ماده**: text-sm sm:text-base md:text-lg (۱۴px در موبایل، قبلاً ۱۶px)
**متن ماده**: text-[0.95rem] leading-relaxed sm:text-base sm:leading-loose (فونت کوچک‌تر + line height بهینه)
**متادیتای کارت ماده**: مخفی شدن در موبایل:
- تعداد واژه‌ها (hidden sm:inline-block)
- تعداد بازدید ماده (hidden sm:inline-flex)
**دکمه‌های اکشن** (کپی، لینک، اشتراک، چاپ، گزارش، یادداشت، ویرایش):
- **موبایل: فقط آیکون** (متن با hidden sm:inline مخفی می‌شود)
- دسکتاپ: آیکون + متن
- این کار فضای قابل‌توجهی آزاد کرد — موبایل قبلاً ۶ دکمه با متن بود، حالا ۶ آیکون فقط.
- gap: gap-1 sm:gap-2 (فشرده‌تر در موبایل)

نتایج تست موبایل (Viewport 375px — iPhone SE)

| سناریو | قبل | بعد |
|--------|-----|-----|
| اندازه badge شماره ماده | ۴۸×۴۸ | ۴۰×۴۰ ✓ |
| padding کارت ماده | ۲۰px | ۱۶px ✓ |
| اندازه فونت عنوان ماده | ۱۶px | ۱۴px ✓ |
| اندازه فونت عنوان قانون | ۳۲-۳۶px | ۲۰px ✓ |
| دکمه‌های اکشن در موبایل | آیکون + متن | فقط آیکون ✓ |
| متادیتای هدر قانون در موبایل | همه نمایش داده می‌شد | شماره قانون + بازدید + نظرات مخفی ✓ |
| متادیتای کارت ماده در موبایل | واژه + دقیقه + سختی + بازدید | فقط دقیقه + سختی ✓ |
| اسکرول افقی | وجود داشت | حذف شد ✓ |

فایل‌های تغییر یافته

php-cms/app/Helpers/Settings.php — اضافه شدن liveStat(), liveArticleCount() و سایر متدهای live
php-cms/app/routes_admin.php — اضافه شدن مسیر POST /admin/articles/dedupe
php-cms/public/index.php — استفاده از Settings::liveStat() در /api/stats
php-cms/resources/views/admin/settings.php — بخش جدید «مدیریت مواد قانونی» + JS dedupe
php-cms/resources/views/home.php — استفاده از Settings::liveStat() + کلاس‌های responsive
php-cms/resources/views/law-detail.php — همه کلاس‌های sm: برای موبایل
php-cms/resources/views/partials/article-card.php — badge کوچک‌تر، آیکون-فقط در موبایل
php-cms/resources/views/layouts/app.php — نسخه ۴.۳.۰

---

v4.2.0



آمار پویا و قابل کنترل صفحه اصلی


**تغییرات کلیدی:** آمار صفحه اصلی حالا کاملاً پویا، زنده و قابل کنترل از تنظیمات است.

#### ۱. آمار زنده از دیتابیس
تعداد قوانین، مواد و سایر آمار به‌صورت **لایو** از دیتابیس خوانده می‌شوند
با افزودن/حذف/تغییر وضعیت قانون، آمار در رفرش بعدی به‌روز می‌شود
تعداد مواد قانونی دقیقاً با ستون «مواد» پنل ادمین مطابقت دارد (WHERE number > 0)

#### ۲. اعداد تقریبی (اختیاری)
نمایش اعداد به‌صورت گرد شده با + برای حفظ حریم خصوصی
- 538540+
- 1,2431,200+
- 8,1838,200+
اعداد زیر ۱۰۰ دقیق نمایش داده می‌شوند
از تنظیمات قابل خاموش/روشن کردن است

#### ۳. کنترل کامل بلوک‌های آماری
در صفحه /admin/settings بخش جدید «آمار صفحه اصلی» اضافه شد
۶ بلوک آماری قابل کنترل:
- ✅ قوانین
- ✅ مواد قانونی
- ✅ دسته‌بندی‌ها
- ✅ **کاربران** ← قابل غیرفعال‌سازی برای حفظ حریم خصوصی
- ☐ برچسب‌ها (جدید)
- ☐ بازدید کل (جدید)
وقتی بلوکی غیرفعال می‌شود:
- از صفحه اصلی حذف می‌شود
- گرید به‌طور خودکار تنظیم می‌شود (۴/۳/۲ ستونی)
- از خروجی /api/stats هم حذف می‌شود (نشت جلوگیری می‌شود)

#### ۴. کلاس App\Helpers\Settings (جدید)
کلاس متمرکز برای خواندن/نوشتن تنظیمات با کش درون‌حافظه‌ای
متدهای نوع‌دار (getBool, getInt)
منطق آمار تقریبی و visibility در یک جا

رفع باگ

رفع باگ array_search === false که باعث می‌شد بلوک «قوانین» در انتها نمایش داده شود
حذف نشت تعداد کاربران از API عمومی وقتی بلوک کاربران خاموش است

---

v4.1.0



هوش مصنوعی

تفسیر هوش مصنوعی مواد قانونی به زبان ساده (پنل مدیریت + نمایش عمومی)
چتبات پرسش‌پاسخ هوش مصنوعی در صفحه هر قانون
داشبورد مدیریت تفسیر با پردازش دسته‌ای
شاخص سختی قانون (۱-۵) با الگوریتم محتوا‌محور
badge سختی هر ماده به‌صورت مستقل
مرتب‌سازی نتایج جستجو بر اساس سختی
نمایش badge سختی روی کارت‌های نتایج جستجو

تجربه کاربری

نوار پیشرفت مطالعه در بالای صفحه قانون
ویجت «مواد کلیدی» (۵ ماده پرمحور هر قانون)
ویجت «پربازدیدترین مواد» در صفحه اصلی
tracking بازدید هر ماده با IntersectionObserver
autocomplete جستجوی زنده در هدر
تاریخچه جستجو (localStorage)
فیلترهای پیشرفته جمع‌شونده در جستجو
دکمه‌های اشتراک و چاپ هر ماده
skeleton loading هنگام بارگذاری مواد بیشتر
اسکرول افقی برطرف شد (overflow-x: clip)

قابلیت‌های کاربری

دنبال کردن قانون (follow) + نوتیفیکیشن به‌روزرسانی
ذخیره سریع (dropdown در هدر با badge تعداد)
یادداشت شخصی روی هر ماده
ویرایش inline مواد توسط ادمین
پنل پیام‌های تماس با parse و پاسخ ایمیل
حالت تاریک خودکار (auto/light/dark با تشخیص سیستم)
نمایش مقدمه قانون با ساختار و تیترها

پنل مدیریت

داشبورد با آمار هوش مصنوعی (پوشش تفسیر + پرسش‌پاسخ)
فید آخرین پرسش‌های کاربران در داشبورد
لیست پربازدیدترین مواد در داشبورد
پنل پیام‌های تماس اختصاصی
ایمپورت قوانین از davoudabadi.ir با ساختار کامل
دکمه‌های سریع دسترسی به تفسیر و پیام‌ها

صفحه اصلی

ویجت هوش مصنوعی (پوشش تفسیر + آخرین پرسش‌ها)
ویجت پربازدیدترین مواد قانونی
کارت‌های دسته‌بندی با آیکون‌های متنوع و رنگ‌بندی متفاوت
افکت‌های hover چندلایه روی کارت‌ها

رفع باگ

رفع اسکرول افقی ریز در همه صفحات
رفع خطای ۵۰۰ صفحه تماس با ما
رفع خطای Fatal در مسیرهای /install
ماده ۱ دیگر در ایمپورت قالب نمی‌شود
مقدمه قانون با تیترهای ساختاریافته نمایش داده می‌شود

---

v2.4.0



پشتیبانی از بخش‌بندی قوانین (بخش اول، فصل اول و...)
نمایش بخش‌ها در فهرست مواد (TOC) به‌صورت تیتر
رفع خطای بارگذاری مواد بیشتر (AJAX)
اصلاح نمایش اعداد زیرهم (۱- ۲- ۳-)
حذف منابع خارجی از نمایش عمومی

v2.0.0



پشتیبانی از ساب‌دایرکتوری
سازگاری MySQL و SQLite
جستجو و فیلتر در پنل مدیریت
چیدمان بلوکی/لیستی قوانین
ویرایش دسته‌بندی‌ها
جستجوی پیشرفته
ابزار مقایسه قوانین
نمایش زمان‌خط قوانین
سیستم تگ
قانون روز
خروجی citation
REST API
PWA
حالت تاریک

v1.0.0



ساختار پایه
پنل مدیریت
طراحی RTL