public function MigrateJSONReader::next in Migrate 7.2
Implementation of Iterator::next().
Populates currentElement (the object being retrieved) and currentId (that object's unique identifier) from the specified JSON file. Sets both to NULL at end-of-file. Handles properly-formed JSON, as well as some improper coding (specifically that generated in Ning exports).
Return value
void
1 call to MigrateJSONReader::next()
- MigrateJSONReader::rewind in plugins/
sources/ json.inc - Implementation of Iterator::rewind().
File
- plugins/
sources/ json.inc, line 265 - Support for migration from JSON sources.
Class
- MigrateJSONReader
- An iterator over a JSON file. As is, this assumes that the file is structured as an array of objects,…
Code
public function next() {
migrate_instrument_start('MigrateJSONReader::next');
$this->currentElement = $this->currentId = NULL;
// Open the file and position it if necessary
if (!$this->fileHandle) {
$this->fileHandle = fopen($this->url, 'r');
if (!$this->fileHandle) {
Migration::displayMessage(t('Could not open JSON file !url', array(
'!url' => $this->url,
)));
return;
}
// We're expecting an array of characters, so the first character should be [.
$char = $this
->getNonBlank();
// Ning exports are wrapped in bogus (), so skip a leading (
if ($char == '(') {
$char = $this
->getNonBlank();
}
if ($char != '[') {
Migration::displayMessage(t('!url is not a JSON file containing an array of objects', array(
'!url' => $this->url,
)));
return;
}
}
// We expect to be positioned either at an object (beginning with {) or
// the end of the file (we should see a ] indicating this). Or, an
// object-separating comma, to be skipped. Note that this treats
// commas as optional between objects, which helps with processing
// malformed JSON with missing commas (as in Ning exports).
$c = $this
->getNonBlank();
if ($c == ',') {
$c = $this
->getNonBlank();
}
elseif ($c == ']') {
$c = $this
->getNonBlank();
if ($c != '{') {
$c = NULL;
}
}
// We expect to be at the first character of an object now.
if ($c == '{') {
// Start building a JSON string for this object.
$json = $c;
// Look for the closing }, ignoring brackets in strings, tracking nested
// brackets. Watch out for escaped quotes, but also note that \\" is not
// an escaped quote.
$depth = 1;
$in_string = FALSE;
$in_escape = FALSE;
while (($c = fgetc($this->fileHandle)) !== FALSE) {
$json .= $c;
if ($in_string) {
// Quietly accept an escaped character
if ($in_escape) {
$in_escape = FALSE;
}
else {
switch ($c) {
// Unescaped " means end of string
case '"':
$in_string = FALSE;
break;
// Unescaped \\ means start of escape
case '\\':
$in_escape = TRUE;
break;
}
}
}
else {
// Outside of strings, recognize {} as depth changes, " as start of
// string.
switch ($c) {
case '{':
$depth++;
break;
case '}':
$depth--;
break;
case '"':
$in_string = TRUE;
break;
}
// We've found our match, exit the loop.
if ($depth < 1) {
break;
}
}
}
// Turn the JSON string into an object.
$this->currentElement = json_decode($json);
$this->currentId = $this->currentElement->{$this->idField};
}
else {
$this->currentElement = NULL;
$this->currentId = NULL;
}
migrate_instrument_stop('MigrateJSONReader::next');
}