كتابة وحدة – الفصل الثاني من كتاب : التطوير الاحترافي لدروبال chapeter 2 – Pro drupal 7 development

facebook-group

     كتابة وحدة   Writing a Module    

ملاحظة : سنقوم ضمن هذا الفصل بإنجاز حيز متقدم من كتابة الوحدات ضمن دروبال , ولإنجاز هذا الكم من التقدم في التطوير ضمن دروبال , سنمر على عدد كبير من الأمور البرمجية , بالإضافة إلى جوانب مختلف ضمن دروبال , وبسبب هذا الكم الكبير من المعلومات , فإننا سنتعلم الكثير وسنضطر إلى المرور على أغلبها بشكل عابر ليتم شرحها لاحقا في فصول قادمة وبالتفصيل لذلك ارجو من القارئ ألا يستعجل الأمور في حال لم تكن كل الأمور واضحة بالنسبة له منذ البداية , وكما يقول المثل : “كلشي بوقته حلو”.

المصطلحات الجديدة ضمن هذا الجزء مع ترجمتها

Module

Node

Hook

taxonomy

function

install

Operation

Core

Implement

وحدة

عقدة

هوك

نظام التصنيف

تابع- وظيفة

تثبيت

عملية

نواة

تنجيز- تحقيق

تعتبر الوحدات بمثابة كتل البناء الأساسية التي تشكل أساس دروبال , وتمثل الآلية والوسيلة لتوسع الوظائف الأساسية المزودة من قبل نواة دروبالDrupal core .

غالبا ما اعمد لشرح مفهوم الوحدات عن طريق التشبيه – لؤلئك الغير متآلفين مع دروبال بعد-  بأن الوحدات تشبه إلى حد كبير لعبة تركيب الكتل المعروفة باسم “ليغو” , حيث نجد بأن هذه الوحدات تنسجم مع بعضها البعض وذلك عند اتباع مجموعة محددة من الخطوات, وعند تجميع عدد من الوحدات modules  , بإمكانك عندها بناء حلول معقدة ومتطورة وغنية.

هنالك تصنيفان من وحدات دروبال :

  1. وحدات النوة core modules.
  2. و الوحدات المساهمة  contributed  modules.

وحدات النواة core modules : وهي الوحدات التي تأتي بشكل افتراضي مع دروبال , مثل استطلاعات الرأي polls, القوائم menu , نظام التصنيف taxonomy , البحث search  , التغذية الراجعة feed  مثل نظام RSS, المنتديات forums …

اما الوحدات المساهمة contributed modules  فهي عبارة عن كل الوحدات modules التي تم انشائها من قبل مجتمع دروبال الذي يسعى دوما لتوسيع وتطوير وظائف نواة دروبال.

هنالك تقريبا الآلاف من الوحدات المساهمة متاحة ليتم تحميلها من الموقع التالي :http://drupal.org/project/modules

وتتنوع هذه المجموعة من الوحدات لتشمل ابسط انواع الوحدات مثل عرض التاريخ والوقت الحالي , امتدادا إلى انواع معقدة من الحلول , مثل التجارة الالكترونية  e-commerce.

ضمن هذا الجزء سوف نريكم كيف يتم بناء وحدات من الصفر. وأثناء قيامك بعملية بناء الوحدة سوف تتعلم الكثير من المعايير التي يتوجب عليك الالتزام بها أثناء بناء الوحدة.

لنبدأ بفكرة جيدة لبناء وحدة …ونحتاج فكرة واقعية , نستمدها من مسائل العالم الحقيقي .على سبيل المثال:عندما تنظر إلى صفحات موقع دروبال , قد ترغب في بعض الأحيان بإضافة وكتابة ملاحظة note  عن الصفحة. بإمكاننا استخدام نظام التعليقات comments في دروبال لتحقيق ذلك , ولكن عادة ما يمكن استعراض التعليقات من قبل اي زائر للصفحة , او الزوار ذوي الصلاحيات المناسبة. بينما الملاحظات التي قد نرغب بإضافتها للصفحة , يمكن استعراضها من قبل الشخص الذي قام بإنشاء هذه الصفحة اي مالك العقدة فقط node’s author  .

إذن فكرتنا الآن بناء نظام ملاحظات وشرح  annotation  حيث يستطيع فقط مؤلف العقدة من إضافة ملاحظات عليها وكذلك بنفس الوقت استعراض تلك الملاحظات.

 إنشاء الملفات   Creating the Files     

أول شيء يتوجب علينا فعله هو اختيار الاسم المناسب للوحدة module name . واسم “annotate” (التعليق ) يبدو مناسب جدا , فهو قصير ومعبر.

ثانياً , نحتاج إلى مكان نضع فيه هذه الوحدة. إن كلاً من الوحدات المساهمة والوحدات التي نقوم بإنشائها تخزن ضمن مسار  sites/all/modules , وهنالك تخزن كل وحدة ضمن مسارها المناسب الذي يحمل نفس اسم الوحدة.

ملاحظة : إن وحدات النواة الخاصين بدروبال يتم تخزينهم ضمن المسار التالي : /modules , والوحدات التي ننشئها لا يجب أبدا ان توضع ضمن نفس مسار وحدات نواة دروبال , وذلك لحمايتها من الحذف أو التعديل أثناء ترقية دروبال لنسخ أحدث.

ولأهداف تنظيمية قد ترغب بإنشاء مسار  sites/all/modules/custom لتضع فيه أية وحدات تقوم بإنشائها من الصفر , ويتم إنشاء مسار sites/all/modules/contrib. وذلك لوضع الوحدات المساهمة ضمنه , وبذلك يستطيع أي شخص يطّلع على موقعك أن يميز بين الوحدات التي قمت بإنشائها , وبين الوحدات المساهمة التي قمت بتحميلها من drupal.org.

ومن ثم سنقوم بإنشاء مسار لمجلدنا annotate كالتالي : sites/all/modules/custom/annotate لنضع فيه الملفات اللازمة لإنشاء وحدة annotate.

أول ملف – من ملفات الوحدة – سنقوم بإنشائه هو ملف annotate.info .

كل وحدة في دروبال يجب ان تملك ملف بلاحقة .info واسم هذا الملف يجب أن يطابق اسم الوحدة module name. وبالتالي بالنسبة لوحدة “annotate”  كان الاسم annotate.info. ويحوي ملف .info على المعلومات الأساسية اللازمة حتى يستطيع دروبال أن يتعرف على الوحدة , وفي مثالنا هي التالية :

 

وتتصف بنية الملف .info بأنها معيارية ضمن كل وحدات drupal 7  . وسنشرح فيما يلي العناصر الموجودة ضمن الملف :

العنصر “name”  يستخدم لعرض اسم الوحدة في صفحة إعدادات الوحدات modules configuration  .

العنصر “description” يستخدم لتقديم شرح عن الوحدة , وكذلك يتم عرضه ضمن صفحة اعدادات الوحدة.

العنصر “package” يعرف المجموعة التي تعتبر هذه الوحدة مرفقة معها.ضمن صفحة اعدادات الوحدات Modules configuration page  , يتم عرض الوحدات مصنفة ضمن مجموعاتها.

الحقل “core” اصدار دروبال الذي يناسب هذه الوحدة

عنصر “PHP” يحدد نسخة PHP التي تحتاجها الوحدة.

عنصر “file” عبارة عن مصفوفة من اسماء الملفات المرفقة مع هذه الوحدة , في حالتنا وحدة “annotate” فإن الملفات المرفقة مع هذه الوحدة هي التالية : annotate.module و annotate.install.

بإمكاننا إضافة عدد اخر من العناصر الاختيارية لملف  .info وفيما يلي بعض الأمثلة على وحدة تحتاج إلى نسخة من PHP ذات اصدار 5.2 , وتعتمد على كل من وحدتي forum  و  taxonomy  لتعمل , اي إن كل من الوحدتين forum  و  taxonomy   يجب ان تكونا مثبتتين حتى تعمل هذه الوحدة

 

الآن , اصبحنا جاهزين لإنشاء الوحدة الفعلية . أنشأ ملفا اسمه annotate.module ضمن المسار الفرعي التالي : sites/all/modules/custom/annotate . ابدأ الملف بتاغ PHP افتتاحية “<?php “  ومن ثم تاغ CVS تعريفية , يتبعها تعليق :


في البداية يجب ان نلاحظ شكل التعليق comment style. يبدأ ب /** وعند بداية  كل سطر جديد نستخدم ايضا * مسبوقة بفراغ. وفي نهاية التعليق نضع */  على سطر منفرد.

يشير الرمز @file إلى أن مايليه من كتابات في السطر التالي هي عبارة عن شرح الملف نفسه. يستخدم هذا الاسلوب “سطر واحد من التوصيف” حتى يستطيع api.module  و مستخلص ومنسق التوثيق الاوتوماتيكي في دروبال من إيجاد ومعرفة ما يقوم به هذا الملف.

وبعد سطر فارغ ( اي الفراغ الذي يترك بعد @file  وما يلي من سطر شرح ) يتم اضافة شرح مطول وتفصيلي يستفيد منه المبرمجون الذين يتفحصون ترميز (كود) وحدتنا.

لاحظ بأننا تعمدنا ألا نضيف تاغ “?>” الخاصة بإغلاق تاغ PHP , لان تاغ الاغلاق خيارية ضمن PHP , وفي حال تم تضمينها فإن بإمكاننا أن تتسبب ببعض المشاكل مثل وجود فراغات في اخر الملف ,( انظر إلى الرابط http://drupal.org/coding-standards#phptags).

ملاحظة: لماذا نحن دقيقين لهذه الدرجة فيما يخص هيكلية كل شي أثناء كتابة وحدة؟ السبب وراء ذلك يتجلى عندما يكون هنالك المئات من الأشخاص حول العالم يعملون مع بعضهم البعض على مشروع, عندها نكون قد وفرنا الوقت وذلك عندما يعمل كل فرد منهم على نفس المعايير. لمزيد من التفاصيل حول معايير الترميز coding standards على الرابط التالي : http://drupal.org/coding-standards

الخطوة التالية التي نريد عملها الآن – فيما يخص الوحدة التي نقوم ببنائها – هي القيام بتعريف بعض الإعدادات التي تمكننا من اختيار انماط العقد المتاحة لاضافة ملاحظات عليه.

هنالك خطوتين لإتمام ذلك :

  1. سنقوم بإعداد وتعريف مسار محدد نستطيع من خلاله النفاذ إلى هذه الإعدادات
  2. إنشاء نموذج لهذه الإعدادات settings form

وحتى نقوم بإنشاء مسار , نحن بحاجة لتطبيق Hook  , وبشكل خاص hook_menu (وهي بشكل عام المسئولة عن إنشاء مسارات وربطها بوظائف )

  تحقيق حدث (هوك)Implementing a Hook         

ملاحظة : تنجيز او تحقيق تابع ما,اي كتابة محتوى هذا التابع To implement a function it means to write the body of this Function

إن دروبال مبنى على نظام من الأحداث (Hooks) , وتدعى احيانا استدعاءات callbacks. خلال فترة التنفيذ , يقوم دروبال بالاستفسار من الوحدات فيما إذا كانت ترغب بفعل شيء ما . على سبيل المثال , عندما يتم تحميل عقدة ما  node من قاعدة المعطيات , وقبل أن يتم عرضها على الصفحة , يفحص دروبال كل الوحدات الفعالة ليرى فيما إذا كانت هذه الوحدات قد قامت بتحقيق(تنجيز) التابع hook_node_load(). وفي حال وجد من يحقق هذا التابع في وحدة ما , فإنه ينفذ سنارة هذه الوحدة module’s hook قبل القيام بتنسيق استعراض صفحة العقدة. سنرى كيف يتم عمل ذلك في وحدة annotate.

أول هوك نريد تنجيزه (تحقيقه وكتابة الترميز الخاص به ) hook_menu . سوف نستخدم هذا التابع function  لإضافة عنصرين للقائمة الإدارة في موقعنا.  سنقوم بإضافة عنصر قائمة باسم “annotate” إلى قائمة المسار التالي admin/config , وذلك بالإضافة إلى قائمة فرعية تقع تحت عنصر “annotate” الذي قمنا بإنشائه للتو , وسنسمي هذه القائمة الفرعية بالإعدادات “ settings” والتي عندما يتم النقر عليها سوف تقوم بتشغيل صفحة إعدادات التهيئة الخاصة ب annotate.

إن القيم الخاصة بعناصر قائمتنا والمعرفة ضمن annotate_menu هي عبارة عن مصفوفات arrays تتالف من مفاتيح keys  وقيم values  توصف مالذي يتوجب على دروبال القيام به عندما يتم طلب هذا المسار. سوف نقوم بتغطية وشرح هذا الموضوع بالتفصيل في الفصل الرابع , الذي سيغطي نظام الاستدعاءات والقوائم في دروبال.

سوف نسمي استدعاء التابع hook_menu  ب “annotate_menu” (عبر استبدال hook باسم الوحدة كما وضحنا ذلك في الفصل الأول). وهذا الاستبدال عام بالنسبة لكل ال Hooks  دوما نستبدل كلمة hook باسم الوحدة التي نكتب ضمنها تنجيز (تحقيق ) هذا التابع.

فيما يلي أدناه الترميز الذي سنقوم بإضافته إلى وحدتنا.

  لا تقلق كثيرا فيما يخص التفاصيل عند هذه النقطة . هذا الترميز “الكود” يقول :

v      عندما يذهب المستخدم إلى المسار التالي : http://example.com/?q=admin/config/annotate/settings ,

v      قم باستدعاء التابع drupal_get_form() ,

v      ومرر له المعرف ID التالي : annotate_admin_settings.

v      ثم ابحث ضمن الملف المسمى ب annotate.admin.inc عن تباع يحمل الاسم annotate_admin_settings ويقوم بتوصيف النموذج form   . وذلك بحيث أن الأشخاص الذين يحملون الصلاحيات “administer site configuration ” هم فقط الذين يستطيعون استعراض عنصر القائمة.

v      عندما يحين وقت استعراض النموذج form  , يطلب منا دروبال بأن نزوده بتعريف هذا النموذج form(مزيد من التفاصيل قريبا). عندما ينتهي دروبال من مسائلة كل الوحدات عن عناصر القوائم الخاصة بهم, يكون قد اصبح لدى دروبال قائمة تستطيع من خلالها اختيار التابع المناسب لاستدعائه بما يناسب المسار المطلوب منه.

ملاحظة: توفر أحداث (هاكات) دروبال hooks إمكانية تعديل كل انواع البرمجيات . يمكنك إيجاد قائمة بكل الأحداث (هاكات) (hooks) المدعومة من قبل دروبال , واستخداماتها على الرابط التالي : http://api.drupal.org/api/group/hooks/7

إضافة الإعدادات الخاصة بالوحدة   Adding Module-Specific Settings             

يملك دروبال انماط عقد مختلفةnode types  (وتدعى ضمن واجهة المستخدم ب “انماط المحتوى” content type ), مثل المقالات articles  والصفحات الأساسية basic pages. ونرغب ضمن الوحدة التي نقوم بإنشائها بإعطاء سماحية اضافة الملاحظات فقط على انواع محددة من العقد. للقيام بذلك , سوف نقوم بإنشاء صفحة نستطيع من خلالها ان نخبر وحدتنا “الوحدة التي نقوم بإنشائها” عن انماط المعطيات التي نرغب بالسماح للمستخدمين بإضافة التعليقات عليها.

على تلك الصفحة – صفحة الإعدادات – سوف نظهر مجموعة من صناديق الاختيار check boxes  , صندوق لكل نمط محتوى موجود ضمن دروبال. ذلك يمكن المستخدم من ان يقرر اي انماط المحتويات سيكون متاحاً لنظام الملاحظات (الذي نقوم بإنشائه ضمن وحدتنا ) , وذلك عبر وضع إشارة (صح) أو إزالتها من تلك الصناديق(الشكل 2-1).

تعتبر مثل هذه الصفحة بأنها صفحة إدارية , وترميز هذه الصفحة يتم تحميله ومعالجته فقط عند الحاجة (عند طلب تلك الصفحة ).لذلك سوف نقوم بوضع ترميز code  تلك الصفحة في ملف منفصل , وليس ضمن ملف anootate.module , التي سيتم تحميله وتشغيله مع كل طلب.

وبما أننا طلبنا من دروبال أن يقوم بالبحث عن نموذج الإعدادات setting form ضمن ملف annotate.admin.inc (تم ذلك ضمن تحقيق الحدث hook_menu فيما سبق والشرح التفصيلي لهذه السنارة يأتي لاحقاً), لذلك سنقوم بإنشاء هذا الملف وإضافة الترميز أدناه إليه :

 

يتم تمثيل النماذج Forms ضمن دروبال على شكل هيكلية شجرية متداخلة nested tree structure – يعني مصفوفة مصفوفات array of arrays .

لسهولة القراءة وضعنا كل عنصر من المصفوفة على سطر. يشار إلى خاصيات النموذج بإشارة (#) ويصبح الحقل بمثابة مفتاح ضمن المصفوفة an array key .

في البداية بدأنا بالتصريح عن نمط عنصر المصفوفة بأنه “checkbox” , وهذا يعني بأنه سيتم بناء عدة صناديق اختيار check boxes  وذلك باستخدام مصفوفة مفتاحيةkeyed array . حيث قمنا بوضع المصفوفة ضمن متحول $options.

اسندنا إلى متحول options خرج التابع node_type_get_types(), والذي بدوره يعيد مصفوفة من الأغراض objects. وسيبدو الخرج شبيها بالشكل التالي ادناه:

 تمثل خاصية النمط(type)ضمن مصفوفة الغرض, الاسماء الداخلية لانماط العقد ضمن دروبال , مع الاسماء السلسة الصديقة friendly names  (تلك التي سوف يتم اظهرها للمستخدم ) مضمنة ضمن خاصية الاسم name attribute  الخاصة بالغرض.

تتطلب واجهة النماذج في دروبال Form API بأن تكون قيمة الخاصية #option  عبارة عن مصفوفة بالشكل التالي : key=>value , وبالتالي , فإن حلقة foreach  تستخدم كل من خاصتي “type, and name” من خواص نمط عقدة ما node type وذلك لإنشاء خاصيتي المفتاح key و الاسم name  لبناء مصفوفة الخيارات . وبالتالي يتم بناء قيم الخيارات للمصفوفة الجديدة التي قمنا بتسميتها $options.

     $options[$node_type->type] = $node_type->name;

                وعبر استخدام القيم ضمن مصفوفة $options ضمن النموذج form , سيقوم دروبال من توليد صناديق اختيار ل : المقالات article  , الصفحة الرئيسية basic page , … ولأي نمط محتوى موجود على دروبال.

يتم اعطاء عناصر النموذج form element  عنوان title  وذلك عبر خاصية #title.

ملاحظة : اي نص يتم عرضه للمستخدم (مثل النصوص التي تسند إلى خاصيتي #title , #description ) توضع ضمن تابع يدعى t() , هذا التابع مزود من قبل دروبال ليسهل عملية ترجمة النصوص . عبر تمرير كل النصوص من خلال تابع الترجمة النصية string translation function , وبالتالي فإن عملية تحويل وحدتك your module  إلى لغة آخرى سيكون سهلاً. أما بالنسبة لعناصر القائمة menu فإننا لا نقوم بذلك ( اي وضع النصوص ضمن تابع t() )   لأنها تخضع للترجمة بشكل اوتوماتيكي.

أما بالنسبة ل #default_value, فإنها تمثل القيمة الافتراضية لعنصر النموذج form element .وبما ان صناديق الاختيار checkboxes  هي عبارة عن عناصر نموذج متعددة بطبيعتها ) مثال : اي هنالك اكثر من صندوق اختيار واحد , وبالتالي هنالك اكثر من قيمة افتراضية ) فإن قيمة الحقل #default_value ستكون عبارة عن مصفوفة .

إن قيمة #default_value  تستحق المناقشة اكثر

Variable_get(‘annotate_node_types’, array(‘page’))

يتيح دروبال للمبرمجين من تخزين واستعادة اي قيمة , وذلك عبر استخدم زوجان من التوابع functions ألا وهما :

Variable_get() and  varibale_set().

يتم تخزين القيم ضمن جدول variables  ضمن قاعدة المعطيات , وتكون القيم متاحة لاستعادتها في اي وقت كان خلال معالجة الطلب.

ولأن هذه القيم يتم استعادتها من قاعدة المعطيات خلال كل طلب , فإن استخدامها ليس بالفكرة الجيدة لتخزين كمية كبيرة من المعطيات بهذه الطريقة. ولكنها تمثل نظام مناسب لتخزين القيم في حالات معينة , مثل تخزين إعدادات الوحدة module configuration settings.

لاحظ بأن المعامل الأول الممرر للتابع variable_get() عبارة عن ما يشبه المفتاح , يوصف القيمة المدخلة (وبالتالي وعبر استخدام نفس المفتاح بإمكاننا استعادة نفس القيمة في وقت لاحق),  أما المعامل الثاني فيمثل القيمة الافتراضية . وفي حالتنا فإن القيمة الافتراضية عبارة عن مصفوفة من انماط العقد المتاحة لنظام الملاحظات annotation. وفي مثالنا سنجعل الملاحظات متاحة لنمط العقد (الصفحة الرئيسية) basic page  بشكل افتراضي .

ملاحظة : عند استخدام system_settings_form() فإنه يتوجب أن يطابق اسم عنصر النموذج form element( في حالتنا , annotate_node_types ) المعامل الأول ضمن تابع variable_get() اي الاسم المفتاحي لاستعادة القيمة.

كما قمنا عبر الخاصة #description  بتزويد مدير الموقع ببعض المعلومات عن هذا الحقل. سوف نقوم بتغطية هذه الخاصيات بشكل تفصيلي ضمن الجزء 11.

الآن , سوف نقوم بإضافة بعض الترميز للتعامل مع عمليتي إضافة وإزالة حقل الملاحظات annotation field  لانماط المحتوى content type.

 إذا قام مدير الموقع بإضافة اشارة (صح) لنمط معطيات ما , عندها سوف اقوم بإضافة حقل الملاحظات annotation field  لنمط محتوى content type  الذي يتم تعليمه(باشارة صح).وفي حال قرر مدير النظام ان يزيل حقل الملاحظات من نمط محتوى ما , عندها يجب ان نزيل الحقل.

سوف نستخدم واجهة الحقول في دروبال drupal’s field API لتعريف الحقل وربطه مع نمط المعطيات.

تقوم واجهة الحقول field API بالتعامل مع كافة العمليات المطلوبة لإنشاء حقل ما , بما فيها ما يلي :

  • إنشاء جدول ضمن قاعدة معطيات دروبال لتخزين قيم المخزنة في هذا الحقل
  • عملية ربط حقل مع نمط محتوى content type
  • إنشاء عنصر النموذج المستخدم لجمع المعلومات المدخلة من قبل من يقوم بتعبئة هذا الحقل ضمن العقدة
  • عرض هذه الحقل ضمن صفحة نموذج تحرير العقدة وصفحة عرضها

سوف نقوم بتغطية Field API بالتفصيل ضمن الفصل 8.

أول ما نقوم به الآن هو إنشاء اجرائية تعالج عملية تسجيل النموذج (اي عندما يضغط المستخدم على زر submit يتم تنفيذ هذه الاجرائية) والتي يتم استدعائها عندما يقوم مدير الموقع بتسجيل النموذج ( اي الضغط على زر submit) .

ضمن هذه الاجرائية سيتم ما يلي :

ستقوم الوحدة التي ننشئها بالتحقق فيما إذا كان قد تم تحديد (وضع اشارة صح ) أو إزالة التحديد عن أحد صناديق الاختيار check box لاحد انماط المحتوى  content type.

في حالة إزالة التحديد unchecked  عن احد انماط المحتوى , عندها سنقوم بالتحقق من عدم امتلاك نمط المحتوى لحقل ملاحظات annotation field مرفق به.

وفي حال كانت نتيجة التحقق ايجابية ( اي انه يملك حقل ملاحظات annotation field  )  فهذا يعني بأن مدير النظام يرغب في إزالة حقل الملاحظات عن نمط المحتوى هذا, بالاضافة إلى ازالة كل الملاحظات الموجودة والمخزنة في قاعدة المعطيات والتابعة له .

أما في حال قيام مدير النظام بتحديد ( وضع اشارة صح ضمن checkbox) لاحد انماط  المحتوى, عندها تقوم الوحدة –التي نقوم بإنشائها – بما يلي :

  • بالتحقق فيما إذا كان نمط المحتوى الذي تم تحديده يملك للتو حقل ملاحظات annotation field
  • وفي حالة النفي ( لا يملك نمط المحتوى على حقل ملاحظات ) , عندها تقوم الوحدة module بإضافة حقل ملاحظات annotation field  لنمط المحتوى ذاك.

 

الخطوة التالي هي إنشاء ملف .install لوحدتنا.

يحوي ملف install على تابع function او اكثر يتم استدعائهم عندما يتم تثبيت الوحدة , أو إزالة تثبيتها.

في حالة وحدتناour module  , فعند تثبيت الوحدة , نريد أن ننشأ حقل ملاحظات annotation field لنتمكن فيما بعد من ربطه مع انماط المحتوى content types وذلك عن طريق مدير النظام ( كما شرحنا في الاسطر القليلة السابقة).

أما في حالة إزالة تثبيت الوحدة , عندها فإننا نريد ان تتم إزالة حقل الملاحظات annotation field من كافة انماط المحتوى التي تم ارفاقه بها , بالاضافة إلى حذف كافة محتويات هذا الحقل من قاعدة المعطيات.

لتحقيق ذلك , أنشأ ملف جديد ضمن مسار وحدتك اي ضمن مجلد annotate وسمي هذا الملف annotate.install.

أول تابع سنقوم باستدعاءه يدعى hook_install() . وبالتالي عندما نعرفه سيكون اسمه annotate_install() ( وذلك وفق المعايير النظامية لتسمية توابع الأحداث (الهاكات ) hook function  في دروبال , حيث نستبدل كلمة hook  باسم الوحدة.

ضمن التابع hook_install() سنقوم بالتحقق فيما إذا كان الحقل (حقل الملاحظات) موجود مسبقاً وذلك باستخدام توابع واجهة الحقول ضمن دروبال Drupal’s field API, وفي حال عدم وجود هذا الحقل نقوم نحن عندها بإنشائه.

 

الخطوة التالية هي إنشاء تابع إزالة التثبيت uninstall function  وذلك باستخدام hook_uninstall. وبالتالي سوف نقوم بإنشاء تابع بالاسم التالي annotate_uninstall الذي يقوم باستخدام تابع watchdog لوضع الرسائل التي تخبر مدير النظام بأنه قد تمت إزالة تثبيت الوحدة. ومن ثم سنقوم باستخدام التابع node_get_types()  الجاهز , لجمع قائمة بكل انماط المحتوى الموجودة ضمن الموقع , وسيقوم بالمرور على هذه القائمة من الانماط , باحثاً عن وجود “حقل الملاحظات ” annotation field  تابع لانماط المحتوى التي يمر عليها. وفي حال وجوده , يتم حذفه.

واخيرا , يتم حذف حقل الملاحظات نهائيا.

اخر خطوة ضمن الإجرائية التي نقوم بها ضمن وحدتنا , تكمن في تضمين إمكانية التحقق فيما إذا كان الشخص الذي يقوم باستعراض العقدة Node  وهو نفسه مؤلف الوحدة. وفي حال لم يكن هو نفسه مؤلف الوحدة , عندها نريد ان نخفي نموذج الملاحظات عن المستخدم – اي تصبح عملية إضافة الملاحظات غير متاحة.

الآن سوف نستخدم السنارة (hook) hook_node_load , والتي يتم استدعائها عند تحميل العقدة. ضمن التابع hook_node_load() , سوف نقوم بالتحقق فيما إذا كان الشخص الذي يقوم باستعراض العقده هو نفسه مؤلف العقدةnode author. في حال لم يكن هو المؤلف لهذه العقدة , عندها سوف نقم بإخفاء إمكانية إضافة الملاحظات على هذه العقدة, وذلك عبر إزالة هذا الحقل (حقل الملاحظات ) باستخدام تابع يدعى unset().


الآن قم بحفظ الملفات التي قمت بإنشائها (.info, .install, .admin.inc, .module) , ثم انقر على رابط الوحدات modules link  ضمن القائمة الإدارية في أعلى الصفحة ضمن الموقع. يجب ان تكون وحدتك الآن مدرجة ضمن الوحدات في هذه الصفحة ,وتحديدا تندرج ضمن تصنيف معنون باسم “pro drupal development” ( وذلك تبعا للاعدادات التي قمنا بإنشائها ضمن ملف .info). الآن فعل الوحدة (وحدتك التي قمت بإنشائها) , وبعد ان فعلت الوحدة , عندما ستذهب إلى المسار التالي , admin/config/annotate/settings ستظهر لك نموذج الاعدادات الخاص ب annotate.module , كما في الشكل 2-1  أدناه.

بعد بضعة سطور من الترميز, اصبح لدينا الآن نموذج إعدادات خاص بوحدتنا , وسيقوم هذا النموذج بشكل اوتوماتيكي بحفظ الإعدادات التي نقوم بتعينها! هذا يعطينا شعور بالقوة عند قيامك بهذه الإنجازات والتغيرات ضمن اطار عمل دروبال.

لنقم الآن باختبار هذه الاجرائية المتكاملة , وذلك عبر تفعيل إمكانية إضافة الملاحظات لكل انماط المحتوى.

 ضع اشارة صح (حدد) على كل صناديق الاختيار ضمن صفحة الاعدادات , ومن ثم انقر على زر “احفظ الاعدادات” save configuration””  . من ثم انشأ نمط محتوى جديد ( عقدة ) من نمط article , ثم انتقل لأسفل الصفحة حتى تصل إلى حقل الملاحظات , كما في الشكل 2-2.

انشأ الآن عقدة جديدة , وادخل قيم العنوان title , المحتوى body , وحقل الملاحظة annotation field . عندما تنتهي , اضغط على زر “حفظ” save ,ويجب أن تر نتائج مشابهه للشكل 2-3.

بما أنك لم تقم مباشرة بأي عملية على قاعدة المعطيات , ربما تتساءل , أين يخزن دروبال المعطيات التي يتلقاها ضمن حقل الملاحظات؟. الجواب : إن واجهة الحقول المدعومة ضمن دروبال 7 Field API تؤمن كل العمليات التي تجري وراء الكواليس , بما فيها :

v      إنشاء الجدول المخصص لحفظ القيم .

v      تخزين القيم (قيم حقل الملاحظات ) لكل عقدة عند حفظها

v      استعادة القيم (قيم حقل الملاحظات ) لكل عقدة عند تحميل العقدة

عندما تقوم باستدعاء تابع field_create_field() – احد توابع واجهة الحقول Field APi – فإنه سيقوم بإنشاء الجدول ضمن قاعدة معطيات دروبال وتسميته ,وذلك باستخدام معايير التسمية ضمن دروبال field_data_<fieldname>. في حالة حقل الملاحظات annotation field , فإن اسم الجدول سيكون field_data_annotations. وسنقوم بتغطية اية تفاصيل آخر متعلقة ب”واجهة الحقول” Field API , ضمن الفصل الرابع.

إعداد وتعريف القسم الإداري الخاص بك  Defining your own administrator section                  

يملك دروبال تصنيفات متنوعة تندرج تحت الاعدادات الادارية administrative settings  , ضمن المسار http://localhost/example.com/admin/config – طبعا المسار يختلف بحسب تثبيت دروبال , ومكان تثبيته وتسمية الموقع –  من تلك التصنيفات المتنوعة  :

  • إدارة المحتوى content management
  • إدارة المستخدم user management

في حال كنت ترغب في إضافة تصنيف جديد, فإنه بإمكانك إنشاء ذلك التصنيف بسهولة.

في مثالنا , أنشأنا تصنيف جديد باسم “Node annotation” (الملاحظات الجديدة). للقيام بذلك , استخدمنا الأحداث (الهاكات)(hooks ) القائمة menu hook وذلك لتعريف تصنيف جديد خاص بوحدتنا.


إن التصنيف الجديد , الموجود على صفحة الإعدادات configuration page  مع الروابط الخاصة بإعدادات الوحدة موضحة في الشكل 2-4.

إذا كنت قد قمت في أي مرة من المرات بتعديل على هاكات (احداث ) القوائم menu hooks , فأنت بحاجة دوما إلى القيام بتفريغ الكاش clear cache , حتى تستطيع رؤية التعديلات التي قمت بها.

بإمكانك القيام بذلك ببساطة عبر استخدام احد الطرق التالية :

  1. عبر افراغ محتوى الجدول “cache_menu”
  2. عبر النقر على رابط “Rebuild menus”  الذي توفره لنا وحدة devel “devel.module”
  3. عبر النقر على زر “clear cached data” الموجود ضمن المسار التالي : admin->config->performance link

ملاحظة : تم كتابة الوحدة http://drupal.org/project/devel  خصوصا ليدعم عملية تطوير دروبال. حيث توفر لك هذه الوحدة نفاذ سريع للعديد من توابع التطوير (وظائف التطوير), مثل إفراغ الكاش , استعراض المتحولات viewing variables , تتبع الاستعلامات  tracking queries…ويعتبر مهم جدا للمطورين.

قمنا فيما سبق بإنشاء التصنيف عبر خطوتين :

  1. الخطوة الأولى : اضفنا عنصر القائمة menu item والذي يمثل ويوصف ترويسة التصنيف category header
  2. يملك عنصر القائمة هذا مسار فريد admin/config/annotate .
  3. وصرحنا بأن عنصر القائمة هذا يجب أن يتوضع ضمن العمود اليميني مع وزن مساوي ل -5 , مع العلم بأن الوزن يحدد توضع التصنيفات ضمن العمود بحسب الوزن الأثقل, ونسبة للوزن الذي اسندناه لهذا التصنيف فإنه سوف يقع فوق تصنيف “web Services”.
  4. الخطوة الثانية : تكمن في اخبار دروبال ان يقوم بتضمين المسار الفعلي لإعدادات الملاحظات ضمن تصنيف “node annotations”. قمنا بذلك عبر إسناد المسار عنصر القائمة إلى المسار التالي : admin/config/annotate/settings.  عندما يقوم دروبال بإعادة بناء شجرة القوائم menu tree , سوف ينظر للمسارات لبناء العلاقة بين المسارات الأباء والمسارات الأبناء. وبما أن المسار admin/config/annotate/settings هو مسار ابن للمسار admin/config/annotate عندها سيتم عرض المسار الأول (الابن ) ضمن تصنيف المسار الثاني (الأب).

يقوم دروبال عادة بتحميل الملفات الضرورية فقط لإكمال اي طلب. وهذه التقنية توفر الكثير من استخدام الذاكرة. وبما أن الاستدعاء الموجود ضمن المفتاح callback المذكور ضمن annotate_menu – يقوم بطلب ملف من خارج إطار وحدتنا ( على سبيل المثال : التابع system_amin_menu_block_page() الموجودة أصلاً ضمن system.module ) فنحن بحاجة لإخبار دروبال بأن يقوم بتحميل الملف modules/system/system.admin.inc بدل من محاولة تحميل الملف من المسار التالي : sites/all/modules/custom/annotate/system.admin.inc. ونقوم بذلك عبر إخبار دروبال بأن يحصل على مسار وحدة النظام system module ويضع النتيجة في المفتاح ” مسار الملف” ” file path ” التابع لعنصر القائمة )أقرأ الملاحظة أدناه).

ملاحظة : ضمن تنجيز الهوك  (hook )  annotate_hook()  وضمن جسم هذا التابع نقوم بإنشاء مصفوفة $items كما هو واضح فيما سبق , وكل عنصر ضمن هذه المصفوفة (هذا العنصر يمثل بالنهاية مسار) عبارة عن مصفوفة على الشكل التالي  (مفتاح -< قيمة ) (key->value) مثلا (‘title’->’Node annotaion’)ونسمي كل من title , description , file path , callback … ضمن تلك المصفوفات بالمفاتيح “keys”وهذا ما قصدناه بكلمة مفتاح في المقطع السابق.

إن المثال المذكور فيما سبق ( عملية إنشاء تصنيف جديد ) هو مثال بهدف الشرح فقط , بينما في امثلة الحياة الواقعية , يجب ايكون لديك سبب مقنع جدا لتنشأ تصنيف جديد , وذلك لتجنب ارباك مدير النظام بوجود العديد من التصنيفات.

تقديم نموذج اعدادات للمستخدم  Presenting a Settings Form to the User

ضمن وحدة annotate , اعطينا مدير النظام القدرة على اختيار انماط العقد node type  التي ستكون متاحة لنظام الملاحظات الذي انشأناه , الشكل 2-1. دعونا نخوض الآن في آلية عمل ذلك.

عندما يرغب مدير النظام في تغيير الاعدادات الافتراضية لوحدة “annotate” , نريد عندها ان نقوم بعرض نموذج form  بحيث يستطيع المدير ان يختار ضمن الخيارات التي ستعرض أمامه ضمن هذا النموذج.

ضمن عنصر القائمة الخاص بنا , جعلنا مفتاح  ال “page callback” ضمن المصفوفة يشير إلى تابع drupal_get_form() , أما بالنسبة للمفتاح “page argument” فقد اسندنا له مصفوفة تحوي على “annotate_admin_settings”.  هذا يعني بأنك عندما تذهب إلى المسار التالي : http://example.com/?q=admin/config/annotate/settings,  , فإنه سيتم تنفيذ الاستدعاء التالي : drupal_get_form(‘annotate_admin_settings’)  , والذي بدوره,وبشكل أساسي ,يخبر دروبال بأنه قد حان الوقت لإنشاء النموذج form المعرف ضمن التابع annotate_admin_settings().

دعونا نلقي نظرة على التابع الذي يقوم بتعريف النموذج , ذاك النموذج الذي يعرّف صندوق اختبار لكل نمط عقد( انظر إلى الشكل 2-1 ) , ولنقم الآن بإضافة خيارات اخرى.

التابع موجود ضمن المسار التالي : sites/all/modules/custom/annotate/annotate.admin.inc

لقد اضفنا radio button لتحديد متى يتوجب حذف الملاحظات , بالاضافة إلى حقل نصي لتحديد عدد الملاحظات المسموحة للعقدة الواحدة ( تحقيق وبرمجة هذه الاضافات ضمن هذه الوحدة سوف نتركها لك كتمرين ).

وبدل ان نقوم بالتحكم بمعالجة النموذج ( بعد ان يتم ضغط زر submit ) سوف نستدعي التابع system_settings_form() وبذلك نمكن وحدة النظام system module  من:

v      اضافة بعض الأزرار للنموذج

v      وإدارة عملية التحقق من صلاحية المعلومات validation

v      وعملية ارسال المعلومات submission الخاصة بالنموذج.

الشكل 2-5 يظهر كيف يبدو النموذج بعد إضافة الخيارات الجديدة.

التحقق من البيانات المدخلة من قبل المستخدم Validating user-submitted settings

إن التابع system_settings_form() يقوم بحفظ البيانات والقيم المدخلة عبر النموذج , ولكن كيف بإمكاننا التحقق فيما إذا كانت القيمة المدخلة ضمن حقل ” عدد الملاحظات الكلي للعقدة ” “annotation per node” هو رقم فعلي وليس عبارة عن محارف اخرى؟ نحن بحاجة لإضافة تحقق يمكننا من معرفة فيما إذا كانت القيمة المدخلة هي قيمة عددية , بإمكاننا تحقيق ذلك عبر تابع التحقق validation function  , واسمه annotate_admin_sttings_validate($form, $form_state) , وطبعا التسمية معيارية حتى يتم استدعاء التابع بشكل اوتوماتيكي , حيث تتم التسمية وفقا لما يلي form_function_name+_validate($form, $form_state) , ويتواجد تابع التحقق ضمن المسار التالي : sites/all/modules/custom/annotate/annotate.admin.inc, وبإمكاننا استخدام هذا التابع لإظهار رسالة خطأ للمستخدم تبين له مكان الخطأ في الادخال.

 

الآن , وعندما يقوم دروبال بمعالجة النموذج , فإنه سوف يستدعي التابع annotate_admin_settings_validate() من أجل القيام بالتحققات المناسبة. في حال اكتشفنا من خلال هذا التابع بأنه قد تم ادخال قيمة غير مناسبة , عندها نضع اشارة خطأ بجوار الحقل الذي حدث عنده خطأ الإدخال, ويتم عرض رسالة تنبيه على الشاشة , بالاضافة إلى تلوين حواف الحقل باللون الأحمر لتبيان مكان الخطأ في الادخال.

كيف يعرف دروبال متى يستدعي هذا التابع؟ كما ذكرنا وسنعيد , بأننا قمنا بتسمية تابع التحقق من الأخطاء بطريقة خاصة , باستخدام اسم تابع النموذج form function name  , وفي حالتنا كان اسم التابع “annotate_admin_settings”مضافاً إليه كلمة “_validate” .

في الفصل 11 يوجد المزيد من الشرح عن الآلية التي يقوم عن طريقها دروبال باستدعاء التابع المناسب للتحقق validation function  .

حفظ الإعدادات Storing settings

ضمن المثال السابق , نلاحظ عندما نفتح على نموذج الإعدادات  ضمن الرابط التالي : http://example.com/?q=admin/config/annotate/settings,   وبالضغط على زر “save configuration” فأن الإعدادات تُحفظ.

في القسم التالي سوف نشرح آلية كيف يتم ذلك.

استخدام جدول “المتحولات” ضمن دروبال Using Drupal’s variable Table  

دعونا ننظر إلى حقل “Annotations per node”. تم اسناد القيمة التالية variable_get(‘annotate_limit_per_node’,1)  إلى مفتاح “#default_value”.

يملك دروبال جدول اسمه variables ضمن قاعدة المعطيات , ويمكن تخزين قيم من النمط ثنائيات : (مفتاح – قيمة) key-value pairs  ضمن هذا الجدول , وذلك باستخدام التابع variable_set($key, $value) ويمكن استعادة هذه القيم باستخدام التابع variable_get($key, $default).

اي إننا ببساطة عبر variable_get(‘annotate_limit_per_node’,1) نقول::  اسند القيمة الخاصة بحقل “Annotation per node” إلى القيمة المخزنة ضمن جدول variables ,وذلك بواسطة المتحول ذو الاسم  annotate _limit_per_node , وفي حال لم يتم ايجاد اي قيمة مخزنة باسم هذا المتحول , عندها اسند القيمة 1 إلى الحقل “Annotation per node”.

أما بالنسبة للحقل “Annotations will be deleted” فإن حالته اعقد بعض الشيء , لانه عبارة عن حقل من نمط radio button . وخيارات #options هذا الحقل هي التالية:

 

   مع العلم بأن php عندما يكونه لديه مصفوفة ذات قيم , وبدون مفاتيح keys , فإنه يقوم بشكل تلقائي من اضافة مفاتيح رقمية , لذلك فإن تمثيل المصفوفة السابقة داخلياً سيكون على الشكل التالي :

 

عندما نقوم بإسناد القيمة الافتراضية لهذا الحقل , فإننا نستخدم الترميز التالي ادناه , هذا يعني في الواقع , بأن القيمة الافتراضية هي العنصر 0 من المصفوفة , وذلك يعنيt(‘Never’) .

‘#default_value’ => variable_get(‘annotate_deletion’, 0) // Default to Never

 

 استعادة القيم المخزنة وذلك باستخدام التابع variable_get()   Retrieving Stored Values with variable_get()

عندما تقوم وحدتك باستعادة القيم المخزنة , عندها يجب استخدام التابع variable_get() , لاننا في التخزين استخدمنا variable_set().

// Get stored setting of maximum number of annotations per node.

$max = variable_get(‘annotate_limit_per_node’, 1);

 

Note the use of a default value for variable_get() here also, in case no stored values are available

(maybe the administrator has not yet visited the settings page).

لاحظ استخدام القيمة الافتراضية للتابع variable_get() ,وذلك من اجل الحالة التي لايوجد فيها قيم مخزنة(ربما لم يكن المدير قد قام بزيارة هذه الصفحة بعد) .

  خطوات اضافية Further Steps 

بما أننا سنقوم بمشاركة الوحدة التي قمنا بكتابتها مع مجتمع المصدر المفتوح open source community  , فمن الطبيعي ان يتواجد ملف README.txt , لذلك يتوجب علينا انشاء هذا الملف ووضعه ضمن مسار مجلد annotate بجوار ملف annotate.info, annotate.module, annotate.admin.inc , annotate.install.

يحوي ملف README.txt بشكل عام على معلومات حول من قام بكتابة هذه الوحدة , وعن كيفية تثبيت هذه الوحدة. ولا يوجد داعي لإضافة معلومات رخصة عن الوحدة, لأن كل الوحدات التي يتم تحميلها إلى موقع drupal.org تعتبر GPL-licensed  , وستقوم سكريبت الحزمة الموجودة على drupal.org بشكل اوتوماتيكي بإضافة ملف LICENSE.txt .

ومن ثم يصبح بإمكانك تحميل ورفع وحدتك لتصبح ضمن مخزن الوحدات المساهمة على موقع drupal.org, وبعدها أنشأ صفحة المشروع وتابع التغذية الراجعة من بقية المشاركين في المجتمع (مجتمع دروبال).

خلاصة   Summary   

بعد قراءة هذا الجزء , أصبح بإمكانك تنفيذ المهام التالية :

  • إنشاء وحدة ضمن دروبال من الصفر
  • فهم آلية تنفيذ التعليمات البرمجية عبر استخدام الهاكات (الأحداث ) hooks ضمن دروبال
  • تخزين واستعادة الإعدادات الخاصة بالوحدات ضمن دروبال
  • إنشاء ومعالجة بعض النماذج البسيطة simple forms  باستخدام واجهة النماذج ضمن دروبال Drupal’s form API
  • إنشاء تصنيف إداري جديد ضمن الصفحة الإدارية الرئيسية ضمن دروبال
  • إنشاء نموذج لمدير النظام لينتقي الخيارات المناسبة عبر استخدام صناديق الاختيار, الحقول النصية , و radio buttons
  • التحقق من الإعدادات المدخلة من قبل المستخدم وإظهار رسالة خطأ في حال كان هنالك خطأ بالمدخلات
  • فهم الآلية التي يقوم دروبال عبرها بتخزين واستعادة الإعدادات وذلك باستخدام نظام المتحولات الدائم المدمج ضمن دروبالbuilt-in persistent variable system .

في حال وجود اي استفسارات , او ملاحظات , لا تترددوا في مراسلتنا

مع تمنياتي لكم بالتوفيق

انقر هنا لتحميل : “كتابة وحدة ” writing a module

انقر هنا لتحميل : “كتابة وحدة ” writing a module

المصطلح

الترجمة

الشرح

core modules

وحدات النوة

contributed  modules

الوحدات المساهمة

Polls

استطلاعات الرأي

Node

عقدة

Annotation

شرح

Taxonomy

نظام التصنيف

Implement

تنجيز أو تحقيق

تنجيز أو تحقيق تابع ما , اي كتابة محتوى هذا التابع

To implement a function it means to write the body of this function

taxonomy term

مصطلح او تصنيف

Core

نواة

Property

خاصية

function

وظيفة أو تابع بحسب السياق

Configuration

الإعدادات

Installer

مثبت

Installation

التثبيت

variable

متحول

                                                  `

, , , , , , , , , , , , , , , ,

  1. #1 by n88d on فبراير 10, 2013 - 8:13 م

    مشكور كتير

اترك رد

Please log in using one of these methods to post your comment:

WordPress.com Logo

أنت تعلق بإستخدام حساب WordPress.com. تسجيل خروج   / تغيير )

صورة تويتر

أنت تعلق بإستخدام حساب Twitter. تسجيل خروج   / تغيير )

Facebook photo

أنت تعلق بإستخدام حساب Facebook. تسجيل خروج   / تغيير )

Google+ photo

أنت تعلق بإستخدام حساب Google+. تسجيل خروج   / تغيير )

Connecting to %s

%d مدونون معجبون بهذه: