list.inc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?php
  2. /**
  3. * @file
  4. * Support for migration from sources with distinct means of listing items to
  5. * import and obtaining the items themselves.
  6. *
  7. * TODO: multiple-field source keys
  8. */
  9. /**
  10. * Extend the MigrateList class to provide a means to obtain a list of IDs to
  11. * be migrated from a given source (e.g., MigrateListXML extends MigrateList to
  12. * obtain a list of IDs from an XML document).
  13. */
  14. abstract class MigrateList {
  15. public function __construct() {}
  16. /**
  17. * Implementors are expected to return a string representing where the listing
  18. * is obtained from (a URL, file directory, etc.)
  19. *
  20. * @return string
  21. */
  22. abstract public function __toString();
  23. /**
  24. * Implementors are expected to return an array of unique IDs, suitable for
  25. * passing to the MigrateItem class to retrieve the data for a single item.
  26. *
  27. * @return Mixed, iterator or array
  28. */
  29. abstract public function getIdList();
  30. /**
  31. * Implementors are expected to return a count of IDs available to be migrated.
  32. *
  33. * @return int
  34. */
  35. abstract public function computeCount();
  36. }
  37. /**
  38. * Extend the MigrateItem class to provide a means to obtain the data for a
  39. * given migratable item given its ID as provided by the MigrateList class.
  40. */
  41. abstract class MigrateItem {
  42. public function __construct() {}
  43. /**
  44. * Implementors are expected to return an object representing a source item.
  45. *
  46. * @param mixed $id
  47. *
  48. * @return stdClass
  49. */
  50. abstract public function getItem($id);
  51. /**
  52. * Implementors may optionally implement a hash function, applied to the
  53. * entire source row, if this particular item type makes it difficult to
  54. * do on the raw row.
  55. *
  56. * @param $row
  57. *
  58. * @return mixed
  59. */
  60. //abstract public function hash($row);
  61. }
  62. /**
  63. * Implementation of MigrateSource, providing the semantics of iterating over
  64. * IDs provided by a MigrateList and retrieving data from a MigrateItem.
  65. */
  66. class MigrateSourceList extends MigrateSource {
  67. /**
  68. * MigrateList object used to obtain ID lists.
  69. *
  70. * @var MigrateList
  71. */
  72. protected $listClass;
  73. /**
  74. * MigrateItem object used to obtain the source object for a given ID.
  75. *
  76. * @var MigrateItem
  77. */
  78. protected $itemClass;
  79. /**
  80. * Iterator of IDs from the listing class.
  81. *
  82. * @var Iterator
  83. */
  84. protected $idIterator;
  85. /**
  86. * List of available source fields.
  87. *
  88. * @var array
  89. */
  90. protected $fields = array();
  91. /**
  92. * Simple initialization.
  93. */
  94. public function __construct(MigrateList $list_class, MigrateItem $item_class, $fields = array(),
  95. $options = array()) {
  96. parent::__construct($options);
  97. $this->listClass = $list_class;
  98. $this->itemClass = $item_class;
  99. $this->fields = $fields;
  100. }
  101. /**
  102. * Return a string representing the source.
  103. *
  104. * @return string
  105. */
  106. public function __toString() {
  107. return (string) $this->listClass;
  108. }
  109. /**
  110. * Returns a list of fields available to be mapped from the source query.
  111. * Since we can't reliably figure out what "fields" are in the source,
  112. * it's up to the implementing Migration constructor to fill them in.
  113. *
  114. * @return array
  115. * Keys: machine names of the fields (to be passed to addFieldMapping)
  116. * Values: Human-friendly descriptions of the fields.
  117. */
  118. public function fields() {
  119. return $this->fields;
  120. }
  121. /**
  122. * It's the list class that knows how many records are available, so ask it.
  123. *
  124. * @return int
  125. */
  126. public function computeCount() {
  127. // @API: Support old count method for now.
  128. if (method_exists($this->listClass, 'computeCount')) {
  129. return $this->listClass->computeCount();
  130. }
  131. else {
  132. return $this->listClass->count();
  133. }
  134. }
  135. /**
  136. * Implementation of MigrateSource::performRewind().
  137. *
  138. * @return void
  139. */
  140. public function performRewind() {
  141. // If there isn't a specific ID list passed in, get it from the list class.
  142. if ($this->idList) {
  143. $this->idsToProcess = $this->idList;
  144. }
  145. else {
  146. $this->idsToProcess = $this->listClass->getIdList();
  147. }
  148. $this->idIterator = ($this->idsToProcess instanceof Iterator) ?
  149. $this->idsToProcess : new ArrayIterator($this->idsToProcess);
  150. $this->idIterator->rewind();
  151. }
  152. /**
  153. * Implementation of MigrateSource::getNextRow().
  154. *
  155. * @return null|stdClass
  156. */
  157. public function getNextRow() {
  158. $row = NULL;
  159. while ($this->idIterator->valid()) {
  160. $ids = $this->idIterator->current();
  161. $this->idIterator->next();
  162. // Skip empty IDs
  163. if (empty($ids)) {
  164. continue;
  165. }
  166. // Got a good ID, get the data and get out.
  167. $row = $this->itemClass->getItem($ids);
  168. if ($row) {
  169. // No matter what $ids is, be it a string, integer, object, or array, we
  170. // cast it to an array so that it can be properly mapped to the source
  171. // keys as specified by the map. This is done after getItem is called so
  172. // that the ItemClass doesn't have to care about this requirement.
  173. $ids = (array) $ids;
  174. foreach (array_keys($this->activeMap->getSourceKey()) as $key_name) {
  175. // Grab the first id and advance the array cursor. Then save the ID
  176. // using the map source key - it will be used for mapping.
  177. list(, $id) = each($ids);
  178. $row->$key_name = $id;
  179. }
  180. break;
  181. }
  182. }
  183. return $row;
  184. }
  185. /**
  186. * Overrides MigrateSource::hash().
  187. */
  188. protected function hash($row) {
  189. // Let the item class override the default hash function.
  190. if (method_exists($this->itemClass, 'hash')) {
  191. $hash = $this->itemClass->hash($row);
  192. }
  193. else {
  194. $hash = parent::hash($row);
  195. }
  196. return $hash;
  197. }
  198. }