vendor/shopware/core/Framework/Feature.php line 138

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework;
  3. use PHPUnit\Framework\TestCase;
  4. use Shopware\Core\DevOps\Environment\EnvironmentHelper;
  5. use Shopware\Core\Framework\Script\Debugging\ScriptTraces;
  6. class Feature
  7. {
  8.     public const ALL_MAJOR 'major';
  9.     /**
  10.      * @var array[]
  11.      */
  12.     private static array $registeredFeatures = [];
  13.     public static function normalizeName(string $name): string
  14.     {
  15.         /*
  16.          * Examples:
  17.          * - NEXT-1234
  18.          * - FEATURE_NEXT_1234
  19.          * - SAAS_321
  20.          * - v6.5.0.0 => v6_5_0_0
  21.          */
  22.         return \strtoupper(\str_replace(['.'':''-'], '_'$name));
  23.     }
  24.     public static function isActive(string $feature): bool
  25.     {
  26.         $env EnvironmentHelper::getVariable('APP_ENV''prod');
  27.         $feature self::normalizeName($feature);
  28.         if (self::$registeredFeatures !== []
  29.             && !isset(self::$registeredFeatures[$feature])
  30.             && $env !== 'prod'
  31.         ) {
  32.             trigger_error('Unknown feature "' $feature '"', \E_USER_WARNING);
  33.         }
  34.         $featureAll EnvironmentHelper::getVariable('FEATURE_ALL''');
  35.         if (self::isTrue((string) $featureAll) && (self::$registeredFeatures === [] || \array_key_exists($featureself::$registeredFeatures))) {
  36.             if ($featureAll === Feature::ALL_MAJOR) {
  37.                 return true;
  38.             }
  39.             // return true if it's registered and not a major feature
  40.             if (isset(self::$registeredFeatures[$feature]) && (self::$registeredFeatures[$feature]['major'] ?? false) === false) {
  41.                 return true;
  42.             }
  43.         }
  44.         if (!EnvironmentHelper::hasVariable($feature) && !EnvironmentHelper::hasVariable(\strtolower($feature))) {
  45.             $fallback self::$registeredFeatures[$feature]['default'] ?? false;
  46.             return (bool) $fallback;
  47.         }
  48.         return self::isTrue(trim((string) EnvironmentHelper::getVariable($feature)));
  49.     }
  50.     public static function ifActive(string $flagName, \Closure $closure): void
  51.     {
  52.         self::isActive($flagName) && $closure();
  53.     }
  54.     /**
  55.      * @param object $object
  56.      * @param mixed[] $arguments
  57.      */
  58.     public static function ifActiveCall(string $flagName$objectstring $methodName, ...$arguments): void
  59.     {
  60.         $closure = function () use ($object$methodName$arguments): void {
  61.             $object->{$methodName}(...$arguments);
  62.         };
  63.         self::ifActive($flagName, \Closure::bind($closure$object$object));
  64.     }
  65.     public static function skipTestIfInActive(string $flagNameTestCase $test): void
  66.     {
  67.         if (self::isActive($flagName)) {
  68.             return;
  69.         }
  70.         $test::markTestSkipped('Skipping feature test for flag  "' $flagName '"');
  71.     }
  72.     public static function skipTestIfActive(string $flagNameTestCase $test): void
  73.     {
  74.         if (!self::isActive($flagName)) {
  75.             return;
  76.         }
  77.         $test::markTestSkipped('Skipping feature test for flag  "' $flagName '"');
  78.     }
  79.     /**
  80.      * Triggers a silenced deprecation notice.
  81.      *
  82.      * @param string $sinceVersion  The version of the package that introduced the deprecation
  83.      * @param string $removeVersion The version of the package when the deprectated code will be removed
  84.      * @param string $message       The message of the deprecation
  85.      * @param mixed  ...$args       Values to insert in the message using printf() formatting
  86.      *
  87.      * @deprecated tag:v6.5.0 - will be removed, use `triggerDeprecationOrThrow` instead
  88.      */
  89.     public static function triggerDeprecated(string $flagstring $sinceVersionstring $removeVersionstring $message, ...$args): void
  90.     {
  91.         self::triggerDeprecationOrThrow(
  92.             'v6.5.0.0',
  93.             self::deprecatedMethodMessage(__CLASS____METHOD__'v6.5.0.0''Feature::triggerDeprecationOrThrow()')
  94.         );
  95.         $message 'Deprecated tag:' $removeVersion '(flag:' $flag '). ' $message;
  96.         if (self::isActive($flag) || !self::has($flag)) {
  97.             if (\PHP_SAPI !== 'cli') {
  98.                 ScriptTraces::addDeprecationNotice(sprintf($message, ...$args));
  99.             }
  100.             trigger_deprecation('shopware/core'$sinceVersion$message$args);
  101.         }
  102.     }
  103.     public static function throwException(string $flagstring $messagebool $state true): void
  104.     {
  105.         if (self::isActive($flag) === $state || !self::has($flag)) {
  106.             throw new \RuntimeException($message);
  107.         }
  108.         if (\PHP_SAPI !== 'cli') {
  109.             ScriptTraces::addDeprecationNotice($message);
  110.         }
  111.     }
  112.     public static function triggerDeprecationOrThrow(string $majorFlagstring $message): void
  113.     {
  114.         if (self::isActive($majorFlag) || !self::has($majorFlag)) {
  115.             throw new \RuntimeException('Tried to access deprecated functionality: ' $message);
  116.         }
  117.         if (\PHP_SAPI !== 'cli') {
  118.             ScriptTraces::addDeprecationNotice($message);
  119.         }
  120.         trigger_deprecation('shopware/core'''$message);
  121.     }
  122.     public static function deprecatedMethodMessage(string $classstring $methodstring $majorVersion, ?string $replacement null): string
  123.     {
  124.         $message = \sprintf(
  125.             'Method "%s::%s()" is deprecated and will be removed in %s.',
  126.             $class,
  127.             $method,
  128.             $majorVersion
  129.         );
  130.         if ($replacement) {
  131.             $message = \sprintf('%s Use "%s" instead.'$message$replacement);
  132.         }
  133.         return $message;
  134.     }
  135.     public static function deprecatedClassMessage(string $classstring $majorVersion, ?string $replacement null): string
  136.     {
  137.         $message = \sprintf(
  138.             'Class "%s" is deprecated and will be removed in %s.',
  139.             $class,
  140.             $majorVersion
  141.         );
  142.         if ($replacement) {
  143.             $message = \sprintf('%s Use "%s" instead.'$message$replacement);
  144.         }
  145.         return $message;
  146.     }
  147.     public static function has(string $flag): bool
  148.     {
  149.         $flag self::normalizeName($flag);
  150.         return isset(self::$registeredFeatures[$flag]);
  151.     }
  152.     public static function getAll(bool $denormalized true): array
  153.     {
  154.         $resolvedFlags = [];
  155.         foreach (self::$registeredFeatures as $name => $_) {
  156.             $active self::isActive($name);
  157.             $resolvedFlags[$name] = $active;
  158.             if (!$denormalized) {
  159.                 continue;
  160.             }
  161.             $resolvedFlags[self::denormalize($name)] = $active;
  162.         }
  163.         return $resolvedFlags;
  164.     }
  165.     /**
  166.      * @internal
  167.      */
  168.     public static function registerFeature(string $name, array $metaData = []): void
  169.     {
  170.         $name self::normalizeName($name);
  171.         // merge with existing data
  172.         $metaData array_merge(
  173.             self::$registeredFeatures[$name] ?? [],
  174.             $metaData
  175.         );
  176.         // set defaults
  177.         $metaData['major'] = (bool) ($metaData['major'] ?? false);
  178.         $metaData['default'] = (bool) ($metaData['default'] ?? false);
  179.         $metaData['description'] = (string) ($metaData['description'] ?? '');
  180.         self::$registeredFeatures[$name] = $metaData;
  181.     }
  182.     /**
  183.      * @internal
  184.      */
  185.     public static function registerFeatures(iterable $registeredFeatures): void
  186.     {
  187.         foreach ($registeredFeatures as $flag => $data) {
  188.             // old format
  189.             if (\is_string($data)) {
  190.                 $flag $data;
  191.                 $data = [];
  192.             }
  193.             self::registerFeature($flag$data);
  194.         }
  195.     }
  196.     /**
  197.      * @internal
  198.      */
  199.     public static function resetRegisteredFeatures(): void
  200.     {
  201.         self::$registeredFeatures = [];
  202.     }
  203.     /**
  204.      * @internal
  205.      */
  206.     public static function getRegisteredFeatures(): array
  207.     {
  208.         return self::$registeredFeatures;
  209.     }
  210.     private static function isTrue(string $value): bool
  211.     {
  212.         return $value
  213.             && $value !== 'false'
  214.             && $value !== '0'
  215.             && $value !== '';
  216.     }
  217.     private static function denormalize(string $name): string
  218.     {
  219.         return \strtolower(\str_replace(['_'], '.'$name));
  220.     }
  221. }