נגישות       נגישות
שינוי גודל טקסט:
א א א
שינוי צבעי האתר:
? מקשי קיצור:

לחיצה חוזרת ונשנית על המקש Tab תעביר אתכם בין הקישורים והאזורים השונים בעמוד.

הפעלת מקשי הקיצור תלויה בדפדפן שבו אתם משתמשים.

Internet Explorer, Chrome ובגרסאות ישנות של Firefox: לחצו על מקש Alt ועל מקש המספר או האות על-פי הרשימה. ב Firefox 3 ומעלה: לחצו על המקשים Alt + Shift + המספר או האות.

S - עבור לתוכן הדף
L - חיפוש
1- עמוד הבית
2 - פרוייקטים
3 - מדריכים
4 - אודות
5 - צרו קשר
6 - הצהרת נגישות
 

כתיבת מודול דרופלי: הפיכת קובץ CSV לטקסונומיה הכוללת היררכיה

מחבר:
בתאריך:

מדריך זה מדגים ומסביר מודול פשוט, שמאפשר העלאת קובץ csv לשרת ( קראו על csv ), והפיכתו ל טקסונומיה דרופלית שכוללת שתי רמות היררכיה – מונחים הורים ומונחים ילדים. לדוגמה, באוצר מילים טקסונומי ששמו אזורים, יכולים להופיע אזורים במדינה, דוגמת "צפון", "מרכז" ו-"דרום" כמונחים הורים, ושמות ישובים כדוגמת "תל אביב", "חיפה" ו- "ירושלים" כמונחים ילדים.

בסרטון המצורף תוכלו למצוא הסבר על אופן פעולת המודול.

 

להורדת המודול מ github

בדרכנו לכתוב את המודול נסביר את הדברים הבאים:

  1. כיצד לבנות טופס דרופלי שמעלה קבצים לשרת?
  2. כיצד להעלות קובץ למקום קבוע בשרת?
  3. כיצד ליצור אוצר מילים טקסונומי חדש באופן תכנותי?
  4. כיצד ליצור, בתוך אוצר המילים, מונחים טקסונומיים הכוללים היררכיה?

המדריך די מתקדם, ולמי שאינו יודע דבר על תכנות מודולים של דרופל מומלץ המדריך:
"כיצד לבנות מודול בדרופל?".

 

מבנה המודול

שמו של המודול csvtax, ועל כן ניצור בתיקייה ששמה csvtax את הקבצים הבאים:

  • csvtax.info
  • csvtax.module

 

קובץ csvtax.info

כולל את המידע הבסיסי על המודול.

name = "Csvtax"
 
description = "Transforms a CSV file to a drupal taxonomy"
 
core = "7.x"
version = "7.x-1.0"
package = "Reshetech"
 
files[] = csvtax.module
 
configure = admin/config/csvtax

 

קובץ csvtax.module

יצירת דף ומתן הרשאות לדף

בשלב ראשון, ניצור דף למודול באמצעות hook_menu(), ונגדיר את הדף כמנהלי באמצעות הגדרת נתיבו ל- 'admin/config'.

כדי למנוע מכל אחד לגשת לדף שיצרנו, ניצור עבור הדף הרשאות באמצעות hook_permission().

/**
 * Implements hook_permission().
 */

function csvtax_permission() {
  return array(
    'access csvtax' => array(
      'title' => t('Acess csvtax configuration page'),
      'description' => t('Which role is allowed to access the csvtax configuration page'),
    ),
  );
}
 
 
/**
 * Implements hook_menu().
 */

function csvtax_menu () {
 
  // Makes "csvtax settings" appear on the administration configuration page.
  $items['admin/config/csvtax'] = array(
    'title' => 'Csvtax settings',
    'description' => 'The csv you want to convert to taxonomy',
    'access arguments' => array('access csvtax'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array( 'csvtax_config_form'),
    'type' => MENU_NORMAL_ITEM,
  );
 
  return $items;
}

 

טופס שמאפשר העלאת קבצים לשרת

כדי להעלות קבצים נזדקק לשני סוגי שדות:

• שדה אחד, שמספק שיטת קידוד לטופס כולו שתומכת בהעלאת קבצים.

$form['#attributes'] = array(
  'enctype' => 'multipart/form-data',
);

• שדה נוסף, שמאפשר העלאת קבצים לשרת.

// The user inputs the csv file.
$form['csvtax']['source'] = array(
  '#title' => t('The csv'),
  '#type' => 'file',
  '#description' => t('Upload a csv file'),
);

כך ייראה הקוד לטופס המלא, שכולל נוסף לשדות שכבר הסברנו גם שדה למילוי על ידי המשתמש שכולל את שם הטקסונומיה שהוא מעוניין ליצור, וכפתור submit, לשליחת הטופס לעיבוד.

/**
 * Implements hook_form().
 */

function csvtax_config_form($form, &$form_state) {
  // An encoding type that allows files to be sent through a POST.
  $form['#attributes'] = array(
    'enctype' => 'multipart/form-data',
  );
  
  // The name of the new vocabulary the user wants to create.
  $form['csvtax']['vocabulary_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Vocabulary name'),
    '#description' => t('The name of the vocabulary to be created'),
    '#size' => 60,
    '#maxlength' => 128,
    '#required' => TRUE,
  );
  
  // The user inputs the csv file.
  $form['csvtax']['source'] = array(
    '#title' => t('The csv'),
    '#type' => 'file',
    '#description' => t('Upload a csv file'),
  );
  
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Create taxonomy vocabulary from the input'),
    '#submit' => array('csvtax_config_form_submit'),
  );
  
  return $form;
}

 

הפונקציה שמטפלת בטופס שנשלח

הפונקציה הבאה תכלול את כל הקוד שישמש לטיפול בטופס שנשלח.

function csvtax_config_form_submit($form, &$form_state) {
  // יתר הקוד במדריך הולך לכאן
}

נתחיל משורות הקוד הבאות, שמקבלות את שם אוצר המלים שהזין המשתמש לטופס. שורות קוד אילו, כמו הבאות, ימוקמו בתוך הפונקציה:

// The values that are passed from the form.
$vocabulary_name = $form_state['values']['vocabulary_name'];

 

העלאת הקבצים לשרת

בשלב ראשון, נשתמש בפונקציה file_save_upload() כדי להוסיף את הקובץ כקובץ זמני. הפונקציה מקבלת את הפרמטרים הבאים:

  • 'source' – לפי שם השדה בטופס.
  • $validators – וידוא של הקובץ שהועלה.
  • 'public://docs' . variable_get('document_path', '') – מיקום הקובץ, בדרך כלל sites/default/files/, וכדי שזה יעבוד צריך להוסיף תיקיית docs.
  • FILE_EXISTS_REPLACE – הוראה לאופן הטיפול בקובץ, ובמקרה זה, החלפת קובץ אם קיים כבר קובץ בשם זהה.

// Necessary, since Drupal doesn't allow the upload of CSV files as default behavior.
$validators = array('file_validate_extensions' => array('csv'),);
 
// The file will be added to the {file_managed} table as a temporary file.
$file = file_save_upload('source', $validators, 'public://docs' . variable_get('document_path', ''), FILE_EXISTS_REPLACE);

בשלב שני, נשמור את הקובץ למקומו הקבוע באמצעות file_save().

if ($file){
  // The file's location.
  $doc_url = file_create_url($file->uri);
 
  // Sets the status of the uploaded file.
  $file->status = FILE_STATUS_PERMANENT;
 
  // Saves a file object to the database.
  file_save($file);
} else {
  form_set_error('source', t('The file failed to upload.'));
}

 

טיפול בקובץ ה-csv

נטפל בקובץ ה-csv, שהעלינו לשרת, באופן הרגיל שבו אנו מטפלים בקבצים מסוג זה ב-php( מדריך php לטיפול בקבצי csv ). לצורך כך, נפתח הקובץ באמצעות fopen, ונסגור באמצעות fclose. בין לבין, נעבור על קובץ ה-csv, שורה-שורה, בתוך לולאה שכוללת את הפונקציה fgetcsv, שמצרפת את הנתונים בכל שורה כמערכים שמקוננים בתוך המערך $the_big_array.

נדגים את את מה שהקוד הזה עושה, באמצעות קובץ csv לדוגמה, שעשוי להראות משהו כזה:

darom, beer sheva
center, tel aviv
center, Yerushalaim

ואחרי שהקוד יטפל בו, הוא יקבל צורה של מערך מקונן, שייראה כך:

$the_big_array = array(
    0 => array(0 => "darom", 1 => "beer sheva"),
    1 => array(0 => "center", 1 => "tel aviv"),
    2 => array(0 => "center", 1 => "Yerushalaim"),
);

שימו לב, שכל שורה יוצרת מערך מקונן חדש, ושהפריטים בתוך המערך מופרדים באמצעות פסיקים. כך נראה הקוד:

// The array of all the data from the csv file.
$the_big_array = array();  
// Opens the file we have just uploaded, and provides a handle.
if (($handle = fopen("{$doc_url}", "r")) !== FALSE) {
 
  // Each line produces one array of $data items seperated by ",".
  while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
    $the_big_array[] = $data;
  }
  fclose($handle);
}

 

יצירת אוצר מילים טקסונומי על פי השם שהזין המשתמש לטופס

יצירת אוצר מילים טקסונומי בדרופל, נעשית באמצעות הפונקציה taxonomy_term_save, שזו הצורה שלה:

$new_vocabulary = (object)array(
  'name' => $vocabulary_name,
  'description' => '',
  'machine_name' => $machine_name,
);
 
taxonomy_vocabulary_save($new_vocabulary);

אבל ראשית עלינו לברר שאוצר המילים לא קיים כבר באמצעות הפונקציה taxonomy_vocabulary_machine_name_load. כך נראה הקוד המלא שנשתמש בו ליצירת אוצר המילים הטקסונומי על פי השם שהזין המשתמש לטופס:

// Creates a machine name from the vocabulary name.
$machine_name = strtolower($vocabulary_name);
 
// Creates a vocabulary name, if it doesn't already exist.
if(taxonomy_vocabulary_machine_name_load($machine_name) !== FALSE){
  form_set_error('vocabulary_name', t('The vocabulary name exists. Please choose another name.'));
  return;
} else {
  // Saves a new vocabulary.
  $new_vocabulary = (object)array(
    'name' => $vocabulary_name,
    'description' => '',
    'machine_name' => $machine_name,
  );
 
  taxonomy_vocabulary_save($new_vocabulary);
 
  // Inform the user we have just created a new vocabulary.
  drupal_set_message("A new vocabulary '{$vocabulary_name}' was created");
}

 

יצירת מונחים טקסונומיים מסוג parents

ראשית, נעלה את אוצר המילים שיצרנו בסעיף קודם, כדי שישמש אותנו להגדרת אוצר המילים אליו ישתייך כל אחד מהמונחים שניצור בהמשך.

// Loads the vocabulary we have just created.
$vocabulary = taxonomy_vocabulary_machine_name_load($machine_name);

ניקח רק את הפריטים הראשונים מכל מערך שיצרנו, וניצור מהם מערך של פריטים ייחודיים שישמשו בתור המונחים ההורים בטקסונומיה. חשוב שהפריטים יהיו ייחודיים, כדי שלכל מונח ילד יהיה מונח הורה אחד בלבד.

// Takes only the first item from each line.
// These items are the parents in the taxonomy we are creating.

$only_first_items = array();
 
$count_big_array = count($the_big_array);
 
for($i=0; $i < $count_big_array; $i++){
  $only_first_items[] = $the_big_array[$i][0];
}
 
// Only unique parents without duplicates,
// since each child term may have only one parent.

$unique_first_items = array_unique($only_first_items);

נשמור את מושג הטקסונומיה באמצעות taxonomy_term_save().

// Creates parent taxonomy terms.
foreach($unique_first_items as $item){
  $term = (object)array(
    'name' => $item,
    'description' => '',
    'vid' => $vocabulary -> vid,
);
 
taxonomy_term_save($term);

אחרי שיצרנו את המונח ההורה, ניצור מערך $highest, שיכלול את שם המונח ואת ה-tid שלו, המזהה הייחודי של הטקסונומיה. מערך זה, ישמש אותנו בסעיף הבא כשנרצה ליצור הורים למונחים הילדים שניצור.

// Taxonomy term name we just created.
$term_load = taxonomy_term_load($term -> tid);
$name = $term_load -> name;
$tid = $term_load -> tid;
 
// Will be used later as described above.
$highest[] = array($name => $tid);
 
// Inform the user with each new parent taxonomy term created.
drupal_set_message("The parent taxonomy term '{$name}' was created.");

 

יצירת מונחים טקסונומיים ילדים

כדי ליצור מונח ילד עלינו להגדיר עבורו הורה. חלק זה יעשה בתוך לולאה שרצה על המערך $the_big_array, ושולפת את שם הילד (פריט שני במערך) ואת שם ההורה (פריט ראשון במערך) עבור כל אחד מפריטי המערך.

// Creates the children in the taxonomy.
for($i=0; $i < $count_big_array; $i++){
 
  $first_item_name = $the_big_array[$i][0];
  $second_item_name = $the_big_array[$i][1];
  //שאר הקוד כפי שיובא בהמשך הסעיף
}

את שם ההורה נשווה עם שם ההורה הקיים במערך $highest, ובמידה ומצאנו התאמה נשמור את ערך ה-tid של ההתאמה, ונשתמש בה בתור ה-tid של ההורה (עבור מונח הילד שאנו יוצרים).

// Creates the children in the taxonomy.
for($i=0; $i < $count_big_array; $i++){
 
  $first_item_name = $the_big_array[$i][0];
  $second_item_name = $the_big_array[$i][1];
 
  $ch = count($highest);
 
  // If matches, we found the parent and can take its' tid.
  for($k=0; $k < $ch; $k++){
    foreach($highest[$k] AS $key => $value){
      if($key == $first_item_name){
        $parent_tid = $value;
      }
    }
  }
 
  // Creates the child terms.
  $term1 = (object)array(
    'name' => $second_item_name,
    'description' => '',
    'parent' => $parent_tid,
    'vid' => $vocabulary -> vid,
  );
 
  taxonomy_term_save($term1);
 
  // The name of the taxonomy term we have just created.
  $term1 = taxonomy_term_load($term1 -> tid);
  $name = $term1->name;
 
  // Inform the user with each new child taxonomy term created.
  drupal_set_message("The child taxonomy term '{$name}' was created.");
}

בקוד שזה עתה הצגתי, חשוב לשים לב, שה-parent מוגדר עבור המונח שאנחנו יוצרים, מפני שכך יוצרים מונח ילד.

 

יצירת מונחים טקסונומיים נכדים, נינים, וכיו"ב

ראינו שכדי להגדיר מונח ילד צריך להגדיר מיהו ההורה. לפי אותו הגיון, ניתן ליצור מונחים נכדים, שההורים שלהם יהיו הילדים. כנ"ל נינים, וכל רמה שצריך.

 

לסיכום

ראינו כיצד דרופל יכול לתת כוח עצום לתוכן שמכניסים אליו. התחלנו מרשימה מופרדת בפסיקים, וקיבלנו בקוד לא מסובך מדי מערכת טקסונומית היררכית שניתנת לסידור ולחיתוך בהתאם לצרכים שלנו.

אתם מוזמנים להוריד את המודל מכאן:

להורדה

הוסף תגובה חדשה

 

= 6 + 6