ObserverImplementationTest.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Test\Integrity;
  7. use Magento\Framework\App\Utility\Files;
  8. /**
  9. * PAY ATTENTION: Current implementation does not support of virtual types
  10. */
  11. class ObserverImplementationTest extends \PHPUnit\Framework\TestCase
  12. {
  13. /**
  14. * Observer interface
  15. */
  16. const OBSERVER_INTERFACE = \Magento\Framework\Event\ObserverInterface::class;
  17. /**
  18. * @var array
  19. */
  20. protected static $observerClasses = [];
  21. public static function setUpBeforeClass()
  22. {
  23. self::$observerClasses = array_merge(
  24. self::getObserverClasses('{*/events.xml,events.xml}', '//observer')
  25. );
  26. }
  27. public function testObserverInterfaceImplementation()
  28. {
  29. $errors = [];
  30. foreach (self::$observerClasses as $observerClass) {
  31. if (!is_subclass_of($observerClass, self::OBSERVER_INTERFACE)) {
  32. $errors[] = $observerClass;
  33. }
  34. }
  35. if ($errors) {
  36. $errors = array_unique($errors);
  37. sort($errors);
  38. $this->fail(
  39. sprintf(
  40. '%d of observers which not implement \Magento\Framework\Event\ObserverInterface: %s',
  41. count($errors),
  42. "\n" . implode("\n", $errors)
  43. )
  44. );
  45. }
  46. }
  47. public function testObserverHasNoExtraPublicMethods()
  48. {
  49. $errors = [];
  50. foreach (self::$observerClasses as $observerClass) {
  51. $reflection = (new \ReflectionClass($observerClass));
  52. $maxCountMethod = $reflection->getConstructor() ? 2 : 1;
  53. if (count($reflection->getMethods(\ReflectionMethod::IS_PUBLIC)) > $maxCountMethod) {
  54. $errors[] = $observerClass;
  55. }
  56. }
  57. if ($errors) {
  58. $errors = array_unique($errors);
  59. sort($errors);
  60. $this->fail(
  61. sprintf(
  62. '%d of observers have extra public methods: %s',
  63. count($errors),
  64. implode("\n", $errors)
  65. )
  66. );
  67. }
  68. }
  69. /**
  70. * @param string $fileNamePattern
  71. * @param string $xpath
  72. * @return array
  73. */
  74. protected static function getObserverClasses($fileNamePattern, $xpath)
  75. {
  76. $observerClasses = [];
  77. foreach (Files::init()->getConfigFiles($fileNamePattern, [], false) as $configFile) {
  78. foreach (simplexml_load_file($configFile)->xpath($xpath) as $observer) {
  79. $className = (string)$observer->attributes()->instance;
  80. // $className may be empty in cases like this <observer name="observer_name" disabled="true" />
  81. if ($className) {
  82. $observerClasses[] = trim((string)$observer->attributes()->instance, '\\');
  83. }
  84. }
  85. }
  86. $blacklistFiles = str_replace('\\', '/', realpath(__DIR__)) . '/_files/blacklist/observers*.txt';
  87. $blacklistExceptions = [];
  88. foreach (glob($blacklistFiles) as $fileName) {
  89. $blacklistExceptions = array_merge(
  90. $blacklistExceptions,
  91. file($fileName, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
  92. );
  93. }
  94. return array_diff(
  95. array_unique($observerClasses),
  96. $blacklistExceptions
  97. );
  98. }
  99. }