From b2035a5c9668c86b25a88f2733b7e8bab119d03b Mon Sep 17 00:00:00 2001 From: Juan Basso Date: Sun, 17 Oct 2010 18:40:33 -0200 Subject: [PATCH 1/7] Fixing tests that failing in Set because merge of Xml class. --- cake/tests/cases/libs/set.test.php | 42 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/cake/tests/cases/libs/set.test.php b/cake/tests/cases/libs/set.test.php index 29f250ca2..91e6c6122 100644 --- a/cake/tests/cases/libs/set.test.php +++ b/cake/tests/cases/libs/set.test.php @@ -2731,7 +2731,7 @@ class SetTest extends CakeTestCase { $xml = Xml::build($string); $result = Set::reverse($xml); $expected = array('rss' => array( - 'version' => '2.0', + '@version' => '2.0', 'channel' => array( 'title' => 'Cake PHP Google Group', 'link' => 'http://groups.google.com/group/cake-php', @@ -2742,7 +2742,7 @@ class SetTest extends CakeTestCase { 'title' => 'constructng result array when using findall', 'link' => 'http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f', 'description' => "i'm using cakephp to construct a logical data model array that will be
passed to a flex app. I have the following model association:
ServiceDay->(hasMany)ServiceTi me->(hasMany)ServiceTimePrice. So what
the current output from my findall is something like this example:

Array(
[0] => Array(", - 'guid' => array('isPermaLink' => 'true', 'value' => 'http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f'), + 'guid' => array('@isPermaLink' => 'true', '@' => 'http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f'), 'author' => 'bmil...@gmail.com(bpscrugs)', 'pubDate' => 'Fri, 28 Dec 2007 00:44:14 UT', ), @@ -2750,7 +2750,7 @@ class SetTest extends CakeTestCase { 'title' => 'Re: share views between actions?', 'link' => 'http://groups.google.com/group/cake-php/msg/8b350d898707dad8', 'description' => 'Then perhaps you might do us all a favour and refrain from replying to
things you do not understand. That goes especially for asinine comments.
Indeed.
To sum up:
No comment.
In my day, a simple "RTFM" would suffice. I\'ll keep in mind to ignore any
further responses from you.
You (and I) were referring to the *online documentation*, not other', - 'guid' => array('isPermaLink' => 'true', 'value' => 'http://groups.google.com/group/cake-php/msg/8b350d898707dad8'), + 'guid' => array('@isPermaLink' => 'true', '@' => 'http://groups.google.com/group/cake-php/msg/8b350d898707dad8'), 'author' => 'subtropolis.z...@gmail.com(subtropolis zijn)', 'pubDate' => 'Fri, 28 Dec 2007 00:45:01 UT' ) @@ -2762,7 +2762,7 @@ class SetTest extends CakeTestCase { $xml = Xml::build($string); $result = Set::reverse($xml); - $expected = array('data' => array('post' => array('title' => 'Title of this post', 'description' => 'cool'))); + $expected = array('data' => array('post' => array('@title' => 'Title of this post', '@description' => 'cool'))); $this->assertEqual($result, $expected); $xml = Xml::build('An example of a correctly reversed SimpleXMLElement'); @@ -2782,7 +2782,7 @@ class SetTest extends CakeTestCase { $expected = array('example' => array( 'item' => array( - 'attr' => '123', + '@attr' => '123', 'titles' => array( 'title' => array('title1', 'title2') ) @@ -2795,11 +2795,11 @@ class SetTest extends CakeTestCase { $result = Set::reverse($xml); $expected = array('example' => array( - 'attr' => 'ex_attr', + '@attr' => 'ex_attr', 'item' => array( - 'attr' => '123', + '@attr' => '123', 'titles' => 'list', - 'value' => 'textforitems' + '@' => 'textforitems' ) ) ); @@ -2841,7 +2841,7 @@ class SetTest extends CakeTestCase { $result = Set::reverse($xml); $expected = array('rss' => array( - 'version' => '2.0', + '@version' => '2.0', 'channel' => array( 'title' => 'Cake PHP Google Group', 'link' => 'http://groups.google.com/group/cake-php', @@ -2852,9 +2852,9 @@ class SetTest extends CakeTestCase { 'title' => 'constructng result array when using findall', 'link' => 'http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f', 'description' => "i'm using cakephp to construct a logical data model array that will be
passed to a flex app. I have the following model association:
ServiceDay->(hasMany)ServiceTi me->(hasMany)ServiceTimePrice. So what
the current output from my findall is something like this example:

Array(
[0] => Array(", - 'creator' => 'cakephp', + 'dc:creator' => 'cakephp', 'category' => array('cakephp', 'model'), - 'guid' => array('isPermaLink' => 'true', 'value' => 'http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f'), + 'guid' => array('@isPermaLink' => 'true', '@' => 'http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f'), 'author' => 'bmil...@gmail.com(bpscrugs)', 'pubDate' => 'Fri, 28 Dec 2007 00:44:14 UT', ), @@ -2862,9 +2862,9 @@ class SetTest extends CakeTestCase { 'title' => 'Re: share views between actions?', 'link' => 'http://groups.google.com/group/cake-php/msg/8b350d898707dad8', 'description' => 'Then perhaps you might do us all a favour and refrain from replying to
things you do not understand. That goes especially for asinine comments.
Indeed.
To sum up:
No comment.
In my day, a simple "RTFM" would suffice. I\'ll keep in mind to ignore any
further responses from you.
You (and I) were referring to the *online documentation*, not other', - 'creator' => 'cakephp', + 'dc:creator' => 'cakephp', 'category' => array('cakephp', 'model'), - 'guid' => array('isPermaLink' => 'true', 'value' => 'http://groups.google.com/group/cake-php/msg/8b350d898707dad8'), + 'guid' => array('@isPermaLink' => 'true', '@' => 'http://groups.google.com/group/cake-php/msg/8b350d898707dad8'), 'author' => 'subtropolis.z...@gmail.com(subtropolis zijn)', 'pubDate' => 'Fri, 28 Dec 2007 00:45:01 UT' ) @@ -2901,8 +2901,8 @@ class SetTest extends CakeTestCase { $expected = array('XRDS' => array( 'XRD' => array( array( - 'id' => 'oauth', - 'version' => '2.0', + '@xml:id' => 'oauth', + '@version' => '2.0', 'Type' => 'xri://$xrds*simple', 'Expires' => '2008-04-13T07:34:58Z', 'Service' => array( @@ -2913,21 +2913,21 @@ class SetTest extends CakeTestCase { ), 'URI' => array( array( - 'value' => 'https://ma.gnolia.com/oauth/authorize', - 'priority' => '10', + '@' => 'https://ma.gnolia.com/oauth/authorize', + '@priority' => '10', ), array( - 'value' => 'http://ma.gnolia.com/oauth/authorize', - 'priority' => '20' + '@' => 'http://ma.gnolia.com/oauth/authorize', + '@priority' => '20' ) ) ) ), array( - 'version' => '2.0', + '@version' => '2.0', 'Type' => 'xri://$xrds*simple', 'Service' => array( - 'priority' => '10', + '@priority' => '10', 'Type' => 'http://oauth.net/discovery/1.0', 'URI' => '#oauth' ) From d77123910457118df5104c2e15533b92d87bedd3 Mon Sep 17 00:00:00 2001 From: Juan Basso Date: Sun, 17 Oct 2010 22:47:43 -0200 Subject: [PATCH 2/7] Fixed support to save XML data in Models. --- cake/libs/model/model.php | 27 ++++++++++++++++++- .../cases/libs/model/model_write.test.php | 14 +++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index 823f8d2d6..c4b693a0c 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -831,7 +831,12 @@ class Model extends Object { return; } if (is_object($one)) { - $one = Set::reverse($one); + if ($one instanceof SimpleXMLElement || $one instanceof DOMNode) { + App::import('Core', 'Xml'); + $one = $this->_normalizeXmlData(Xml::toArray($one)); + } else { + $one = Set::reverse($one); + } } if (is_array($one)) { @@ -868,6 +873,26 @@ class Model extends Object { return $data; } +/** + * Normalize Xml::toArray() to use in Model::save() + * + * @param array $xml XML as array + * @return array + */ + protected function _normalizeXmlData(array $xml) { + $return = array(); + foreach ($xml as $key => $value) { + if (is_array($value)) { + $return[Inflector::camelize($key)] = $this->_normalizeXmlData($value); + } elseif ($key[0] === '@') { + $return[substr($key, 1)] = $value; + } else { + $return[$key] = $value; + } + } + return $return; + } + /** * Deconstructs a complex data type (array or object) into a single field value. * diff --git a/cake/tests/cases/libs/model/model_write.test.php b/cake/tests/cases/libs/model/model_write.test.php index fcf7c8e8f..4693bf30a 100644 --- a/cake/tests/cases/libs/model/model_write.test.php +++ b/cake/tests/cases/libs/model/model_write.test.php @@ -1019,12 +1019,20 @@ class ModelWriteTest extends BaseModelTest { App::import('Core', 'Xml'); $Article = new Article(); - $Article->save(new Xml('

')); - $result = $Article->save(new Xml('
')); + $result = $Article->save(Xml::build('
')); $this->assertFalse(empty($result)); - $results = $Article->find(array('Article.title' => 'test xml')); $this->assertFalse(empty($results)); + + $result = $Article->save(Xml::build('
testing6
')); + $this->assertFalse(empty($result)); + $results = $Article->find(array('Article.title' => 'testing')); + $this->assertFalse(empty($results)); + + $result = $Article->save(Xml::build('
testing with DOMDocument7
', array('return' => 'domdocument'))); + $this->assertFalse(empty($result)); + $results = $Article->find(array('Article.title' => 'testing with DOMDocument')); + $this->assertFalse(empty($results)); } /** From 7aaf7e6b68ee198e259b2186ffd174fc629fc2fc Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 23 Oct 2010 11:01:13 -0400 Subject: [PATCH 3/7] Fixing issue where Xml would not read CDATA blocks. --- cake/libs/xml.php | 4 ++-- cake/tests/cases/libs/xml.test.php | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/cake/libs/xml.php b/cake/libs/xml.php index 9b1905b82..42097597a 100644 --- a/cake/libs/xml.php +++ b/cake/libs/xml.php @@ -88,14 +88,14 @@ class Xml { return self::fromArray((array)$input, $options); } elseif (strpos($input, '<') !== false) { if ($options['return'] === 'simplexml' || $options['return'] === 'simplexmlelement') { - return new SimpleXMLElement($input); + return new SimpleXMLElement($input, LIBXML_NOCDATA); } $dom = new DOMDocument(); $dom->loadXML($input); return $dom; } elseif (file_exists($input) || strpos($input, 'http://') === 0 || strpos($input, 'https://') === 0) { if ($options['return'] === 'simplexml' || $options['return'] === 'simplexmlelement') { - return new SimpleXMLElement($input, null, true); + return new SimpleXMLElement($input, LIBXML_NOCDATA, true); } $dom = new DOMDocument(); $dom->load($input); diff --git a/cake/tests/cases/libs/xml.test.php b/cake/tests/cases/libs/xml.test.php index 0392a449a..666a4f45d 100644 --- a/cake/tests/cases/libs/xml.test.php +++ b/cake/tests/cases/libs/xml.test.php @@ -797,6 +797,19 @@ class XmlTest extends CakeTestCase { $this->assertEqual(str_replace(array("\r", "\n"), '', $xmlResponse->asXML()), $expected); } +/** + * test that CDATA blocks don't get screwed up by SimpleXml + * + * @return void + */ + function testCdata() { + $xml = '<' . '?xml version="1.0" encoding="UTF-8"?>' . + ''; + + $result = Xml::build($xml); + $this->assertEquals(' Mark ', (string)$result->name); + } + /** * data provider for toArray() failures * From 3e2d09a802dd259c8f63bfb0cd375d1182b7f084 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 23 Oct 2010 12:18:39 -0400 Subject: [PATCH 4/7] Making h() preserve keys when escaping an array. --- cake/basics.php | 4 ++-- cake/tests/cases/basics.test.php | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/cake/basics.php b/cake/basics.php index ca262cb0a..88ea14bdb 100644 --- a/cake/basics.php +++ b/cake/basics.php @@ -151,8 +151,8 @@ if (!function_exists('sortByKey')) { function h($text, $double = true, $charset = null) { if (is_array($text)) { $texts = array(); - foreach ($text as $t) { - $texts[] = h($t, $double, $charset); + foreach ($text as $k => $t) { + $texts[$k] = h($t, $double, $charset); } return $texts; } diff --git a/cake/tests/cases/basics.test.php b/cake/tests/cases/basics.test.php index 8df308ba9..723254a20 100644 --- a/cake/tests/cases/basics.test.php +++ b/cake/tests/cases/basics.test.php @@ -228,6 +228,14 @@ class BasicsTest extends CakeTestCase { ' ' ); $this->assertEqual($expected, $result); + + $arr = array('f' => '', 'n' => ' '); + $result = h($arr, false); + $expected = array( + 'f' => '<foo>', + 'n' => ' ' + ); + $this->assertEqual($expected, $result); } /** From bf7b8b0e932014b75f883cf3467e2f3f9d7d91c8 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 23 Oct 2010 13:11:50 -0400 Subject: [PATCH 5/7] Fixing issues with RssHelper and updating tests to reflect changes in how Xml::build() differs from previous versions' Xml. --- cake/libs/view/helpers/rss.php | 15 ++- .../cases/libs/view/helpers/rss.test.php | 109 ++++++++---------- 2 files changed, 58 insertions(+), 66 deletions(-) diff --git a/cake/libs/view/helpers/rss.php b/cake/libs/view/helpers/rss.php index b6c773d0f..ae1ab6239 100644 --- a/cake/libs/view/helpers/rss.php +++ b/cake/libs/view/helpers/rss.php @@ -315,8 +315,9 @@ class RssHelper extends AppHelper { if (!empty($namespace)) { $xml .= ' xmlns:"' . $namespace . '"'; } + $bareName = $name; if (strpos($name, ':') !== false) { - list($prefix, ) = explode(':', $name, 2); + list($prefix, $bareName) = explode(':', $name, 2); switch ($prefix) { case 'atom': $xml .= ' xmlns:atom="http://www.w3.org/2005/Atom"'; @@ -327,15 +328,17 @@ class RssHelper extends AppHelper { $content = ''; } $xml .= '>' . $content . ''; - $elem = Xml::build($xml); + $elem = Xml::build($xml, array('return' => 'domdocument')); + $nodes = $elem->getElementsByTagName($bareName); foreach ($attrib as $key => $value) { - $elem->addAttribute($key, $value); + $nodes->item(0)->setAttribute($key, $value); } - foreach ($children as $child) { - $elem->addChild($child); + foreach ($children as $k => $child) { + $child = $elem->createElement($name, $child); + $nodes->item(0)->appendChild($child); } - $xml = $elem->asXML(); + $xml = $elem->saveXml(); $xml = trim(substr($xml, strpos($xml, '?>') + 2)); return $xml; } diff --git a/cake/tests/cases/libs/view/helpers/rss.test.php b/cake/tests/cases/libs/view/helpers/rss.test.php index b61d6dd32..6b8b36887 100644 --- a/cake/tests/cases/libs/view/helpers/rss.test.php +++ b/cake/tests/cases/libs/view/helpers/rss.test.php @@ -35,7 +35,7 @@ class RssHelperTest extends CakeTestCase { * @return void */ function setUp() { - $controller = null; + parent::setUp(); $this->View = new View($controller); $this->Rss = new RssHelper($this->View); } @@ -47,6 +47,7 @@ class RssHelperTest extends CakeTestCase { * @return void */ function tearDown() { + parent::tearDown(); unset($this->Rss); } @@ -65,15 +66,6 @@ class RssHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); - $result = $this->Rss->document(array('contrived' => 'parameter')); - $expected = array( - 'rss' => array( - 'version' => '2.0' - ), - 'assertTags($result, $expected); - $result = $this->Rss->document(null, 'content'); $expected = array( 'rss' => array( @@ -173,6 +165,7 @@ class RssHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); } + function testChannelElementAttributes() { $attrib = array(); $elements = array( @@ -288,15 +281,9 @@ class RssHelperTest extends CakeTestCase { $this->assertTags($result, $expected); $item = array( - 'title' => array( - 'value' => 'My Title', - 'cdata' => true, - ), + 'title' => 'My Title', 'link' => 'http://www.example.com/1', - 'description' => array( - 'value' => 'descriptive words', - 'cdata' => true, - ), + 'description' => 'descriptive words', 'pubDate' => '2008-05-31 12:00:00', 'guid' => 'http://www.example.com/1' ); @@ -305,13 +292,13 @@ class RssHelperTest extends CakeTestCase { $expected = array( 'assertTags($result, $expected); $item = array( - 'title' => array( - 'value' => 'My Title & more', - 'cdata' => true - ) + 'title' => 'My Title & more' + ); + $result = $this->Rss->item(null, $item); + $expected = array( + 'assertTags($result, $expected); + + $item = array( + 'title' => 'Foo bar', + 'link' => array( + 'url' => 'http://example.com/foo?a=1&b=2', + 'convertEntities' => false + ), + 'description' => array( + 'value' => 'descriptive words', + 'cdata' => true, + ), + 'pubDate' => '2008-05-31 12:00:00' ); $result = $this->Rss->item(null, $item); $expected = array( 'assertTags($result, $expected); + } +/** + * test item() with cdata blocks. + * + * @return void + */ + function testItemCdata() { $item = array( 'title' => array( 'value' => 'My Title & more', @@ -360,7 +383,7 @@ class RssHelperTest extends CakeTestCase { 'category' => array( 'value' => 'CakePHP', 'cdata' => true, - 'domain' => 'http://www.cakephp.org' + 'domain' => 'http://www.cakephp.org', ) ); $result = $this->Rss->item(null, $item); @@ -454,40 +477,6 @@ class RssHelperTest extends CakeTestCase { '/item' ); $this->assertTags($result, $expected); - - $item = array( - 'title' => 'Foo bar', - 'link' => array( - 'url' => 'http://example.com/foo?a=1&b=2', - 'convertEntities' => false - ), - 'description' => array( - 'value' => 'descriptive words', - 'cdata' => true, - ), - 'pubDate' => '2008-05-31 12:00:00' - ); - $result = $this->Rss->item(null, $item); - $expected = array( - 'assertTags($result, $expected); } /** From eb3cc3db3ab84941b0e4800eb16e456dbd492ed7 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 24 Oct 2010 19:30:22 -0400 Subject: [PATCH 6/7] Making default scaffold views html escape contents. Refs #1186 --- cake/libs/view/scaffolds/index.ctp | 2 +- cake/libs/view/scaffolds/view.ctp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cake/libs/view/scaffolds/index.ctp b/cake/libs/view/scaffolds/index.ctp index bbd999e9d..094a32e09 100644 --- a/cake/libs/view/scaffolds/index.ctp +++ b/cake/libs/view/scaffolds/index.ctp @@ -47,7 +47,7 @@ echo "\n"; } } if ($isKey !== true) { - echo "\t\t\n\t\t\t" . ${$singularVar}[$modelClass][$_field] . " \n\t\t\n"; + echo "\t\t" . h(${$singularVar}[$modelClass][$_field]) . "\n"; } } diff --git a/cake/libs/view/scaffolds/view.ctp b/cake/libs/view/scaffolds/view.ctp index 9a1b944ee..d1f9963dc 100644 --- a/cake/libs/view/scaffolds/view.ctp +++ b/cake/libs/view/scaffolds/view.ctp @@ -40,7 +40,7 @@ foreach ($scaffoldFields as $_field) { } if ($isKey !== true) { echo "\t\t" . Inflector::humanize($_field) . "\n"; - echo "\t\t\n\t\t\t{${$singularVar}[$modelClass][$_field]}\n \t\t\n"; + echo "\t\t" . h(${$singularVar}[$modelClass][$_field]) . " \n"; } } ?> From c6c3295c5cdb58043136fb16e8fb8a75208a14b5 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 24 Oct 2010 19:34:37 -0400 Subject: [PATCH 7/7] Making default bake templates escape HTML. Fixes #1186 --- cake/console/templates/default/views/index.ctp | 2 +- cake/console/templates/default/views/view.ctp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cake/console/templates/default/views/index.ctp b/cake/console/templates/default/views/index.ctp index fa2f1f754..4d4c8cde2 100644 --- a/cake/console/templates/default/views/index.ctp +++ b/cake/console/templates/default/views/index.ctp @@ -48,7 +48,7 @@ } } if ($isKey !== true) { - echo "\t\t \n"; + echo "\t\t \n"; } } diff --git a/cake/console/templates/default/views/view.ctp b/cake/console/templates/default/views/view.ctp index 1af692b27..1f6dbd72f 100644 --- a/cake/console/templates/default/views/view.ctp +++ b/cake/console/templates/default/views/view.ctp @@ -35,7 +35,7 @@ foreach ($fields as $field) { } if ($isKey !== true) { echo "\t\t>\n"; - echo "\t\t>\n\t\t\t\n\t\t\t \n\t\t\n"; + echo "\t\t>\n\t\t\t\n\t\t\t \n\t\t\n"; } } ?>