/** * @param Node $key * Array element's key. * @param Node $value * Array element's value. * * @return ArrayPairNode */ public static function create($key, $value) { $node = new ArrayPairNode(); $node->addChild($key, 'key'); $node->addChild(Token::space()); $node->addChild(Token::doubleArrow()); $node->addChild(Token::space()); $node->addChild($value, 'value'); return $node; }
private function updateArray(ArrayNode $node, $data) { $i = 0; foreach ($node->getElements() as $el) { if ($el instanceof ArrayPairNode) { $k = (string) $el->getKey(); $k = trim($k, '"\''); $v = $el->getValue(); if (!isset($data[$k])) { $this->cleanAround($el); } else { if ($v instanceof ArrayNode && is_array($data[$k])) { $v = $this->updateArray($v, $data[$k]); unset($data[$k]); } else { $v->replaceWith(Parser::parseExpression($data[$k])); unset($data[$k]); } } } elseif ($el instanceof ArrayNode && (!isset($data[$i]) || is_array($data[$i]))) { if (!isset($data[$i])) { $this->cleanAround($el); } else { $this->updateArray($el, $data[$i]); unset($data[$i]); $i++; } } else { if (!isset($data[$i])) { $this->cleanAround($el); } else { $el->replaceWith(Parser::parseExpression($data[$i])); unset($data[$i]); $i++; } } } foreach ($data as $key => $val) { $v = Parser::parseExpression(self::var_codify($val)); if (!is_integer($key)) { $v = ArrayPairNode::create(Node::fromValue($key), $v); } $comma = false; $list = $node->getElementList(); $children = []; foreach ($list->children() as $child) { $children[] = $child; } $prev = end($children); if ($prev) { do { if ((string) $prev === ',') { $comma = true; break; } } while (is_object($prev) && ($prev = $prev->previous()) instanceof WhitespaceNode); } else { $comma = true; } $indent = 0; $prev = end($children); while ($prev && strpos($prev, "\n") === false) { $prev = $prev->previous(); } $indent = ''; if ($prev) { $prev = explode("\n", (string) $prev); $prev = array_pop($prev); for ($i = 0; $i < strlen($prev); $i++) { if (in_array($prev[$i], ["\t", ' '])) { $indent .= $prev[$i]; } else { break; } } } if (!$comma) { $list->append(Token::comma()); } $list->append(Token::newline()); if ($indent) { $list->append(WhitespaceNode::create($indent)); } $list->append($v); } }
/** * Parse an array pair. * @return Node */ private function arrayPair() { if ($this->currentType === '&') { return $this->writeVariable(); } $node = $this->expr(); if ($this->currentType === T_DOUBLE_ARROW) { $expr = $node; $node = new ArrayPairNode(); $node->addChild($expr, 'key'); $this->mustMatch(T_DOUBLE_ARROW, $node); if ($this->currentType === '&') { $node->addChild($this->writeVariable(), 'value'); } else { $node->addChild($this->expr(), 'value'); } } return $node; }
/** * Creates a Node from a php value. * * @param string|integer|float|boolean|array|null $value * The value to create a node for. * * @return FloatNode|IntegerNode|StringNode|BooleanNode|NullNode|ArrayNode * * @throws \InvalidArgumentException if $value is not a scalar. */ public static function fromValue($value) { if (is_array($value)) { $elements = []; foreach ($value as $k => $v) { $elements[] = ArrayPairNode::create(static::fromValue($k), static::fromValue($v)); } return ArrayNode::create($elements); } elseif (is_string($value)) { return StringNode::create(var_export($value, TRUE)); } elseif (is_integer($value)) { return new IntegerNode(T_LNUMBER, $value); } elseif (is_float($value)) { return new FloatNode(T_DNUMBER, $value); } elseif (is_bool($value)) { return BooleanNode::create($value); } elseif (is_null($value)) { return NullNode::create('NULL'); } else { throw new \InvalidArgumentException(); } }