EscaperTest.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Tests\Components\OutputEscaper;
  11. use Symfony\Components\OutputEscaper\Escaper;
  12. use Symfony\Components\OutputEscaper\SafeDecorator;
  13. use Symfony\Components\OutputEscaper\IteratorDecorator;
  14. use Symfony\Components\OutputEscaper\ArrayDecorator;
  15. use Symfony\Components\OutputEscaper\ObjectDecorator;
  16. class EscaperTest extends \PHPUnit_Framework_TestCase
  17. {
  18. public function testEscapeDoesNotEscapeSpecialValues()
  19. {
  20. $this->assertSame(Escaper::escape('entities', null), null, '::escape() returns null if the value to escape is null');
  21. $this->assertSame(Escaper::escape('entities', false), false, '::escape() returns false if the value to escape is false');
  22. $this->assertSame(Escaper::escape('entities', true), true, '::escape() returns true if the value to escape is true');
  23. }
  24. public function testEscapeDoesNotEscapeAValueWhenEscapingMethodIsRAW()
  25. {
  26. $this->assertEquals('<strong>escaped!</strong>', Escaper::escape('raw', '<strong>escaped!</strong>'), '::escape() takes an escaping strategy function name as its first argument');
  27. }
  28. public function testEscapeEscapesStrings()
  29. {
  30. $this->assertEquals('&lt;strong&gt;escaped!&lt;/strong&gt;', Escaper::escape('entities', '<strong>escaped!</strong>'), '::escape() returns an escaped string if the value to escape is a string');
  31. $this->assertEquals('&lt;strong&gt;&eacute;chapp&eacute;&lt;/strong&gt;', Escaper::escape('entities', '<strong>échappé</strong>'), '::escape() returns an escaped string if the value to escape is a string');
  32. }
  33. public function testEscapeEscapesArrays()
  34. {
  35. $input = array(
  36. 'foo' => '<strong>escaped!</strong>',
  37. 'bar' => array('foo' => '<strong>escaped!</strong>'),
  38. );
  39. $output = Escaper::escape('entities', $input);
  40. $this->assertTrue($output instanceof ArrayDecorator, '::escape() returns a ArrayDecorator object if the value to escape is an array');
  41. $this->assertEquals('&lt;strong&gt;escaped!&lt;/strong&gt;', $output['foo'], '::escape() escapes all elements of the original array');
  42. $this->assertEquals('&lt;strong&gt;escaped!&lt;/strong&gt;', $output['bar']['foo'], '::escape() is recursive');
  43. $this->assertEquals($input, $output->getRawValue(), '->getRawValue() returns the unescaped value');
  44. }
  45. public function testEscapeEscapesObjects()
  46. {
  47. $input = new OutputEscaperTestClass();
  48. $output = Escaper::escape('entities', $input);
  49. $this->assertTrue($output instanceof ObjectDecorator, '::escape() returns a ObjectDecorator object if the value to escape is an object');
  50. $this->assertEquals('&lt;strong&gt;escaped!&lt;/strong&gt;', $output->getTitle(), '::escape() escapes all methods of the original object');
  51. $this->assertEquals('&lt;strong&gt;escaped!&lt;/strong&gt;', $output->title, '::escape() escapes all properties of the original object');
  52. $this->assertEquals('&lt;strong&gt;escaped!&lt;/strong&gt;', $output->getTitleTitle(), '::escape() is recursive');
  53. $this->assertEquals($input, $output->getRawValue(), '->getRawValue() returns the unescaped value');
  54. $this->assertEquals('&lt;strong&gt;escaped!&lt;/strong&gt;', Escaper::escape('entities', $output)->getTitle(), '::escape() does not double escape an object');
  55. $this->assertTrue(Escaper::escape('entities', new \DirectoryIterator('.')) instanceof IteratorDecorator, '::escape() returns a IteratorDecorator object if the value to escape is an object that implements the ArrayAccess interface');
  56. }
  57. public function testEscapeDoesNotEscapeObjectMarkedAsBeingSafe()
  58. {
  59. $this->assertTrue(Escaper::escape('entities', new SafeDecorator(new OutputEscaperTestClass())) instanceof OutputEscaperTestClass, '::escape() returns the original value if it is marked as being safe');
  60. Escaper::markClassAsSafe('Symfony\Tests\Components\OutputEscaper\OutputEscaperTestClass');
  61. $this->assertTrue(Escaper::escape('entities', new OutputEscaperTestClass()) instanceof OutputEscaperTestClass, '::escape() returns the original value if the object class is marked as being safe');
  62. $this->assertTrue(Escaper::escape('entities', new OutputEscaperTestClassChild()) instanceof OutputEscaperTestClassChild, '::escape() returns the original value if one of the object parent class is marked as being safe');
  63. }
  64. public function testEscapeCannotEscapeResources()
  65. {
  66. $fh = fopen(__FILE__, 'r');
  67. try
  68. {
  69. Escaper::escape('entities', $fh);
  70. $this->fail('::escape() throws an InvalidArgumentException if the value cannot be escaped');
  71. }
  72. catch (\InvalidArgumentException $e)
  73. {
  74. }
  75. fclose($fh);
  76. }
  77. public function testUnescapeDoesNotUnescapeSpecialValues()
  78. {
  79. $this->assertTrue(Escaper::unescape(null) === null, '::unescape() returns null if the value to unescape is null');
  80. $this->assertTrue(Escaper::unescape(false) === false, '::unescape() returns false if the value to unescape is false');
  81. $this->assertTrue(Escaper::unescape(true) === true, '::unescape() returns true if the value to unescape is true');
  82. }
  83. public function testUnescapeUnescapesStrings()
  84. {
  85. $this->assertEquals('<strong>escaped!</strong>', Escaper::unescape('&lt;strong&gt;escaped!&lt;/strong&gt;'), '::unescape() returns an unescaped string if the value to unescape is a string');
  86. $this->assertEquals('<strong>échappé</strong>', Escaper::unescape('&lt;strong&gt;&eacute;chapp&eacute;&lt;/strong&gt;'), '::unescape() returns an unescaped string if the value to unescape is a string');
  87. }
  88. public function testUnescapeUnescapesArrays()
  89. {
  90. $input = Escaper::escape('entities', array(
  91. 'foo' => '<strong>escaped!</strong>',
  92. 'bar' => array('foo' => '<strong>escaped!</strong>'),
  93. ));
  94. $output = Escaper::unescape($input);
  95. $this->assertTrue(is_array($output), '::unescape() returns an array if the input is a ArrayDecorator object');
  96. $this->assertEquals('<strong>escaped!</strong>', $output['foo'], '::unescape() unescapes all elements of the original array');
  97. $this->assertEquals('<strong>escaped!</strong>', $output['bar']['foo'], '::unescape() is recursive');
  98. }
  99. public function testUnescapeUnescapesObjects()
  100. {
  101. $object = new OutputEscaperTestClass();
  102. $input = Escaper::escape('entities', $object);
  103. $output = Escaper::unescape($input);
  104. $this->assertTrue($output instanceof OutputEscaperTestClass, '::unescape() returns the original object when a ObjectDecorator object is passed');
  105. $this->assertEquals('<strong>escaped!</strong>', $output->getTitle(), '::unescape() unescapes all methods of the original object');
  106. $this->assertEquals('<strong>escaped!</strong>', $output->title, '::unescape() unescapes all properties of the original object');
  107. $this->assertEquals('<strong>escaped!</strong>', $output->getTitleTitle(), '::unescape() is recursive');
  108. $this->assertTrue(IteratorDecorator::unescape(Escaper::escape('entities', new \DirectoryIterator('.'))) instanceof \DirectoryIterator, '::unescape() unescapes IteratorDecorator objects');
  109. }
  110. public function testUnescapeDoesNotUnescapeObjectMarkedAsBeingSafe()
  111. {
  112. $this->assertTrue(Escaper::unescape(Escaper::escape('entities', new SafeDecorator(new OutputEscaperTestClass()))) instanceof OutputEscaperTestClass, '::unescape() returns the original value if it is marked as being safe');
  113. Escaper::markClassAsSafe('OutputEscaperTestClass');
  114. $this->assertTrue(Escaper::unescape(Escaper::escape('entities', new OutputEscaperTestClass())) instanceof OutputEscaperTestClass, '::unescape() returns the original value if the object class is marked as being safe');
  115. $this->assertTrue(Escaper::unescape(Escaper::escape('entities', new OutputEscaperTestClassChild())) instanceof OutputEscaperTestClassChild, '::unescape() returns the original value if one of the object parent class is marked as being safe');
  116. }
  117. public function testUnescapeDoesNothingToResources()
  118. {
  119. $fh = fopen(__FILE__, 'r');
  120. $this->assertEquals($fh, Escaper::unescape($fh), '::unescape() do nothing to resources');
  121. }
  122. public function testUnescapeUnescapesMixedArrays()
  123. {
  124. $object = new OutputEscaperTestClass();
  125. $input = array(
  126. 'foo' => 'bar',
  127. 'bar' => Escaper::escape('entities', '<strong>bar</strong>'),
  128. 'foobar' => Escaper::escape('entities', $object),
  129. );
  130. $output = array(
  131. 'foo' => 'bar',
  132. 'bar' => '<strong>bar</strong>',
  133. 'foobar' => $object,
  134. );
  135. $this->assertEquals($output, Escaper::unescape($input), '::unescape() unescapes values with some escaped and unescaped values');
  136. }
  137. }
  138. class OutputEscaperTestClass
  139. {
  140. public $title = '<strong>escaped!</strong>';
  141. public function getTitle()
  142. {
  143. return $this->title;
  144. }
  145. public function getTitleTitle()
  146. {
  147. $o = new self;
  148. return $o->getTitle();
  149. }
  150. }
  151. class OutputEscaperTestClassChild extends OutputEscaperTestClass
  152. {
  153. }