EscaperTest.php 9.0 KB

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