آموزش ماژول نویسی در دروپال 7 - بخش هشت

By کوشا حسینی, 13 اکتبر, 2013

ماژول نویسی دروپال بخش یک
ماژول نویسی دروپال بخش دو
ماژول نویسی دروپال بخش سه
ماژول نویسی دروپال بخش چهار
ماژول نویسی دروپال بخش پنج
ماژول نویسی دروپال بخش شش
ماژول نویسی دروپال بخش هفت
 

در بخش‌های قبلی مقاله ماشین حساب ساده‌ای نوشتیم، که فقط عملیات جمع، ضرب، تقسیم و تفریق رو انجام می‌داد. برای گسترش قابلیت‌های ماشین حساب، باید عملیات جدید رو به تایع _my_calculator_calculate اضافه کنیم. این کار چندین مشکل رو در بر داره. برای افزودن قابلیت‌های جدید نیاز به ایجاد تغییر در کدهای اصلی خودمون هستیم. همچنین اگر توسعه‌دهندگان دیگری بخواهند عملیات دیگری به این ماشین حساب اضافه کنند، نیاز به Patch زدن روی ماژول اصلی هست. باید راه بهتری برای توسعه‌پذیری ماژول ماشین حساب درنظر بگیریم. می‌تونیم هوکی رو در ماژول خودمون معرفی کنیم که امکان تعریف عملیات حسابی رو به سایر توسعه دهندگان می‌ده. بعد لازمه توی فرم، نتایج هوک‌های پیاده‌سازی شده رو جمع‌آوری کنیم و به عنوان عملیات ممکن نشان بدیم. در زمان ثبت فرم هم باز با مراجعه به اطلاعات هوک‌ها، تابع مسؤل محاسبه نتیجه رو پیدا کنیم و اطلاعات فرم رو در اختیار اون قرار بدیم. سیستم هوک برای چنین کار ساده‌ای، به قول فرنگی‌ها! overkill حساب می‌شه. سیستم plugin یا افزونه‌ها سیستم جامع‌تریست که درک ساختار کلی هر plugin رو ساده‌تر می‌کنه. در ابتدا شاید نحوه‌ی کار با اون گیج کننده به نظر بیاد اما پس از آشنایی، همه چیز ساده خواهد شد.

در این بخش از مقاله، برای آشنایی بیشتر با سیستم pluginها، ابتدا برای Panels یک plugin می‌نوسیم و در بخش بعدی، به ماژول ماشین حساب این قابلیت رو اضافه می‌کنیم. ماژول Panels، ماژول فوق‌العاده قدرتمندیست که اجازه می‌ده محتوای مختلف رو بر اساس شرایط خاص، در یک صفحه بچینیم (البته از این هم گسترده‌تر هست ولی برای شروع تعریف خوبیه). از جمله بخش‌هایی که میشه در یک پنل کنار هم قرار داد، نماها(views)، بلوک‌ها، محتوا و ... است. ماژول پنل، جدا از کل وب‌سایت، دارای «انواع محتوا»ست. این نوع محتوا در کد با نوشتن پلاگین‌های content_type در هر ماژول تعریف می‌شه (بر خلاف انواع محتوای وب‌سایت که در فرم‌ها تعریف می‌شه). ما یک نوع محتوا که فقط متن «سلام کاربر عزیز: *****» رو نمایش می‌دیم و ستاره‌ها رو با نام کاربر جایگرین می‌کنیم. شما می‌تونید برای بررسی بیشتر، ماژول ماشین‌حساب رو به عنوان بک نوع محتوا به پنل معرفی کنید.

ساخت یک پنل

برای شروع کار، در دروپال ماژول‌های devel، ctools، panels و به صورت پیشنهادی! admin_menu رو نصب و فعال کنید. ماژول دیگری که به همراه ctools دانلود می‌شه ولی فعال نیست Page manager هست. برای مدیریت پنل‌ها بهتره اون رو هم فعال کنید. به صفحه‌ی admin/structure/pages/add برای ساخت یک پنل بروید. Administrative title نام پنل در صفحات مدیریتی و Path مسیر صفحه‌ای که پنل از آن قابل دسترسی هست رو تعیین می‌کنه. من در این مقاله نام و مسیر رو «test» در نظر می‌گیرم. به هبچ کدام از گزینه‌های دیگر احتیاجی نیست. Continue رو بزنید. در فرم‌های Choose layout، Panel settings و Panel content هم نیازی به تغییر نیست. در نهایت Save رو برای ذخیره پنل بزنین.

تعریف ماژول

name = Plugin Test
description = A module to test cTools plugin functionality, Adds a custom panel content type.
core = 7.x
dependencies[] = ctools
dependencies[] = panels

اولین کاری که در فایل .module باید انجام بدیم، معرفی شاخه (پوشه)‌ای است که ctools در آن باید به دنبال پلاگین‌های تعریف‌ شده‌ی ما بگردد. به این صورت:

/**
 * Implements hook_ctools_plugin_directory().
 */
function plugintest_ctools_plugin_directory($plugin_owner, $plugin_type) {
  if ($plugin_owner == 'ctools' && $plugin_type == 'content_types') {
    return 'plugins/' . $plugin_type;
  }
}

توضیحات:

  • برای معرفی شاخه پلاگین‌ها، هوک hook_ctools_plugin_directory رو پیاده‌سازی کردیم. این هوک باید مسیر این شاخه رو به صورت نسبی، از شاخه‌ی ماژول برگرداند. یعنی اگر شاخه‌ی plugins رو در شاخه‌ی ماژول کنار سایر فایل‌ها (,module و .info) ساختید، مسیر نهایی رشته‌ی plugins/PLUGIN_TYPE خواهد بود. PLUGIN_TYPE باید با نوع پلاگینی که پیاده‌سازی می‌کنیم جایگزین شود.
  • Panels برای تعریف نوع محتوای جدید، سیستمی پیاده‌سازی نکرده، بلکه این سیستم خود در ماژول ctools پیاده‌سازی شده، و پنل از این سیستم استفاده می‌کنه. به همین خاطر ما پلاگین رو برای ماژول ctools می‌نویسم و پنل بعدا از آن استفاده خواهد کرد.
  • آرگومان $plugin_owner نام ماژولی است که پلاگین رو پیاده‌سازی کرده و $plugin_type نوع پلاگینی است که این ماژول به دنبال آن می‌گردد. هر ماژول می‌تواند پلاگین‌های متعددی تعریف کند که ما شاید بخواهیم فقط یکی از آن‌ها را پیاده‌سازی کنیم. در اینجا ما فقط به پلاگین content_type نیاز داشتیم و اون رو پیاده‌سازی کردیم.
  • این هوک، به تعداد پلاگین‌های تعریف شده در سیستم صدا زده می‌شه، پس در هربار صدا زده شدن، باید بررسی کنیم که آیا واقعا پلاگینی است که ما پیاده سازی کردیم (عبارت if بالا) در این صورت مسیر پلاگین رو برگردونیم، در غیر این صورت هیچ رشته‌ای بر نمیگردانیم (NULL).
  • برای جلوگیری از سردرگمی: توجه کنید که پیاده‌سازی پلاگین برای ماژول ctools و پیاده‌سازی پلاگین با استفاده از ctools ارتباطی باهم ندارند! ابتدا سیستم پلاگین‌ها در ctools پیاده‌سازی شده است. سپس خود ctools از همین سیستم، پلاگینی از نوع content_type تعریف کرده که ما اون رو پیاده‌سازی می‌کنیم. این پلاگین می‌توانست در ماژول Panels تعریف شود، در این صورت هوک همان hook_ctools_plugin_directory باقی‌ می‌ماند تنها تفاوت plugin_owner بود که به oanales تغییر پیدا می‌کرد.

نوشتن پلاگین

با توجه به مسیری که در بالا تعریف کردیم (plugins/PLUGIN_TYPE که در نهایت معادل plugins/content_type خواهد بود) شاخه‌ای با این مسیر بسازید و فایلی با نام دلخواه و پسوند inc بسازید. توجه کنید می‌تونید چندین پلاگین در فایل‌های متعدد تعریف کنید. ما فقط یک پلاگین تعریف می‌کنیم. نام فایل رو plugintest_content_type_test.inc می‌گذاریم. هنگامی که این فایل توسط ctools باز می‌شه، باید شامل یک متغیر سراسری به نام $plugin باشه. این متغیر رو در این فایل به این صورت تعریف می‌کنیم؛

<?php

/**
 * @file
 * CTools plugin test, Adds a custom content pane to panels.
 */

$plugin = array(
    'single' => 'true',
    'title' => t('Plugintest Plugin'),
    'description' => t('some desc here'),
    'category' => t('Drupalion'),
    'edit form' => '_plugintest_plugin_settings_form',
    'render callback' => '_plugintest_plugin_render',
    'defaults' => array(
      'msg' => 'Hello',
    ),
);

توضیحات:

  • edit_form نام تابعی است که فرم ویرایش تنظیمات پلاگین رو تولید می‌کنه. این تابع رو بعدا پیاده‌سازی می‌کنیم.
  • render callback نام تابعی است که در زمان نمایش پنل به کاربران برای تولید خروجی صدا می‌شه.
  • defaults شامل تنظیمات پیش‌فرض پلاگین است.

توابع callback برای تولید فرم تنظیمات و تولید خروجی رو به این صورت پیاده‌سازی می‌کنیم.:

function _plugintest_plugin_settings_form($form, &$form_state) {
    $cfg = $form_state['conf'];
    
    $form['msg'] = array(
      '#type' => 'textfield',
      '#title' => t('Message'),
      '#description' => t('Message to show to user.'),
      '#default_value' => $cfg['msg'],
    );

    return $form;
}

function _plugintest_plugin_settings_form_submit(&$form, &$form_state) {
  $form_state['conf']['msg'] = $form_state['values']['msg'];
}

توضیحات:

  • پیاده‌سازی این تابع callback همانند پیاده‌سازی سایر فرم‌هاست.
  • کلید‌های آرایه‌ی فرم به عنوان تنظیماتی که باید ذخیره شوند در نظر گرفته می‌شوند. در اینجا msg ذخیره خواهد شد.
  • #default_value اعلانی است به Form API تا در صورتی که کاربر هنوز مقداری در فرم وارد نکرده، این مقدار رو به صورت پیش‌فرض در فرم قرار می‌دهد. توجه کنید که باید مقداری که کاربر قبلا در نظر گرفته رو به عنوان پیش‌فرض در فرم وارد کنیم در غیر این صورت در هربار مراجعه مجدد به فرم، پیغام کاربر پاک خواهد شد و باید مجددا قبل از ذخیره‌ی فرم نوشته شود. این مقدار در کنار سایر تنظیمات در کلید conf در متغیر form ذخیره شده.
  • در بالا هوکی تحت عنوان FORM_ID_submit پیاده‌سازی شده. نام تایع هر فرم به عنوان شناسه‌ی فرم (Form ID) در نظر گرفته میشه(_plugintest_plugin_settings_form در بالا) و هوکی تحت عنوان FORM_ID_submit پس از ذخیره‌ی فرم با مقادیر ورودی صدا زده می‌شه تا اطلاعات اون مورد پردازش قرار بگیره. در اینجا دکمه‌ی ثبت توسط panels مدیریت می‌شه و ما خودمون دکمه‌ای در فرم نگذاشتیم بلکه فقط این هوک رو پیاده‌سازی کردیم.
  • پس از ثبت فرم هرچیزی که در کلید conf از form_state قرار بگیره به عنوان تنظیمات پلاگین ذخیره خواهد شد. بنابراین لازمه مقدار msg ورودی کاربر رو در این کلید قرار بدهیم.

برای نمایش هم این تابع رو پیاده‌سازی می‌کنیم:

function _plugintest_plugin_render($subtype, $conf, $args, $contexts) {
    $block = new stdClass();
    $block->title = t('Hello');
    $block->content = $conf['msg'] . ' ' . $GLOBALS['user']->name;

  return $block;
}

این تایع برای نمایش محتوا باید شیئی از نوع stdClass شامل title و content برگرداند.

حالا می‌توانید به صفحه مدیریت پنل بازگردید، در بخش Variants » Panel » Content بر روی علامت چرخ‌دنده کیلک کنید و add content را انتخاب کنید. در نوار سمت چپ در گروهی که در  بالا تعریف کردید، content type شما آمده است. با انتخاب آن فرم تنظیمات آن باز خواهد شد که Message را با پیش‌فرض Hello از شما خواهد پرسید. با زدن دکمه‌ی Finish و سپس ذخیره‌ی پنل (کاری که من همیشه فراموش می‌کنم!) و رفتن به مسیری که قبلا انتخاب کردید، محتوای خود رو خواهید دید.

در باره‌ی عکس مطلب: سازه‌ی ماژولار Clound City، کاری از Tomás Saraceno، عکاس: Andreas Praefcke،  فرانکفورت.
فایل ماژول ضیمیمه شده است

دسته بندی مطلب