آموزش طراحی ماژول نیوک

نمایه کاربر
iman64
مدیر کل سایت
مدیر کل سایت
پست: 3479
تاریخ عضویت: شنبه ۱۸ اسفند ۱۳۸۶, ۸:۳۰ ب.ظ
محل اقامت: ایران سرافراز - بوشهر - دلوار
تشکر کرده: 397 دفعه
تشکر شده: 4754 دفعه

آموزش طراحی ماژول نیوک

پست توسط iman64 »

سلام به کاربران گرامی
در این بخش آموزش طراحی یک ماژول برای سیستم نیوک رو میخوام بزارم.
خوب اول باید یه توضیح کوتاه در مورد ماژولهای نیوک بدم.
در نیوک ما از چند طریق میتونیم بخشهایی رو به نیوک اضافه کنیم. بلوکها، مازولها و امکانات قالب
بلوکها و امکانات قالب بیشتر جنبه نمایشی دارن. اما ماژولها دامنه وسیعتری از امکانات رو شامل میشن و ما میتونیم برای هر ماژول بلوکهای متفاوتی هم تعبیه کنیم.
یه ویژگی مهم ماژولها قابلیت لینکدهی هست. یعنی ما نمیتونیم به یه بلوک لینک اختصاص بدیم ولی ماژولها لینک اختصاصی دارن.
در مورد بلوکها در بخش مجزایی توضیحات بیشتری میدم.
اما یک ماژول از چه قسمتهایی تشکیل شده و نحوه طراحیشون به چه شکلی هست رو تو این بخش توضیح میدم. من این تاپیک رو قفل میکنم تا مباحث پیوسته باشه و پستهای اضافی بینشون نیاد.
ما ابتدا با یک ماژول خیلی ساده شروع میکنیم و کم کم پر و بالش میدیم.
برای ساخت یک ماژول باید پوشه ای با نام دلخواه در پوشه modules ایجاد کنیم. به عنوان مثال ماژول test
اولین فایلی که باید یک ماژول داشته باشه فایل index.php هست. این فایل شامل محتویاتی هست که در ادامه ذکر میکنم.
فرض کنید ما میخوایم ماژولی طراحی کنیم که یک جمله ساده رو خروجی بده.
محتویات ثابت فایل index.php به این شکل هست:

کد: انتخاب همه

<?php
/**
 *
 * This file is part of the PHP-NUKE Software package.
 *
 * @copyright (c) PHP-NUKE <https://www.phpnuke.ir>
 * @license GNU General Public License, version 2 (GPL-2.0)
 *
 */

if (!defined('MODULE_FILE')) {
    die ("You can't access this file directly...");
}

$module_name = basename(dirname(__FILE__));

$contents = '';
$contents = '<p align="center">سلام. به سایت ما خوش اومدید</p>';

include("header.php");
$html_output .= $contents;
include("footer.php");

?>

توضیحات کدها:
    

کد: انتخاب همه

if (!defined('MODULE_FILE')) {
    die ("You can't access this file directly...");
}

کد بالا برای اینه که فایل index.php ماژول مستقیماً و خارج از چهارچوب نیوک اجرا نشه. پس وجودش الزامیه

کد: انتخاب همه

$module_name = basename(dirname(__FILE__));

این کد اسم پوشه ماژول رو در متغیر module_name ذخیره میکنه. این نام قابلیت استفاده دز کلیه بخش های ماژول داره که در آینده در موردش توضیح میدم. بعضی مواقع شما ماژولتون رو طوری طراحی میکنین که میتونین اسم ماژول رو به دلخواه عوض کنین. از طریق همین متغیر این نام دلخواه در همه بخشهای ماژول مورد استفاده قرار میگیره. بخصوص زمانی که قصد فروش یک ماژول تحت عناوین مختلف به چند مشتری رو دارین.

بعد از این کدها میخوایم خروجی ماژول رو نمایش بدیم.
فرض کنیم قصد نمایش جمله "سلام. به سایت ما خوش اومدید" رو داریم.

کد زیر رو وارد میکنیم و مقدار پیشفرضی برای این متغیر در نظر میگیریم

کد: انتخاب همه

$contents = '';

من دارم خیلی ساده شروع میکنم و کم کم این پست رو توسعه میدم.

حالا این کد رو وارد میکنیم.

کد: انتخاب همه

$contents = '<p align="center">سلام. به سایت ما خوش اومدید</p>';

حالا قسمت هدر سایت رو فراخونی میکنیم با کد

کد: انتخاب همه

include("header.php");

بعد از فراخونی هدر متغیری هست به نام output_html
ما باید کل محتویاتی که تا اینجا آماده کردیم رو بدیم به این متغیر و ادامه بدیم. توجه کنید که این متغیر بعد از فراخونی فایل هدر مقادیری داره و نباید این مقادیر از بین برن. به همین جهت مقدار contents رو به متغیر output_html اضافه میکنیم. به این شکل

کد: انتخاب همه

$html_output .= $contents;

و در نهایت باید فوتر سایت رو فراخونی کنیم. با این کد

کد: انتخاب همه

include("footer.php");

حالا برای مشاهده نتیجه اول باید بریم به مدیریت ماژولها و ماژولی که ساختیم رو فعال کنیم.

بعد از فعالسازی ماژول به آدرس زیر میریم.

کد: انتخاب همه

http://www.site.com/index.php?modname=test
این یه لینک ثابت و کلی برای هر ماژولی هست. به عبارتی همین که شما یک ماژول رو میسازید این آدرس فعال و قایل اجرا میشه.

با اجرای این لینک نتیجه ای به این شکل حاصل میشه.
ماژول test.png
شما دسترسی جهت مشاهده فایل پیوست این پست را ندارید.


Phpnuke.ir
نمایه کاربر
iman64
مدیر کل سایت
مدیر کل سایت
پست: 3479
تاریخ عضویت: شنبه ۱۸ اسفند ۱۳۸۶, ۸:۳۰ ب.ظ
محل اقامت: ایران سرافراز - بوشهر - دلوار
تشکر کرده: 397 دفعه
تشکر شده: 4754 دفعه

آموزش طراحی ماژول نیوک

پست توسط iman64 »

خوب حالا تصور کنید میخوایم برای ماژولمون چند بخش تعریف کنیم. طوری که هر بخش لینک مجزایی داشته باشه.
برای این کار ما چند روش داریم:
1. همین فایل index.php رو با شرطهایی به بخشهای مختلف تقسیم کنیم که من توصیه نمیکنم.
2. از file استفاده کنیم و برای هر بخش یه فایل در نظر بگیریم.
3. از تابع استفاده کنیم و هر بخش رو در یک تابع دسته بندی و نمایش بدیم.

مورد اول رو با توجه به اینکه کدها رو در هم آمیخته میکنه من توضیحی نمیدم ولی اگر ماژولتون ساده بود و اونقدر بخشهای مختلف نداشت که نخواین از دو روش بعدی استفاده کنید میتونین درخواست بدین تا روشش رو براتون توضیح بدم.

تصور کنید بخش اول ماژول ما قراره لیستی از امکانات حرفه ما رو نشون بده. من این کار رو با یک جدول ساده که متشکل از نام خدمت و لینک مشاهده اون خدمت هست نشون میدم. من همون ماژول پست اول رو بسط میدم و این عملیات رو روش اجرا میکنم:

کد: انتخاب همه

$contents .= "
<table width=\"100\" class=\"table table-hover\">
    <tr>
        <th class=\"text-center\">نام خدمت</th>
        <th class=\"text-center\">عملیات</th>
    </tr>
    <tr>
        <td class=\"text-center\">خدمت شماره 1</td>
        <td class=\"text-center\"><a href=\"".LinkToGT("index.php?modname=$module_name&op=details&id=1")."\">مشاهده</a></td>
    </tr>
    <tr>
        <td class=\"text-center\">خدمت شماره 2</td>
        <td class=\"text-center\"><a href=\"".LinkToGT("index.php?modname=$module_name&op=details&id=2")."\">مشاهده</a></td>
    </tr>
    <tr>
        <td class=\"text-center\">خدمت شماره 3</td>
        <td class=\"text-center\"><a href=\"".LinkToGT("index.php?modname=$module_name&op=details&id=3")."\">مشاهده</a></td>
    </tr>
</table>";

یه توضیح در مورد این کدها بدم.
لینک ها رو اکر متوحه شده باشین در یک تابعی به نام LinkToGT قرار دادم.
این تابع کارش تبدیل لینکهای اصلی به لینکهای ساده و کوتاهی هست که در ادامه روش این تبدیل رو آموزش میدم. اما یه کار مهم دیگه هم میکنه. این تابع لینکهایی که کامل نیستن رو به کامل میکنه. به عبارتی اگر لینکی با http:// یا امثالهم شروع نشده باشه رو بررسی میکته و لینک اصلی سایت رو در ابتدای اون اضافه میکنه. همزمان اگر لینک متناظری هم برای اون توی تنظیماتی که گفتم یافت کنه با اون لینک جایگزین میکنه.
در این صورت تحت هر شرایطی لینکهایی که در هر جای نیوک استفاده میکنین رو به این تابع بدید تا لینکهای شما کامل بشه. چون اینجا قصد توضیح در مورد این توابع رو ندارم به همین توضیحات بسنده میکنم و ادامه میدم.

خود لینکها رو یه بررسی کنیم.
همونطور که قبلا هم گفتم لینک هر ماژول بلا استثنا با این قسمت شروع میشه

کد: انتخاب همه

index.php?modname=$module_name
که اون متغیر module_name اسم ماژول هست.
و اگه قراره وارد جزئیات بشیم متغیرهای جدید به این لینک اضافه میشه

قسمت بعدی لینک

کد: انتخاب همه

op=details

این متغیر op نشون دهنده اون بخشی هست که ما به ماژولمون اضافه کردیم. اینجا ما میتونیم از file به جای op استفاده کنیم و بخش جدید رو در فایل جداگانه ای در پوشه ماژول راه بندازیم. مثلا قدیمیهای نیوک میدونن لینکهای ادامه مطلب نسخه های قبل نیوک به این شکل بود:

کد: انتخاب همه

modules.php?name=New&file=article_seo&sid=$sid
که مشخصات ادامه مطلب در فایلی به نام article_seo.php کارسازی میشد.

در نسخه جدید ما همه بخشها رو از فایلی به تابعی تغییر دادیم. هرچند حالت فایلی همچنان کار میکنه و شما اگه دوست داشتین میتونین با فایلها کار کنین.

به هر حال من ادامه آموزش رو با متغیر op و به صورت تابعی توضیح میدم.

یه نکته اینکه op اصلی هر ماژولی تابع main هست. یعنی اگر شما برای op هیچ مقداری تعیین نکرده باشید وقتی کسی آدرس صفحه اول ماژولتون رو باز میکنه op=main براش تنظیم شده. اما این main کاربردش چیه.
در ماژولهای چند بخشی باید هر بخش بخصوص بخش اول در توابع خاص خودشون قرار بگیرن. پس ما باید محتویات فایل index.php ماژولمون رو یه تغییراتی بدیم و اون جدول بالا رو در تابع main قرار بدیم. به این شکل

کد: انتخاب همه

<?php
/**
 *
 * This file is part of the PHP-NUKE Software package.
 *
 * @copyright (c) PHP-NUKE <https://www.phpnuke.ir>
 * @license GNU General Public License, version 2 (GPL-2.0)
 *
 */

if (!defined('MODULE_FILE')) {
    die ("You can't access this file directly...");
}

$module_name = basename(dirname(__FILE__));

function main() {
    global $module_name;
    $contents = '';
    $contents = "
    <table width=\"100\" class=\"table table-hover\">
        <tr>
            <th class=\"text-center\">نام خدمت</th>
            <th class=\"text-center\">عملیات</th>
        </tr>
        <tr>
            <td class=\"text-center\">خدمت شماره 1</td>
            <td class=\"text-center\"><a href=\"".LinkToGT("index.php?modname=$module_name&op=details&id=1")."\">مشاهده</a></td>
        </tr>
        <tr>
            <td class=\"text-center\">خدمت شماره 2</td>
            <td class=\"text-center\"><a href=\"".LinkToGT("index.php?modname=$module_name&op=details&id=2")."\">مشاهده</a></td>
        </tr>
        <tr>
            <td class=\"text-center\">خدمت شماره 3</td>
            <td class=\"text-center\"><a href=\"".LinkToGT("index.php?modname=$module_name&op=details&id=3")."\">مشاهده</a></td>
        </tr>
    </table>";

    include("header.php");
    $html_output .= $contents;
    include("footer.php");
}

?>
چون متغیر module_name در خارح از تابع تعریف و مقداردهی شده باید global بشه. به این صورت

کد: انتخاب همه

global $module_name;
در ابتدای تابع بالا میتونین ببینین

و حالا باید راهی برای فراخونی این تابع پیدا کنید

برای این کار این کد رو به انتهای فایل اضافه میکنیم.

کد: انتخاب همه

switch($op)
{
    default:
        main();
    break;
}
نتیجه تا اینجا به این شکل میشه.
ماژول test 2.png
حالا میخوایم بخش دوم یا همون بخش مشاهده جزئیات هر خدمت رو ایجاد کنیم.
برای این کار تابع دومی به نام details که در لینکهای بالا بهش اشاره شد رو باید بنویسیم.

این تابع وظیفه دریافت id خدمت و نمایش جزئیاتش رو داره.

برای دریافت این متغیر در نیوک دو راه وجود داره. یا متغیر رو مستقیماً از آدرس میگیره (به صورت global در خود تابع) که خیلی خطرناکه و ممکنه عواقب سنگینی داشته باشه یا از طریق فیلترهایی این متغیر به تابع ارسال میشه.

خوب اول یه وضعیت جدید به switch اضافه میکنیم که برای op=details چه تابعی مد نظرمون هست.
نکته :الزامی برای اینکه نام تابع متناظر با op ما هم اسم باهاش باشه نیست. مثلا من میتونم اسم تابع جدید رو بزارم show_details

کد: انتخاب همه

switch($op)
{
    default:
        main();
    break;
    case"details":
        details($id);
    break;
}

برای فی.لت.ر کردن متغیرها و داده های ورودی از طرف کاربر یا لینک صفحه، قبل از شرط switch باید این کار رو انجام داد. به این شکل

کد: انتخاب همه

$op = isset($op) ? filter($op, "nohtml") : "";
خود متغیر op رو فی.لت.ر کردیم که اگر مقدار داشت فی.لت.ر بشه در غیر این صورت خالی بشه و شرط switch تابع main رو اجرا کنه.

کد: انتخاب همه

$id = (isset($id) && intval($id) > 0) ? intval($id) : 0;
متغیر id رو در صورتی که تعریف شده باشه و مقدار هم داشته باشه فی.لت.ر میکنیم و در غیر این صورت عدد 0 رو براش در نظر میگیرم.

حالا در زیر تابع main تابع details رو شروع میکنیم. من تابع رو مینویسم و بعد توضیحاتش رو میدم

کد: انتخاب همه

function details($id) {
    global $module_name;
    
    $id = intval($id);
    $name_details = '';
    
    switch($id) {
        case"1":
            $name_details = "توضیحات خدمت شماره 1";
        break;
        case"2":
            $name_details = "توضیحات خدمت شماره 2";
        break;
        case"3":
            $name_details = "توضیحات خدمت شماره 3";
        break;
        default:
            $name_details = "هیچ خدمتی انتخاب نشده است";
        break;
    }
    
    $contents = '';
    $contents = "<p class=\"text-center\">$name_details</p>";
    
    include("header.php");
    $html_output .= $contents;
    include("footer.php");
}

خوب همه چی واضحه. برای هر id یک توضیحات خدمت درج شده و در صورتی که id مقدارش به در هر دلیلی 0 باشه پیغام جداکانه ای در نظر گرفته شده.

در نیوک هر مازولی که ساخته میشه به صورت پیش فرض لینک کوتاهش میشه به این شکل:

کد: انتخاب همه

http://www.site.com/test/
ولی باید حتما این لینکها تعریف بشن.در پست بعدی با نحوه تعریف لینکها و چگونگی مدیریتشون توضیح میدم.
شما دسترسی جهت مشاهده فایل پیوست این پست را ندارید.
Phpnuke.ir
نمایه کاربر
iman64
مدیر کل سایت
مدیر کل سایت
پست: 3479
تاریخ عضویت: شنبه ۱۸ اسفند ۱۳۸۶, ۸:۳۰ ب.ظ
محل اقامت: ایران سرافراز - بوشهر - دلوار
تشکر کرده: 397 دفعه
تشکر شده: 4754 دفعه

آموزش طراحی ماژول نیوک - مدیریت لینکهای ماژولها

پست توسط iman64 »

خوب حالا با دو فایل دیگه برای هر ماژول آشنا میشیم.
1. فایل config_functions.php
2. فایل GT-test.php

فایل config_functions.php برای نگهداری توابع و تنظیمات اختصاصی هر ماژول هست که در همه جای نیوک قابل بهره برداری هست. یعنی اگر تابعی یا متغیری تو این فایل تعریف بشه هر جای نیوک که لازم بود امکان دسترسی بهشون هست.

فایل GT-test.php برای نگهداری ساختار لینکهای هر ماژول به کار میره.

تو این پست قصد مدیریت لینکهای هر ماژول رو داریم.
همونطور که قبلا هم گفتم لینک هر ماژول به طور پیشفرض اسم اون ماژول هست مگر اینکه ما چیز دیگه ای تعریف کنیم براش. در مثال ما لینک ماژول به این شکل بود

کد: انتخاب همه

http://www.site.com/test/

تو این فایل ما دو متغیر از نوع آرایه داریم:
1. friendly_links
که وظیقه تبدیل لینکهای اصلی هر ماژول به لینکهای کوتاه تر و به عبارتی کاربر پسند تر رو بر عهده داره.
هر عنصر این آرایه از یک key  و یک value تشکیل شده که key لینک اصلی و value مقدار تبدیل شده هست.
value در این قسمت به دو روش مقدار دهی میشه. یا مستقیماً و به وسیله regex ها تنظیم میشه یا در صورتی که نیاز به عملیات بیشتری روی متغیرهای لینک اصلی هست باشه از طریق تابع مقدار دهی میشه. که تابع متناظر باهاش رو در فایل config_functions.php تابع باید تعریف کنیم.
نمونه هایی از مقدار دهی:

کد: انتخاب همه

$friendly_links = array(
    "index.php\?modname=test$" => "test/",
);

به صورت پیشفرض این حالت برای هر ماژول تنظیم شده و اگر ما این عنصر رو هم به این آرایه اضافه نکنیم این حالت اتفاق میفته مگر اینکه ما بخوایم لینک ماژول رو تغییر بدیم. مثلا به این شکل

کد: انتخاب همه

$friendly_links = array(
    "index.php\?modname=test$" => "my-module/",
);
در این صورت لینکهای این ماژول با این لینک باز میشه:

کد: انتخاب همه

http://www.site.com/my-module/
نکته: الگوها عیناً بررسی میشه و کوچکترین مغایرتی در الگوها نتیجه درستی به ما نمیده.

یه نکته مهم در زمینه تنظیم لینکها اینه که هربار خواستید نتیجه رو بررسی کنید باید از بخش مدیریت سایت - ذخیره و بهینه سازی کش مربوط به لینکهای گوگل تب رو بازسازی کنید. یا میتونین کلاً کش رو تخلیه کنید. در غیر این صورت نتیجه تغییرات رو مشاهده نمیکنین

حالا میخوایم برای صفحه جزئیات خدمت لینک جدیدی بدیم. به این لینک دقت کنین:

کد: انتخاب همه

index.php?modname=test&op=details&id=1
ما باید برای این قسمت از کدمون یه الگو داشته باشیم.
همونطور که مشخصه فعلا عدد 1 هست که تو ماژول ما تغییر میکنه. پس یک الگوی regex برای بررسی عدد بودنش بهش میدیم. نتیجه میشه این

کد: انتخاب همه

&op=details&id=([0-9]*)
حالا متناظر این الگو باید یک لینک دلخواه تعیین کنیم مثلا به این شکل:

کد: انتخاب همه

test/details/$1/

و نتیجه کلی:

کد: انتخاب همه

$friendly_links = array(
    "index.php\?modname=test&op=details&id=([0-9]*)$" => "test/details/$1/",
    "index.php\?modname=test$" => "test/",
);

از این به بعد هر جا در نیوک شما لینکهای

کد: انتخاب همه

index.php?modname=test&op=details&id=1
رو به تابع LinkToGT بدید نتیجه ای به این شکل برای شما بر میگردونه

کد: انتخاب همه

test/details/1/
ماژول test 3.png

در پست بعدی روشهای بعدی رو توضیح میدم.
 
شما دسترسی جهت مشاهده فایل پیوست این پست را ندارید.
Phpnuke.ir
نمایه کاربر
iman64
مدیر کل سایت
مدیر کل سایت
پست: 3479
تاریخ عضویت: شنبه ۱۸ اسفند ۱۳۸۶, ۸:۳۰ ب.ظ
محل اقامت: ایران سرافراز - بوشهر - دلوار
تشکر کرده: 397 دفعه
تشکر شده: 4754 دفعه

آموزش طراحی ماژول نیوک

پست توسط iman64 »

یک روش دیگه برای تعیین مقدار value استفاده از تابع است. زمانی از تابع استفاده میکنیم که یا تعیین regex دلخواه ما مشکل باشه یا واقعا نیاز به بررسی متغیرهای ورودی باشه.
در این صورت به جای اینکه برای value یک رشته تعیین کنیم یک آرایه تعریف میکنیم. به این شکل

کد: انتخاب همه

$friendly_links = array(
    "index.php\?modname=test&op=details&id=([^/]+)?$" => array("parse_test_link"),
);

تو این قسمت ما الگوی متغیر id رو از عددی فراتر بردیم و گفتیم هر چی بود تابع parse_test_link زحمت بررسی رو بکشه و یه نتیجه مناسب ارائه بده
اینجا ممکنه id یک مقداری غیر از عدد داشته باشه.

اما این تابه parse_test_link کجاست.
ما باید این تابع رو در فایل config_function.php ماژول قرار بدیم.

قبلش اجازه بدید من در مورد خود محتویات فایل config_function.php یه توضیحی بدم. این فایل هم باید در ابتداش یک فیلتری به این شکل قرار بگیره

کد: انتخاب همه

if (!defined('CONFIG_FUNCTIONS_FILE')) {
    die("You can't access this file directly...");
}
$this_module_name = basename(dirname(__FILE__));
که دسترسی برای اجرای مستقیم این فایل رو میبنده
متغیر this_module_name هم برای نگهداری اسم ماژول و عدم تداخلش با متغیر module_name هست که بعداً در تنظمیات همین فایل به درد میخوره.

خوب تابع رو به این شکل تعریف میکنیم.

کد: انتخاب همه

function parse_test_link($matches)
این تابع یک آرگومان داره که مربوط به همون regex آخر در

کد: انتخاب همه

"index.php\?modname=test&op=details&id=([^/]+)?$"
هست یعنی هر چیزی بعد از id اومد رو بفرست برای تابع
تو ماژول تست ما ابن هر چیزی فقط یک عدد هست و ممکنه در ماژولهای دیگه مقادیر متفاوتی باشه. برای نمونه میتونین سایر ماژولهای پیشفرض نیوک رو چک کنین. مثل ماژول جستجو

تو این تابع ما با عنصر شماره 1 کار داریم.
البته همه ی این توضیحات مثالی هست و شما بنا به نیازتون میتونین از هر قسمت این آرگومان استفاده کنید.
اگر عنصر شماره 1 آرگومان یک رشته از متغیرها و مقادیرشون باشه میتونیم هر متغیر و مقدارش رو درون یک آرایه بریزیم و به این ترتیب بهش یک نظمی بدیم.
مثلا خارج از این مثال تصور کنید عنصر شماره 1 آرگومان ما باشه

کد: انتخاب همه

fullname=iman&old=36&from=iran
ما این رشته رو به تابع parse_str میدیم تا این متغیرها رو به صورت یک آرایه منظم کنه. به این شکل

کد: انتخاب همه

    if(isset($matches[1]))
        parse_str($matches[1], $output);

که محتویات متغیر جدید output میشه

کد: انتخاب همه

array(
    "fullname" => "iman",
    "old" => "36",
    "from" => "iran",
)

و حالا میتونیم رو این مقادیر کار کنیم و نتیجه دلخواهمون رو رقم بزنیم.

تو مثال ما عنصر شماره 1 آرگومان فقط یک عدد هست پس نیازی به این کار نیست و مستقیماً از خودش استفاده میکنیم.

کد: انتخاب همه

function parse_test_link($matches)
{
    $id = (isset($matches[1]) && $matches[1] != '') ? $matches[1]:0;
    
    $return = 'test/';
    
    if($id < 0)
        $return .= "bad-id/";
    
    if($id == 1)
        $return .= "special-product/";
    
    elseif($id == 2)
        $return .= "second-product/";
    
    else
        $return .= "$id/";
    
    return $return;
}

من به دلخواه خودم یه بررسی رو کدها انجام دادم و گفتم اگر id کمتر از 0 بود لینک bad-id رو برگردون. و اگر 1 یا 2 بود عبارتهای مشخص شده و در غیر این صورت خود id رو برگردون.

نتیجه رو میتونین خودتون ببینین.
پاک کردن کش فراموش نشه.
test.zip
شما دسترسی جهت مشاهده فایل پیوست این پست را ندارید.
Phpnuke.ir
نمایه کاربر
iman64
مدیر کل سایت
مدیر کل سایت
پست: 3479
تاریخ عضویت: شنبه ۱۸ اسفند ۱۳۸۶, ۸:۳۰ ب.ظ
محل اقامت: ایران سرافراز - بوشهر - دلوار
تشکر کرده: 397 دفعه
تشکر شده: 4754 دفعه

آموزش طراحی ماژول نیوک

پست توسط iman64 »

تا اینجا ما لینکهای اصلی رو به لینکهای کوتاه و کاربرپسند تبدیل کردیم.
حالا نوبت به این میرسه که این لینکها در صورتی که در مرورگر فراخونی شدن بازیابی بشن و به مسیر مشخصی در هسته نیوک هدایت بشن
در نسخه های قبل ما این کار رو با فایل htaccess انجام میدادیم.
استفاده از htaccess محدودیاهای خاصی داشت به عناون مثال محدودیت متغیر وحود داشت یا تو تعریف regex ها مشکلاتی بخصوص با حروف غیر لاتین پیش میومد و سایر مشکلات.
تو نسخه 8.4 ما این وظیفه رو به هسته نیوک محول کردیم که هم دستمون رو بازتر میکنه هم اون مشکلات رو مرتفع.
بر می گردیم به فایل GT-test.php
متغیر دیگری در این فایل تعریف میکنیم تحت عنوان : rewrite_rule
این متغیر هم یک آرایه هست و key اصلیش اسم تابع میشه.
به این شکل

کد: انتخاب همه

$rewrite_rule["test"] = array(
    //
);

حالا ما باید برای تمام لینکهایی که الگوشون رو قبلا به سیستم دادیم اینجا حالت بازگشنی بدیم. به عنوان مثال ما تو پست قبل تعیین کردیم که اگر id خدمت شماره 1 بود سیستم لینک زیر رو برگردونه

کد: انتخاب همه

test/special-product/
خوب اگر این لیتم در مرورگر فراخونی شد سیستم از کجا بفهمه چه خدمتی رو باید نمایش بده ؟
تو این مرحله هم مثل پست قبل عناصر آرایه از یک key که همون لینک ساده و کاربرپسند هست و یک value که مسیر اجرای این درخواست در ماژول مورد نظر هست رو نشون میده.
فرض کنیم اون تغییرات آخر رو نداشتیم و متغیر friendly_links ما به این شکل بود:

کد: انتخاب همه

$friendly_links = array(
    "index.php\?modname=test&op=details&id=([0-9]*)$" => "test/details/$1/",
    "index.php\?modname=test$" => "test/",
);

حالا ما باید متغیر rewrite_rule رو به این شکل تعریف کنیم

کد: انتخاب همه

$rewrite_rule["test"] = array(
    "test/details/([0-9]*)/$" => "index.php?modname=test&op=details&id=$1",
    "test/$" => "index.php?modname=test",
);

اگر خوب دقت کنید متوحه میشید که همه جای key  و value تغییر کرد هم ترتیب قرارگیری عناصر.

حالا فرض کنید تغییرات آخر پست قبل وجود داشت یعنی متغیر friendly_links ما به این شکل بود

کد: انتخاب همه

$friendly_links = array(
    "index.php\?modname=test&op=details&id=([0-9]*)$" => array("parse_test_link"),
    "index.php\?modname=test$" => "test/",
);

حالا ما باید متغیر rewrite_rule رو به این شکل تعریف کنیم

کد: انتخاب همه

$rewrite_rule["test"] = array(
    "test/([^/]+)?/$" => array("parse_details_test_link"),
    "test/$" => "index.php?modname=test",
);

پس باید یک تابع جدید در فایل config_function.php تعبیه کنیم. به این شکل

کد: انتخاب همه

function parse_details_test_link($matches) {

    $matches[1] = trim($matches[1], "/");
    
    $id = (isset($matches[1]) && $matches[1] != '') ? $matches[1]:0;

    $return = "index.php?modname=test&op=details";
    
    if($id == 'bad-id')
        $return .= "&id=0";
    elseif($id == 'special-product')
        $return .= "&id=1";
    elseif($id == 'second-product')
        $return .= "&id=2";
    else
        $return .= "&id=$id";
        
    return $return;
    
}

حالا همه لینکهایی که تا اینجا برای این تابع در نظر گرفتیم کار میکنن.
ما برای طراحی ماژولمون باید این قسمت لینکها رو قبل از بقیه قسمتها توضیح میدادیم تا موقع چرخیدن تو بخشهای مختلف به مشکل لینک بر نخوریم.

من ماژول سادمون رو تا اینجای کار برای مشاهده بهتر نتیجه پیوست میکنم.
شما دسترسی جهت مشاهده فایل پیوست این پست را ندارید.
Phpnuke.ir
نمایه کاربر
iman64
مدیر کل سایت
مدیر کل سایت
پست: 3479
تاریخ عضویت: شنبه ۱۸ اسفند ۱۳۸۶, ۸:۳۰ ب.ظ
محل اقامت: ایران سرافراز - بوشهر - دلوار
تشکر کرده: 397 دفعه
تشکر شده: 4754 دفعه

آموزش طراحی ماژول نیوک - اعتبار سنجی داده های ورودی

پست توسط iman64 »

خوب تو این قسمت میخوام در مورد فی.لت.ر کردن متغیرهای ورودی هر ماژول صحبت کنیم.
ما ممکنه متغیرهای متعدد با انواع مختلفی لازم باشه از ورودی یا از کاربر بگیریم. برای اینکه این متغیرها قبل از استفاده فی.لت.ر بشن وبدون هیچ خطر امنیتی وارد توابع ماژولها بشن دو روش وجود داره:
1. متغیرهای ورودی قبل از شرط switch بررسی و فیتر بشن.
2. متغیرها درون هر تابع global بشه و بعد فی.لت.ر بشه.

ما تو نیوک از روش اول استفاده کردیم. شما اگه دوست داشتین میتونین از روش دوم استفاده کنین.

با توجه به اینکه در شرط switch ما توابعی که بر اساس op قراره فراخونی بشن رو با متغیرهایی همراه میکنیم میابیست قبل از اجرای این توابع متغیرهاشون رو مقدار دهی کنیم در غیر این صورت سیستم خطا بر میگردنه.

به ازای هر تعداد متغیر در توابع باید یکبار این کار رو انجام بدیم.

فرض کنید تابع details در ماژول نمونه علاوه بر id متغیرهای title و fields رو هم قراره استفاده کنه که اولی از نوع یک رشته کاراکتری و دومی از نوع آرایه باشه
به این شکل فیلترشون میکنیم.

کد: انتخاب همه

$op    = isset($op) ? filter($op, "nohtml") : "main";
$title    = isset($title) ? filter($title, "nohtml") : "";
$id    = (isset($id) && intval($id) > 0) ? intval($id) : 0;
$fields    = request_var('fields', array('name' => 'nuke', 'code' => 843), "_POST");

متغیر اول همون op هست که قبلا در موردش توضیح داده بودیم
متغیر دوم title هست که با تابع filter فی.لت.ر شده.
متغیر سوم هم از نوع عددی برای id هست.
متغیر سوم بر اساس یک روش که تو نسخه 8.4.3 اضافه شده فی.لت.ر شده. در این روش از تابع request_var استفاده میکنیم که سه آرگومان داره.
آرگومان اول اسم فیلدی هست که قراره از ورودی گرفته بشه
آرگومان دوم مقدار پیشفرض هست در صورتی که این متغیر در اعتبار سنجی دچار مشکل بشه یا خالی ارسال شده باشه
آرگومان سوم برای متغیرهایی هست که به صورت post یا get قراره اعتبار سنجی بشن. یعنی اگر ما اینجا نوع ورودی field رو گذاشتیم بر اساس POST دیگه این متغیر نمیتونه به صورت GET ارسال بشه و حتماً باید از طریق فرم ارسال شده باشه.
این قابلیت امنیت داده های ورودی از طرف کاربر رو خیلی بالاتر میبره.
تابع request_var میتونه برای انواع دیگه ای هم استفاده بشه و صرفا مختص آرایه ها نیست.


 
Phpnuke.ir
نمایه کاربر
iman64
مدیر کل سایت
مدیر کل سایت
پست: 3479
تاریخ عضویت: شنبه ۱۸ اسفند ۱۳۸۶, ۸:۳۰ ب.ظ
محل اقامت: ایران سرافراز - بوشهر - دلوار
تشکر کرده: 397 دفعه
تشکر شده: 4754 دفعه

آموزش طراحی ماژول نیوک

پست توسط iman64 »

تو این قسمت وارد توابع ماژولها میشیم.
ما روی تابع details ماژول تستمون مثال رو ادامه میدیم.
در کل هر ماژول الگوریتم خاص خودش رو داره و ما قصد نداریم اختصاصی در مورد این امور صحبت کنیم. مثلا اینکه ماژول فروشگاه چی کار میکنه تو این بحث نمیگنجه ولی موراد عمومی رو تو این پست تشریح میکنم که لازمه هر ماژولی هست.
اولین مورد عنوان صفحه هست. همونطور که گفتم هر ماژول میتونه یه صفحه برای سایت شما ایجاد کنه که لزوماً اون صفحه یک مطلب خبری یا امثالهم نیست و میتونه مثلا یه فرم، یه گالری و یا غیره باشه پس باید یه عنوان داشته باشه.
ما همه این اطلاعات رو در متغیری به نام meta_tags نگهداری میکنیم. به این شکل

کد: انتخاب همه

$meta_tags = array(
        "url"                => LinkToGT($page_url),
        "title"                => $page_title,
        "description"        => '',
        "keywords"            => '',
        "prev"                => '',
        "next"                => '',
        "extra_meta_tags"    => '',
    );

عنصر اول url هست که آدرس صفحه حاضره. این لینک در هدر سایت قرار میگیره. البته هر جای دیگه هم لازم باشه قابل استفاده هست.
عنصر بعدی عنوان هست که در بالای مرورگر خودشو نشون میده و باز هم در هدر سایت قرار میگیره.
عنصر بعدی توضیحات مختصری در مورد صفحه هست که این هم تو هدر قرار میگیره.
عنصر بعدی کلمات کلیدی صفحه هست.
عنصر بعدی prev و بعدش next هست که اگر ماژولتون طوری باشه که صفحات مرتبط به هم داشته باشه میتونین صفحه بعدی و قبلی رو به سیستم معرفی کنین که این مورد علاوه بر اینکه در هدر قرار میگیره در قسمتهای دیگه سایت هم قابل استفاده هست.
عنصر بعدی متاتگ های اضافی هست که شاید بخواید در هدر سایتتون در صفحه مورد نظر قرار بگیره که بنا به محتویات صفحه قابل تغییر هست.مثلا در ماژول مطالب این کد رو ببینید:

کد: انتخاب همه

"extra_meta_tags"    => ($catid > 0) ? array(
            "<link rel=\"alternate\" type=\"application/atom+xml\" title=\"Atom - $cat_title\" href=\"".LinkToGT("index.php?modname=Feed&module_link=".$nuke_configs['REQUESTURL']."")."\" />\n"
        ):"",
این داره میگه اگر موضوع فراخونی شده باشه خروجی یا فید مربوط به اون موضوع هم در هدر سایت قرار بگیره در غیر این صورت هیچی.
بعد از این قسمت باید این اطلاعات رو وارد سیستم کنیم. این کار رو با فیلترها انجام میدیم.
در خصوص فیلترهای مختلف در نیوک در تاپیک دیگه ای توضیحات رو دادم.
فعلا در حد کاربرد بدونید

کد: انتخاب همه

$hooks->add_filter("site_header_meta", function ($all_meta_tags) use($meta_tags)
    {
        return array_merge($all_meta_tags, $meta_tags);
    }, 10);        
    unset($meta_tags);
در آخر هم این متغیر رو unset میکنیم تا حافظه رو اشغال نکنه.


در قسمت بعدی ما باید چیدمان بلوکی هر ماژول یا صفحه رو مشخص کنیم.
در حال حاضر ماژول مطالب که شامل پستها، گالری تصاویر، مقالات، دانلودها، سؤالات رایج و صفحات اضافه میشه امکان تعریف چیدمان اختصاصی برای هر صفحه و هر مطلب رو جداگونه داره.

کد: انتخاب همه

$contents = show_modules_boxes($module_name, 'details', array("bottom_full", "top_full","left","top_middle","bottom_middle","right"), $contents);

این یه کد کامل برای این قسمت هست.
متغیر contents که قبلتر محتویات اصلی صفحه رو در خودش نگهداری کرده وارد تابع show_module_boxes میشه و طی فرآیندی خروجی دیگری همراه با بلوکها رو ارائه میده. اما این تابع چه آرگومانهایی داره و کارش چیه:
آرگومان اول نام ماژولی هست که ما ساختیم که ما اینجا از متغیر module_name استفاده کردیم.
آرگومان دوم آی دی صفحاتی هست که قراره چیدمان بلوکی خاصی داشته باشن.
اما این آی دی ها کجا تعریف میشه
در فایل config_function ماژول باید یه همچین کدی رو اضافه کنیم

کد: انتخاب همه

function test_boxes_parts($nuke_modules_boxes_parts)
{
    $nuke_modules_boxes_parts['test'] = array(
        "index" => _INDEX,
        "details" => _TEST_DETAILS,
    );
    
    return $nuke_modules_boxes_parts;
}

$hooks->add_filter("modules_boxes_parts", "test_boxes_parts", 10);
همونطور که میبینین این ماژول تا اینجا دو بخش داره. index و details که مقدار این ها رو تو فایل زبان ماژول میتونیم تعریف کنیم. در مورد فایل زبان تو پست جداگانه ای توضیح میدم.

این دو عنصر خودشون رو تو مدیریت ماژولها -> ویرایش ماژول -> چیدمان بلوکی نشون میده. میتونین برای مثال ماژولهایی پیش فرض نیوک رو چک کنین.

خوب ما آی دی details رو برای این صفحات مشخص کردیم و تو مدیریت اکر چیدمان بلوکی خاصی برای این قسمت تعریف کردیم اینجا خودشو نشون میده
آرگومان سوم یه آرایه هست که عناصرش به این ترتیب هست:
bottom_full : بلوکهایی که زیر محتویات ماژول نشون داده میشن
top_full : بلوکهایی که بالای محتویات ماژول نشون داده میشن
left: بلوکهای سمت چپ
right: بلئوکهای سمت راست
top_middle: بلوکهای بالای محتویات اصلی ماژول
bottom_middle : بلوکهای زیر محتویات اصلی ماژول
این تصویر نمای کلی رو بهتون میده

چیدمان.png

وقتی همه عناصر بالا رو در این آرایه قرار بدیم یعنی این ماژول مجازه همه قسمتهایی که در چیدمان بلوکی امکان تعریف دارن رو داشته باشه. مثلا اکر left رو نداشته باشه تو مدیریت هر چی بلوک برای سمت چپ هم انتخاب کنین تو ماژول نشون داده نمیشه.

آرگوکان بعدی محتویات اصلی ماژول هست که قبلتر مقدار دهی شده و قراره بین این بلوکهای قرار بگیره

آرگومان بعدی که تو این مثال نیومده شماره آی دی بلوکهایی هست که میخواین فقط همینا نشون داده بشه.

نکته ای که باید بگم اینه که تو بخش چیدمان بلوکی ماژولها ما باید باکهسایی که قبلا تو مدیریت بلوکها تشکیل دادیم رو تو ماژول قرار بدیم. یه باکس میتونه چندین بلوک داشته باشه.
حالا اگه ما چند تا بلوک رو مثلا تو مجموعه right قرار بدیم و فقط بخوایم یکی از اون بلوکها تو ماژول ما نشون داده بشه اینجا شماره آی دیش رو وارد میکنیم.

آرگومان بعدی برعکس آرگومان قبلی عمل میکنه و شماره آی دی بلوکهایی هست که ما نمیخوایم تو ماژول نشون داده بشن حتی اگه تو مجموعه بلوک مورد نظر وجود داشته باشه.
مثلا فرض کنید مجموعه left شامل بلوکهای آمار کاربران، آخرین مطالب و محبوبترین مطالب باشه
آیدیشون هم به این شکل باشه:
آمار کاربران 3
آخرین مطالب 5
محبوبترین مطالب 6
حالا اگه بخواین فقط بلوک محبوبترین ها نشون داده بشه این کار رو میکنیم.

کد: انتخاب همه

$contents = show_modules_boxes($module_name, 'details', array("bottom_full", "top_full","left","top_middle","bottom_middle","right"), $contents, array(6));

حالا اگه بخواین همه بلوکها نشون داده بشه بجز آمار کاربران این کار رو میکنیم.

کد: انتخاب همه

$contents = show_modules_boxes($module_name, 'details', array("bottom_full", "top_full","left","top_middle","bottom_middle","right"), $contents, array(), array(3));

و در نهایت باید متغیر contents رو که حالا تقریبا کل محتویات سایت رو جمع کرده دور خودش رو به خروجی سایت بفرستیم.
به این شکل

کد: انتخاب همه

include("header.php");
    $html_output .= $boxes_contents;
    include("footer.php");
    
این کل کارهایی هست که ما باید به صورت عمومی برای توابع ماژولمون استفاده کنیم.
شما دسترسی جهت مشاهده فایل پیوست این پست را ندارید.
Phpnuke.ir
نمایه کاربر
iman64
مدیر کل سایت
مدیر کل سایت
پست: 3479
تاریخ عضویت: شنبه ۱۸ اسفند ۱۳۸۶, ۸:۳۰ ب.ظ
محل اقامت: ایران سرافراز - بوشهر - دلوار
تشکر کرده: 397 دفعه
تشکر شده: 4754 دفعه

آموزش طراحی ماژول نیوک

پست توسط iman64 »

خوب حالا اگر ماژول چند زبانه باشه باید یه پوشه به نام language به ماژولمون اضافه کنیم.
تو این پوشه دو فایل index.html و .htaccess رو میتونین از ماژولهای دیگه کپی کنین و بزارین.
برای هر زبانی که تو ماژولمون قراره پشتیبانی کنیم باید یه فایل هم با محتوای زیر اضافه کنیم:
این برای زبان فارسی هست.

کد: انتخاب همه

<?php

if (empty($nuke_languages['farsi']) || !is_array($nuke_languages['farsi']))
{
    $nuke_languages['farsi'] = array();
}

$nuke_languages['farsi'] = array_merge($nuke_languages['farsi'], array(
    "_TEST_PHRASE1" => "عبارت تستی 1",
    "_TEST_PHRASE2" => "عبارت تستی 2",
    "_TEST_PHRASE3" => "این مثال %d بازدید داشته و در موضوع %s دسته بندی شده است.",
));
?>
توجه کنید که باید عبارت farsi با نام فایل یکی باشه.

این که نام فایل چی باشه هم بستگی به زبانهایی داره که در پوشه language اصلی نیوک تعریف شدن. تا الآن farsi , english تعریف شده.

تو مثال بالا عبارت سوم رو اگر دقت کنید با کاراکترهایی همراه شده. ما وقتی تو ماژولمون نیاز داشته باشیم یک عبارتی رو با مقادیر مختلفی بنا به شرایط خاصی نمایش بدیم به جای اینکه عبارت رو چند تکه کنیم و مقادیر لازم رو بینشون جاسازی کنیم از این روش استفاده میکنیم. مثال این قسمت به این شکل میشه:

کد: انتخاب همه

$contents .= sprintf(_TEST_PHRASE3, 5, "موسیقی");
نتیجه عملیات بالا میشه این:

کد: انتخاب همه

این مثال 5 بازدید داشته و در موضوع موسیقی دسته بندی شده است.
در مورد نحوه کار تابع sprintf میتونین اینجا توضیحات بهتر و کاملتری رو ببینید.
Phpnuke.ir
نمایه کاربر
iman64
مدیر کل سایت
مدیر کل سایت
پست: 3479
تاریخ عضویت: شنبه ۱۸ اسفند ۱۳۸۶, ۸:۳۰ ب.ظ
محل اقامت: ایران سرافراز - بوشهر - دلوار
تشکر کرده: 397 دفعه
تشکر شده: 4754 دفعه

آموزش طراحی ماژول نیوک

پست توسط iman64 »

خوب تو این قسمت میریم سراغ مدیریت ماژول
مدیریت ماژولها رو به سه روش میتونیم انجام بدیم.
اول اینکه یه سری تنظیمات رو تو فایل config_function.php بزاریم و هر بار لازم بود از طریق ویرایش فایل تغییرشون بدیم(اصلاً پیشنهاد نمیشه این روش)
روش دوم اینه که اگر ماژول صرفا تنظیمات داره و مدیریت آنچنانی نداره به عنوان یک تب جدید در مدیریت سایت -> تنظیمات سیستم اضافه کنیم. مثل تنظیمات نظرات، زبان، قالب و ...
برای این کار یه تابع تو فایل config_function.php ماژول تعریف میکنیم و محتویاتش رو به این شکل تنظیم میکنیم:

کد: انتخاب همه

function test_module_config()
{
    global $nuke_configs, $db, $admin_file;
    
    $contents = '';
    $test_module_config = (isset($nuke_configs['test_module_config']) && $nuke_configs['test_module_config'] != '') ? phpnuke_unserialize(stripslashes($nuke_configs['test_module_config'])):array();
    
    $contents .= "
    <div class=\"text-center\"><font class='option'><b>"._TEST_MODULES_CONFIGS."</b></font></div>
        
    <form action='".$admin_file.".php' method='post'>
        <table border=\"0\" align=\"center\" cellpadding=\"3\" class=\"id-form product-table no-border\" width=\"100%\">
            <tr>
                <th>عنوان فیلد</th>
                <td>
                    <input type=\"text\" name=\"config_fields[test_module_config][field]\" size=\"40\" class=\"inp-form-ltr\" value=\"".$test_module_config['field']."\">
                </td>
            </tr>        
            <tr>
                <td colspan=\"2\"><input type='hidden' name='op' value='save_configs'>
                    <input type='hidden' name='return_op' value='settings#test_module_config'>
                    <input type=\"hidden\" name=\"csrf_token\" value=\""._PN_CSRF_TOKEN."\" />
                    <input class=\"form-submit\" type='submit' name='submit' value='" . _SAVECHANGES . "'>
                </td>
            </tr>
        </table>
    </form>";
    
     return $contents;
}
و بعدش این کد رو اضافه میکنیم

کد: انتخاب همه

$other_admin_configs['test_module_config'] = array("title" => "_TEST_MODULES_CONFIGS", "function" => "test_module_config", "God" => false);

این آرایه سه عنصر داره:
اولی عنوان تب تنظیمات هست. ثابت _TEST_MODULES_CONFIGS رو باید حتماً قبلش تو فایل زبان تعریف شده باشه.

دومی اسم تابعی که تنظیمات از اون طریق انجام نمیشه
سومی هم در صورتی که مدیریت این قسمت صرفا برای مدیریت اصلی سایت یا همون God باشه true و در غیر این صورت false میزاریم.
نتیجه به این شکل میشه

newtab.png
من عمدا اون ارور بالای فیلد رو نشون دادم که یه نکته رو ذکر کنم. چون هنوز این فیلد تو تنظیمات سیستم وارد نشده به عنوان یک متغیر ناشناس دیده شده. بعد که مقدار دهی کردیم و ارسال رو زدیم این ارور رفع میشه. جای نگرانی نیست.

و بعدش تو توابع ماژول میتونیم از این تنظیمات به این شکل استفاده کنیم. فرض کنید تو تابع details بخوایم این کار رو کنیم

کد: انتخاب همه

function details($id) {
    global $module_name, $nuke_configs;
    
    $test_module_config = (isset($nuke_configs['test_module_config']) && $nuke_configs['test_module_config'] != '') ? phpnuke_unserialize(stripslashes($nuke_configs['test_module_config'])):array();
    .....

این ساده ترین روش برای مدیریت تنظیمات ماژول هست. این در صورتیه که ماژول محتوا نداشته باشه. مثلا برای ماژول ثبت نام آنلاین باید کار رو فراتر ببریم و اطلاعات ورودی و عملیات بعدیش رو کنترل کنیم.

روش سوم
برای این کار باید یه پوشه به ماژول اضافه کنیم به نام admin
سه فایل تو این پوشه لازم داریم.
case.php:
این فایل کارش اینه که وقتی ما یه درخواستی رو سمت فایل مدیریت اصلی نیوک میفرستیم و به ماژول و op خاصی اشاره میکنیم فایلی رو که این توابع توش قرار گرفته برای ما بر میگردونه.
محتواش باید به این شکل باشه:

کد: انتخاب همه

<?php

if (!defined('ADMIN_FILE'))
{
    die ("Access Denied");
}

$module_name = dirname(__FILE__);
$module_name = explode("/", str_replace("\\","/", $module_name));
array_pop($module_name);
$module_name = end($module_name);

switch($op)
{
    case "test_admin":
    case "test_admin_save":
        include("modules/$module_name/admin/index.php");
    break;
}

?>

مثلا ما دو تابع test_admin برای مدیریت محتوای ماژول و test_admin_save برای ذخیره اون محتوا در نظر گرفتیم.
همه اینا تستیه و شاید معنی خاصی هم نداشته باشه. میخوام فقط با چند و چون کار آشنا بشید.

links.php
این فایل برای اضافه کردن یه آیکون به آیکونها صفحه اول مدیریت نیوک هست.
محتواش باید به این شکل باشه:

کد: انتخاب همه

<?php

if (!defined('ADMIN_FILE')) {
    die ("Access Denied");
}

global $admin_file;

$module_name = dirname(__FILE__);
$module_name = explode("/", str_replace("\\","/", $module_name));
array_pop($module_name);
$module_name = end($module_name);

$module_menus = adminmenu("".$admin_file.".php?op=test_admin", ""._TEST_ADMIN."", "modules/$module_name/includes/test.png");
?>
برای تابع adminmenu چند آرگومان در نظر داریم:
اولی لینک صفحه اصلی مدیریت ماژول هست.
دومی عنوان زیر آیکون هست
سومی هم لینک عکس آیکون هست. مثلا ما اینجا یه عکس تو مسیر مورد نظر اضافه کردیم. این لینک حتی میتونه به خارج از سایت هم باشه.

نکته اینکه ما میتونیم به هر تعداد بخوایم آیکون اضافه کنیم به مدیریت. کافیه این خط رو تکرار کنیم و مقادیر دلخواه رو اضافه کنیم.مثلا اینجوری:

[/code]$module_menus = adminmenu("".$admin_file.".php?op=test_admin", ""._TEST_ADMIN."", "modules/$module_name/includes/test.png");
$module_menus = adminmenu("".$admin_file.".php?op=test_admin_main", ""._TEST_ADMIN_MAIN."", "modules/$module_name/includes/test_main.png");
$module_menus = adminmenu("".$admin_file.".php?op=test_admin_module", ""._TEST_ADMIN_MODULE."", "modules/$module_name/includes/test_admin_module.png");
[/code]

index.php
این فایل هم قراره مدیریت ماژول رو بر عهده بگیره.
ساختار این فایل هم کم و بیش شبیه index.php خود ماژول هست. شمای کلی به این شکل هست :

کد: انتخاب همه

<?php

if (!defined('ADMIN_FILE')) {
    die ("Access Denied");
}

if (check_admin_permission($module_name, false, true))
{
    define("MODULE_FILE", true);

    $test_module_config = (isset($test_module_config) && !empty($test_module_config)) ? $test_module_config:((isset($nuke_configs['test_module_config']) && $nuke_configs['test_module_config'] != '') ? phpnuke_unserialize(stripslashes($nuke_configs['test_module_config'])):array());
    
    function test_admin()
    {
        global $db, $hooks, $module_name, $admin_file, $nuke_configs, $test_module_config;
            
        $contents = '';
                
        $hooks->add_filter("set_page_title", function() {return array("test_admin" => _TEST_ADMIN);});
        
        $contents .= GraphicAdmin();
        
        $contents .= OpenAdminTable();
        
        $contents .= "محتویات مدیریت ماژول";

        $contents .= "<br /><pre>".print_r($test_module_config, true)."</pre>";
        
        /*
            some php codes
        */
        
        $contents .= CloseAdminTable();
        
        phpnuke_db_error();
        include("header.php");
        $html_output .= $contents;
        include("footer.php");
    }
    
    function test_admin_save($submit, $mode, $form_type, $test_fields)
    {
        global $db, $hooks, $module_name, $admin_file, $nuke_configs, $test_module_config;
            
        /*
            some php codes
        */
        
        redirect_to("".$admin_file.".php?op=test_admin");
    }
    
    $op = (isset($op)) ? filter($op, "nohtml"):'';
    $submit = filter(request_var('submit', '', '_POST'), "nohtml");
    $mode = (isset($mode)) ? filter($mode, "nohtml"):'new';
    $form_type = (isset($form_type)) ? intval($form_type):1;
    $test_fields = request_var('credits_fields', array(), '_POST');
    
    switch($op)
    {
        default:
        case"test_admin":
            test_admin();
        break;
        
        case"test_admin_save":
            test_admin_save($submit, $mode, $form_type, $test_fields);
        break;
    }
    
} else {
    include("header.php");
    GraphicAdmin();
    OpenAdminTable();
    echo "<div class=\"text-center\"><b>"._ERROR."</b><br><br>You do not have administration permission for module \"$module_name\"</div>";
    CloseAdminTable();
    include("footer.php");
}

?>

اول کار باید حق دسترسی به مدیریت ماژول رو چک کنیم. ببینیم کدوم مدیر اجازه دسترسی داره:

کد: انتخاب همه

check_admin_permission($module_name, false, true))
این تابع سه آرگومان داره:
اولیش اسم ماژول هست
دومیش مشخص میکنه که آیا مدیر باید God باشه یا نه
سومیش مشخص میکنه که آیا این فایل مدیریت برای ماژول هست یا جزء منوهای اصلی مدیریت تیوک هست. منوهای اصلی مثل مدیریت بلوک ها یا مدریت سئو و بقیه هست که تو پوشه admin/modules قرار گرفتن.
اگر حق دسترسی وجود نداشته باشه آخر فایل این خطا رو بر میگردونیم

کد: انتخاب همه

} else {
    include("header.php");
    GraphicAdmin();
    OpenAdminTable();
    echo "<div class=\"text-center\"><b>"._ERROR."</b><br><br>You do not have administration permission for module \"$module_name\"</div>";
    CloseAdminTable();
    include("footer.php");
}

کمی پایینتر مشخص میکنیم که این فایل برای ماژول هست:

کد: انتخاب همه

define("MODULE_FILE", true);
این اختیاریه.

بعدش هم اگر تنظیمات ماژول لازم باشه فراخونی بشه این کار رو میکنیم.

کد: انتخاب همه

$test_module_config = (isset($test_module_config) && !empty($test_module_config)) ? $test_module_config:((isset($nuke_configs['test_module_config']) && $nuke_configs['test_module_config'] != '') ? phpnuke_unserialize(stripslashes($nuke_configs['test_module_config'])):array());

بقیه کار شبیه همون فایل index.php ماژول هست. یعنی توابع و بعدش متغیرها و بعدش شرط switch

کلیت کار به این شکل بود که عرض کردم.
یه نکته در مورد کد

کد: انتخاب همه

$hooks->add_filter("set_page_title", function() {return array("test_admin" => _TEST_ADMIN);});
این کد برای عنوان صفحه مدیریت هست. که به این شکل میشه نشونش داد. بعضی مواقع لازمه این عنوان با شرایی تغییر کنه. مثلا نوع محتوا وقتی عوض بشه.
تصور کنید میخوایم عنوان ابتدا مطالب باشه.
یه موقع میشه میخوایم مطالب پیش نویس رو مدیریت کنیم. به این شکل عمل میکنیم

کد: انتخاب همه

$pagetitle = "مدیریت مطالب".(($mode == "draft") ? " - پیش نویس":"").";
$hooks->add_filter("set_page_title", function() use($pagetitle){return array("test_admin" => $pagetitle);});
من تو محتوای مدیریت ماژول اون متغیر مربوط به تنظیمات مدیریت ماژول رو خروجی دادم که نتیجه اینم ببینید چجوری میشه.
این آموزش کلی طراحی ماژول نیوک بود. امیدوارم بتونیم ماژولهای خوب و با کیفیتی رو بنویسیم.
من ماژول تستی رو که تا اینجا اوکی کردیم براتون میزارم.
چند نمونه عکس از نتیجه کار رو هم اینجا میبینید.
test_admin.png
newtab.png
icon.png
شما دسترسی جهت مشاهده فایل پیوست این پست را ندارید.
Phpnuke.ir

بازگشت به “آموزش های نیوک”