You are here

class FeedsEnclosure in Feeds 7.2

Same name and namespace in other branches
  1. 6 plugins/FeedsParser.inc \FeedsEnclosure
  2. 7 plugins/FeedsParser.inc \FeedsEnclosure

Enclosure element, can be part of the result array.

Hierarchy

Expanded class hierarchy of FeedsEnclosure

File

plugins/FeedsParser.inc, line 303
Contains FeedsParser and related classes.

View source
class FeedsEnclosure extends FeedsElement {

  /**
   * The mime type of the enclosure.
   *
   * @param string
   */
  protected $mime_type;

  /**
   * The default list of allowed extensions.
   *
   * @param string
   */
  protected $allowedExtensions = 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp';

  /**
   * The sanitized local file name.
   *
   * @var string
   */
  protected $safeFilename;

  /**
   * Constructor, requires MIME type.
   *
   * @param $value
   *   A path to a local file or a URL to a remote document.
   * @param $mimetype
   *   The mime type of the resource.
   */
  public function __construct($value, $mime_type) {
    parent::__construct($value);
    $this->mime_type = $mime_type;
  }

  /**
   * @return
   *   MIME type of return value of getValue().
   */
  public function getMIMEType() {
    return $this->mime_type;
  }

  /**
   * Sets the list of allowed extensions.
   *
   * @param string $extensions
   *   The list of allowed extensions separated by a space.
   */
  public function setAllowedExtensions($extensions) {

    // Normalize whitespace so that empty extensions are not allowed.
    $this->allowedExtensions = drupal_strtolower(trim(preg_replace('/\\s+/', ' ', $extensions)));
  }

  /**
   * Use this method instead of FeedsElement::getValue() when fetching the file
   * from the URL.
   *
   * @return
   *   Value with encoded space characters to safely fetch the file from the URL.
   *
   * @see FeedsElement::getValue()
   */
  public function getUrlEncodedValue() {
    return str_replace(' ', '%20', $this
      ->getValue());
  }

  /**
   * Returns the full path to the file URI with a safe file name.
   *
   * @return string
   *   The safe file URI.
   *
   * @throws RuntimeException
   *   Thrown if the file extension is invalid.
   */
  public function getSanitizedUri() {
    return drupal_dirname($this
      ->getValue()) . '/' . $this
      ->getSafeFilename();
  }

  /**
   * Returns the file name transformed for better local saving.
   *
   * @return string
   *   Value with space characters changed to underscores.
   *
   * @throws RuntimeException
   *   Thrown if the file extension is invalid.
   */
  public function getLocalValue() {
    return str_replace(' ', '_', $this
      ->getSafeFilename());
  }

  /**
   * Returns the safe file name.
   *
   * @return string
   *   A filename that is safe to save to the filesystem.
   *
   * @throws RuntimeException
   *   Thrown if the file extension is invalid.
   */
  protected function getSafeFilename() {
    if (isset($this->safeFilename)) {
      return $this->safeFilename;
    }

    // Strip any query string or fragment from file name.
    list($filename) = explode('?', $this
      ->getValue());
    list($filename) = explode('#', $filename);
    $filename = rawurldecode(drupal_basename($filename));

    // Remove leading and trailing whitespace and periods.
    $filename = trim($filename, " \t\n\r\0\v.");
    if (strpos($filename, '.') === FALSE) {
      $extension = FALSE;
    }
    else {
      $extension = drupal_strtolower(substr($filename, strrpos($filename, '.') + 1));
    }
    if (!$extension || !in_array($extension, explode(' ', $this->allowedExtensions), TRUE)) {
      throw new RuntimeException(t('The file @file has an invalid extension.', array(
        '@file' => $filename,
      )));
    }
    $this->safeFilename = file_munge_filename($filename, $this->allowedExtensions, FALSE);
    return $this->safeFilename;
  }

  /**
   * Downloads the content from the file URL.
   *
   * @return string
   *   The content of the referenced resource.
   *
   * @throws FeedsHTTPRequestException
   *   In case the result code of the HTTP request is not in the 2xx series.
   */
  public function getContent() {
    feeds_include_library('http_request.inc', 'http_request');
    $result = feeds_http_request($this
      ->getUrlEncodedValue());
    http_request_check_result($this
      ->getUrlEncodedValue(), $result);
    return $result->data;
  }

  /**
   * Get a Drupal file object of the enclosed resource, download if necessary.
   *
   * @param string $destination
   *   The path or uri specifying the target directory in which the file is
   *   expected. Don't use trailing slashes unless it's a streamwrapper scheme.
   * @param int $replace
   *   Replace behavior when the destination file already exists.
   *
   * @see file_save_data()
   *
   * @return object|false
   *   A Drupal temporary file object of the enclosed resource or FALSE if the
   *   value is empty.
   *
   * @throws Exception
   *   If file object could not be created.
   */
  public function getFile($destination, $replace = FILE_EXISTS_RENAME) {
    $file = FALSE;
    if ($this
      ->getValue()) {

      // Prepare destination directory.
      file_prepare_directory($destination, FILE_MODIFY_PERMISSIONS | FILE_CREATE_DIRECTORY);

      // Copy or save file depending on whether it is remote or local.
      if (drupal_realpath($this
        ->getSanitizedUri())) {
        $file = new stdClass();
        $file->uid = 0;
        $file->uri = $this
          ->getSanitizedUri();
        $file->filemime = $this
          ->getMIMEType();
        $file->filename = $this
          ->getSafeFilename();
        if (drupal_dirname($file->uri) !== $destination) {
          $file = file_copy($file, $destination, $replace);
        }
        else {

          // If file is not to be copied, check whether file already exists,
          // as file_save() won't do that for us (compare file_copy() and
          // file_save())
          $existing_files = file_load_multiple(array(), array(
            'uri' => $file->uri,
          ));
          if (count($existing_files)) {
            $existing = reset($existing_files);
            if ($replace == FEEDS_FILE_EXISTS_SKIP) {
              return $existing;
            }
            $file->fid = $existing->fid;
            $file->filename = $existing->filename;
          }
          file_save($file);
        }
      }
      else {
        if (file_uri_target($destination)) {
          $destination = trim($destination, '/') . '/';
        }
        try {
          $filename = $this
            ->getLocalValue();
          if (module_exists('transliteration')) {
            require_once drupal_get_path('module', 'transliteration') . '/transliteration.inc';
            $filename = transliteration_clean_filename($filename);
          }
          $file = file_save_data($this
            ->getContent(), $destination . $filename, $replace);
        } catch (Exception $e) {
          watchdog_exception('Feeds', $e, nl2br(check_plain($e)));
        }
      }

      // We couldn't make sense of this enclosure, throw an exception.
      if (!$file) {
        throw new Exception(t('Invalid enclosure %enclosure', array(
          '%enclosure' => $this
            ->getValue(),
        )));
      }
      return $file;
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
FeedsElement::$value protected property The standard value of this element. This value can contain be a simple type, a FeedsElement or an array of either.
FeedsElement::getValue public function @todo Make value public and deprecate use of getValue(). 3
FeedsElement::__toString public function Magic method __toString() for printing and string conversion of this object.
FeedsEnclosure::$allowedExtensions protected property The default list of allowed extensions.
FeedsEnclosure::$mime_type protected property The mime type of the enclosure.
FeedsEnclosure::$safeFilename protected property The sanitized local file name.
FeedsEnclosure::getContent public function Downloads the content from the file URL.
FeedsEnclosure::getFile public function Get a Drupal file object of the enclosed resource, download if necessary.
FeedsEnclosure::getLocalValue public function Returns the file name transformed for better local saving.
FeedsEnclosure::getMIMEType public function 1
FeedsEnclosure::getSafeFilename protected function Returns the safe file name.
FeedsEnclosure::getSanitizedUri public function Returns the full path to the file URI with a safe file name.
FeedsEnclosure::getUrlEncodedValue public function Use this method instead of FeedsElement::getValue() when fetching the file from the URL.
FeedsEnclosure::setAllowedExtensions public function Sets the list of allowed extensions.
FeedsEnclosure::__construct public function Constructor, requires MIME type. Overrides FeedsElement::__construct 1