Merge branch '3.1' into 3.2

This commit is contained in:
Daniel Hensby 2016-06-29 11:40:27 +01:00
commit 3fe8d30c2c
No known key found for this signature in database
GPG Key ID: B00D1E9767F0B06E
2 changed files with 90 additions and 31 deletions

View File

@ -220,19 +220,23 @@ abstract class Object {
// Keep track of the current bucket that we're putting data into // Keep track of the current bucket that we're putting data into
$bucket = &$args; $bucket = &$args;
$bucketStack = array(); $bucketStack = array();
$had_ns = false; $hadNamespace = false;
$currentKey = null;
foreach($tokens as $token) { foreach($tokens as $token) {
$tName = is_array($token) ? $token[0] : $token; // $forceResult used to allow null result to be detected
// Get the class naem $result = $forceResult = null;
if($class == null && is_array($token) && $token[0] == T_STRING) { $tokenName = is_array($token) ? $token[0] : $token;
// Get the class name
if($class === null && is_array($token) && $token[0] === T_STRING) {
$class = $token[1]; $class = $token[1];
} elseif(is_array($token) && $token[0] == T_NS_SEPARATOR) { } elseif(is_array($token) && $token[0] === T_NS_SEPARATOR) {
$class .= $token[1]; $class .= $token[1];
$had_ns = true; $hadNamespace = true;
} elseif ($had_ns && is_array($token) && $token[0] == T_STRING) { } elseif($hadNamespace && is_array($token) && $token[0] === T_STRING) {
$class .= $token[1]; $class .= $token[1];
$had_ns = false; $hadNamespace = false;
// Get arguments // Get arguments
} else if(is_array($token)) { } else if(is_array($token)) {
switch($token[0]) { switch($token[0]) {
@ -240,52 +244,85 @@ abstract class Object {
$argString = $token[1]; $argString = $token[1];
switch($argString[0]) { switch($argString[0]) {
case '"': case '"':
$argString = stripcslashes(substr($argString,1,-1)); $result = stripcslashes(substr($argString,1,-1));
break; break;
case "'": case "'":
$argString = str_replace(array("\\\\", "\\'"),array("\\", "'"), substr($argString,1,-1)); $result = str_replace(array("\\\\", "\\'"),array("\\", "'"), substr($argString,1,-1));
break; break;
default: default:
throw new Exception("Bad T_CONSTANT_ENCAPSED_STRING arg $argString"); throw new Exception("Bad T_CONSTANT_ENCAPSED_STRING arg $argString");
} }
$bucket[] = $argString;
break; break;
case T_DNUMBER: case T_DNUMBER:
$bucket[] = (double)$token[1]; $result = (double)$token[1];
break; break;
case T_LNUMBER: case T_LNUMBER:
$bucket[] = (int)$token[1]; $result = (int)$token[1];
break;
case T_DOUBLE_ARROW:
// We've encountered an associative array (the array itself has already been
// added to the bucket), so the previous item added to the bucket is the key
end($bucket);
$currentKey = current($bucket);
array_pop($bucket);
break; break;
case T_STRING: case T_STRING:
switch($token[1]) { switch($token[1]) {
case 'true': $bucket[] = true; break; case 'true': $result = true; break;
case 'false': $bucket[] = false; break; case 'false': $result = false; break;
case 'null': $bucket[] = null; break; case 'null': $result = null; $forceResult = true; break;
default: throw new Exception("Bad T_STRING arg '{$token[1]}'"); default: throw new Exception("Bad T_STRING arg '{$token[1]}'");
} }
break; break;
case T_ARRAY: case T_ARRAY:
// Add an empty array to the bucket $result = array();
$bucket[] = array(); break;
$bucketStack[] = &$bucket; }
$bucket = &$bucket[sizeof($bucket)-1]; } else {
if($tokenName === '[') {
$result = array();
} elseif(($tokenName === ')' || $tokenName === ']') && ! empty($bucketStack)) {
// Store the bucket we're currently working on
$oldBucket = $bucket;
// Fetch the key for the bucket at the top of the stack
end($bucketStack);
$key = key($bucketStack);
reset($bucketStack);
// Re-instate the bucket from the top of the stack
$bucket = &$bucketStack[$key];
// Add our saved, "nested" bucket to the bucket we just popped off the stack
$bucket[$key] = $oldBucket;
// Remove the bucket we just popped off the stack
array_pop($bucketStack);
}
}
// If we've got something to add to the bucket, add it
if($result !== null || $forceResult) {
if($currentKey) {
$bucket[$currentKey] = $result;
$currentKey = null;
} else {
$bucket[] = $result;
} }
} else { // If we've just pushed an array, that becomes our new bucket
if($tName == '[') { if($result === array()) {
// Add an empty array to the bucket // Fetch the key that the array was pushed to
$bucket[] = array(); end($bucket);
$bucketStack[] = &$bucket; $key = key($bucket);
$bucket = &$bucket[sizeof($bucket)-1]; reset($bucket);
} elseif($tName == ')' || $tName == ']') { // Store reference to "old" bucket in the stack
// Pop-by-reference $bucketStack[$key] = &$bucket;
$bucket = &$bucketStack[sizeof($bucketStack)-1]; // Set the active bucket to be our newly-pushed, empty array
array_pop($bucketStack); $bucket = &$bucket[$key];
} }
} }
} }

View File

@ -427,7 +427,7 @@ class ObjectTest extends SapphireTest {
// 5.4 Shorthand Array // 5.4 Shorthand Array
$this->assertEquals( $this->assertEquals(
array('Enum',array(array('Accepted', 'Pending', 'Declined', 'Unsubmitted'), 'Unsubmitted')), array('Enum',array(array('Accepted', 'Pending', 'Declined', 'Unsubmitted'), 'Unsubmitted')),
Object::parse_class_spec("Enum(['Accepted', 'Pending', 'Declined', 'Unsubmitted'), 'Unsubmitted']") Object::parse_class_spec("Enum(['Accepted', 'Pending', 'Declined', 'Unsubmitted'], 'Unsubmitted')")
); );
// 5.4 Nested shorthand array // 5.4 Nested shorthand array
$this->assertEquals( $this->assertEquals(
@ -436,6 +436,28 @@ class ObjectTest extends SapphireTest {
Object::parse_class_spec( Object::parse_class_spec(
"Enum(['Accepted', 'Pending', 'Declined', ['UnsubmittedA','UnsubmittedB']], 'Unsubmitted')") "Enum(['Accepted', 'Pending', 'Declined', ['UnsubmittedA','UnsubmittedB']], 'Unsubmitted')")
); );
// Associative array
$this->assertEquals(
array('Varchar', array(255, array('nullifyEmpty' => false))),
Object::parse_class_spec("Varchar(255, array('nullifyEmpty' => false))")
);
// Nested associative array
$this->assertEquals(
array('Test', array('string', array('nested' => array('foo' => 'bar')))),
Object::parse_class_spec("Test('string', array('nested' => array('foo' => 'bar')))")
);
// 5.4 shorthand associative array
$this->assertEquals(
array('Varchar', array(255, array('nullifyEmpty' => false))),
Object::parse_class_spec("Varchar(255, ['nullifyEmpty' => false])")
);
// 5.4 shorthand nested associative array
$this->assertEquals(
array('Test', array('string', array('nested' => array('foo' => 'bar')))),
Object::parse_class_spec("Test('string', ['nested' => ['foo' => 'bar']])")
);
// Namespaced class // Namespaced class
$this->assertEquals( $this->assertEquals(
array('Test\MyClass', array()), array('Test\MyClass', array()),