Browse Source

Add detection for toArray() method in Xml

If values or parameters have `toArray()` use that method to convert the
value into an array. This lets ORM\ResultSet and ORM\Query objects to
interoperate with Xml. It also defines a simple duck type that userland
code can use.
mark_story 11 years ago
parent
commit
699ce324cc
2 changed files with 33 additions and 9 deletions
  1. 11 7
      src/Utility/Xml.php
  2. 22 2
      tests/TestCase/Utility/XmlTest.php

+ 11 - 7
src/Utility/Xml.php

@@ -1,9 +1,5 @@
 <?php
 /**
- * XML handling for Cake.
- *
- * The methods in these classes enable the datasources that use XML to work.
- *
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  *
@@ -18,6 +14,7 @@
  */
 namespace Cake\Utility;
 
+use Cake\Collection\Collection;
 use Cake\Core\Configure;
 use Cake\Network\Error\SocketException;
 use Cake\Network\Http\Client;
@@ -94,7 +91,7 @@ class Xml {
 		$options += $defaults;
 
 		if (is_array($input) || is_object($input)) {
-			return static::fromArray((array)$input, $options);
+			return static::fromArray($input, $options);
 		} elseif (strpos($input, '<') !== false) {
 			return static::_loadXml($input, $options);
 		} elseif (file_exists($input)) {
@@ -183,12 +180,15 @@ class Xml {
  *
  * `<root><tag id="1" value="defect">description</tag></root>`
  *
- * @param array $input Array with data
+ * @param array|\Cake\Collection\Collection $input Array with data or a collection instance.
  * @param string|array $options The options to use
  * @return \SimpleXMLElement|\DOMDocument SimpleXMLElement or DOMDocument
  * @throws \Cake\Utility\Error\XmlException
  */
-	public static function fromArray(array $input, $options = array()) {
+	public static function fromArray($input, $options = array()) {
+		if (method_exists($input, 'toArray')) {
+			$input = $input->toArray();
+		}
 		if (!is_array($input) || count($input) !== 1) {
 			throw new Error\XmlException('Invalid input.');
 		}
@@ -238,6 +238,10 @@ class Xml {
 		}
 		foreach ($data as $key => $value) {
 			if (is_string($key)) {
+				if (method_exists($value, 'toArray')) {
+					$value = $value->toArray();
+				}
+
 				if (!is_array($value)) {
 					if (is_bool($value)) {
 						$value = (int)$value;

+ 22 - 2
tests/TestCase/Utility/XmlTest.php

@@ -1,7 +1,5 @@
 <?php
 /**
- * XmlTest file
- *
  * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  *
@@ -16,6 +14,7 @@
  */
 namespace Cake\Test\TestCase\Utility;
 
+use Cake\Collection\Collection;
 use Cake\Core\Configure;
 use Cake\TestSuite\TestCase;
 use Cake\Utility\Error\XmlException;
@@ -112,6 +111,27 @@ class XmlTest extends TestCase {
 	}
 
 /**
+ * Test build() with a Collection instance.
+ *
+ * @return void
+ */
+	public function testBuildCollection() {
+		$xml = new Collection(['tag' => 'value']);
+		$obj = Xml::build($xml);
+
+		$this->assertEquals('tag', $obj->getName());
+		$this->assertEquals('value', (string)$obj);
+
+		$xml = new Collection([
+			'response' => [
+				'users' => new Collection(['leonardo', 'raphael'])
+			]
+		]);
+		$obj = Xml::build($xml);
+		$this->assertContains('<users>leonardo</users>', $obj->saveXML());
+	}
+
+/**
  * data provider function for testBuildInvalidData
  *
  * @return array