ดูด feed และรูปที่เป็น enclosure ใน Drupal

โมดูล feedapi และ feedapi_mapper ใช้สำหรับดูด feed มาสร้างเป็น node ใน Drupal แต่ถ้าอยากดูดรูปมาด้วย (เฉพาะ feed ที่มีรูปใน enclosure หรือส่วนอื่นที่แยกจากเนื้อหาอย่างชัดเจน) ก็สามารถใช้ mapper ด้านล่าง (อันนี้เป็นตัวแก้บั๊กของ ImageField mapper) โดยจะดึงรูปมาบันทึกไว้ และแสดงโดยใช้ filefield และ imagefield ครับ (mapper ด้านล่างเอาไว้ใช้ชั่วคราวครับ จนกว่า FileField mapper จะสามารถทำได้)

  1. เปิดโมดูลทั้ง 4 ที่กล่าวไว้
  2. บันทึกไฟล์ด้านล่างชื่อ feedapi_mapper_imagefield.inc ไว้ใน sites/all/modules/feedapi_mapper
  3. เพิ่ม imagefield เข้าไปใน "ชนิดเนื้อหา" (content-type) ที่จะเอาไว้สร้าง node สำหรับ feed นี้
  4. ตั้งค่า "[user]" ใน Path ของ imagefield ของชนิดเนื้อหา
  5. สร้างผู้ใช้ใหม่ เช่น "host.com"
  6. สร้าง feed node โดยผู้ใช้ใหม่นี้
  7. ไปที่ Map ของ feed node แล้วเลือก map รูปไปยัง field ที่ต้องการ เช่น options->enclosures->image->jpeg: Map to field_image (imagefield): Original file name
  8. รูปที่ดูดมาจะถูกบันทึกไว้ใน sites/default/files/host.com/ ครับ ^ ^
  9. ดูตัวอย่าง node ที่สร้างเสร็จแล้วได้ที่ ข่าวฟุตบอลไทย
<?php
// $Id$

/**
 * @file
 * Implements a FeedAPI mapper on behalf of the ImageField module.
 * @link http://drupal.org/project/imagefield
 */

/**
 * Implementation of hook_feedapi_mapper().
 */
function imagefield_feedapi_mapper($op, $node, $feed_element = array(), $field_name = '', $sub_field = '') {
  switch ($op) {
  case 'describe':
    return t('Maps image URLs to CCK ImageFields. The image will be downloaded and saved as a local file. You can choose whether to keep the original file name or use a hash value of the URL. The latter is better for images that are returned by scripts (like getimage.php?foo=), otherwise they would all be saved as "getimage.php".');

  case 'list':
    $sub_fields = array(
      'original' => t('Original file name'),
      'md5' => t('Hashed URL'),
    );
    
    $info = content_types($node->type);
    $fields = array();
    if (@count($info['fields'])) {
      foreach ($info['fields'] as $field_name => $field) {
        //drupal_set_message('<pre>'.htmlspecialchars(print_r($field, TRUE), ENT_QUOTES).'</pre>');
        if ($field['type'] == 'filefield' && $field['widget']['type'] == 'imagefield_widget') {
          $fields[$field_name] = $sub_fields;
        }
      }
    }
    //drupal_set_message('<pre>'.htmlspecialchars(print_r(array($fields), TRUE), ENT_QUOTES).'</pre>');
    if (count($fields)) {
      return $fields;
    }
    return FALSE;

  case 'map':
    //drupal_set_message('<pre>'.htmlspecialchars(print_r(array($node), TRUE), ENT_QUOTES).'</pre>');
    // Here is where the actual mapping happens.
    if (isset($node->{$field_name})) {
      $items = $node->{$field_name};
    }
    else {
      $items = array();
    }
    $field = content_fields($field_name);
    foreach ((array)$feed_element as $element) {
      //drupal_set_message('<pre>'.htmlspecialchars(print_r("element: $element", TRUE), ENT_QUOTES).'</pre>');
      $url = NULL;
      if (is_array($element)) {
        // is this an options->enclosure-media->type array
        if (valid_url($element['link'])) {
          $url = $element['link'];
        }
        elseif (valid_url($element['player'])) {
          $url = $element['player'];
        }
      }
      elseif (is_string($element) && valid_url($element)) {
        // straight link usually from options->original_url or options->guid
        $url = $element;
      }
      //drupal_set_message('<pre>'.htmlspecialchars(print_r("url: $url", TRUE), ENT_QUOTES).'</pre>');
      if ($url 
        && $file = _feedapi_mapper_imagefield_file_insert($node, $url, $sub_field, $field)) {
        // Always add as last, Image Field takes care of deleting the
        // first image for non-multiple fields. Has this been confirmed??
        $items[] = $file;
        // update the file status in the database
        field_file_save($node, $file);
        if (!$field['multiple']) {
          break;
        }
      }
    }
    $node->$field_name = $items;
    return $node;
  }
}

function _feedapi_mapper_imagefield_file_insert($node, $url, $filename_option, $field) {
  global $user;
  static $users = array(); // user_load() cache

  // Download the image.
  $result = drupal_http_request(html_entity_decode($url));
  //drupal_set_message('<pre>'.htmlspecialchars(print_r($result, TRUE), ENT_QUOTES).'</pre>');
  if ($result->code != 200) {
    return FALSE;
  }

  // Build the filename.
  $mime_type = $result->headers['Content-Type'];
  $filename = _feedapi_mapper_imagefield_get_filename($filename_option, $url, $mime_type);
  if (!$filename) {
    return FALSE;
  }
  
  // Write to temporary file. If a file with the specified name already exists, an alternative will be used.
  $tmpfile = file_create_filename($filename, file_directory_temp());
  $fp = fopen($tmpfile, 'w');
  if (!fp) {
    return FALSE;
  }
  $file = FALSE;
  if (fwrite($fp, $result->data)
    && fclose($fp)) {
    // detokenize & transliterate path by filefield_widget
    // doesn't work with http://drupal.org/project/filefield_paths
    $feedapi_node_user = $user;
    //drupal_set_message('<pre>'.htmlspecialchars(print_r($node->feedapi_node->feed_nids, TRUE), ENT_QUOTES).'</pre>');
    if ($node->feedapi_node->feed_nids) {
      // use feedapi_node's user to replace tokens
      $feed_nids = array_keys($node->feedapi_node->feed_nids);
      $feed_node = node_load($feed_nids[0]); // use the first one
      $feedapi_node_user = ($users[$feed_node->uid] ? $users[$feed_node->uid] : user_load($feed_node->uid));
      $users[$feed_node->uid] = $feedapi_node_user; // cache
    }
    $file_path = filefield_widget_file_path($field, $feedapi_node_user);
    
    // make sure path exists and writable
    if (file_check_directory($file_path, FILE_CREATE_DIRECTORY)
      || (mkdir($file_path, 0775, true) // recursive 
        && file_check_directory($file_path))) { // & check again
      // save file
      //drupal_set_message('<pre>'.htmlspecialchars(print_r(array('field_file_save_file: ', $filename, $tmpfile, $file_path), TRUE), ENT_QUOTES).'</pre>');
      $file = field_file_save_file($tmpfile, array(), $file_path);
      if ($file) {
        watchdog('feedapi_mapper', 'Saved feed image as %name from %url', array('%name' => $file['filepath'], '%url' => $url), WATCHDOG_INFO);
      }
    }
  }
   
  // delete the temporary file
  @unlink($tmpfile);
  
  return $file;
}

/**
 * Get local filename from image URL.
 *
 * @param $filename_option
 *   The selected filename generation option.
 * @param $url
 *   The feed URL.
 * @param &$mime_type
 *   The MIME type of the downloaded image.
 * @return
 *   The local filename or FALSE if the file was no image.
 */
function _feedapi_mapper_imagefield_get_filename($filename_option, $url, &$mime_type) {
  // Figure out the proper file extension from the MIME type.
  static $types = array(
    'image/gif' => 'gif',
    'image/jpeg' => 'jpg',
    'image/png' => 'png',
    'image/psd' => 'psd',
    'image/bmp' => 'bmp',
    'image/tiff' => 'tif',
    'image/jp2' => 'jp2',
    'image/iff' => 'iff',
    'image/vnd.wap.wbmp' => 'wbmp',
    'image/xbm' => 'xbm',
    'image/vnd.microsoft.icon' => 'ico',
  );
  if (!isset($types[$mime_type])) {
    return FALSE;
  }

  $ext = $types[$mime_type];

  // Create filename.
  switch ($filename_option) {
  case 'original':
    $components = parse_url($url);
    $filename = basename(urldecode($components['path']));
    if (!empty($filename)) {
      if (module_exists('transliteration')) {
        $filename = transliteration_get($filename);
      }
      if (strrchr($filename, '.') != '.'.$ext) {
        $filename .= '.'.$ext;
      }
      $munged = file_munge_filename($filename, implode(' ', array_values($types)));
      //drupal_set_message('<pre>'.htmlspecialchars(print_r(array($filename, $munged), TRUE), ENT_QUOTES).'</pre>');
      return $munged;
    }
    // falls through; can this occur?

  case 'md5':
    return file_munge_filename(md5($url) .'.'. $ext, implode(' ', array_values($types)));
  }
}

1 ความเห็น

ขอสอบถามหน่อย เนื่องจากได้ลองทำตามหลายรอบแล้ว ไม่ได้สักทีครับ จึงอยากขอสอบถามเพิ่มเติม ว่า modules ที่ใช้มีอะไรบ้าง และเวอร์ชั่นไหน แก้ไขไฟล์ไหน มีจุดสำคัญตรงไหน และหากไม่รบกวนเกินไป อยากทราบแบบ ละเอียดหน่อยได้ไหมครับ ทาง e-mail ก็ได้ครับ พอดี ต้องใช้แบบนี้จริง และที่ทดลองมาดึง feed มาจาก http://rssfeeds.sanook.com/rss/feeds/sanook/sport.football.xml

และไม่ทราบฝั่งส่ง feed แบบ http://rssfeeds.sanook.com/rss/feeds/sanook/sport.football.xml drupal มี modules รองรับไหมครับ (สร้าง feed มาจาก view นะ )

ขอบคุณ ล่วงหน้า ครับ

แสดงความเห็น

เนื้อหาของข้อมูลนี้ถูกรักษาเป็นความลับและไม่แสดงต่อสาธารณะ

 

sponsor 3a sponsor 3a sponsor 3a

Ruzzy รับสมัครทีมงานคอลัมนิสครับ ^^ 3 ชั่วโมงก่อน
serena สบายดี..น่ารัก 7 ชั่วโมงก่อน
ball.in.th พบกับเว็บรูปโฉมใหม่ สุดแจ่ม พร้อมเนื้อหาแน่นปึก เร็วๆนี้!! และยินดีต้อนรับทีมงานใหม่ทุกๆท่าน ^^ 23 ชั่วโมงก่อน
หนาว...นะ » ๙๙๙กุมารทอง๙๙๙ ไม่น่าเล้ยย..ลิเวอร์พลู จะได้อันดับ 4 ไหมเนี๊ย... 2 วันก่อน
๙๙๙กุมารทอง๙๙๙ » หนาว...นะ ก็ดีอะวันนี้บราชิลดีป่ะ 1 สัปดาห์ก่อน