באחד הפרויקטים האחרונים שלי, נתקלתי בדרישה מעניינת – משלוח מייל למנהל האתר בכל פעם שיש פרסום כלשהו בדרופל. בדרך כלל אני משתמש להתראות כאלו במודול Triggers (שמובנה בליבת דרופל) או במודול Rules. הבעיה היא שהדרישה היתה שמשלוח המייל יקרה לא בשעת יצירת התוכן אלא בשעת הפרסום (published) שלו שיכול להיות בשעה שונה לחלוטין מהשעה שבה הוא נוצר. בנוסף, אם התוכן פורסם בעבר ואני עורך אותו מחדש ועושה לו שוב publish, הדרישה היא שהוא לא ישלח מייל.
איך עושים את זה? באמצעות מודול מהיר שייצרתי לצורך העניין. מה המודול עושה? אני מכניס וולידציה לטופס יצירה/עריכה של node. הוולידציה, שרצה לאחר הוולידציות האחרות – בודקת את מצב ה-node. במידה והוא חדש והוא published, היא תשלח מייל למנהל האתר (user 1). במידה והוא ישן, היא תבדוק את מצבו הקודם באמצעות node_load, במידה והמצב משתנה מ'לא מפורסם' ל'מפורסם', יישלח מייל. במידה ולא, דבר לא יקרה.
אני יוצא מנקודת הנחה שכל מי שממשיך לקרוא טרח לקרוא את המאמר הקודם שלי על יצירת מודולים בדרופל 6 ו-7. המאמר מסביר על בניית מודולים ועל קובץ info ומה זה hook. שם המודול בדוגמה הזו הוא: mail_admin_on_publish.
איך עושים את זה בדרופל 6? בקלי קלות! ראשית אנו נשתמש ב-hook_form_alter על מנת להכנס ל-form ולהוסיף לו פונקצית וולידציה נוספת:
< ?php
/**
*
* Implementation of hook_form_alter - adding validation function
* @param $form
* @param $form_state
* @param $form_id
*/
function mail_admin_on_publish_form_alter(&$form, &$form_state, $form_id) {
$form['#validate'][] ='mail_admin_on_publish_validate';
}
שם פונקציה הוולידציה הוא כמובן mail_admin_on_publish_validate. הפונקציה הזו היא ליבת המודול:
/**
*
* Validation function for adding form. checks if node is published.
* @param $form_id
* @param $form_values
*/
function mail_admin_on_publish_validate($form_id, $form_values) {
if($form_values['values']['status'] == '1') {
$form_values['values']['nid'] ? $node = node_load($form_values['values']['nid']) : $node = $form_values['values'];
if($node->status == '0') { //If it is updated from unpublished to published
$params = array(
'title' => $node->title,
'type' => $node->type,
'path' => $node->path,
'teaser' => $node->field_teaser[0][value],
'lang' => $node->language,
);
drupal_mail('mail_admin_on_publish', 'invitation', user_load(1)->mail , language_default(), $params);
}
if (!$form_values['values']['nid']) { //If it brand new and published already.
$params = array(
'title' => $node[title],
'type' => $node[type],
'path' => $node[path],
'teaser' => $node[field_teaser][0][value],
'lang' => $node[language],
);
drupal_mail('mail_admin_on_publish', 'invitation', user_load(1)->mail , language_default(), $params);
}
}
}
בפונקצית וולידציה עוברים באופן אוטומטי, נרצה או לא נרצה, שני פרמטרים – form_id שהוא בעצם ה-id של הטופס (אני לא משתמש בו פה) ושנית ה-form_values שמכיל את כל הערכים של הטופס – כלומר רוב המידע על ה-node החדש או זה שנערך.
ראשית אני בודק באמצעות התנאי $form_values['values']['status'] אם בכלל המשתמש פרסם את ה-node או לא. כי אם המשתמש לא סימן את תיבת ה-publish בטופס, אין לי ממש מה לעשות איתו. במידה וכן, אני אמשיך הלאה.
אחרי כן אני מאכלס את משתנה node שאותו אצטרך למשלוח המייל (כדי לשלוח כל מני פרמטרים כמו שם ה-node, השפה שלו וכו' וכו'). במידה ויש לטופס nid, סימן שה-node קיים כבר וה-node_load יעבוד. במידה ולא, מדובר ב-node חדש דנדש והוא יקבל את הערכים של הטופס. כך או כך, אני צריך node$ ואת זה אני מקבל.
ועכשיו למבחן האמיתי, בתנאי הראשון if($node->status == '0 אני בודק אם הסטטוס של ה-node שנטען באמצעות node_load הוא unpublished, כיוון שבמידה והוא כבר published, מדובר בעדכון של node קיים ומפורסם ואין לי מה לעשות איתו. במידה וכן, אני מאכלס את מערך params שישמש אותי במשלוח המייל ויורה את המייל שלי באמצעות פונקצית drupal_mail.
בתנאי השני,
!$form_values['values']['nid']
אני בודק אם מדובר ב-node חדש. אם הוא חדש, לא יהיה לי nid (כיוון שהטופס הוא לפני וולידציה). אני מאכלס את הפרמטרים שאני רוצה (שימו לב שמשתנה node כאן מעט שונה ממה שאני מקבל ב-node_load) ומשתמש ב-drupal_mail.
drupal_mail היא פונקציה פשוטה יחסית. בדרופל אני שולחים מייל באמצעות drupal_mail שמכיל כמה פרמטרים, ראשית שם המודול, שנית שם חד חד ערכי למייל שלי לשימוש עתידי, השלישי הוא הנמען – במקרה הזה המייל של משתמש 1. הרביעי הוא שפת המייל והחמישי הוא הפרמטרים שלי שאותם אספתי בעמל רב.
תוכן המייל נקבע באמצעות hook_mail באופן הבא:
/**
*
* Implementation of hook_mail
* @param string $key
* @param array $message
* @param array $params
*/
function mail_admin_on_publish_mail($key, &$message, $params) {
switch ($key) {
case 'invitation':
$message['subject'] = t('@title is published', array('@title' => $params['title']));
$message['body'] = t('type: @type. url: @path. teaser: @teaser', array(
'@type' => $params['type'],
'@path' => $params['path'],
'@teaser' => $params['teaser']));
break;
}
}
במקרה הזה קל מאד להבין מה הולך פה. ראשית אני קובע את הכותרת ושנית אני קובע את ה-body. במייל הפשוט הזה אני משתמש בפונקצית t (תרגום) בשילוב הפרמטרים כדי להפיק מייל שאחר כך אפשר לתרגם אותו בקלות. תמיד תמיד תשלבו פרמטרים בפונקצית t באופן הזה.
ו… זהו! לפחות בדרופל 6. מה עם דרופל 7?
בדרופל 7 אין שום שינוי ב-API בנוגע לכל הפונקציות שהשתמשתי בהן – ולפיכך המודול מתאים גם לדרופל 7!