Issue #1231492 by Mark Theunissen: Added source handler for retrieving content from...
authormarktheunissen
Mon, 24 Oct 2011 00:40:50 +0000 (20:40 -0400)
committerMike Ryan
Mon, 24 Oct 2011 00:40:50 +0000 (20:40 -0400)
CHANGELOG.txt
migrate.info
plugins/sources/files.inc [new file with mode: 0644]

index 6af9dd3..c193b2f 100644 (file)
@@ -3,6 +3,7 @@ Next release
 ============
 
 Features and enhancements
+- #1231492 - Added source handler for retrieving content from file directories.
 - #1290706 - Centralize loading of XML.
 - #1295040 - Support --update functionality in UI.
 - #1304444 - Added static displayMessage(), deprecating showMessage().
index 49337e1..b34ece1 100755 (executable)
@@ -24,6 +24,7 @@ files[] = plugins/destinations/fields.inc
 files[] = plugins/destinations/table.inc
 files[] = plugins/destinations/table_copy.inc
 files[] = plugins/sources/csv.inc
+files[] = plugins/sources/files.inc
 files[] = plugins/sources/json.inc
 files[] = plugins/sources/list.inc
 files[] = plugins/sources/multiitems.inc
diff --git a/plugins/sources/files.inc b/plugins/sources/files.inc
new file mode 100644 (file)
index 0000000..19e038e
--- /dev/null
@@ -0,0 +1,176 @@
+<?php
+
+/**
+ * @file
+ * Support for migration from files sources.
+ */
+
+/**
+ * Implementation of MigrateList, for retrieving a list of IDs to be migrated
+ * from a directory listing. Each item is a file, it's ID is the path.
+ */
+class MigrateListFiles extends MigrateList {
+
+  protected $listDirs;
+  protected $baseDir;
+  protected $fileMask;
+  protected $directoryOptions;
+
+  /**
+   * Constructor.
+   *
+   * @param $list_dirs
+   *   Array of directory paths that will be scanned for files. No trailing
+   *   slash. For example:
+   *     array(
+   *       '/var/html_source/en/news',
+   *       '/var/html_source/fr/news',
+   *       '/var/html_source/zh/news',
+   *     );
+   * @param $base_dir
+   *   The base dir is the part of the path that will be excluded when making
+   *   an ID for each file. To continue the example from above, you want base_dir
+   *   to be = '/var/html_source', so that the files will have IDs in the format
+   *   '/en/news/news_2011_03_4.html'.
+   * @param $file_mask
+   *   Passed on and used to filter for certain types of files. Use a regular
+   *   expression, for example '/(.*\.htm$|.*\.html$)/i' to match all .htm and
+   *   .html files, case insensitive.
+   * @param $options
+   *   Options that will be passed on to file_scan_directory(). See docs of that
+   *   core Drupal function for more information.
+   */
+  public function __construct($list_dirs, $base_dir, $file_mask = NULL, $options = array()) {
+    parent::__construct();
+    $this->listDirs = $list_dirs;
+    $this->baseDir = $base_dir;
+    $this->fileMask = $file_mask;
+    $this->directoryOptions = $options;
+  }
+
+  /**
+   * Our public face is the directories we're getting items from.
+   */
+  public function __toString() {
+    if (is_array($this->listDirs)) {
+      return implode(',', $this->listDirs);
+    }
+    else {
+      return $this->listDirs;
+    }
+  }
+
+  /**
+   * Retrieve a list of files based on parameters passed for the migration.
+   */
+  public function getIdList() {
+    $files = array();
+    foreach ($this->listDirs as $dir) {
+      migrate_instrument_start("Retrieve $dir");
+      $files = array_merge(file_scan_directory($dir, $this->fileMask, $this->directoryOptions), $files);
+      migrate_instrument_stop("Retrieve $dir");
+    }
+
+    if (isset($files)) {
+      return $this->getIDsFromFiles($files);
+    }
+    $migration = Migration::currentMigration();
+    $migration->showMessage(t('Loading of !listuri failed:', array('!listuri' => $this->listUri)));
+    return NULL;
+  }
+
+  /**
+   * Given an array generated from file_scan_directory(), parse out the IDs for
+   * processing and return them as an array.
+   */
+  protected function getIDsFromFiles(array $files) {
+    $ids = array();
+    foreach ($files as $file) {
+      $ids[] = str_replace($this->baseDir, '', (string) $file->uri);
+    }
+    return array_unique($ids);
+  }
+
+  /**
+   * Return a count of all available IDs from the source listing.
+   */
+  public function computeCount() {
+    $count = 0;
+    $files = $this->getIdList();
+    if ($files) {
+      $count = count($files);
+    }
+    return $count;
+  }
+
+}
+
+/**
+ * Implementation of MigrateItem, for retrieving a file from the file system
+ * based on source directory and an ID provided by a MigrateList class.
+ */
+class MigrateItemFile extends MigrateItem {
+
+  protected $baseDir;
+  protected $getContents;
+
+  /**
+   * Constructor.
+   *
+   * @param $base_dir
+   *   The base directory from which all file paths are calculated.
+   * @param $get_contents
+   *   TRUE if we should try load the contents of each file (in the case
+   *   of a text file), or FALSE if we just want to confirm it exists (binary).
+   */
+  public function __construct($base_dir, $get_contents = TRUE) {
+    parent::__construct();
+    $this->baseDir = $base_dir;
+    $this->getContents = $get_contents;
+  }
+
+  /**
+   * Return an object representing a file.
+   *
+   * @param $id
+   *   The file id, which is the file URI.
+   *
+   * @return object
+   *   The item object for migration.
+   */
+  public function getItem($id) {
+    $item_uri = $this->baseDir . $id;
+    // Get the file data at the specified URI
+    $data = $this->loadFile($item_uri);
+    if (is_string($data)) {
+      $return = new stdClass;
+      $return->filedata = $data;
+      return $return;
+    }
+    else if ($data === TRUE) {
+      $return = new stdClass;
+      return $return;
+    }
+    else {
+      $migration = Migration::currentMigration();
+      $message = t('Loading of !objecturi failed:', array('!objecturi' => $item_uri));
+      $migration->getMap()->saveMessage(
+              array($id), $message, MigrationBase::MESSAGE_ERROR);
+      return NULL;
+    }
+  }
+
+  /**
+   * Default file loader.
+   */
+  protected function loadFile($item_uri) {
+    // Only try load the contents if we have this flag set.
+    if ($this->getContents) {
+      $data = file_get_contents($item_uri);
+    }
+    else {
+      $data = file_exists($item_uri);
+    }
+    return $data;
+  }
+}
\ No newline at end of file