0

I have a migration class that creates nodes from tables in an SQL database. A second migration class uses MigrateSourceList with MigrateListXML and MigrateItemXML (grabs IDs from list xml, ID is the name of each item xml, same as wine example with MigrateSourceList). I want the second migration to write to the same nodes from the first migration.

The issue is I am getting a 500 response right after the preImport successfully runs on the second migration.

Here is my migration class:

class ArticlesXML extends XMLMigration {
  public function __construct($arguments) {
    parent::__construct($arguments);

    $this->description = t('Articles: XML Content');

    $dependencies = array(
      'ArticlesStubs'
    );

    $this->dependencies = $dependencies;

    $fields = array(
      'Title' => t('Title'),
      'Intro' => t('Intro'),
      'BodyContent' => t('Body Content'),

    );

    $xml_folder = 'public://Articles/';
    $list_url = $xml_folder . 'Articles.xml';
    $item_url = $xml_folder . ':id.xml';

    $this->source = new MigrateSourceList(new MyListXML($list_url), new MigrateItemXML($item_url), $fields);

    $this->destination = new MigrateDestinationNode('article');

    $source_key = array(
      'ID' => array(
        'type' => 'varchar',
        'length' => 20,
      )
    );

    $this->map = new MigrateSQLMap($this->machineName, $source_key, MigrateDestinationNode::getKeySchema());

    $this->addFieldMapping('nid', 'ID')
         ->sourceMigration('ArticlesStubs');
    $this->addFieldMapping('title', 'Title')
         ->xpath('wcm:element[@name="Title"]');
    $this->addFieldMapping('field_introduction', 'Intro')
         ->xpath('wcm:element[@name="Intro"]');
    $this->addFieldMapping('body', 'BodyContent')
         ->xpath('wcm:element[@name="BodyContent"]');    

  }

  public function preImport() {
    parent::preImport();
    $data = array();
    $query = db_select('migrate_files_info', 'm');
    $query->join('migrate_files_data', 'i', 'm.ID = i.ID');
    $query->isNotNull('m.Description');
    $or = db_or()->condition('m.ArticleType', '1', '=')->condition('m.ArticleType', '2', '=')->condition('m.ArticleType', '4', '=')->condition('m.ArticleType', '5', '=')->condition('m.ArticleType', '6', '=')->condition('m.ArticleType', '8', '=');
    $query->condition($or);
    $query->fields('i', array('URL', 'ID'));
    $query->range(0,20);
    $result = $query->execute();
    while($record = $result->fetchAssoc()) {
      $data[] = $record;
    }
    $xml_data = new SimpleXMLElement("<?xml version=\"1.0\"?><articles></articles>");
    my_module_migrate_array_to_xml($data, $xml_data);
    $xml_data->asXML('public://Articles/Articles.xml');
    $url_prefix = 'http://mysite.com';
    $caught = array();
    foreach($data as $record) {
      foreach($record as $key=>$value) {
        if($key = 'URL') {
          if ($wrapper = file_stream_wrapper_get_instance_by_uri('public://')) {
            $realpath = $wrapper->realpath();
          }
          $xml_file = $url_prefix . $record['URL'];
          $file_headers = @get_headers($xml_file);
          if($file_headers[0] == 'HTTP/1.1 404 Not Found' || $file_headers[0] =='HTTP/1.1 404 Not Found') {
            continue;
          } else if ($file_headers[0] == 'HTTP/1.1 302 Found' && $file_headers[7] == 'HTTP/1.0 404 Not Found') {
              continue;
          } else if(file_exists($realpath . '/Articles/' . $record['ID'] . 'xml')){
              continue;
          } else {
            try {
              file_put_contents('public://Articles/' . $record['ID'] . '.xml', file_get_contents($xml_file));
            } catch (Exception $e) {
              $caught[] = $xml_file;
              echo $e->getMessage;
            }
          }
        }
      }
    }
    foreach($caught as $xml_file) {
      if ($wrapper = file_stream_wrapper_get_instance_by_uri('public://')) {
        $realpath = $wrapper->realpath();
      }
      $file_headers = @get_headers($xml_file);
      if($file_headers[0] == 'HTTP/1.1 404 Not Found' || $file_headers[0] =='HTTP/1.1 404 Not Found') {
        continue;
      } else if ($file_headers[0] == 'HTTP/1.1 302 Found' && $file_headers[7] == 'HTTP/1.0 404 Not Found') {
          continue;
      } else if(file_exists($realpath . '/Articles/' . $record['ID'] . 'xml')){
          continue;
      } else {
        file_put_contents('public://Articles/' . $record['ID'] . '.xml', file_get_contents($xml_file));
      }
    }
  }

  public function postImport() {
    $data = simplexml_load_file('public://Articles/Articles.xml');
    usnet($data->articles);
    file_put_contents('public://Articles/Articles.xml', $data->saveXML());
    $files = glob('public://Articles/*');
    foreach($files as $file) {
      if(is_file($file) && $file != 'Articles.xml') {
        unlink($file);
      }
    }
  }

}

This is another class I created because the default MigrateListXML will not properly parse my ID list XML file (this is the same file as ArticlesXML class):

class MyListXML extends MigrateListXML {

  protected function getIDsFromXML(SimpleXMLElement $xml) {
    $ids = array();
    foreach ($xml as $article) {
      $step = 1;
      foreach($article as $element) {
        if ($step == 0) {
          $ids[] = (string)$element;
        } else {
          $step--;
        }
      }
    }
    return array_unique($ids);
  }

}

This is my XML with the list of IDs:

<?xml version="1.0"?>
<articles><article><URL>/path/to/file.xml</URL><ID>1233</ID></article><article><URL>/path/to/file2.xml</URL><ID>1234</ID></article></articles>

Here is an example of an individual XML file that is supposed to be imported:

<?xml version="1.0" encoding="UTF-8"?>
<wcm:root xmlns:wcm="http://www.stellent.com/wcm-data/ns/8.0.0" version="8.0.0.0">
<wcm:element name="Title">SomeTitle</wcm:element>
  <wcm:element name="Intro">introintrointro</wcm:element>
  <wcm:element name="BodyContent">contentcontentcontent</wcm:element>
<wcm:list name="TestB"/>
</wcm:root>

This is the error I get:

An AJAX HTTP error occurred. HTTP Result Code: 500 Debugging information follows. Path: /batch?id=756&op=do StatusText: Internal Server Error ResponseText:

Unfortunately there are no other clues as to what the issue is.

  • Always when you ask about 500 do your best to provide data from drupal's dblog and server's error.log - without actual error message we cannot know what happened, unless one of us encountered identical situation, and that is not likely. Basically, HTTP 500 means "there is an error, full text in logs" ;) – Mołot Dec 19 '13 at 14:37
  • @Mołot there is no further info from either of those sources unfortunately. Only that it is 500. That's why there is no text after "ResponseText:" in the error provided. – CR47 Dec 19 '13 at 14:50
  • Well, many http servers are configured not to provide full error to user agent, but to log it none the less. Thus, I can't accept empty response text as a thing related to existence (or not) the entry in error.log - errorlevels for both are pretty independent, to make sure mistake in code will not trigger a code giveaway for crackers visiting your site. If there is no message in error.log, please make sure you log errors, preferably all levels (for the time of testing) and try again. – Mołot Dec 19 '13 at 14:57
0

The issue was with the migrate module source file xml.inc. I had previously applied a patch that added the ability to define namespaces on IDs for XML sources, however the patch was incomplete and called a function that was never defined. Removing that call allowed for the migration to run successfully.

  • 1
    I bet if you ran the migration from Drush via the CLI you would have seen PHP: Error, undefined function. It's just the Ajax that makes it hard(er) to debug. – tenken Dec 19 '13 at 15:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.