تطوير الستايلات
ستايل كليجا مجلد يضم قوالب HTML وملفات تصميم تتحكم بشكل واجهة الموقع. تعيش الستايلات داخل styles/، ويختار المدير الستايل النشط من لوحة التحكم.
القوالب صفحات HTML عادية تعلوها لغة وسوم صغيرة. يترجم كليجا كل قالب إلى PHP مرة واحدة، ويخزّن الناتج مؤقتاً، ثم يقدّم الملف المخزَّن في الطلبات التالية. لا تكتب PHP داخل القالب إطلاقاً — فالمحلّل يحذفها.
includes/style.php، ومدير الستايلات في includes/adm/m_styles.php.كيف يعمل النظام
يبني ملف includes/common.php مسارات الستايل من إعدادين اثنين: يحمل style مجلد الستايل النشط، ويحمل style_depend_on اسم الستايل الأب حين يرث الستايل من ستايل آخر.
حين تستدعي الصفحة $tpl->display('login')، يبحث المحرك عن login.html في الستايل النشط، ثم يرجع إلى الستايل الأب أو إلى default، ثم يترجم الملف إلى cache/tpl_login.php ويضمّنه. يُعاد استخدام الملف المترجَم حتى يُمسح المخزون المؤقت.
كل متغير عام في PHP هو متغير قالب. تنسخ الدالة display() مصفوفة $GLOBALS إلى المحرك قبل العرض، فتصبح $config و$lang و$userinfo وكل ما تعرّفه الصفحة متاحاً بالصيغة {config.sitename} و{lang.LOGIN} وهكذا.
بنية المجلد
الستايل مجلد داخل styles/ يتكوّن اسمه من حروف صغيرة وأرقام ونقاط وشرطات سفلية، وبطول ثلاثة محارف على الأقل.
styles/
└── my_style/
├── info.txt # مطلوب — بيانات الستايل
├── header.html # مطلوب — يفتح الصفحة ويحمّل ملفات CSS
├── footer.html # مطلوب — يغلق الصفحة
├── index_body.html # مطلوب — نموذج الرفع
├── up_boxes.html # مطلوب — صناديق النتائج بعد الرفع
├── info.html # مطلوب — رسائل المعلومات
├── err.html # مطلوب — رسائل الأخطاء
├── login.html # ... ملف لكل صفحة، انظر الجدول أدناه
├── screenshot.png # اختياري — صورة مصغّرة في لوحة التحكم
├── index.html # اختياري — يمنع عرض محتويات المجلد
├── css/
└── images/
styles/bootstrap_black/ ملف header.html واحداً مع ملف تنسيق، ويرث ما تبقّى من bootstrap.القوالب
| القالب | يعرضه | الصفحة |
|---|---|---|
header.html | Saaheader() | الشيفرة الافتتاحية لكل صفحة. |
footer.html | Saafooter() | الشيفرة الختامية لكل صفحة. |
index_body.html | index.php | نموذج الرفع في الصفحة الرئيسة. |
up_boxes.html | get_up_tpl_box() | صناديق الروابط بعد نجاح الرفع. |
info.html | kleeja_info() | رسائل المعلومات. ويحل محل الصفحة الرئيسة عند تعطيل الرفع. |
err.html | kleeja_err() | رسائل الأخطاء. |
download.html | do.php | صفحة تحميل الملف. |
login.html | ucp.php | نموذج تسجيل الدخول. |
register.html | ucp.php | نموذج التسجيل. |
profile.html | ucp.php | نموذج الملف الشخصي. |
fileuser.html | ucp.php | مدير ملفات المستخدم. |
get_pass.html | ucp.php | استعادة كلمة المرور. |
guide.html | go.php | صفحة الشرح. |
rules.html | go.php | صفحة القوانين. |
report.html | go.php | نموذج الإبلاغ عن ملف. |
call.html | go.php | نموذج التواصل. |
stats.html | go.php | إحصاءات الموقع. |
default، يوقف الطلب برسالة No Template !.ملف info.txt
يحمل كل ستايل ملف info.txt تقرؤه لوحة التحكم. يتجاهل المحلّل الأسطر الفارغة والأسطر التي تبدأ بـ #، ويقسم الباقي عند أول =، ويعامل النقطتين في المفتاح كمفتاح فرعي.
#
# This is a configuration file of the style.
#
#Style name
name = My Style
#Style desc
desc:en = A clean, responsive style for Kleeja
desc:ar = ستايل بسيط ومتجاوب لكليجا
#Style copyright
copyright = 2026 Your Name
#Version of style
version = 1.0
#Min. required version of kleeja
kleeja_version = 3.2.0
#name of the style required by this style
#depend_on = bootstrap
#plugins required to install this style
#plugins_required = test, test2
| المفتاح | الغرض |
|---|---|
name | الاسم المعروض في قائمة الستايلات. |
desc:<lang> | الوصف لكل لغة، ويرجع إلى desc:en. |
copyright | سطر حقوق النشر المعروض مع الستايل. |
version | إصدار الستايل. يستخدمه المتجر لاكتشاف التحديثات. |
kleeja_version | أدنى إصدار مطلوب من كليجا. يفشل التفعيل على ما هو أقدم منه. |
depend_on | مجلد الستايل الأب. تُلتمس القوالب الناقصة فيه. |
plugins_required | أسماء مجلدات الإضافات المطلوب تثبيتها وتفعيلها، مفصولة بفواصل. |
info.txt الفحوص التي تجري عند تفعيل المدير للستايل. يمنع التفعيلَ برسالة واضحة أيٌّ من: غياب مجلد الستايل الأب، أو إصدار كليجا أقدم من kleeja_version، أو إضافة مطلوبة غير مثبّتة.صياغة القوالب
يحوّل المحلّل مجموعة صغيرة من الوسوم شبه البرمجية إلى PHP، ويمرّر ما عداها كما هو.
المتغيرات
ضع اسم المتغير بين قوسين معقوفين مفردين. تنقلك النقطة داخل المصفوفة.
<title>{title} - {config.sitename}</title>
<p>{lang.WELCOME}، {username}</p>
<link rel="stylesheet" href="{STYLE_PATH}css/stylesheet.css" />
يجوز أن تحتوي الأسماء على حروف وأرقام وشرطات سفلية ونقاط، ولا شيء غير ذلك. أما {lang.X} و{olang.X} فلهما سلوك خاص: عند غياب المفتاح يطبع المحرك الوسم نفسه بدل نص فارغ، ما يسهّل اكتشاف الترجمات الناقصة.
الحلقات
يكرّر الوسم <LOOP> عناصر المصفوفة. داخل الحلقة، تقرأ الأقواس المزدوجة الصف الحالي، ويطبع {%key%} المفتاح الحالي، ويطبع {%value%} القيمة الحالية.
<ul class="menu">
<LOOP NAME="top_menu">
<IF LOOP="show">
<li><a href="{{url}}">{{title}}</a></li>
</IF>
</LOOP>
</ul>
أما المصفوفة المسطّحة من النصوص فيكفيها {%value%}:
<IF NAME="ERRORS">
<ul class="alert">
<LOOP NAME="ERRORS">
<li>{%value%}</li>
</LOOP>
</ul>
</IF>
{{field}} بعد إغلاق الداخلية يشير إلى الخارجية. سطّح البيانات في PHP بدل تداخل الحلقات.الشروط
يأخذ الوسم <IF> خصائص بدل تعبير حر. استخدم NAME للمتغير العام، وLOOP لحقل من صف الحلقة الحالي.
<IF NAME="user_is">
<p>{lang.WELCOME} {username}</p>
<ELSE>
<a href="{action_login}">{lang.LOGIN}</a>
</IF>
<IF NAME="config.safe_code">
<img src="{captcha_file_path}" alt="{lang.REFRESH_CAPTCHA}" />
</IF>
| الخاصية | المعنى |
|---|---|
NAME | متغير عام، مع إمكانية إضافة مقارنة. |
LOOP | حقل من صف الحلقة الحالي. |
AND | يربط الفحص السابق بالمعامل &&. |
OR | يربط الفحص السابق بالمعامل ||. |
ISSET | يغلّف المتغير المسمّى بالدالة isset(). |
EMPTY | يغلّف المتغير المسمّى بالدالة empty(). |
تقبل المقارنات الرموز والكلمات معاً:
| المعامل | الصيغة الكلامية |
|---|---|
== | eq |
!= | neq |
< | lt |
> | gt |
<= | lte |
>= | gte |
<IF NAME="go_to==start" AND="" ISSET="go_menu_html">
<nav>{go_menu_html}</nav>
</IF>
تُترجَم الخصائص دائماً بالترتيب NAME ثم LOOP ثم AND ثم OR ثم ISSET ثم EMPTY. مرّر AND="" فارغة لوضع المعامل && قبل فحص ISSET أو EMPTY، كما في المثال أعلاه.
يمدّد الوسم <ELSEIF> سلسلة الشروط، ويعكس الوسم <UNLESS> الفحص. أغلق الثلاثة بـ </IF> أو </UNLESS> أو الوسم العام </END>.
<IF NAME="current_smt == users">
...
<ELSEIF NAME="current_smt == team">
...
</IF>
<UNLESS NAME="no_results">
<p>{lang.RESULTS}</p>
</UNLESS>
<IF NAME="style == bootstrap4"> إلى شيفرة PHP غير صالحة. قارن بنص خالص أو برقم خالص، وانقل ما عدا ذلك إلى متغير تضبطه في PHP.الشروط المختصرة
الشرط الثلاثي بين قوسين اختصارٌ لكتلة <IF> قصيرة، ولا يقبل علامات اقتباس ولا فواصل.
(page_stats?<div class="footer_stats">{page_stats}</div>:)
<a href="{{url}}" (go_current=={{name}}?class="current":)>{{title}}</a>
اترك أحد الطرفين فارغاً كي لا يُعرض شيء في تلك الحالة.
كشف المتصفح
يعرض الوسم <IS_BROWSER> كتلته للمتصفحات التي تسمّيها فقط. استخدم != لعكس الشرط، وقائمة مفصولة بفواصل لمطابقة أكثر من متصفح.
<IS_BROWSER!="mobile">
<img src="{user_avatar}" alt="{username}" />
</IS_BROWSER>
<IS_BROWSER="ie,opera">
<link rel="stylesheet" href="{THIS_STYLE_PATH}css/legacy.css" />
</IS_BROWSER>
الأسماء المدعومة هي ie وfirefox وsafari وchrome وflock وopera وkonqueror وmozilla وwebkit وmobile. وأضف رقم إصدار بعد ie أو firefox لاستهدافه، مثل ie6.
مساعدات الصفوف
داخل الحلقة، يفحص الوسمان <ODD> و<EVEN> حقلاً رقمياً من الصف الحالي، ويناوب الوسم <RAND> بين نصّين مع كل استدعاء.
<LOOP NAME="files">
<tr class="<RAND="row_a","row_b">">
<td>{{name}}</td>
</tr>
</LOOP>
تضمين قالب
يعرض الوسم <INCLUDE> قالباً آخر في مكانه. أضف PATH لجلبه من مجلد خارج الستايل النشط.
<INCLUDE NAME="sidebar">
الحماية من التحليل
يحذف المحلّل شيفرة PHP من القوالب، فلا تبقى كتل <?php ?> ولا <? ?> ولا <% %> ولا <script language="php"> بعد الترجمة. وغلّف الشيفرة بالوسم <IGNORE> لإخفائها عن المحلّل تماماً — وهو مفيد مع JavaScript أو CSS التي قد تبدو كوسم قالب.
<IGNORE>
<script>const tpl = { name: "{not a variable}" };</script>
</IGNORE>
متغيرات القوالب
المسارات
| المتغير | يشير إلى |
|---|---|
{STYLE_PATH} | رابط الستايل الأب حين يكون depend_on مضبوطاً، وإلا رابط الستايل النشط. استخدمه للملفات الموروثة. |
{THIS_STYLE_PATH} | رابط مجلد الستايل النشط. استخدمه لملفاتك التي تتجاوز الأب. |
{STYLE_PATH_ADMIN} | رابط قالب لوحة التحكم. |
{DEFAULT_PATH_ADMIN} | رابط قالب لوحة التحكم الافتراضي. |
{STYLE_PATH} إلى الأب. لذا فتحميل {STYLE_PATH}css/stylesheet.css ثم {THIS_STYLE_PATH}css/stylesheet.css يمنحك ملف الأب متبوعاً بتعديلاتك — وهو تماماً ما يفعله bootstrap_black.الصفحة والمستخدم
| المتغير | المحتوى |
|---|---|
{title} | عنوان الصفحة. |
{dir} | اتجاه النص، rtl أو ltr، حسب اللغة النشطة. |
{charset} | ترميز المحارف، وهو utf-8 دائماً. |
{username} | اسم الزائر، أو تسمية الضيف. |
{user_is} | صحيح حين يكون الزائر مسجّل الدخول. |
{user_avatar} | رابط صورة Gravatar، ويرجع إلى صورة الستايل الافتراضية. |
{userinfo.*} | صف المستخدم المسجّل. |
{config.*} | أي إعداد من لوحة التحكم، مثل {config.sitename} و{config.siteurl}. |
{lang.*} | العبارات اللغوية من lang/<code>/. |
{olang.*} | العبارات اللغوية التي تضيفها الإضافات. |
{text} | نص الرسالة في info.html وerr.html. |
القوائم والكتل
| المتغير | المحتوى |
|---|---|
{top_menu} | حلقة القائمة العلوية: {{name}} و{{title}} و{{url}} و{{show}}. |
{side_menu} | حلقة قائمة المستخدم، بالحقول نفسها. |
{go_current} | اسم الصفحة الحالية، لتعليم عنصر القائمة النشط. |
{extras.header} | شيفرة إضافية تُحقن فوق المحتوى. |
{extras.footer} | شيفرة إضافية تُحقن أسفل المحتوى. |
{EXTRA_CODE_META} | وسوم إضافية داخل <head>، وفيها تضيف الإضافات وسوم الميتا. |
{page_stats} | زمن التوليد وعدد الاستعلامات، عند تفعيلهما. |
{admin_page} | رابط لوحة التحكم، ويظهر للمديرين. |
{run_queue} | بكسل المهام المجدولة. أبقِه في footer.html. |
{googleanalytics} | شيفرة التحليلات، عند ضبطها. |
{go_back_browser} | عبارة «العودة» المترجمة. |
footer.html بالمتغير {run_queue}، فهو يشغّل مهام كليجا المجدولة ومنها حذف الملفات القديمة، وإسقاطه يوقفها بصمت.صناديق نتائج الرفع
ملف up_boxes.html ليس قالباً عادياً. يقسّمه كليجا إلى كتل مسمّاة ويستبدل فيها المتغيرات {var} استبدالاً نصياً بسيطاً، بلا شروط ولا حلقات. وتُحدَّد الكتل بتعليقات HTML.
<!-- BEGIN image -->
<table class="up_box_input">
<tr>
<td class="btitle">{b_title}</td>
<td><textarea readonly rows="1">{b_url_link}</textarea></td>
</tr>
</table>
<!-- END image -->
| الكتلة | تظهر مع |
|---|---|
image_thumb | صورة مرفوعة مع مصغّرة. |
image | صورة مرفوعة، بروابط مباشرة وروابط BBCode. |
file | ملف مرفوع غير صورة. |
del_file_code | رمز حذف الملف المرفوع. |
المتغيرات المتاحة هي {b_title} و{b_bbc_title} و{b_url_link} و{b_img_link} و{b_code_link}، إضافة إلى {siteurl} و{sitename}. ويجب أن توجد الكتل الأربع كلها، لأن نظام الرفع يطلبها بالاسم.
وراثة الستايلات
اضبط depend_on في info.txt للبناء على ستايل قائم. يكتب تفعيلُ الابن كلا الإعدادين style وstyle_depend_on، ثم يلتمس المحرك كل قالب ناقص عند الأب.
name = Bootstrap Black
version = 1.0
kleeja_version = 2.0
depend_on = bootstrap
يجري البحث عن القالب بهذا الترتيب:
الستايل النشط
المسار styles/<style>/<template>.html.
الستايل الأب
حين يكون style_depend_on مضبوطاً، يُبحث عن الاسم نفسه داخل مجلد الأب.
الستايل الافتراضي
حين لا يكون للستايل أب ولا يكون هو default نفسه، يُبحث عن الاسم نفسه داخل styles/default/.
depend_on يرجع إلى أبيه فقط، ولا يرجع إلى default أبداً. لذا تأكد من اكتمال الستايل الأب، أو اشحن القوالب الناقصة بنفسك.داخل الستايل الوارث، حمّل ملفات الأب عبر {STYLE_PATH} وملفاتك عبر {THIS_STYLE_PATH}:
<link href="{STYLE_PATH}css/bootstrap.min.css" rel="stylesheet">
<link href="{STYLE_PATH}css/stylesheet.css" rel="stylesheet">
<link href="{THIS_STYLE_PATH}css/stylesheet.css" rel="stylesheet">
الملفات والاتجاه
ضع ملفات التنسيق في css/ والصور في images/، وأشر إليها عبر متغير مسار كي يبقى الستايل عاملاً بعد إعادة تسميته أو وراثته.
يدعم كليجا العربية والإنجليزية، لذا يجب أن يتعامل الستايل مع الاتجاهين. يحمل المتغير {dir} القيمة rtl أو ltr، ما يتيح لك ضبط اتجاه المستند وتحميل ملف تنسيق خاص بالاتجاه:
<html dir="{dir}">
...
<IF NAME="lang.DIR==ltr">
<link rel="stylesheet" href="{STYLE_PATH}css/ltr.css" />
</IF>
أضف ملف screenshot.png إلى مجلد الستايل للحصول على صورة مصغّرة في قائمة الستايلات. وبدونه تعرض لوحة التحكم أيقونة عامة.
سير العمل أثناء التطوير
تُخزَّن القوالب المترجَمة في مجلد cache/، لذا لا تظهر تعديلاتك على ملف .html حتى يُمسح المخزون المؤقت. أوقف التخزين المؤقت أثناء العمل:
define('DEV_STAGE', true);
يوقف الثابت DEV_STAGE تخزين القوالب مؤقتاً، ويعرض كل أخطاء PHP، ويضيف رابط تنقيح إلى التذييل. ولإيقاف التخزين المؤقت وحده دون بقية مخرجات التنقيح، استخدم STOP_TPL_CACHE بدلاً منه.
قراءة الناتج المترجَم
يُترجَم كل قالب إلى cache/tpl_<name>.php، بعد تحويل الاسم إلى حروف صغيرة واستبدال كل محرف خارج النطاق a-z0-9-_ بشرطة. وفتح ذلك الملف أسرع وسيلة لمعرفة إلى ماذا تحوّل الوسم حين يسيء القالب التصرّف.
إدارة الستايلات
يدير المديرون الستايلات من لوحة التحكم ← الستايلات. تعرض الصفحة الستايلات الموجودة في styles/، وتعرض في تبويب المتجر الستايلات المتاحة في الفهرس البعيد.
| الإجراء | الأثر |
|---|---|
| الاختيار | يكتب style وstyle_depend_on ثم يمسح المخزون المؤقت، بعد إجراء فحوص الأب والإصدار والإضافات المطلوبة. |
| الرفع | يفكّ ضغط ملف .zip مرفوع داخل styles/. |
| التنزيل | يجلب الستايل من الفهرس البعيد ويفكّ ضغطه، مع تراجع تلقائي عند الفشل. لحسابات المؤسسين فقط. |
| حذف المجلد | يحذف مجلد الستايل. ولا يمكن حذف الستايل النشط. |
يفشل التفعيل برسالة محددة في ثلاث حالات: غياب المجلد المسمّى في depend_on، أو كون kleeja_version أحدث من إصدار كليجا العامل، أو غياب إضافة مذكورة في plugins_required أو تعطيلها.
التحزيم والتوزيع
وزّع الستايل كملف .zip يحتوي مجلداً واحداً في جذره، بالبنية نفسها التي في styles/.
zip -r my_style.zip my_style -x "*.git*"
يرفع المديرون الأرشيف من لوحة التحكم ← الستايلات، ويفكّ كليجا ضغطه مباشرة داخل styles/. أما الستايلات المدرجة في الفهرس العام فتُثبَّت بنقرة واحدة:
قالب لوحة التحكم
تستخدم لوحة التحكم قالبها الخاص المثبّت في admin/Masmak/، وقوالبه هي الملفات التي تبدأ بـ admin_. ويوجّه المحرك أي اسم قالب يحمل هذه البادئة إلى قالب لوحة التحكم بدل الستايل النشط.
قوالب لوحة التحكم ليست جزءاً من ستايل الواجهة. ولاستبدالها اشحن إضافة تعيد كتابة متغيرات مسار اللوحة — وهذا تماماً ما تفعله الإضافة المرفقة zaki_admin_theme من خطّاف end_common.
حلّ المشكلات
| العَرَض | السبب |
|---|---|
No Template ! | القالب غير موجود في الستايل ولا في أبيه ولا في default. تحقق من اسم الملف ومن سلسلة depend_on. |
| التعديلات بلا أثر | القالب المترجَم مخزَّن مؤقتاً. فعّل DEV_STAGE أو امسح المخزون المؤقت. |
متغير {variable} يُطبع كما هو | في حالة {lang.*} و{olang.*} يعني أن المفتاح مفقود. وفي غيرها يعني أن المتغير العام غير موجود في تلك الصفحة. |
| صفحة بيضاء بعد تعديل شرط | قيمة مقارنة تحتوي رقماً تُرجمت إلى شيفرة PHP غير صالحة. يجب أن تكون القيم بلا اقتباس نصاً خالصاً أو رقماً خالصاً. |
| تعطُّل JavaScript بعد الترجمة | الأقواس المعقوفة في الشيفرة بدت كوسوم قوالب. غلّف الكتلة بالوسم <IGNORE>. |
| توقّف التنظيف المجدول | حُذف المتغير {run_queue} من footer.html. |
المرجع
الوسوم
| الوسم | يُترجَم إلى |
|---|---|
{var} و{a.b} | طباعة متغير عام. |
{{field}} | طباعة حقل من صف الحلقة الحالي. |
{%key%} و{%value%} | طباعة مفتاح الحلقة الحالي أو قيمته. |
<LOOP NAME="x"> … </LOOP> | تكرار foreach على مصفوفة. |
<IF NAME="x"> … </IF> | كتلة شرطية. |
<ELSEIF …> و<ELSE> | سلسلة شروط. |
<UNLESS …> … </UNLESS> | شرط معكوس. |
(cond?a:b) | شرط مختصر. |
<IS_BROWSER="x"> … </IS_BROWSER> | فحص المتصفح، و!= لعكسه. |
<ODD="field"> … </ODD> | العرض عند القيم الفردية. |
<EVEN="field"> … </EVEN> | العرض عند القيم الزوجية. |
<RAND="a","b"> | المناوبة بين نصّين. |
<INCLUDE NAME="tpl"> | عرض قالب آخر. |
<IGNORE> … </IGNORE> | إخفاء كتلة عن المحلّل. |
</END> | وسم إغلاق عام. |
واجهة المحرك
| الدالة | التوقيع |
|---|---|
display() | display(string $template_name, string $style_path = ''): string |
assign() | assign(string $var, mixed $to): void |
template_exists() | template_exists(string $template_name, string $style_path = ''): string|false |
kleeja_style_info() | kleeja_style_info(string $style_name): array|false — في includes/functions_display.php |
get_up_tpl_box() | get_up_tpl_box(string $box_name, array $extra = []): string — في includes/functions_display.php |
is_browser() | is_browser(string $b): bool — في includes/functions_display.php |
الإعدادات والثوابت
| الاسم | المعنى |
|---|---|
config.style | اسم مجلد الستايل النشط. |
config.style_depend_on | اسم مجلد الستايل الأب، أو فارغ. |
ACP_STYLE_NAME | مجلد قالب لوحة التحكم، وهو Masmak. |
DEV_STAGE | يوقف تخزين القوالب مؤقتاً ويفعّل مخرجات التنقيح. |
STOP_TPL_CACHE | يوقف تخزين القوالب مؤقتاً فقط. |
PATH | المسار المطلق لجذر كليجا على نظام الملفات، وينتهي بشرطة مائلة. |