NoMixedEchoPrintFixerTest.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. <?php
  2. /*
  3. * This file is part of PHP CS Fixer.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. * Dariusz Rumiński <dariusz.ruminski@gmail.com>
  7. *
  8. * This source file is subject to the MIT license that is bundled
  9. * with this source code in the file LICENSE.
  10. */
  11. namespace PhpCsFixer\Tests\Fixer\Alias;
  12. use PhpCsFixer\AbstractFixer;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @author Sullivan Senechal <soullivaneuh@gmail.com>
  16. * @author SpacePossum
  17. *
  18. * @internal
  19. *
  20. * @covers \PhpCsFixer\Fixer\Alias\NoMixedEchoPrintFixer
  21. */
  22. final class NoMixedEchoPrintFixerTest extends AbstractFixerTestCase
  23. {
  24. /**
  25. * @param string $expected
  26. * @param null|string $input
  27. *
  28. * @dataProvider provideEchoToPrintFixCases
  29. * @dataProvider provideEchoToPrintFixNewCases
  30. */
  31. public function testFixEchoToPrint($expected, $input = null)
  32. {
  33. $this->fixer->configure(['use' => 'print']);
  34. $this->doTest($expected, $input);
  35. }
  36. public function provideEchoToPrintFixCases()
  37. {
  38. return [
  39. [
  40. '<?php
  41. print "test";
  42. ',
  43. ],
  44. [
  45. '<?php
  46. print ("test");
  47. ',
  48. ],
  49. [
  50. '<?php
  51. print("test");
  52. ',
  53. ],
  54. // `echo` can take multiple parameters (although such usage is rare) while `print` can take only one argument,
  55. // @see https://php.net/manual/en/function.echo.php and @see https://php.net/manual/en/function.print.php
  56. [
  57. '<?php
  58. echo "This ", "string ", "was ", "made ", "with multiple parameters.";
  59. ',
  60. ],
  61. [
  62. '<?php
  63. print "test";
  64. ',
  65. '<?php
  66. echo "test";
  67. ',
  68. ],
  69. [
  70. '<?php
  71. print ("test");
  72. ',
  73. '<?php
  74. echo ("test");
  75. ',
  76. ],
  77. [
  78. '<?php
  79. print("test");
  80. ',
  81. '<?php
  82. echo("test");
  83. ',
  84. ],
  85. [
  86. '<?php
  87. print foo(1, 2);
  88. ',
  89. '<?php
  90. echo foo(1, 2);
  91. ',
  92. ],
  93. [
  94. '<?php
  95. print ["foo", "bar", "baz"][$x];
  96. ',
  97. '<?php
  98. echo ["foo", "bar", "baz"][$x];
  99. ',
  100. ],
  101. [
  102. '<?php
  103. print $foo ? "foo" : "bar";
  104. ',
  105. '<?php
  106. echo $foo ? "foo" : "bar";
  107. ',
  108. ],
  109. [
  110. "<?php print 'foo' ?>...<?php echo 'bar', 'baz' ?>",
  111. "<?php echo 'foo' ?>...<?php echo 'bar', 'baz' ?>",
  112. ],
  113. [
  114. '<?php
  115. if ($foo) {
  116. print "foo";
  117. }
  118. print "bar";
  119. ',
  120. '<?php
  121. if ($foo) {
  122. echo "foo";
  123. }
  124. echo "bar";
  125. ',
  126. ],
  127. [
  128. '<?=$foo?>',
  129. ],
  130. ];
  131. }
  132. public static function provideEchoToPrintFixNewCases()
  133. {
  134. foreach (self::getCodeSnippetsToConvertBothWays() as $name => $codeSnippet) {
  135. yield [
  136. sprintf($codeSnippet, 'print'),
  137. sprintf($codeSnippet, 'echo'),
  138. ];
  139. }
  140. }
  141. /**
  142. * @param string $expected
  143. * @param null|string $input
  144. *
  145. * @dataProvider providePrintToEchoFixCases
  146. * @dataProvider providePrintToEchoFixNewCases
  147. */
  148. public function testFixPrintToEcho($expected, $input = null)
  149. {
  150. $this->fixer->configure(['use' => 'echo']);
  151. $this->doTest($expected, $input);
  152. }
  153. public function providePrintToEchoFixCases()
  154. {
  155. return [
  156. [
  157. '<?php
  158. echo "test";
  159. ',
  160. ],
  161. [
  162. '<?php
  163. echo ("test");
  164. ',
  165. ],
  166. [
  167. '<?php
  168. echo("test");
  169. ',
  170. ],
  171. // https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues/1502#issuecomment-156436229
  172. [
  173. '<?php
  174. ($some_var) ? print "true" : print "false";
  175. ',
  176. ],
  177. // echo has no return value while print has a return value of 1 so it can be used in expressions.
  178. // https://www.w3schools.com/php/php_echo_print.asp
  179. [
  180. '<?php
  181. $ret = print "test";
  182. ',
  183. ],
  184. [
  185. '<?php
  186. @print foo();
  187. ',
  188. ],
  189. [
  190. '<?php
  191. function testFunction() {
  192. return print("test");
  193. }
  194. $a = testFunction();
  195. $b += print($a);
  196. $c=\'\';
  197. $c .= $b.print($a);
  198. $d = print($c) > 0 ? \'a\' : \'b\';
  199. switch(print(\'a\')) {}
  200. if (1 === print($a)) {}
  201. ',
  202. ],
  203. [
  204. '<?php
  205. some_function_call();
  206. echo "test";
  207. ',
  208. '<?php
  209. some_function_call();
  210. print "test";
  211. ',
  212. ],
  213. [
  214. '<?php
  215. echo "test";
  216. ',
  217. '<?php
  218. print "test";
  219. ',
  220. ],
  221. [
  222. '<?php
  223. echo ("test");
  224. ',
  225. '<?php
  226. print ("test");
  227. ',
  228. ],
  229. [
  230. '<?php
  231. echo("test");
  232. ',
  233. '<?php
  234. print("test");
  235. ',
  236. ],
  237. [
  238. '<?php
  239. echo foo(1, 2);
  240. ',
  241. '<?php
  242. print foo(1, 2);
  243. ',
  244. ],
  245. [
  246. '<?php
  247. echo $foo ? "foo" : "bar";
  248. ',
  249. '<?php
  250. print $foo ? "foo" : "bar";
  251. ',
  252. ],
  253. [
  254. '<?php
  255. if ($foo) {
  256. echo "foo";
  257. }
  258. echo "bar";
  259. ',
  260. '<?php
  261. if ($foo) {
  262. print "foo";
  263. }
  264. print "bar";
  265. ',
  266. ],
  267. ];
  268. }
  269. public static function providePrintToEchoFixNewCases()
  270. {
  271. foreach (self::getCodeSnippetsToConvertBothWays() as $name => $codeSnippet) {
  272. yield [
  273. sprintf($codeSnippet, 'echo'),
  274. sprintf($codeSnippet, 'print'),
  275. ];
  276. }
  277. }
  278. /**
  279. * @group legacy
  280. * @expectedDeprecation Passing NULL to set default configuration is deprecated and will not be supported in 3.0, use an empty array instead.
  281. */
  282. public function testLegacyDefaultConfig()
  283. {
  284. $this->fixer->configure(null);
  285. static::assertCandidateTokenType(T_PRINT, $this->fixer);
  286. }
  287. public function testDefaultConfig()
  288. {
  289. $this->fixer->configure([]);
  290. static::assertCandidateTokenType(T_PRINT, $this->fixer);
  291. }
  292. /**
  293. * @dataProvider provideWrongConfigCases
  294. *
  295. * @param mixed $wrongConfig
  296. * @param string $expectedMessage
  297. */
  298. public function testWrongConfig($wrongConfig, $expectedMessage)
  299. {
  300. $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class);
  301. $this->expectExceptionMessageMatches($expectedMessage);
  302. $this->fixer->configure($wrongConfig);
  303. }
  304. public function provideWrongConfigCases()
  305. {
  306. return [
  307. [
  308. ['a' => 'b'],
  309. '#^\[no_mixed_echo_print\] Invalid configuration: The option "a" does not exist\. (Known|Defined) options are: "use"\.$#',
  310. ],
  311. [
  312. ['a' => 'b', 'b' => 'c'],
  313. '#^\[no_mixed_echo_print\] Invalid configuration: The options "a", "b" do not exist\. (Known|Defined) options are: "use"\.$#',
  314. ],
  315. [
  316. [1],
  317. '#^\[no_mixed_echo_print\] Invalid configuration: The option "0" does not exist\. (Known|Defined) options are: "use"\.$#',
  318. ],
  319. [
  320. ['use' => '_invalid_'],
  321. '#^\[no_mixed_echo_print\] Invalid configuration: The option "use" with value "_invalid_" is invalid\. Accepted values are: "print", "echo"\.$#',
  322. ],
  323. ];
  324. }
  325. private static function assertCandidateTokenType($expected, AbstractFixer $fixer)
  326. {
  327. $reflectionProperty = new \ReflectionProperty($fixer, 'candidateTokenType');
  328. $reflectionProperty->setAccessible(true);
  329. static::assertSame($expected, $reflectionProperty->getValue($fixer));
  330. }
  331. private static function getCodeSnippetsToConvertBothWays()
  332. {
  333. yield 'inside of HTML' => '<div><?php %1$s "foo" ?></div>';
  334. yield 'foreach without curly brackets' => '<?php
  335. %1$s "There will be foos: ";
  336. foreach ($foos as $foo)
  337. %1$s $foo;
  338. %1$s "End of foos";
  339. ';
  340. yield 'if and else without curly brackets' => '<?php
  341. if ($foo)
  342. %1$s "One";
  343. elseif ($bar)
  344. %1$s "Two";
  345. else
  346. %1$s "Three";
  347. ';
  348. }
  349. }